summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/asn1/asn_mime.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/asn1/asn_mime.c')
-rw-r--r--src/lib/libcrypto/asn1/asn_mime.c597
1 files changed, 334 insertions, 263 deletions
diff --git a/src/lib/libcrypto/asn1/asn_mime.c b/src/lib/libcrypto/asn1/asn_mime.c
index 6cde8fd44e..890557578d 100644
--- a/src/lib/libcrypto/asn1/asn_mime.c
+++ b/src/lib/libcrypto/asn1/asn_mime.c
@@ -10,7 +10,7 @@
10 * are met: 10 * are met:
11 * 11 *
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 14 *
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in 16 * notice, this list of conditions and the following disclaimer in
@@ -71,24 +71,24 @@
71 */ 71 */
72 72
73typedef struct { 73typedef struct {
74char *param_name; /* Param name e.g. "micalg" */ 74 char *param_name; /* Param name e.g. "micalg" */
75char *param_value; /* Param value e.g. "sha1" */ 75 char *param_value; /* Param value e.g. "sha1" */
76} MIME_PARAM; 76} MIME_PARAM;
77 77
78DECLARE_STACK_OF(MIME_PARAM) 78DECLARE_STACK_OF(MIME_PARAM)
79IMPLEMENT_STACK_OF(MIME_PARAM) 79IMPLEMENT_STACK_OF(MIME_PARAM)
80 80
81typedef struct { 81typedef struct {
82char *name; /* Name of line e.g. "content-type" */ 82 char *name; /* Name of line e.g. "content-type" */
83char *value; /* Value of line e.g. "text/plain" */ 83 char *value; /* Value of line e.g. "text/plain" */
84STACK_OF(MIME_PARAM) *params; /* Zero or more parameters */ 84 STACK_OF(MIME_PARAM) *params; /* Zero or more parameters */
85} MIME_HEADER; 85} MIME_HEADER;
86 86
87DECLARE_STACK_OF(MIME_HEADER) 87DECLARE_STACK_OF(MIME_HEADER)
88IMPLEMENT_STACK_OF(MIME_HEADER) 88IMPLEMENT_STACK_OF(MIME_HEADER)
89 89
90static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags, 90static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
91 const ASN1_ITEM *it); 91 const ASN1_ITEM *it);
92static char * strip_ends(char *name); 92static char * strip_ends(char *name);
93static char * strip_start(char *name); 93static char * strip_start(char *name);
94static char * strip_end(char *name); 94static char * strip_end(char *name);
@@ -96,9 +96,9 @@ static MIME_HEADER *mime_hdr_new(char *name, char *value);
96static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value); 96static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value);
97static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio); 97static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio);
98static int mime_hdr_cmp(const MIME_HEADER * const *a, 98static int mime_hdr_cmp(const MIME_HEADER * const *a,
99 const MIME_HEADER * const *b); 99 const MIME_HEADER * const *b);
100static int mime_param_cmp(const MIME_PARAM * const *a, 100static int mime_param_cmp(const MIME_PARAM * const *a,
101 const MIME_PARAM * const *b); 101 const MIME_PARAM * const *b);
102static void mime_param_free(MIME_PARAM *param); 102static void mime_param_free(MIME_PARAM *param);
103static int mime_bound_check(char *line, int linelen, char *bound, int blen); 103static int mime_bound_check(char *line, int linelen, char *bound, int blen);
104static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret); 104static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret);
@@ -112,15 +112,17 @@ static void mime_hdr_free(MIME_HEADER *hdr);
112 112
113/* Output an ASN1 structure in BER format streaming if necessary */ 113/* Output an ASN1 structure in BER format streaming if necessary */
114 114
115int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, 115int
116 const ASN1_ITEM *it) 116i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
117 const ASN1_ITEM *it)
117{ 118{
118 /* If streaming create stream BIO and copy all content through it */ 119 /* If streaming create stream BIO and copy all content through it */
119 if (flags & SMIME_STREAM) { 120 if (flags & SMIME_STREAM) {
120 BIO *bio, *tbio; 121 BIO *bio, *tbio;
121 bio = BIO_new_NDEF(out, val, it); 122 bio = BIO_new_NDEF(out, val, it);
122 if (!bio) { 123 if (!bio) {
123 ASN1err(ASN1_F_I2D_ASN1_BIO_STREAM,ERR_R_MALLOC_FAILURE); 124 ASN1err(ASN1_F_I2D_ASN1_BIO_STREAM,
125 ERR_R_MALLOC_FAILURE);
124 return 0; 126 return 0;
125 } 127 }
126 SMIME_crlf_copy(in, bio, flags); 128 SMIME_crlf_copy(in, bio, flags);
@@ -142,14 +144,16 @@ int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
142 144
143/* Base 64 read and write of ASN1 structure */ 145/* Base 64 read and write of ASN1 structure */
144 146
145static int B64_write_ASN1(BIO *out, ASN1_VALUE *val, BIO *in, int flags, 147static int
146 const ASN1_ITEM *it) 148B64_write_ASN1(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
149 const ASN1_ITEM *it)
147{ 150{
148 BIO *b64; 151 BIO *b64;
149 int r; 152 int r;
153
150 b64 = BIO_new(BIO_f_base64()); 154 b64 = BIO_new(BIO_f_base64());
151 if(!b64) { 155 if (!b64) {
152 ASN1err(ASN1_F_B64_WRITE_ASN1,ERR_R_MALLOC_FAILURE); 156 ASN1err(ASN1_F_B64_WRITE_ASN1, ERR_R_MALLOC_FAILURE);
153 return 0; 157 return 0;
154 } 158 }
155 /* prepend the b64 BIO so all data is base64 encoded. 159 /* prepend the b64 BIO so all data is base64 encoded.
@@ -164,29 +168,31 @@ static int B64_write_ASN1(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
164 168
165/* Streaming ASN1 PEM write */ 169/* Streaming ASN1 PEM write */
166 170
167int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, 171int
168 const char *hdr, 172PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
169 const ASN1_ITEM *it) 173 const char *hdr, const ASN1_ITEM *it)
170{ 174{
171 int r; 175 int r;
176
172 BIO_printf(out, "-----BEGIN %s-----\n", hdr); 177 BIO_printf(out, "-----BEGIN %s-----\n", hdr);
173 r = B64_write_ASN1(out, val, in, flags, it); 178 r = B64_write_ASN1(out, val, in, flags, it);
174 BIO_printf(out, "-----END %s-----\n", hdr); 179 BIO_printf(out, "-----END %s-----\n", hdr);
175 return r; 180 return r;
176} 181}
177 182
178static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it) 183static ASN1_VALUE *
184b64_read_asn1(BIO *bio, const ASN1_ITEM *it)
179{ 185{
180 BIO *b64; 186 BIO *b64;
181 ASN1_VALUE *val; 187 ASN1_VALUE *val;
182 if(!(b64 = BIO_new(BIO_f_base64()))) { 188 if (!(b64 = BIO_new(BIO_f_base64()))) {
183 ASN1err(ASN1_F_B64_READ_ASN1,ERR_R_MALLOC_FAILURE); 189 ASN1err(ASN1_F_B64_READ_ASN1, ERR_R_MALLOC_FAILURE);
184 return 0; 190 return 0;
185} 191 }
186 bio = BIO_push(b64, bio); 192 bio = BIO_push(b64, bio);
187 val = ASN1_item_d2i_bio(it, bio, NULL); 193 val = ASN1_item_d2i_bio(it, bio, NULL);
188 if(!val) 194 if (!val)
189 ASN1err(ASN1_F_B64_READ_ASN1,ASN1_R_DECODE_ERROR); 195 ASN1err(ASN1_F_B64_READ_ASN1, ASN1_R_DECODE_ERROR);
190 (void)BIO_flush(bio); 196 (void)BIO_flush(bio);
191 bio = BIO_pop(bio); 197 bio = BIO_pop(bio);
192 BIO_free(b64); 198 BIO_free(b64);
@@ -195,10 +201,12 @@ static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it)
195 201
196/* Generate the MIME "micalg" parameter from RFC3851, RFC4490 */ 202/* Generate the MIME "micalg" parameter from RFC3851, RFC4490 */
197 203
198static int asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR) *mdalgs) 204static int
205asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR) *mdalgs)
199{ 206{
200 const EVP_MD *md; 207 const EVP_MD *md;
201 int i, have_unknown = 0, write_comma, ret = 0, md_nid; 208 int i, have_unknown = 0, write_comma, ret = 0, md_nid;
209
202 have_unknown = 0; 210 have_unknown = 0;
203 write_comma = 0; 211 write_comma = 0;
204 for (i = 0; i < sk_X509_ALGOR_num(mdalgs); i++) { 212 for (i = 0; i < sk_X509_ALGOR_num(mdalgs); i++) {
@@ -219,33 +227,33 @@ static int asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR) *mdalgs)
219 if (rv != -2) 227 if (rv != -2)
220 goto err; 228 goto err;
221 } 229 }
222 switch(md_nid) { 230 switch (md_nid) {
223 case NID_sha1: 231 case NID_sha1:
224 BIO_puts(out, "sha1"); 232 BIO_puts(out, "sha1");
225 break; 233 break;
226 234
227 case NID_md5: 235 case NID_md5:
228 BIO_puts(out, "md5"); 236 BIO_puts(out, "md5");
229 break; 237 break;
230 238
231 case NID_sha256: 239 case NID_sha256:
232 BIO_puts(out, "sha-256"); 240 BIO_puts(out, "sha-256");
233 break; 241 break;
234 242
235 case NID_sha384: 243 case NID_sha384:
236 BIO_puts(out, "sha-384"); 244 BIO_puts(out, "sha-384");
237 break; 245 break;
238 246
239 case NID_sha512: 247 case NID_sha512:
240 BIO_puts(out, "sha-512"); 248 BIO_puts(out, "sha-512");
241 break; 249 break;
242 250
243 case NID_id_GostR3411_94: 251 case NID_id_GostR3411_94:
244 BIO_puts(out, "gostr3411-94"); 252 BIO_puts(out, "gostr3411-94");
245 goto err; 253 goto err;
246 break; 254 break;
247 255
248 default: 256 default:
249 if (have_unknown) 257 if (have_unknown)
250 write_comma = 0; 258 write_comma = 0;
251 else { 259 else {
@@ -258,23 +266,23 @@ static int asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR) *mdalgs)
258 } 266 }
259 267
260 ret = 1; 268 ret = 1;
261 err:
262 269
270err:
263 return ret; 271 return ret;
264
265} 272}
266 273
267/* SMIME sender */ 274/* SMIME sender */
268 275
269int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags, 276int
270 int ctype_nid, int econt_nid, 277SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
271 STACK_OF(X509_ALGOR) *mdalgs, 278 int ctype_nid, int econt_nid, STACK_OF(X509_ALGOR) *mdalgs,
272 const ASN1_ITEM *it) 279 const ASN1_ITEM *it)
273{ 280{
274 char bound[33], c; 281 char bound[33], c;
275 int i; 282 int i;
276 const char *mime_prefix, *mime_eol, *cname = "smime.p7m"; 283 const char *mime_prefix, *mime_eol, *cname = "smime.p7m";
277 const char *msg_type=NULL; 284 const char *msg_type = NULL;
285
278 if (flags & SMIME_OLDMIME) 286 if (flags & SMIME_OLDMIME)
279 mime_prefix = "application/x-pkcs7-"; 287 mime_prefix = "application/x-pkcs7-";
280 else 288 else
@@ -284,16 +292,18 @@ int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
284 mime_eol = "\r\n"; 292 mime_eol = "\r\n";
285 else 293 else
286 mime_eol = "\n"; 294 mime_eol = "\n";
287 if((flags & SMIME_DETACHED) && data) { 295 if ((flags & SMIME_DETACHED) && data) {
288 /* We want multipart/signed */ 296 /* We want multipart/signed */
289 /* Generate a random boundary */ 297 /* Generate a random boundary */
290 RAND_pseudo_bytes((unsigned char *)bound, 32); 298 RAND_pseudo_bytes((unsigned char *)bound, 32);
291 for(i = 0; i < 32; i++) { 299 for (i = 0; i < 32; i++) {
292 c = bound[i] & 0xf; 300 c = bound[i] & 0xf;
293 if(c < 10) c += '0'; 301 if (c < 10)
294 else c += 'A' - 10; 302 c += '0';
303 else
304 c += 'A' - 10;
295 bound[i] = c; 305 bound[i] = c;
296 } 306 }
297 bound[32] = 0; 307 bound[32] = 0;
298 BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol); 308 BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol);
299 BIO_printf(bio, "Content-Type: multipart/signed;"); 309 BIO_printf(bio, "Content-Type: multipart/signed;");
@@ -301,9 +311,9 @@ int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
301 BIO_puts(bio, " micalg=\""); 311 BIO_puts(bio, " micalg=\"");
302 asn1_write_micalg(bio, mdalgs); 312 asn1_write_micalg(bio, mdalgs);
303 BIO_printf(bio, "\"; boundary=\"----%s\"%s%s", 313 BIO_printf(bio, "\"; boundary=\"----%s\"%s%s",
304 bound, mime_eol, mime_eol); 314 bound, mime_eol, mime_eol);
305 BIO_printf(bio, "This is an S/MIME signed message%s%s", 315 BIO_printf(bio, "This is an S/MIME signed message%s%s",
306 mime_eol, mime_eol); 316 mime_eol, mime_eol);
307 /* Now write out the first part */ 317 /* Now write out the first part */
308 BIO_printf(bio, "------%s%s", bound, mime_eol); 318 BIO_printf(bio, "------%s%s", bound, mime_eol);
309 if (!asn1_output_data(bio, data, val, flags, it)) 319 if (!asn1_output_data(bio, data, val, flags, it))
@@ -312,18 +322,18 @@ int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
312 322
313 /* Headers for signature */ 323 /* Headers for signature */
314 324
315 BIO_printf(bio, "Content-Type: %ssignature;", mime_prefix); 325 BIO_printf(bio, "Content-Type: %ssignature;", mime_prefix);
316 BIO_printf(bio, " name=\"smime.p7s\"%s", mime_eol); 326 BIO_printf(bio, " name=\"smime.p7s\"%s", mime_eol);
317 BIO_printf(bio, "Content-Transfer-Encoding: base64%s", 327 BIO_printf(bio, "Content-Transfer-Encoding: base64%s",
318 mime_eol); 328 mime_eol);
319 BIO_printf(bio, "Content-Disposition: attachment;"); 329 BIO_printf(bio, "Content-Disposition: attachment;");
320 BIO_printf(bio, " filename=\"smime.p7s\"%s%s", 330 BIO_printf(bio, " filename=\"smime.p7s\"%s%s",
321 mime_eol, mime_eol); 331 mime_eol, mime_eol);
322 B64_write_ASN1(bio, val, NULL, 0, it); 332 B64_write_ASN1(bio, val, NULL, 0, it);
323 BIO_printf(bio,"%s------%s--%s%s", mime_eol, bound, 333 BIO_printf(bio, "%s------%s--%s%s", mime_eol, bound,
324 mime_eol, mime_eol); 334 mime_eol, mime_eol);
325 return 1; 335 return 1;
326} 336 }
327 337
328 /* Determine smime-type header */ 338 /* Determine smime-type header */
329 339
@@ -349,7 +359,7 @@ int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
349 BIO_printf(bio, " smime-type=%s;", msg_type); 359 BIO_printf(bio, " smime-type=%s;", msg_type);
350 BIO_printf(bio, " name=\"%s\"%s", cname, mime_eol); 360 BIO_printf(bio, " name=\"%s\"%s", cname, mime_eol);
351 BIO_printf(bio, "Content-Transfer-Encoding: base64%s%s", 361 BIO_printf(bio, "Content-Transfer-Encoding: base64%s%s",
352 mime_eol, mime_eol); 362 mime_eol, mime_eol);
353 if (!B64_write_ASN1(bio, val, data, flags, it)) 363 if (!B64_write_ASN1(bio, val, data, flags, it))
354 return 0; 364 return 0;
355 BIO_printf(bio, "%s", mime_eol); 365 BIO_printf(bio, "%s", mime_eol);
@@ -359,8 +369,9 @@ int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
359/* Handle output of ASN1 data */ 369/* Handle output of ASN1 data */
360 370
361 371
362static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags, 372static int
363 const ASN1_ITEM *it) 373asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
374 const ASN1_ITEM *it)
364{ 375{
365 BIO *tmpbio; 376 BIO *tmpbio;
366 const ASN1_AUX *aux = it->funcs; 377 const ASN1_AUX *aux = it->funcs;
@@ -377,7 +388,7 @@ static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
377 388
378 if (!aux || !aux->asn1_cb) { 389 if (!aux || !aux->asn1_cb) {
379 ASN1err(ASN1_F_ASN1_OUTPUT_DATA, 390 ASN1err(ASN1_F_ASN1_OUTPUT_DATA,
380 ASN1_R_STREAMING_NOT_SUPPORTED); 391 ASN1_R_STREAMING_NOT_SUPPORTED);
381 return 0; 392 return 0;
382 } 393 }
383 394
@@ -406,7 +417,6 @@ static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
406 } 417 }
407 418
408 return rv; 419 return rv;
409
410} 420}
411 421
412/* SMIME reader: handle multipart/signed and opaque signing. 422/* SMIME reader: handle multipart/signed and opaque signing.
@@ -414,7 +424,8 @@ static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
414 * pointed to by "bcont". In opaque this is set to NULL 424 * pointed to by "bcont". In opaque this is set to NULL
415 */ 425 */
416 426
417ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it) 427ASN1_VALUE *
428SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
418{ 429{
419 BIO *asnin; 430 BIO *asnin;
420 STACK_OF(MIME_HEADER) *headers = NULL; 431 STACK_OF(MIME_HEADER) *headers = NULL;
@@ -424,106 +435,114 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
424 ASN1_VALUE *val; 435 ASN1_VALUE *val;
425 int ret; 436 int ret;
426 437
427 if(bcont) *bcont = NULL; 438 if (bcont)
439 *bcont = NULL;
428 440
429 if (!(headers = mime_parse_hdr(bio))) { 441 if (!(headers = mime_parse_hdr(bio))) {
430 ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_MIME_PARSE_ERROR); 442 ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_MIME_PARSE_ERROR);
431 return NULL; 443 return NULL;
432} 444 }
433 445
434 if(!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) { 446 if (!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) {
435 sk_MIME_HEADER_pop_free(headers, mime_hdr_free); 447 sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
436 ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_CONTENT_TYPE); 448 ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_CONTENT_TYPE);
437 return NULL; 449 return NULL;
438} 450 }
439 451
440 /* Handle multipart/signed */ 452 /* Handle multipart/signed */
441 453
442 if(!strcmp(hdr->value, "multipart/signed")) { 454 if (!strcmp(hdr->value, "multipart/signed")) {
443 /* Split into two parts */ 455 /* Split into two parts */
444 prm = mime_param_find(hdr, "boundary"); 456 prm = mime_param_find(hdr, "boundary");
445 if(!prm || !prm->param_value) { 457 if (!prm || !prm->param_value) {
446 sk_MIME_HEADER_pop_free(headers, mime_hdr_free); 458 sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
447 ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BOUNDARY); 459 ASN1err(ASN1_F_SMIME_READ_ASN1,
460 ASN1_R_NO_MULTIPART_BOUNDARY);
448 return NULL; 461 return NULL;
449 } 462 }
450 ret = multi_split(bio, prm->param_value, &parts); 463 ret = multi_split(bio, prm->param_value, &parts);
451 sk_MIME_HEADER_pop_free(headers, mime_hdr_free); 464 sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
452 if(!ret || (sk_BIO_num(parts) != 2) ) { 465 if (!ret || (sk_BIO_num(parts) != 2) ) {
453 ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BODY_FAILURE); 466 ASN1err(ASN1_F_SMIME_READ_ASN1,
467 ASN1_R_NO_MULTIPART_BODY_FAILURE);
454 sk_BIO_pop_free(parts, BIO_vfree); 468 sk_BIO_pop_free(parts, BIO_vfree);
455 return NULL; 469 return NULL;
456 } 470 }
457 471
458 /* Parse the signature piece */ 472 /* Parse the signature piece */
459 asnin = sk_BIO_value(parts, 1); 473 asnin = sk_BIO_value(parts, 1);
460 474
461 if (!(headers = mime_parse_hdr(asnin))) { 475 if (!(headers = mime_parse_hdr(asnin))) {
462 ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_MIME_SIG_PARSE_ERROR); 476 ASN1err(ASN1_F_SMIME_READ_ASN1,
477 ASN1_R_MIME_SIG_PARSE_ERROR);
463 sk_BIO_pop_free(parts, BIO_vfree); 478 sk_BIO_pop_free(parts, BIO_vfree);
464 return NULL; 479 return NULL;
465 } 480 }
466 481
467 /* Get content type */ 482 /* Get content type */
468 483
469 if(!(hdr = mime_hdr_find(headers, "content-type")) || 484 if (!(hdr = mime_hdr_find(headers, "content-type")) ||
470 !hdr->value) { 485 !hdr->value) {
471 sk_MIME_HEADER_pop_free(headers, mime_hdr_free); 486 sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
472 ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_SIG_CONTENT_TYPE); 487 ASN1err(ASN1_F_SMIME_READ_ASN1,
488 ASN1_R_NO_SIG_CONTENT_TYPE);
473 return NULL; 489 return NULL;
474 } 490 }
475 491
476 if(strcmp(hdr->value, "application/x-pkcs7-signature") && 492 if (strcmp(hdr->value, "application/x-pkcs7-signature") &&
477 strcmp(hdr->value, "application/pkcs7-signature")) { 493 strcmp(hdr->value, "application/pkcs7-signature")) {
478 ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_SIG_INVALID_MIME_TYPE); 494 ASN1err(ASN1_F_SMIME_READ_ASN1,
495 ASN1_R_SIG_INVALID_MIME_TYPE);
479 ERR_add_error_data(2, "type: ", hdr->value); 496 ERR_add_error_data(2, "type: ", hdr->value);
480 sk_MIME_HEADER_pop_free(headers, mime_hdr_free); 497 sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
481 sk_BIO_pop_free(parts, BIO_vfree); 498 sk_BIO_pop_free(parts, BIO_vfree);
482 return NULL; 499 return NULL;
483 } 500 }
484 sk_MIME_HEADER_pop_free(headers, mime_hdr_free); 501 sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
485 /* Read in ASN1 */ 502 /* Read in ASN1 */
486 if(!(val = b64_read_asn1(asnin, it))) { 503 if (!(val = b64_read_asn1(asnin, it))) {
487 ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_ASN1_SIG_PARSE_ERROR); 504 ASN1err(ASN1_F_SMIME_READ_ASN1,
505 ASN1_R_ASN1_SIG_PARSE_ERROR);
488 sk_BIO_pop_free(parts, BIO_vfree); 506 sk_BIO_pop_free(parts, BIO_vfree);
489 return NULL; 507 return NULL;
490 } 508 }
491 509
492 if(bcont) { 510 if (bcont) {
493 *bcont = sk_BIO_value(parts, 0); 511 *bcont = sk_BIO_value(parts, 0);
494 BIO_free(asnin); 512 BIO_free(asnin);
495 sk_BIO_free(parts); 513 sk_BIO_free(parts);
496 } else sk_BIO_pop_free(parts, BIO_vfree); 514 } else sk_BIO_pop_free(parts, BIO_vfree);
497 return val; 515 return val;
498} 516 }
499 517
500 /* OK, if not multipart/signed try opaque signature */ 518 /* OK, if not multipart/signed try opaque signature */
501 519
502 if (strcmp (hdr->value, "application/x-pkcs7-mime") && 520 if (strcmp (hdr->value, "application/x-pkcs7-mime") &&
503 strcmp (hdr->value, "application/pkcs7-mime")) { 521 strcmp (hdr->value, "application/pkcs7-mime")) {
504 ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_INVALID_MIME_TYPE); 522 ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_INVALID_MIME_TYPE);
505 ERR_add_error_data(2, "type: ", hdr->value); 523 ERR_add_error_data(2, "type: ", hdr->value);
506 sk_MIME_HEADER_pop_free(headers, mime_hdr_free); 524 sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
507 return NULL; 525 return NULL;
508} 526 }
509 527
510 sk_MIME_HEADER_pop_free(headers, mime_hdr_free); 528 sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
511 529
512 if(!(val = b64_read_asn1(bio, it))) { 530 if (!(val = b64_read_asn1(bio, it))) {
513 ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_PARSE_ERROR); 531 ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_PARSE_ERROR);
514 return NULL; 532 return NULL;
515} 533 }
516 return val; 534 return val;
517
518} 535}
519 536
520/* Copy text from one BIO to another making the output CRLF at EOL */ 537/* Copy text from one BIO to another making the output CRLF at EOL */
521int SMIME_crlf_copy(BIO *in, BIO *out, int flags) 538int
539SMIME_crlf_copy(BIO *in, BIO *out, int flags)
522{ 540{
523 BIO *bf; 541 BIO *bf;
524 char eol; 542 char eol;
525 int len; 543 int len;
526 char linebuf[MAX_SMLEN]; 544 char linebuf[MAX_SMLEN];
545
527 /* Buffer output so we don't write one line at a time. This is 546 /* Buffer output so we don't write one line at a time. This is
528 * useful when streaming as we don't end up with one OCTET STRING 547 * useful when streaming as we don't end up with one OCTET STRING
529 * per line. 548 * per line.
@@ -532,17 +551,18 @@ int SMIME_crlf_copy(BIO *in, BIO *out, int flags)
532 if (!bf) 551 if (!bf)
533 return 0; 552 return 0;
534 out = BIO_push(bf, out); 553 out = BIO_push(bf, out);
535 if(flags & SMIME_BINARY) { 554 if (flags & SMIME_BINARY) {
536 while((len = BIO_read(in, linebuf, MAX_SMLEN)) > 0) 555 while ((len = BIO_read(in, linebuf, MAX_SMLEN)) > 0)
537 BIO_write(out, linebuf, len); 556 BIO_write(out, linebuf, len);
538 } else { 557 } else {
539 if(flags & SMIME_TEXT) 558 if (flags & SMIME_TEXT)
540 BIO_printf(out, "Content-Type: text/plain\r\n\r\n"); 559 BIO_printf(out, "Content-Type: text/plain\r\n\r\n");
541 while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0) { 560 while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0) {
542 eol = strip_eol(linebuf, &len); 561 eol = strip_eol(linebuf, &len);
543 if (len) 562 if (len)
544 BIO_write(out, linebuf, len); 563 BIO_write(out, linebuf, len);
545 if(eol) BIO_write(out, "\r\n", 2); 564 if (eol)
565 BIO_write(out, "\r\n", 2);
546 } 566 }
547 } 567 }
548 (void)BIO_flush(out); 568 (void)BIO_flush(out);
@@ -552,7 +572,8 @@ int SMIME_crlf_copy(BIO *in, BIO *out, int flags)
552} 572}
553 573
554/* Strip off headers if they are text/plain */ 574/* Strip off headers if they are text/plain */
555int SMIME_text(BIO *in, BIO *out) 575int
576SMIME_text(BIO *in, BIO *out)
556{ 577{
557 char iobuf[4096]; 578 char iobuf[4096];
558 int len; 579 int len;
@@ -560,23 +581,23 @@ int SMIME_text(BIO *in, BIO *out)
560 MIME_HEADER *hdr; 581 MIME_HEADER *hdr;
561 582
562 if (!(headers = mime_parse_hdr(in))) { 583 if (!(headers = mime_parse_hdr(in))) {
563 ASN1err(ASN1_F_SMIME_TEXT,ASN1_R_MIME_PARSE_ERROR); 584 ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_MIME_PARSE_ERROR);
564 return 0; 585 return 0;
565} 586 }
566 if(!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) { 587 if (!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) {
567 ASN1err(ASN1_F_SMIME_TEXT,ASN1_R_MIME_NO_CONTENT_TYPE); 588 ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_MIME_NO_CONTENT_TYPE);
568 sk_MIME_HEADER_pop_free(headers, mime_hdr_free); 589 sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
569 return 0; 590 return 0;
570} 591 }
571 if (strcmp (hdr->value, "text/plain")) { 592 if (strcmp (hdr->value, "text/plain")) {
572 ASN1err(ASN1_F_SMIME_TEXT,ASN1_R_INVALID_MIME_TYPE); 593 ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_INVALID_MIME_TYPE);
573 ERR_add_error_data(2, "type: ", hdr->value); 594 ERR_add_error_data(2, "type: ", hdr->value);
574 sk_MIME_HEADER_pop_free(headers, mime_hdr_free); 595 sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
575 return 0; 596 return 0;
576} 597 }
577 sk_MIME_HEADER_pop_free(headers, mime_hdr_free); 598 sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
578 while ((len = BIO_read(in, iobuf, sizeof(iobuf))) > 0) 599 while ((len = BIO_read(in, iobuf, sizeof(iobuf))) > 0)
579 BIO_write(out, iobuf, len); 600 BIO_write(out, iobuf, len);
580 if (len < 0) 601 if (len < 0)
581 return 0; 602 return 0;
582 return 1; 603 return 1;
@@ -586,7 +607,8 @@ int SMIME_text(BIO *in, BIO *out)
586 * canonical parts in a STACK of bios 607 * canonical parts in a STACK of bios
587 */ 608 */
588 609
589static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret) 610static int
611multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret)
590{ 612{
591 char linebuf[MAX_SMLEN]; 613 char linebuf[MAX_SMLEN];
592 int len, blen; 614 int len, blen;
@@ -603,27 +625,28 @@ static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret)
603 *ret = parts; 625 *ret = parts;
604 while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) { 626 while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) {
605 state = mime_bound_check(linebuf, len, bound, blen); 627 state = mime_bound_check(linebuf, len, bound, blen);
606 if(state == 1) { 628 if (state == 1) {
607 first = 1; 629 first = 1;
608 part++; 630 part++;
609 } else if(state == 2) { 631 } else if (state == 2) {
610 sk_BIO_push(parts, bpart); 632 sk_BIO_push(parts, bpart);
611 return 1; 633 return 1;
612 } else if(part) { 634 } else if (part) {
613 /* Strip CR+LF from linebuf */ 635 /* Strip CR+LF from linebuf */
614 next_eol = strip_eol(linebuf, &len); 636 next_eol = strip_eol(linebuf, &len);
615 if(first) { 637 if (first) {
616 first = 0; 638 first = 0;
617 if(bpart) sk_BIO_push(parts, bpart); 639 if (bpart)
640 sk_BIO_push(parts, bpart);
618 bpart = BIO_new(BIO_s_mem()); 641 bpart = BIO_new(BIO_s_mem());
619 BIO_set_mem_eof_return(bpart, 0); 642 BIO_set_mem_eof_return(bpart, 0);
620 } else if (eol) 643 } else if (eol)
621 BIO_write(bpart, "\r\n", 2); 644 BIO_write(bpart, "\r\n", 2);
622 eol = next_eol; 645 eol = next_eol;
623 if (len) 646 if (len)
624 BIO_write(bpart, linebuf, len); 647 BIO_write(bpart, linebuf, len);
648 }
625 } 649 }
626}
627 return 0; 650 return 0;
628} 651}
629 652
@@ -638,7 +661,8 @@ static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret)
638#define MIME_COMMENT 6 661#define MIME_COMMENT 6
639 662
640 663
641static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio) 664static
665STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio)
642{ 666{
643 char *p, *q, c; 667 char *p, *q, c;
644 char *ntmp; 668 char *ntmp;
@@ -649,254 +673,294 @@ static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio)
649 673
650 headers = sk_MIME_HEADER_new(mime_hdr_cmp); 674 headers = sk_MIME_HEADER_new(mime_hdr_cmp);
651 while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) { 675 while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) {
652 /* If whitespace at line start then continuation line */ 676 /* If whitespace at line start then continuation line */
653 if(mhdr && isspace((unsigned char)linebuf[0])) state = MIME_NAME; 677 if (mhdr && isspace((unsigned char)linebuf[0]))
654 else state = MIME_START; 678 state = MIME_NAME;
655 ntmp = NULL; 679 else
656 /* Go through all characters */ 680 state = MIME_START;
657 for(p = linebuf, q = linebuf; (c = *p) && (c!='\r') && (c!='\n'); p++) { 681 ntmp = NULL;
658 682
659 /* State machine to handle MIME headers 683 /* Go through all characters */
660 * if this looks horrible that's because it *is* 684 for (p = linebuf, q = linebuf;
661 */ 685 (c = *p) && (c != '\r') && (c != '\n'); p++) {
662 686
663 switch(state) { 687 /* State machine to handle MIME headers
688 * if this looks horrible that's because it *is*
689 */
690
691 switch (state) {
664 case MIME_START: 692 case MIME_START:
665 if(c == ':') { 693 if (c == ':') {
666 state = MIME_TYPE; 694 state = MIME_TYPE;
667 *p = 0; 695 *p = 0;
668 ntmp = strip_ends(q); 696 ntmp = strip_ends(q);
669 q = p + 1; 697 q = p + 1;
670 } 698 }
671 break; 699 break;
672 700
673 case MIME_TYPE: 701 case MIME_TYPE:
674 if(c == ';') { 702 if (c == ';') {
675 mime_debug("Found End Value\n"); 703 mime_debug("Found End Value\n");
676 *p = 0; 704 *p = 0;
677 mhdr = mime_hdr_new(ntmp, strip_ends(q)); 705 mhdr = mime_hdr_new(ntmp,
678 sk_MIME_HEADER_push(headers, mhdr); 706 strip_ends(q));
679 ntmp = NULL; 707 sk_MIME_HEADER_push(headers, mhdr);
680 q = p + 1; 708 ntmp = NULL;
681 state = MIME_NAME; 709 q = p + 1;
682 } else if(c == '(') { 710 state = MIME_NAME;
683 save_state = state; 711 } else if (c == '(') {
684 state = MIME_COMMENT; 712 save_state = state;
685 } 713 state = MIME_COMMENT;
686 break; 714 }
715 break;
687 716
688 case MIME_COMMENT: 717 case MIME_COMMENT:
689 if(c == ')') { 718 if (c == ')') {
690 state = save_state; 719 state = save_state;
691 } 720 }
692 break; 721 break;
693 722
694 case MIME_NAME: 723 case MIME_NAME:
695 if(c == '=') { 724 if (c == '=') {
696 state = MIME_VALUE; 725 state = MIME_VALUE;
697 *p = 0; 726 *p = 0;
698 ntmp = strip_ends(q); 727 ntmp = strip_ends(q);
699 q = p + 1; 728 q = p + 1;
700 } 729 }
701 break ; 730 break;
702 731
703 case MIME_VALUE: 732 case MIME_VALUE:
704 if(c == ';') { 733 if (c == ';') {
705 state = MIME_NAME; 734 state = MIME_NAME;
706 *p = 0; 735 *p = 0;
707 mime_hdr_addparam(mhdr, ntmp, strip_ends(q)); 736 mime_hdr_addparam(mhdr, ntmp,
708 ntmp = NULL; 737 strip_ends(q));
709 q = p + 1; 738 ntmp = NULL;
710 } else if (c == '"') { 739 q = p + 1;
711 mime_debug("Found Quote\n"); 740 } else if (c == '"') {
712 state = MIME_QUOTE; 741 mime_debug("Found Quote\n");
713 } else if(c == '(') { 742 state = MIME_QUOTE;
714 save_state = state; 743 } else if (c == '(') {
715 state = MIME_COMMENT; 744 save_state = state;
716 } 745 state = MIME_COMMENT;
717 break; 746 }
747 break;
718 748
719 case MIME_QUOTE: 749 case MIME_QUOTE:
720 if(c == '"') { 750 if (c == '"') {
721 mime_debug("Found Match Quote\n"); 751 mime_debug("Found Match Quote\n");
722 state = MIME_VALUE; 752 state = MIME_VALUE;
753 }
754 break;
755 }
723 } 756 }
724 break;
725 }
726}
727 757
728 if(state == MIME_TYPE) { 758 if (state == MIME_TYPE) {
729 mhdr = mime_hdr_new(ntmp, strip_ends(q)); 759 mhdr = mime_hdr_new(ntmp, strip_ends(q));
730 sk_MIME_HEADER_push(headers, mhdr); 760 sk_MIME_HEADER_push(headers, mhdr);
731} else if(state == MIME_VALUE) 761 } else if (state == MIME_VALUE)
732 mime_hdr_addparam(mhdr, ntmp, strip_ends(q)); 762 mime_hdr_addparam(mhdr, ntmp, strip_ends(q));
733 if(p == linebuf) break; /* Blank line means end of headers */
734}
735 763
736return headers; 764 if (p == linebuf)
765 break; /* Blank line means end of headers */
766 }
737 767
768 return headers;
738} 769}
739 770
740static char *strip_ends(char *name) 771static char *
772strip_ends(char *name)
741{ 773{
742 return strip_end(strip_start(name)); 774 return strip_end(strip_start(name));
743} 775}
744 776
745/* Strip a parameter of whitespace from start of param */ 777/* Strip a parameter of whitespace from start of param */
746static char *strip_start(char *name) 778static char *
779strip_start(char *name)
747{ 780{
748 char *p, c; 781 char *p, c;
782
749 /* Look for first non white space or quote */ 783 /* Look for first non white space or quote */
750 for(p = name; (c = *p) ;p++) { 784 for (p = name; (c = *p); p++) {
751 if(c == '"') { 785 if (c == '"') {
752 /* Next char is start of string if non null */ 786 /* Next char is start of string if non null */
753 if(p[1]) return p + 1; 787 if (p[1])
788 return p + 1;
754 /* Else null string */ 789 /* Else null string */
755 return NULL; 790 return NULL;
791 }
792 if (!isspace((unsigned char)c))
793 return p;
756 } 794 }
757 if(!isspace((unsigned char)c)) return p;
758}
759 return NULL; 795 return NULL;
760} 796}
761 797
762/* As above but strip from end of string : maybe should handle brackets? */ 798/* As above but strip from end of string : maybe should handle brackets? */
763static char *strip_end(char *name) 799static char *
800strip_end(char *name)
764{ 801{
765 char *p, c; 802 char *p, c;
766 if(!name) return NULL; 803
804 if (!name)
805 return NULL;
806
767 /* Look for first non white space or quote */ 807 /* Look for first non white space or quote */
768 for(p = name + strlen(name) - 1; p >= name ;p--) { 808 for (p = name + strlen(name) - 1; p >= name; p--) {
769 c = *p; 809 c = *p;
770 if(c == '"') { 810 if (c == '"') {
771 if(p - 1 == name) return NULL; 811 if (p - 1 == name)
812 return NULL;
772 *p = 0; 813 *p = 0;
773 return name; 814 return name;
815 }
816 if (isspace((unsigned char)c))
817 *p = 0;
818 else
819 return name;
774 } 820 }
775 if(isspace((unsigned char)c)) *p = 0;
776 else return name;
777}
778 return NULL; 821 return NULL;
779} 822}
780 823
781static MIME_HEADER *mime_hdr_new(char *name, char *value) 824static MIME_HEADER *
825mime_hdr_new(char *name, char *value)
782{ 826{
783 MIME_HEADER *mhdr; 827 MIME_HEADER *mhdr;
784 char *tmpname, *tmpval, *p; 828 char *tmpname, *tmpval, *p;
785 int c; 829 int c;
786 if(name) { 830 if (name) {
787 if(!(tmpname = BUF_strdup(name))) return NULL; 831 if (!(tmpname = BUF_strdup(name)))
788 for(p = tmpname ; *p; p++) { 832 return NULL;
833 for (p = tmpname; *p; p++) {
789 c = (unsigned char)*p; 834 c = (unsigned char)*p;
790 if(isupper(c)) { 835 if (isupper(c)) {
791 c = tolower(c); 836 c = tolower(c);
792 *p = c; 837 *p = c;
838 }
793 } 839 }
794 } 840 } else
795} else tmpname = NULL; 841 tmpname = NULL;
796 if(value) { 842 if (value) {
797 if(!(tmpval = BUF_strdup(value))) return NULL; 843 if (!(tmpval = BUF_strdup(value)))
798 for(p = tmpval ; *p; p++) { 844 return NULL;
845 for (p = tmpval; *p; p++) {
799 c = (unsigned char)*p; 846 c = (unsigned char)*p;
800 if(isupper(c)) { 847 if (isupper(c)) {
801 c = tolower(c); 848 c = tolower(c);
802 *p = c; 849 *p = c;
850 }
803 } 851 }
804 } 852 } else tmpval = NULL;
805} else tmpval = NULL; 853 mhdr = (MIME_HEADER *)malloc(sizeof(MIME_HEADER));
806 mhdr = (MIME_HEADER *) malloc(sizeof(MIME_HEADER));
807 if (!mhdr) { 854 if (!mhdr) {
808 OPENSSL_free(tmpname); 855 OPENSSL_free(tmpname);
809 return NULL; 856 return NULL;
810} 857 }
811 mhdr->name = tmpname; 858 mhdr->name = tmpname;
812 mhdr->value = tmpval; 859 mhdr->value = tmpval;
813 if (!(mhdr->params = sk_MIME_PARAM_new(mime_param_cmp))) { 860 if (!(mhdr->params = sk_MIME_PARAM_new(mime_param_cmp))) {
814 free(mhdr); 861 free(mhdr);
815 return NULL; 862 return NULL;
816} 863 }
817 return mhdr; 864 return mhdr;
818} 865}
819 866
820static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value) 867static int
868mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value)
821{ 869{
822 char *tmpname, *tmpval, *p; 870 char *tmpname, *tmpval, *p;
823 int c; 871 int c;
824 MIME_PARAM *mparam; 872 MIME_PARAM *mparam;
825 if(name) { 873
874 if (name) {
826 tmpname = BUF_strdup(name); 875 tmpname = BUF_strdup(name);
827 if(!tmpname) return 0; 876 if (!tmpname)
828 for(p = tmpname ; *p; p++) { 877 return 0;
878 for (p = tmpname; *p; p++) {
829 c = (unsigned char)*p; 879 c = (unsigned char)*p;
830 if(isupper(c)) { 880 if (isupper(c)) {
831 c = tolower(c); 881 c = tolower(c);
832 *p = c; 882 *p = c;
883 }
833 } 884 }
834 } 885 } else
835} else tmpname = NULL; 886 tmpname = NULL;
836 if(value) { 887 if (value) {
837 tmpval = BUF_strdup(value); 888 tmpval = BUF_strdup(value);
838 if(!tmpval) return 0; 889 if (!tmpval)
839} else tmpval = NULL; 890 return 0;
891 } else
892 tmpval = NULL;
840 /* Parameter values are case sensitive so leave as is */ 893 /* Parameter values are case sensitive so leave as is */
841 mparam = (MIME_PARAM *) malloc(sizeof(MIME_PARAM)); 894 mparam = (MIME_PARAM *) malloc(sizeof(MIME_PARAM));
842 if(!mparam) return 0; 895 if (!mparam)
896 return 0;
843 mparam->param_name = tmpname; 897 mparam->param_name = tmpname;
844 mparam->param_value = tmpval; 898 mparam->param_value = tmpval;
845 sk_MIME_PARAM_push(mhdr->params, mparam); 899 sk_MIME_PARAM_push(mhdr->params, mparam);
846 return 1; 900 return 1;
847} 901}
848 902
849static int mime_hdr_cmp(const MIME_HEADER * const *a, 903static int
850 const MIME_HEADER * const *b) 904mime_hdr_cmp(const MIME_HEADER * const *a, const MIME_HEADER * const *b)
851{ 905{
852 if (!(*a)->name || !(*b)->name) 906 if (!(*a)->name || !(*b)->name)
853 return !!(*a)->name - !!(*b)->name; 907 return !!(*a)->name - !!(*b)->name;
854 908 return (strcmp((*a)->name, (*b)->name));
855 return(strcmp((*a)->name, (*b)->name));
856} 909}
857 910
858static int mime_param_cmp(const MIME_PARAM * const *a, 911static int
859 const MIME_PARAM * const *b) 912mime_param_cmp(const MIME_PARAM * const *a, const MIME_PARAM * const *b)
860{ 913{
861 if (!(*a)->param_name || !(*b)->param_name) 914 if (!(*a)->param_name || !(*b)->param_name)
862 return !!(*a)->param_name - !!(*b)->param_name; 915 return !!(*a)->param_name - !!(*b)->param_name;
863 return(strcmp((*a)->param_name, (*b)->param_name)); 916 return (strcmp((*a)->param_name, (*b)->param_name));
864} 917}
865 918
866/* Find a header with a given name (if possible) */ 919/* Find a header with a given name (if possible) */
867 920
868static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, char *name) 921static MIME_HEADER *
922mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, char *name)
869{ 923{
870 MIME_HEADER htmp; 924 MIME_HEADER htmp;
871 int idx; 925 int idx;
872 htmp.name = name; 926 htmp.name = name;
873 idx = sk_MIME_HEADER_find(hdrs, &htmp); 927 idx = sk_MIME_HEADER_find(hdrs, &htmp);
874 if(idx < 0) return NULL; 928 if (idx < 0)
929 return NULL;
875 return sk_MIME_HEADER_value(hdrs, idx); 930 return sk_MIME_HEADER_value(hdrs, idx);
876} 931}
877 932
878static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name) 933static MIME_PARAM *
934mime_param_find(MIME_HEADER *hdr, char *name)
879{ 935{
880 MIME_PARAM param; 936 MIME_PARAM param;
881 int idx; 937 int idx;
882 param.param_name = name; 938 param.param_name = name;
883 idx = sk_MIME_PARAM_find(hdr->params, &param); 939 idx = sk_MIME_PARAM_find(hdr->params, &param);
884 if(idx < 0) return NULL; 940 if (idx < 0)
941 return NULL;
885 return sk_MIME_PARAM_value(hdr->params, idx); 942 return sk_MIME_PARAM_value(hdr->params, idx);
886} 943}
887 944
888static void mime_hdr_free(MIME_HEADER *hdr) 945static void
946mime_hdr_free(MIME_HEADER *hdr)
889{ 947{
890 if(hdr->name) free(hdr->name); 948 if (hdr->name)
891 if(hdr->value) free(hdr->value); 949 free(hdr->name);
892 if(hdr->params) sk_MIME_PARAM_pop_free(hdr->params, mime_param_free); 950 if (hdr->value)
951 free(hdr->value);
952 if (hdr->params)
953 sk_MIME_PARAM_pop_free(hdr->params, mime_param_free);
893 free(hdr); 954 free(hdr);
894} 955}
895 956
896static void mime_param_free(MIME_PARAM *param) 957static void
958mime_param_free(MIME_PARAM *param)
897{ 959{
898 if(param->param_name) free(param->param_name); 960 if (param->param_name)
899 if(param->param_value) free(param->param_value); 961 free(param->param_name);
962 if (param->param_value)
963 free(param->param_value);
900 free(param); 964 free(param);
901} 965}
902 966
@@ -905,21 +969,28 @@ static void mime_param_free(MIME_PARAM *param)
905 * 1 : part boundary 969 * 1 : part boundary
906 * 2 : final boundary 970 * 2 : final boundary
907 */ 971 */
908static int mime_bound_check(char *line, int linelen, char *bound, int blen) 972static int
973mime_bound_check(char *line, int linelen, char *bound, int blen)
909{ 974{
910 if(linelen == -1) linelen = strlen(line); 975 if (linelen == -1)
911 if(blen == -1) blen = strlen(bound); 976 linelen = strlen(line);
977 if (blen == -1)
978 blen = strlen(bound);
912 /* Quickly eliminate if line length too short */ 979 /* Quickly eliminate if line length too short */
913 if(blen + 2 > linelen) return 0; 980 if (blen + 2 > linelen)
981 return 0;
914 /* Check for part boundary */ 982 /* Check for part boundary */
915 if(!strncmp(line, "--", 2) && !strncmp(line + 2, bound, blen)) { 983 if (!strncmp(line, "--", 2) && !strncmp(line + 2, bound, blen)) {
916 if(!strncmp(line + blen + 2, "--", 2)) return 2; 984 if (!strncmp(line + blen + 2, "--", 2))
917 else return 1; 985 return 2;
918} 986 else
987 return 1;
988 }
919 return 0; 989 return 0;
920} 990}
921 991
922static int strip_eol(char *linebuf, int *plen) 992static int
993strip_eol(char *linebuf, int *plen)
923{ 994{
924 int len = *plen; 995 int len = *plen;
925 char *p, c; 996 char *p, c;