Numerous fixes to get it to compile.

2001-05-31  Jeffrey Stedfast  <fejj@ximian.com>

	* camel-smime-context.c: Numerous fixes to get it to compile.

svn path=/trunk/; revision=10073
This commit is contained in:
Jeffrey Stedfast
2001-05-31 22:30:06 +00:00
committed by Jeffrey Stedfast
parent 69e9359204
commit e86a28e484
4 changed files with 383 additions and 62 deletions

View File

@ -1,5 +1,7 @@
2001-05-31 Jeffrey Stedfast <fejj@ximian.com>
* camel-smime-context.c: Numerous fixes to get it to compile.
* camel.h: Added camel-cipher-context.h, camel-cms-context.h,
camel-smime-context.h, and camel-smime-utils.h

View File

@ -1736,27 +1736,211 @@ header_decode_int(const char **in)
return v;
}
static int
header_decode_param(const char **in, char **paramp, char **valuep)
#define HEXVAL(c) (isdigit (c) ? (c) - '0' : tolower (c) - 'a' + 10)
static char *
hex_decode (const char *in, int len)
{
const guchar *inend = (const guchar *) in + len;
guchar *inptr, *outptr;
char *outbuf;
outptr = outbuf = g_malloc (len);
inptr = (guchar *) in;
while (inptr < inend) {
if (*inptr == '%') {
if (isxdigit (inptr[1]) && isxdigit (inptr[2])) {
*outptr++ = HEXVAL (inptr[1]) * 16 + HEXVAL (inptr[2]);
inptr += 3;
} else
*outptr++ = *inptr++;
} else
*outptr++ = *inptr++;
}
*outptr = '\0';
return outbuf;
}
/* an rfc2184 encoded string looks something like:
* us-ascii'en'This%20is%20even%20more%20
*/
static char *
rfc2184_decode (const char *in, int len)
{
const char *inptr = in;
const char *inend = in + len;
char *decoded = NULL;
char *encoding;
inptr = memchr (inptr, '\'', len);
if (!inptr)
return NULL;
encoding = g_strndup (in, inptr - in);
inptr = memchr (inptr + 1, '\'', inend - inptr - 1);
if (!inptr) {
g_free (encoding);
return NULL;
}
inptr++;
if (inptr < inend) {
char *decword, *inbuf, *outbase, *outbuf;
int inlen, outlen;
iconv_t ic;
inbuf = decword = hex_decode (inptr, inend - inptr);
inlen = strlen (inbuf);
outlen = inlen * 6 + 16;
outbuf = outbase = g_malloc (outlen);
ic = iconv_open ("UTF-8", encoding);
if (ic != (iconv_t) -1) {
int ret;
ret = iconv (ic, &inbuf, &inlen, &outbuf, &outlen);
if (ret >= 0) {
iconv (ic, NULL, 0, &outbuf, &outlen);
*outbuf = '\0';
g_free (decoded);
decoded = outbase;
}
iconv_close (ic);
} else {
decoded = decword;
}
}
return decoded;
}
/* This function is basically the same as decode_token()
* except that it will not accept *'s which have a special
* meaning for rfc2184 params */
static char *
decode_param_token (const char **in)
{
const char *inptr = *in;
char *param, *value=NULL;
const char *start;
header_decode_lwsp (&inptr);
start = inptr;
while (is_ttoken (*inptr) && *inptr != '*')
inptr++;
if (inptr > start) {
*in = inptr;
return g_strndup (start, inptr-start);
} else {
return NULL;
}
}
param = decode_token(&inptr);
header_decode_lwsp(&inptr);
static gboolean
header_decode_rfc2184_param (const char **in, char **paramp, int *part, gboolean *value_is_encoded)
{
gboolean is_rfc2184 = FALSE;
const char *inptr = *in;
char *param;
param = decode_param_token (&inptr);
header_decode_lwsp (&inptr);
if (*inptr == '*') {
is_rfc2184 = TRUE;
inptr++;
header_decode_lwsp (&inptr);
if (*inptr == '=') {
/* form := param*=value */
if (value_is_encoded)
*value_is_encoded = TRUE;
} else {
/* form := param*#=value or param*#*=value */
*part = header_decode_int (&inptr);
header_decode_lwsp (&inptr);
if (*inptr == '*') {
/* form := param*#*=value */
if (value_is_encoded)
*value_is_encoded = TRUE;
inptr++;
header_decode_lwsp (&inptr);
}
}
}
if (paramp)
*paramp = param;
if (param)
*in = inptr;
return is_rfc2184;
}
static int
header_decode_param(const char **in, char **paramp, char **valuep, int *is_rfc2184_param)
{
gboolean is_rfc2184_encoded = FALSE;
gboolean is_rfc2184 = FALSE;
const char *inptr = *in;
char *param, *value = NULL;
int rfc2184_part = -1;
*is_rfc2184_param = FALSE;
is_rfc2184 = header_decode_rfc2184_param (&inptr, &param, &rfc2184_part,
&is_rfc2184_encoded);
if (*inptr == '=') {
inptr++;
value = header_decode_value(&inptr);
value = header_decode_value (&inptr);
if (is_rfc2184) {
/* We have ourselves an rfc2184 parameter */
if (rfc2184_part == -1) {
/* rfc2184 allows the value to be broken into
* multiple parts - this isn't one of them so
* it is safe to decode it.
*/
char *val;
val = rfc2184_decode (value, strlen (value));
g_free (value);
value = val;
} else {
/* Since we are expecting to find the rest of
* this paramter value later, let our caller know.
*/
*is_rfc2184_param = TRUE;
}
} else if (value && !strcmp (value, "=?")) {
/* We have a broken param value that is rfc2047 encoded.
* Since both Outlook and Netscape/Mozilla do this, we
* should handle this case.
*/
char *val;
val = rfc2047_decode_word (value, strlen (value));
if (val) {
g_free (value);
value = val;
}
}
}
if (param && value) {
*paramp = param;
*valuep = value;
*in = inptr;
return 0;
} else {
g_free(param);
g_free(value);
g_free (param);
g_free (value);
return 1;
}
}
@ -2425,28 +2609,73 @@ header_decode_param_list(const char **in)
{
const char *inptr = *in;
struct _header_param *head = NULL, *tail = NULL;
header_decode_lwsp(&inptr);
gboolean last_was_rfc2184 = FALSE;
gboolean is_rfc2184 = FALSE;
header_decode_lwsp (&inptr);
while (*inptr == ';') {
char *param, *value;
struct _header_param *p;
inptr++;
/* invalid format? */
if (header_decode_param(&inptr, &param, &value) != 0)
if (header_decode_param (&inptr, &param, &value, &is_rfc2184) != 0)
break;
p = g_malloc(sizeof(*p));
p->name = param;
p->value = value;
p->next = NULL;
if (head == NULL)
head = p;
if (tail)
tail->next = p;
tail = p;
header_decode_lwsp(&inptr);
if (is_rfc2184 && tail && !g_strcasecmp (param, tail->name)) {
/* rfc2184 allows a parameter to be broken into multiple parts
* and it looks like we've found one. Append this value to the
* last value.
*/
GString *gvalue;
gvalue = g_string_new (tail->value);
g_string_append (gvalue, value);
g_free (tail->value);
g_free (value);
tail->value = gvalue->str;
g_string_free (gvalue, FALSE);
} else {
if (last_was_rfc2184) {
/* We've finished gathering the values for the last param
* so it is now safe to decode it.
*/
char *val;
val = rfc2184_decode (tail->value, strlen (tail->value));
g_free (tail->value);
tail->value = val;
}
p = g_malloc (sizeof (struct _header_param));
p->name = param;
p->value = value;
p->next = NULL;
if (head == NULL)
head = p;
if (tail)
tail->next = p;
tail = p;
}
last_was_rfc2184 = is_rfc2184;
header_decode_lwsp (&inptr);
}
if (last_was_rfc2184) {
/* We've finished gathering the values for the last param
* so it is now safe to decode it.
*/
char *val;
val = rfc2184_decode (tail->value, strlen (tail->value));
g_free (tail->value);
tail->value = val;
}
*in = inptr;
return head;
}
@ -2460,31 +2689,115 @@ header_param_list_decode(const char *in)
return header_decode_param_list(&in);
}
/* FIXME: I wrote this in a quick & dirty fasion - it may not be 100% correct */
static char *
header_encode_param (const unsigned char *in, gboolean *encoded)
{
const unsigned char *inptr = in;
char *outstr, *charset;
int encoding;
GString *out;
*encoded = FALSE;
g_return_val_if_fail (g_utf8_validate (in, -1, NULL), NULL);
if (in == NULL)
return NULL;
/* do a quick us-ascii check (the common case?) */
while (*inptr) {
if (*inptr > 127)
break;
inptr++;
}
if (*inptr == '\0')
return g_strdup (in);
out = g_string_new ("");
inptr = in;
encoding = 0;
while (inptr && *inptr) {
gunichar c;
const char *newinptr;
newinptr = g_utf8_next_char (inptr);
c = g_utf8_get_char (inptr);
if (newinptr == NULL || !g_unichar_validate (c)) {
w(g_warning ("Invalid UTF-8 sequence encountered (pos %d, char '%c'): %s",
(inptr-in), inptr[0], in));
inptr++;
continue;
}
if (c > 127 && c < 256) {
encoding = MAX (encoding, 1);
g_string_sprintfa (out, "%%%c%c", tohex[(c >> 4) & 0xf], tohex[c & 0xf]);
} else if (c >= 256) {
encoding = MAX (encoding, 2);
g_string_sprintfa (out, "%%%c%c", tohex[(c >> 4) & 0xf], tohex[c & 0xf]);
} else if (is_lwsp (c) || camel_mime_special_table[c] & IS_ESAFE) {
g_string_sprintfa (out, "%%%c%c", tohex[(c >> 4) & 0xf], tohex[c & 0xf]);
} else {
g_string_append_c (out, c);
}
inptr = newinptr;
}
switch (encoding) {
default:
g_string_prepend (out, "iso-8859-1''");
break;
case 2:
charset = g_strdup_printf ("%s''", camel_charset_best (in, inptr - in));
g_string_prepend (out, charset);
g_free (charset);
break;
}
outstr = out->str;
g_string_free (out, FALSE);
*encoded = TRUE;
return outstr;
}
void
header_param_list_format_append(GString *out, struct _header_param *p)
{
int len = out->len;
char *ch;
while (p) {
gboolean encoded = FALSE;
char *value, *ch = NULL;
int here = out->len;
if (len+strlen(p->name)+strlen(p->value)>60) {
out = g_string_append(out, ";\n\t");
value = header_encode_param (p->value, &encoded);
if (!encoded) {
for (ch = value; *ch; ch++) {
if (is_tspecial (*ch) || is_lwsp (*ch))
break;
}
}
if (len + strlen (p->name) + strlen (value) > 60) {
out = g_string_append (out, ";\n\t");
len = 0;
} else
out = g_string_append (out, "; ");
g_string_sprintfa(out, "%s=", p->name);
for (ch = p->value; *ch; ch++) {
if (is_tspecial (*ch) || is_lwsp (*ch))
break;
}
if (!*ch)
g_string_append(out, p->value);
g_string_sprintfa (out, "%s%s=", p->name, encoded ? "*" : "");
if (!ch || !*ch)
g_string_append (out, value);
else
quote_word(out, TRUE, p->value, strlen(p->value));
quote_word (out, TRUE, value, strlen (value));
g_free (value);
len += (out->len - here);
p = p->next;
}

View File

@ -32,9 +32,15 @@
#include "camel-stream-filter.h"
#include "camel-stream-fs.h"
#include "camel-stream-mem.h"
#include "camel-mime-part.h"
#include "camel-multipart.h"
#include "nss.h"
#include <cms.h>
#include <cert.h>
#include <certdb.h>
#include <pkcs11.h>
#include <smime.h>
#include <gtk/gtk.h> /* for _() macro */
@ -64,7 +70,7 @@ static CamelMimeMessage *smime_envelope (CamelCMSContext *ctx, CamelMimeMessage
static CamelMimeMessage *smime_decode (CamelCMSContext *ctx, CamelMimeMessage *message,
CamelCMSValidityInfo **info, CamelException *ex);
static CamelCipherContextClass *parent_class;
static CamelCMSContextClass *parent_class;
static void
camel_smime_context_init (CamelSMimeContext *context)
@ -89,11 +95,11 @@ camel_smime_context_class_init (CamelSMimeContextClass *camel_smime_context_clas
parent_class = CAMEL_CMS_CONTEXT_CLASS (camel_type_get_global_classfuncs (camel_cms_context_get_type ()));
camel_cms_context_class->sign = cms_sign;
camel_cms_context_class->certsonly = cms_certsonly;
camel_cms_context_class->encrypt = cms_encrypt;
camel_cms_context_class->envelope = cms_envelope;
camel_cms_context_class->decode = cms_decode;
camel_cms_context_class->sign = smime_sign;
camel_cms_context_class->certsonly = smime_certsonly;
camel_cms_context_class->encrypt = smime_encrypt;
camel_cms_context_class->envelope = smime_envelope;
camel_cms_context_class->decode = smime_decode;
}
CamelType
@ -198,7 +204,7 @@ signed_data (CamelSMimeContext *ctx, const char *userid, gboolean signing_time,
return NULL;
}
if ((cert = CERT_FindCertByNickname (ctx->priv->certdb, userid)) == NULL) {
if ((cert = CERT_FindCertByNickname (ctx->priv->certdb, (char *) userid)) == NULL) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("The signature certificate for \"%s\" does not exist."),
userid);
@ -386,17 +392,17 @@ smime_sign (CamelCMSContext *ctx, CamelMimeMessage *message,
static NSSCMSMessage *
certsonly_data (CamelSMimeContext *ctx, const char *userid, GByteArray *recipients, CamelException *ex)
certsonly_data (CamelSMimeContext *ctx, const char *userid, GPtrArray *recipients, CamelException *ex)
{
NSSCMSMessage *cmsg = NULL;
NSSCMSContentInfo *cinfo;
NSSCMSSignedData *sigd;
CERTCertificate **rcerts;
int i;
int i = 0;
/* find the signer's and the recipients' certs */
rcerts = g_new (CERTCertificate *, recipients->len + 2);
rcerts[0] = CERT_FindCertByNicknameOrEmailAddr (ctx->priv->certdb, userid);
rcerts[0] = CERT_FindCertByNicknameOrEmailAddr (ctx->priv->certdb, (char *) userid);
if (!rcerts[0]) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Failed to find certificate for \"%s\"."),
@ -424,7 +430,7 @@ certsonly_data (CamelSMimeContext *ctx, const char *userid, GByteArray *recipien
/* add the recipient cert chain */
for (i = 0; i < recipients->len; i++) {
NSS_CMSSignedData_AddCertChain (sigd, certs[i]);
NSS_CMSSignedData_AddCertChain (sigd, rcerts[i]);
}
cinfo = NSS_CMSMessage_GetContentInfo (cmsg);
@ -452,6 +458,7 @@ smime_certsonly (CamelCMSContext *ctx, CamelMimeMessage *message,
CamelException *ex)
{
CamelMimeMessage *mesg = NULL;
struct _GetPasswdData *data;
NSSCMSMessage *cmsg = NULL;
PLArenaPool *arena;
NSSCMSEncoderContext *ecx;
@ -512,7 +519,7 @@ enveloped_data (CamelSMimeContext *ctx, const char *userid, GPtrArray *recipient
/* find the recipient certs by email address or nickname */
rcerts = g_new (CERTCertificate *, recipients->len + 2);
rcerts[0] = CERT_FindCertByNicknameOrEmailAddr (ctx->priv->certdb, userid);
rcerts[0] = CERT_FindCertByNicknameOrEmailAddr (ctx->priv->certdb, (char *) userid);
if (!rcerts[0]) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Failed to find certificate for \"%s\"."),
@ -574,6 +581,7 @@ smime_envelope (CamelCMSContext *ctx, CamelMimeMessage *message,
CamelException *ex)
{
CamelMimeMessage *mesg = NULL;
struct _GetPasswdData *data;
NSSCMSMessage *cmsg = NULL;
PLArenaPool *arena;
NSSCMSEncoderContext *ecx;
@ -622,8 +630,8 @@ smime_envelope (CamelCMSContext *ctx, CamelMimeMessage *message,
struct _BulkKey {
PK11KeySym *bulkkey;
SECOidTag bulkkeytag;
PK11SymKey *bulkkey;
SECOidTag bulkalgtag;
int keysize;
};
@ -754,8 +762,8 @@ smime_encrypt (CamelCMSContext *ctx, CamelMimeMessage *message,
static NSSCMSMessage *
decode (CamelSMimeContext *ctx, GByteArray *input, CamelStream *ostream,
CamelCMSValidityInfo **info, CamelExcepton *ex)
decode_data (CamelSMimeContext *ctx, GByteArray *input, CamelStream *ostream,
CamelCMSValidityInfo **info, CamelException *ex)
{
NSSCMSDecoderContext *dcx;
struct _GetPasswdData *data;
@ -765,17 +773,14 @@ decode (CamelSMimeContext *ctx, GByteArray *input, CamelStream *ostream,
NSSCMSSignedData *sigd = NULL;
NSSCMSEnvelopedData *envd;
NSSCMSEncryptedData *encd;
SECAlgorithmID **digestalgs;
int nlevels, i, nsigners, j;
char *signercn;
NSSCMSSignerInfo *si;
SECOidTag typetag;
SECItem **digests;
PLArenaPool *arena;
SECItem *item, sitem = { 0, 0, 0 };
SECItem *item;
data = g_new (struct _GetPasswdData, 1);
data->session = ctx->session;
data->session = CAMEL_CMS_CONTEXT (ctx)->session;
data->userid = NULL;
data->ex = ex;
@ -783,7 +788,7 @@ decode (CamelSMimeContext *ctx, GByteArray *input, CamelStream *ostream,
NULL, NULL,
smime_get_password, data,
decode_key_cb,
decodeOptions->bulkkey);
NULL);
NSS_CMSDecoder_Update (dcx, input->data, input->len);
@ -861,7 +866,7 @@ decode (CamelSMimeContext *ctx, GByteArray *input, CamelStream *ostream,
certUsageEmailSigner);
if (signers) {
signers->signeercn = g_strdup (signercn);
signers->signercn = g_strdup (signercn);
signers->status = g_strdup (
NSS_CMSUtil_VerificationStatusToString (
NSS_CMSSignerInfo_GetVerificationStatus (si)));
@ -918,7 +923,7 @@ smime_decode (CamelCMSContext *ctx, CamelMimeMessage *message,
buf = CAMEL_STREAM_MEM (stream)->buffer;
ostream = camel_stream_mem_new ();
cmsg = decode (CAMEL_SMIME_CONTEXT (ctx), buf, ostream, info, ex);
cmsg = decode_data (CAMEL_SMIME_CONTEXT (ctx), buf, ostream, info, ex);
camel_object_unref (CAMEL_OBJECT (stream));
if (!cmsg) {
camel_object_unref (CAMEL_OBJECT (ostream));

View File

@ -42,6 +42,7 @@ typedef struct _CamelSMimeContext {
struct _CamelSMimeContextPrivate *priv;
char *encryption_key;
} CamelSMimeContext;
typedef struct _CamelSMimeContextClass {