diff options
Diffstat (limited to 'src/lib/libcrypto/asn1/asn_mime.c')
-rw-r--r-- | src/lib/libcrypto/asn1/asn_mime.c | 597 |
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 | ||
73 | typedef struct { | 73 | typedef struct { |
74 | char *param_name; /* Param name e.g. "micalg" */ | 74 | char *param_name; /* Param name e.g. "micalg" */ |
75 | char *param_value; /* Param value e.g. "sha1" */ | 75 | char *param_value; /* Param value e.g. "sha1" */ |
76 | } MIME_PARAM; | 76 | } MIME_PARAM; |
77 | 77 | ||
78 | DECLARE_STACK_OF(MIME_PARAM) | 78 | DECLARE_STACK_OF(MIME_PARAM) |
79 | IMPLEMENT_STACK_OF(MIME_PARAM) | 79 | IMPLEMENT_STACK_OF(MIME_PARAM) |
80 | 80 | ||
81 | typedef struct { | 81 | typedef struct { |
82 | char *name; /* Name of line e.g. "content-type" */ | 82 | char *name; /* Name of line e.g. "content-type" */ |
83 | char *value; /* Value of line e.g. "text/plain" */ | 83 | char *value; /* Value of line e.g. "text/plain" */ |
84 | STACK_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 | ||
87 | DECLARE_STACK_OF(MIME_HEADER) | 87 | DECLARE_STACK_OF(MIME_HEADER) |
88 | IMPLEMENT_STACK_OF(MIME_HEADER) | 88 | IMPLEMENT_STACK_OF(MIME_HEADER) |
89 | 89 | ||
90 | static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags, | 90 | static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags, |
91 | const ASN1_ITEM *it); | 91 | const ASN1_ITEM *it); |
92 | static char * strip_ends(char *name); | 92 | static char * strip_ends(char *name); |
93 | static char * strip_start(char *name); | 93 | static char * strip_start(char *name); |
94 | static char * strip_end(char *name); | 94 | static char * strip_end(char *name); |
@@ -96,9 +96,9 @@ static MIME_HEADER *mime_hdr_new(char *name, char *value); | |||
96 | static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value); | 96 | static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value); |
97 | static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio); | 97 | static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio); |
98 | static int mime_hdr_cmp(const MIME_HEADER * const *a, | 98 | static int mime_hdr_cmp(const MIME_HEADER * const *a, |
99 | const MIME_HEADER * const *b); | 99 | const MIME_HEADER * const *b); |
100 | static int mime_param_cmp(const MIME_PARAM * const *a, | 100 | static int mime_param_cmp(const MIME_PARAM * const *a, |
101 | const MIME_PARAM * const *b); | 101 | const MIME_PARAM * const *b); |
102 | static void mime_param_free(MIME_PARAM *param); | 102 | static void mime_param_free(MIME_PARAM *param); |
103 | static int mime_bound_check(char *line, int linelen, char *bound, int blen); | 103 | static int mime_bound_check(char *line, int linelen, char *bound, int blen); |
104 | static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret); | 104 | static 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 | ||
115 | int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, | 115 | int |
116 | const ASN1_ITEM *it) | 116 | i2d_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 | ||
145 | static int B64_write_ASN1(BIO *out, ASN1_VALUE *val, BIO *in, int flags, | 147 | static int |
146 | const ASN1_ITEM *it) | 148 | B64_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 | ||
167 | int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, | 171 | int |
168 | const char *hdr, | 172 | PEM_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 | ||
178 | static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it) | 183 | static ASN1_VALUE * |
184 | b64_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 | ||
198 | static int asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR) *mdalgs) | 204 | static int |
205 | asn1_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 | ||
270 | err: | ||
263 | return ret; | 271 | return ret; |
264 | |||
265 | } | 272 | } |
266 | 273 | ||
267 | /* SMIME sender */ | 274 | /* SMIME sender */ |
268 | 275 | ||
269 | int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags, | 276 | int |
270 | int ctype_nid, int econt_nid, | 277 | SMIME_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 | ||
362 | static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags, | 372 | static int |
363 | const ASN1_ITEM *it) | 373 | asn1_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 | ||
417 | ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it) | 427 | ASN1_VALUE * |
428 | SMIME_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 */ |
521 | int SMIME_crlf_copy(BIO *in, BIO *out, int flags) | 538 | int |
539 | SMIME_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 */ |
555 | int SMIME_text(BIO *in, BIO *out) | 575 | int |
576 | SMIME_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 | ||
589 | static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret) | 610 | static int |
611 | multi_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 | ||
641 | static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio) | 664 | static |
665 | STACK_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 | ||
736 | return headers; | 764 | if (p == linebuf) |
765 | break; /* Blank line means end of headers */ | ||
766 | } | ||
737 | 767 | ||
768 | return headers; | ||
738 | } | 769 | } |
739 | 770 | ||
740 | static char *strip_ends(char *name) | 771 | static char * |
772 | strip_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 */ |
746 | static char *strip_start(char *name) | 778 | static char * |
779 | strip_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? */ |
763 | static char *strip_end(char *name) | 799 | static char * |
800 | strip_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 | ||
781 | static MIME_HEADER *mime_hdr_new(char *name, char *value) | 824 | static MIME_HEADER * |
825 | mime_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 | ||
820 | static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value) | 867 | static int |
868 | mime_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 | ||
849 | static int mime_hdr_cmp(const MIME_HEADER * const *a, | 903 | static int |
850 | const MIME_HEADER * const *b) | 904 | mime_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 | ||
858 | static int mime_param_cmp(const MIME_PARAM * const *a, | 911 | static int |
859 | const MIME_PARAM * const *b) | 912 | mime_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 | ||
868 | static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, char *name) | 921 | static MIME_HEADER * |
922 | mime_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 | ||
878 | static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name) | 933 | static MIME_PARAM * |
934 | mime_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, ¶m); | 939 | idx = sk_MIME_PARAM_find(hdr->params, ¶m); |
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 | ||
888 | static void mime_hdr_free(MIME_HEADER *hdr) | 945 | static void |
946 | mime_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 | ||
896 | static void mime_param_free(MIME_PARAM *param) | 957 | static void |
958 | mime_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 | */ |
908 | static int mime_bound_check(char *line, int linelen, char *bound, int blen) | 972 | static int |
973 | mime_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 | ||
922 | static int strip_eol(char *linebuf, int *plen) | 992 | static int |
993 | strip_eol(char *linebuf, int *plen) | ||
923 | { | 994 | { |
924 | int len = *plen; | 995 | int len = *plen; |
925 | char *p, c; | 996 | char *p, c; |