diff options
Diffstat (limited to 'deps/openssl/openssl/crypto/asn1/asn_mime.c')
-rw-r--r-- | deps/openssl/openssl/crypto/asn1/asn_mime.c | 292 |
1 files changed, 148 insertions, 144 deletions
diff --git a/deps/openssl/openssl/crypto/asn1/asn_mime.c b/deps/openssl/openssl/crypto/asn1/asn_mime.c index 02b7c9b7ef..84475e9470 100644 --- a/deps/openssl/openssl/crypto/asn1/asn_mime.c +++ b/deps/openssl/openssl/crypto/asn1/asn_mime.c @@ -1,65 +1,21 @@ -/* asn_mime.c */ /* - * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL - * project. - */ -/* ==================================================================== - * Copyright (c) 1999-2018 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== + * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include <stdio.h> #include <ctype.h> -#include "cryptlib.h" +#include "internal/cryptlib.h" #include <openssl/rand.h> #include <openssl/x509.h> #include <openssl/asn1.h> #include <openssl/asn1t.h> +#include "internal/evp_int.h" +#include "internal/bio.h" #include "asn1_locl.h" /* @@ -72,41 +28,35 @@ * from parameter values. Quotes are stripped off */ -typedef struct { +struct mime_param_st { char *param_name; /* Param name e.g. "micalg" */ char *param_value; /* Param value e.g. "sha1" */ -} MIME_PARAM; +}; -DECLARE_STACK_OF(MIME_PARAM) -IMPLEMENT_STACK_OF(MIME_PARAM) - -typedef struct { +struct mime_header_st { char *name; /* Name of line e.g. "content-type" */ char *value; /* Value of line e.g. "text/plain" */ STACK_OF(MIME_PARAM) *params; /* Zero or more parameters */ -} MIME_HEADER; - -DECLARE_STACK_OF(MIME_HEADER) -IMPLEMENT_STACK_OF(MIME_HEADER) +}; static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags, const ASN1_ITEM *it); static char *strip_ends(char *name); static char *strip_start(char *name); static char *strip_end(char *name); -static MIME_HEADER *mime_hdr_new(char *name, char *value); -static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value); +static MIME_HEADER *mime_hdr_new(const char *name, const char *value); +static int mime_hdr_addparam(MIME_HEADER *mhdr, const char *name, const char *value); static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio); static int mime_hdr_cmp(const MIME_HEADER *const *a, const MIME_HEADER *const *b); static int mime_param_cmp(const MIME_PARAM *const *a, const MIME_PARAM *const *b); static void mime_param_free(MIME_PARAM *param); -static int mime_bound_check(char *line, int linelen, char *bound, int blen); -static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret); -static int strip_eol(char *linebuf, int *plen); -static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, char *name); -static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name); +static int mime_bound_check(char *line, int linelen, const char *bound, int blen); +static int multi_split(BIO *bio, const char *bound, STACK_OF(BIO) **ret); +static int strip_eol(char *linebuf, int *plen, int flags); +static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, const char *name); +static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, const char *name); static void mime_hdr_free(MIME_HEADER *hdr); #define MAX_SMLEN 1024 @@ -151,7 +101,7 @@ static int B64_write_ASN1(BIO *out, ASN1_VALUE *val, BIO *in, int flags, BIO *b64; int r; b64 = BIO_new(BIO_f_base64()); - if (!b64) { + if (b64 == NULL) { ASN1err(ASN1_F_B64_WRITE_ASN1, ERR_R_MALLOC_FAILURE); return 0; } @@ -182,7 +132,8 @@ static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it) { BIO *b64; ASN1_VALUE *val; - if (!(b64 = BIO_new(BIO_f_base64()))) { + + if ((b64 = BIO_new(BIO_f_base64())) == NULL) { ASN1err(ASN1_F_B64_READ_ASN1, ERR_R_MALLOC_FAILURE); return 0; } @@ -191,7 +142,7 @@ static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it) if (!val) ASN1err(ASN1_F_B64_READ_ASN1, ASN1_R_DECODE_ERROR); (void)BIO_flush(bio); - bio = BIO_pop(bio); + BIO_pop(bio); BIO_free(b64); return val; } @@ -246,7 +197,6 @@ static int asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR) *mdalgs) case NID_id_GostR3411_94: BIO_puts(out, "gostr3411-94"); goto err; - break; default: if (have_unknown) @@ -370,7 +320,7 @@ static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags, int rv = 1; /* - * If data is not deteched or resigning then the output BIO is already + * If data is not detached or resigning then the output BIO is already * set up to finalise when it is written through. */ if (!(flags & SMIME_DETACHED) || (flags & PKCS7_REUSE_DIGEST)) { @@ -430,12 +380,13 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it) if (bcont) *bcont = NULL; - if (!(headers = mime_parse_hdr(bio))) { + if ((headers = mime_parse_hdr(bio)) == NULL) { ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_MIME_PARSE_ERROR); return NULL; } - if (!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) { + if ((hdr = mime_hdr_find(headers, "content-type")) == NULL + || hdr->value == NULL) { sk_MIME_HEADER_pop_free(headers, mime_hdr_free); ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_CONTENT_TYPE); return NULL; @@ -443,7 +394,7 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it) /* Handle multipart/signed */ - if (!strcmp(hdr->value, "multipart/signed")) { + if (strcmp(hdr->value, "multipart/signed") == 0) { /* Split into two parts */ prm = mime_param_find(hdr, "boundary"); if (!prm || !prm->param_value) { @@ -462,7 +413,7 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it) /* Parse the signature piece */ asnin = sk_BIO_value(parts, 1); - if (!(headers = mime_parse_hdr(asnin))) { + if ((headers = mime_parse_hdr(asnin)) == NULL) { ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_MIME_SIG_PARSE_ERROR); sk_BIO_pop_free(parts, BIO_vfree); return NULL; @@ -470,7 +421,8 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it) /* Get content type */ - if (!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) { + if ((hdr = mime_hdr_find(headers, "content-type")) == NULL + || hdr->value == NULL) { sk_MIME_HEADER_pop_free(headers, mime_hdr_free); ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_SIG_CONTENT_TYPE); sk_BIO_pop_free(parts, BIO_vfree); @@ -487,7 +439,7 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it) } sk_MIME_HEADER_pop_free(headers, mime_hdr_free); /* Read in ASN1 */ - if (!(val = b64_read_asn1(asnin, it))) { + if ((val = b64_read_asn1(asnin, it)) == NULL) { ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_SIG_PARSE_ERROR); sk_BIO_pop_free(parts, BIO_vfree); return NULL; @@ -514,7 +466,7 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it) sk_MIME_HEADER_pop_free(headers, mime_hdr_free); - if (!(val = b64_read_asn1(bio, it))) { + if ((val = b64_read_asn1(bio, it)) == NULL) { ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_PARSE_ERROR); return NULL; } @@ -534,20 +486,32 @@ int SMIME_crlf_copy(BIO *in, BIO *out, int flags) * when streaming as we don't end up with one OCTET STRING per line. */ bf = BIO_new(BIO_f_buffer()); - if (!bf) + if (bf == NULL) return 0; out = BIO_push(bf, out); if (flags & SMIME_BINARY) { while ((len = BIO_read(in, linebuf, MAX_SMLEN)) > 0) BIO_write(out, linebuf, len); } else { + int eolcnt = 0; if (flags & SMIME_TEXT) BIO_printf(out, "Content-Type: text/plain\r\n\r\n"); while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0) { - eol = strip_eol(linebuf, &len); - if (len) + eol = strip_eol(linebuf, &len, flags); + if (len) { + /* Not EOF: write out all CRLF */ + if (flags & SMIME_ASCIICRLF) { + int i; + for (i = 0; i < eolcnt; i++) + BIO_write(out, "\r\n", 2); + eolcnt = 0; + } BIO_write(out, linebuf, len); - if (eol) + if (eol) + BIO_write(out, "\r\n", 2); + } else if (flags & SMIME_ASCIICRLF) + eolcnt++; + else if (eol) BIO_write(out, "\r\n", 2); } } @@ -565,11 +529,12 @@ int SMIME_text(BIO *in, BIO *out) STACK_OF(MIME_HEADER) *headers; MIME_HEADER *hdr; - if (!(headers = mime_parse_hdr(in))) { + if ((headers = mime_parse_hdr(in)) == NULL) { ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_MIME_PARSE_ERROR); return 0; } - if (!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) { + if ((hdr = mime_hdr_find(headers, "content-type")) == NULL + || hdr->value == NULL) { ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_MIME_NO_CONTENT_TYPE); sk_MIME_HEADER_pop_free(headers, mime_hdr_free); return 0; @@ -593,7 +558,7 @@ int SMIME_text(BIO *in, BIO *out) * canonical parts in a STACK of bios */ -static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret) +static int multi_split(BIO *bio, const char *bound, STACK_OF(BIO) **ret) { char linebuf[MAX_SMLEN]; int len, blen; @@ -608,24 +573,32 @@ static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret) first = 1; parts = sk_BIO_new_null(); *ret = parts; + if (*ret == NULL) + return 0; while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) { state = mime_bound_check(linebuf, len, bound, blen); if (state == 1) { first = 1; part++; } else if (state == 2) { - sk_BIO_push(parts, bpart); + if (!sk_BIO_push(parts, bpart)) { + BIO_free(bpart); + return 0; + } return 1; } else if (part) { /* Strip CR+LF from linebuf */ - next_eol = strip_eol(linebuf, &len); + next_eol = strip_eol(linebuf, &len, 0); if (first) { first = 0; if (bpart) - sk_BIO_push(parts, bpart); + if (!sk_BIO_push(parts, bpart)) { + BIO_free(bpart); + return 0; + } bpart = BIO_new(BIO_s_mem()); if (bpart == NULL) - return 1; + return 0; BIO_set_mem_eof_return(bpart, 0); } else if (eol) BIO_write(bpart, "\r\n", 2); @@ -634,6 +607,7 @@ static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret) BIO_write(bpart, linebuf, len); } } + BIO_free(bpart); return 0; } @@ -652,12 +626,12 @@ static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio) char *p, *q, c; char *ntmp; char linebuf[MAX_SMLEN]; - MIME_HEADER *mhdr = NULL; + MIME_HEADER *mhdr = NULL, *new_hdr = NULL; STACK_OF(MIME_HEADER) *headers; int len, state, save_state = 0; headers = sk_MIME_HEADER_new(mime_hdr_cmp); - if (!headers) + if (headers == NULL) return NULL; while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) { /* If whitespace at line start then continuation line */ @@ -689,8 +663,13 @@ static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio) if (c == ';') { mime_debug("Found End Value\n"); *p = 0; - mhdr = mime_hdr_new(ntmp, strip_ends(q)); - sk_MIME_HEADER_push(headers, mhdr); + new_hdr = mime_hdr_new(ntmp, strip_ends(q)); + if (new_hdr == NULL) + goto err; + if (!sk_MIME_HEADER_push(headers, new_hdr)) + goto err; + mhdr = new_hdr; + new_hdr = NULL; ntmp = NULL; q = p + 1; state = MIME_NAME; @@ -741,8 +720,13 @@ static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio) } if (state == MIME_TYPE) { - mhdr = mime_hdr_new(ntmp, strip_ends(q)); - sk_MIME_HEADER_push(headers, mhdr); + new_hdr = mime_hdr_new(ntmp, strip_ends(q)); + if (new_hdr == NULL) + goto err; + if (!sk_MIME_HEADER_push(headers, new_hdr)) + goto err; + mhdr = new_hdr; + new_hdr = NULL; } else if (state == MIME_VALUE) mime_hdr_addparam(mhdr, ntmp, strip_ends(q)); if (p == linebuf) @@ -751,6 +735,10 @@ static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio) return headers; +err: + mime_hdr_free(new_hdr); + sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + return NULL; } static char *strip_ends(char *name) @@ -800,13 +788,14 @@ static char *strip_end(char *name) return NULL; } -static MIME_HEADER *mime_hdr_new(char *name, char *value) +static MIME_HEADER *mime_hdr_new(const char *name, const char *value) { - MIME_HEADER *mhdr; - char *tmpname, *tmpval, *p; + MIME_HEADER *mhdr = NULL; + char *tmpname = NULL, *tmpval = NULL, *p; int c; + if (name) { - if (!(tmpname = BUF_strdup(name))) + if ((tmpname = OPENSSL_strdup(name)) == NULL) return NULL; for (p = tmpname; *p; p++) { c = (unsigned char)*p; @@ -815,11 +804,10 @@ static MIME_HEADER *mime_hdr_new(char *name, char *value) *p = c; } } - } else - tmpname = NULL; + } if (value) { - if (!(tmpval = BUF_strdup(value))) - return NULL; + if ((tmpval = OPENSSL_strdup(value)) == NULL) + goto err; for (p = tmpval; *p; p++) { c = (unsigned char)*p; if (isupper(c)) { @@ -827,27 +815,32 @@ static MIME_HEADER *mime_hdr_new(char *name, char *value) *p = c; } } - } else - tmpval = NULL; - mhdr = (MIME_HEADER *)OPENSSL_malloc(sizeof(MIME_HEADER)); - if (!mhdr) - return NULL; + } + mhdr = OPENSSL_malloc(sizeof(*mhdr)); + if (mhdr == NULL) + goto err; mhdr->name = tmpname; mhdr->value = tmpval; - if (!(mhdr->params = sk_MIME_PARAM_new(mime_param_cmp))) - return NULL; + if ((mhdr->params = sk_MIME_PARAM_new(mime_param_cmp)) == NULL) + goto err; return mhdr; + + err: + OPENSSL_free(tmpname); + OPENSSL_free(tmpval); + OPENSSL_free(mhdr); + return NULL; } -static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value) +static int mime_hdr_addparam(MIME_HEADER *mhdr, const char *name, const char *value) { - char *tmpname, *tmpval, *p; + char *tmpname = NULL, *tmpval = NULL, *p; int c; - MIME_PARAM *mparam; + MIME_PARAM *mparam = NULL; if (name) { - tmpname = BUF_strdup(name); + tmpname = OPENSSL_strdup(name); if (!tmpname) - return 0; + goto err; for (p = tmpname; *p; p++) { c = (unsigned char)*p; if (isupper(c)) { @@ -855,22 +848,26 @@ static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value) *p = c; } } - } else - tmpname = NULL; + } if (value) { - tmpval = BUF_strdup(value); + tmpval = OPENSSL_strdup(value); if (!tmpval) - return 0; - } else - tmpval = NULL; + goto err; + } /* Parameter values are case sensitive so leave as is */ - mparam = (MIME_PARAM *)OPENSSL_malloc(sizeof(MIME_PARAM)); - if (!mparam) - return 0; + mparam = OPENSSL_malloc(sizeof(*mparam)); + if (mparam == NULL) + goto err; mparam->param_name = tmpname; mparam->param_value = tmpval; - sk_MIME_PARAM_push(mhdr->params, mparam); + if (!sk_MIME_PARAM_push(mhdr->params, mparam)) + goto err; return 1; + err: + OPENSSL_free(tmpname); + OPENSSL_free(tmpval); + OPENSSL_free(mparam); + return 0; } static int mime_hdr_cmp(const MIME_HEADER *const *a, @@ -892,22 +889,28 @@ static int mime_param_cmp(const MIME_PARAM *const *a, /* Find a header with a given name (if possible) */ -static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, char *name) +static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, const char *name) { MIME_HEADER htmp; int idx; - htmp.name = name; + + htmp.name = (char *)name; + htmp.value = NULL; + htmp.params = NULL; + idx = sk_MIME_HEADER_find(hdrs, &htmp); if (idx < 0) return NULL; return sk_MIME_HEADER_value(hdrs, idx); } -static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name) +static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, const char *name) { MIME_PARAM param; int idx; - param.param_name = name; + + param.param_name = (char *)name; + param.param_value = NULL; idx = sk_MIME_PARAM_find(hdr->params, ¶m); if (idx < 0) return NULL; @@ -916,10 +919,10 @@ static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name) static void mime_hdr_free(MIME_HEADER *hdr) { - if (hdr->name) - OPENSSL_free(hdr->name); - if (hdr->value) - OPENSSL_free(hdr->value); + if (hdr == NULL) + return; + OPENSSL_free(hdr->name); + OPENSSL_free(hdr->value); if (hdr->params) sk_MIME_PARAM_pop_free(hdr->params, mime_param_free); OPENSSL_free(hdr); @@ -927,10 +930,8 @@ static void mime_hdr_free(MIME_HEADER *hdr) static void mime_param_free(MIME_PARAM *param) { - if (param->param_name) - OPENSSL_free(param->param_name); - if (param->param_value) - OPENSSL_free(param->param_value); + OPENSSL_free(param->param_name); + OPENSSL_free(param->param_value); OPENSSL_free(param); } @@ -940,7 +941,7 @@ static void mime_param_free(MIME_PARAM *param) * 1 : part boundary * 2 : final boundary */ -static int mime_bound_check(char *line, int linelen, char *bound, int blen) +static int mime_bound_check(char *line, int linelen, const char *bound, int blen) { if (linelen == -1) linelen = strlen(line); @@ -950,8 +951,9 @@ static int mime_bound_check(char *line, int linelen, char *bound, int blen) if (blen + 2 > linelen) return 0; /* Check for part boundary */ - if (!strncmp(line, "--", 2) && !strncmp(line + 2, bound, blen)) { - if (!strncmp(line + blen + 2, "--", 2)) + if ((strncmp(line, "--", 2) == 0) + && strncmp(line + 2, bound, blen) == 0) { + if (strncmp(line + blen + 2, "--", 2) == 0) return 2; else return 1; @@ -959,7 +961,7 @@ static int mime_bound_check(char *line, int linelen, char *bound, int blen) return 0; } -static int strip_eol(char *linebuf, int *plen) +static int strip_eol(char *linebuf, int *plen, int flags) { int len = *plen; char *p, c; @@ -969,6 +971,8 @@ static int strip_eol(char *linebuf, int *plen) c = *p; if (c == '\n') is_eol = 1; + else if (is_eol && flags & SMIME_ASCIICRLF && c < 33) + continue; else if (c != '\r') break; } |