1656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* asn_mime.c */ 2656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * project. 4656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */ 5656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* ==================================================================== 6656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Copyright (c) 1999-2008 The OpenSSL Project. All rights reserved. 7656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 8656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Redistribution and use in source and binary forms, with or without 9656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * modification, are permitted provided that the following conditions 10656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * are met: 11656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 12656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 1. Redistributions of source code must retain the above copyright 13656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * notice, this list of conditions and the following disclaimer. 14656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 15656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 16656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * notice, this list of conditions and the following disclaimer in 17656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * the documentation and/or other materials provided with the 18656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * distribution. 19656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 20656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 3. All advertising materials mentioning features or use of this 21656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * software must display the following acknowledgment: 22656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * "This product includes software developed by the OpenSSL Project 23656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 25656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * endorse or promote products derived from this software without 27656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * prior written permission. For written permission, please contact 28656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * licensing@OpenSSL.org. 29656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 30656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 5. Products derived from this software may not be called "OpenSSL" 31656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * nor may "OpenSSL" appear in their names without prior written 32656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * permission of the OpenSSL Project. 33656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 34656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 6. Redistributions of any form whatsoever must retain the following 35656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * acknowledgment: 36656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * "This product includes software developed by the OpenSSL Project 37656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 39656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * OF THE POSSIBILITY OF SUCH DAMAGE. 51656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * ==================================================================== 52656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 53656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */ 54656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 55656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include <stdio.h> 56656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include <ctype.h> 57656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include "cryptlib.h" 58656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include <openssl/rand.h> 59656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include <openssl/x509.h> 60656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include <openssl/asn1.h> 61656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include <openssl/asn1t.h> 62221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include "asn1_locl.h" 63656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 64656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* Generalised MIME like utilities for streaming ASN1. Although many 65656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * have a PKCS7/CMS like flavour others are more general purpose. 66656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */ 67656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 68656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* MIME format structures 69656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Note that all are translated to lower case apart from 70656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * parameter values. Quotes are stripped off 71656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */ 72656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 73656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projecttypedef struct { 74656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectchar *param_name; /* Param name e.g. "micalg" */ 75656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectchar *param_value; /* Param value e.g. "sha1" */ 76656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} MIME_PARAM; 77656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 78656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectDECLARE_STACK_OF(MIME_PARAM) 79656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectIMPLEMENT_STACK_OF(MIME_PARAM) 80656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 81656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projecttypedef struct { 82656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectchar *name; /* Name of line e.g. "content-type" */ 83656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectchar *value; /* Value of line e.g. "text/plain" */ 84656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectSTACK_OF(MIME_PARAM) *params; /* Zero or more parameters */ 85656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} MIME_HEADER; 86656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 87656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectDECLARE_STACK_OF(MIME_HEADER) 88656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectIMPLEMENT_STACK_OF(MIME_HEADER) 89656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 90221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags, 91221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom const ASN1_ITEM *it); 92656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic char * strip_ends(char *name); 93656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic char * strip_start(char *name); 94656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic char * strip_end(char *name); 95656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic MIME_HEADER *mime_hdr_new(char *name, char *value); 96656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value); 97656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio); 98656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int mime_hdr_cmp(const MIME_HEADER * const *a, 99656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project const MIME_HEADER * const *b); 100656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int mime_param_cmp(const MIME_PARAM * const *a, 101656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project const MIME_PARAM * const *b); 102656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic void mime_param_free(MIME_PARAM *param); 103656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int mime_bound_check(char *line, int linelen, char *bound, int blen); 104656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret); 105656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int strip_eol(char *linebuf, int *plen); 106656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, char *name); 107656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name); 108656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic void mime_hdr_free(MIME_HEADER *hdr); 109656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 110656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#define MAX_SMLEN 1024 111656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#define mime_debug(x) /* x */ 112656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 113221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom/* Output an ASN1 structure in BER format streaming if necessary */ 114221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 115221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromint i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, 116221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom const ASN1_ITEM *it) 117221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 118221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom /* If streaming create stream BIO and copy all content through it */ 119221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (flags & SMIME_STREAM) 120221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 121221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom BIO *bio, *tbio; 122221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom bio = BIO_new_NDEF(out, val, it); 123221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!bio) 124221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 125221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom ASN1err(ASN1_F_I2D_ASN1_BIO_STREAM,ERR_R_MALLOC_FAILURE); 126221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 0; 127221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 128221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom SMIME_crlf_copy(in, bio, flags); 129221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom (void)BIO_flush(bio); 130221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom /* Free up successive BIOs until we hit the old output BIO */ 131221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom do 132221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 133221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom tbio = BIO_pop(bio); 134221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom BIO_free(bio); 135221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom bio = tbio; 136221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } while (bio != out); 137221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 138221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom /* else just write out ASN1 structure which will have all content 139221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * stored internally 140221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom */ 141221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom else 142221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom ASN1_item_i2d_bio(it, out, val); 143221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return 1; 144221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 145221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 146656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* Base 64 read and write of ASN1 structure */ 147656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 148656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int B64_write_ASN1(BIO *out, ASN1_VALUE *val, BIO *in, int flags, 149656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project const ASN1_ITEM *it) 150656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project { 151656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO *b64; 152656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project int r; 153656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project b64 = BIO_new(BIO_f_base64()); 154656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(!b64) 155656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project { 156656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ASN1err(ASN1_F_B64_WRITE_ASN1,ERR_R_MALLOC_FAILURE); 157656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return 0; 158656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 159656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* prepend the b64 BIO so all data is base64 encoded. 160656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */ 161656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project out = BIO_push(b64, out); 162221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom r = i2d_ASN1_bio_stream(out, val, in, flags, it); 163656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project (void)BIO_flush(out); 164656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_pop(out); 165656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_free(b64); 166656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return r; 167656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 168656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 169221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom/* Streaming ASN1 PEM write */ 170221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 171221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromint PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, 172221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom const char *hdr, 173221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom const ASN1_ITEM *it) 174221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 175221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom int r; 176221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom BIO_printf(out, "-----BEGIN %s-----\n", hdr); 177221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom r = B64_write_ASN1(out, val, in, flags, it); 178221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom BIO_printf(out, "-----END %s-----\n", hdr); 179221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return r; 180221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 181221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 182656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it) 183656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{ 184656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO *b64; 185656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ASN1_VALUE *val; 186656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(!(b64 = BIO_new(BIO_f_base64()))) { 187656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ASN1err(ASN1_F_B64_READ_ASN1,ERR_R_MALLOC_FAILURE); 188656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return 0; 189656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 190656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project bio = BIO_push(b64, bio); 191656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project val = ASN1_item_d2i_bio(it, bio, NULL); 192656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(!val) 193656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ASN1err(ASN1_F_B64_READ_ASN1,ASN1_R_DECODE_ERROR); 194656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project (void)BIO_flush(bio); 195656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project bio = BIO_pop(bio); 196656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_free(b64); 197656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return val; 198656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 199656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 200656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* Generate the MIME "micalg" parameter from RFC3851, RFC4490 */ 201656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 202656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR) *mdalgs) 203656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project { 204221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom const EVP_MD *md; 205221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom int i, have_unknown = 0, write_comma, ret = 0, md_nid; 206656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project have_unknown = 0; 207656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project write_comma = 0; 208656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project for (i = 0; i < sk_X509_ALGOR_num(mdalgs); i++) 209656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project { 210656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (write_comma) 211656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_write(out, ",", 1); 212656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project write_comma = 1; 213656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project md_nid = OBJ_obj2nid(sk_X509_ALGOR_value(mdalgs, i)->algorithm); 214221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom md = EVP_get_digestbynid(md_nid); 215221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (md && md->md_ctrl) 216221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 217221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom int rv; 218221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom char *micstr; 219221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom rv = md->md_ctrl(NULL, EVP_MD_CTRL_MICALG, 0, &micstr); 220221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (rv > 0) 221221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom { 222221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom BIO_puts(out, micstr); 223221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom OPENSSL_free(micstr); 224221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom continue; 225221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 226221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (rv != -2) 227221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto err; 228221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom } 229656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project switch(md_nid) 230656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project { 231656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project case NID_sha1: 232656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_puts(out, "sha1"); 233656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project break; 234656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 235656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project case NID_md5: 236656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_puts(out, "md5"); 237656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project break; 238656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 239656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project case NID_sha256: 240656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_puts(out, "sha-256"); 241656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project break; 242656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 243656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project case NID_sha384: 244656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_puts(out, "sha-384"); 245656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project break; 246656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 247656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project case NID_sha512: 248656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_puts(out, "sha-512"); 249656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project break; 250656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 251221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom case NID_id_GostR3411_94: 252221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom BIO_puts(out, "gostr3411-94"); 253221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom goto err; 254221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom break; 255221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 256656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project default: 257656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (have_unknown) 258656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project write_comma = 0; 259656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project else 260656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project { 261656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_puts(out, "unknown"); 262656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project have_unknown = 1; 263656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 264656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project break; 265656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 266656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 267656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 268656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 269221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom ret = 1; 270221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom err: 271221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom 272221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom return ret; 273656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 274656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 275656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 276656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* SMIME sender */ 277656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 278221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromint SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags, 279656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project int ctype_nid, int econt_nid, 280656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project STACK_OF(X509_ALGOR) *mdalgs, 281656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project const ASN1_ITEM *it) 282656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{ 283656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project char bound[33], c; 284656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project int i; 285656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project const char *mime_prefix, *mime_eol, *cname = "smime.p7m"; 286656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project const char *msg_type=NULL; 287656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (flags & SMIME_OLDMIME) 288656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project mime_prefix = "application/x-pkcs7-"; 289656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project else 290656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project mime_prefix = "application/pkcs7-"; 291656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 292656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (flags & SMIME_CRLFEOL) 293656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project mime_eol = "\r\n"; 294656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project else 295656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project mime_eol = "\n"; 296656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if((flags & SMIME_DETACHED) && data) { 297656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* We want multipart/signed */ 298656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* Generate a random boundary */ 299656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project RAND_pseudo_bytes((unsigned char *)bound, 32); 300656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project for(i = 0; i < 32; i++) { 301656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project c = bound[i] & 0xf; 302656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(c < 10) c += '0'; 303656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project else c += 'A' - 10; 304656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project bound[i] = c; 305656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 306656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project bound[32] = 0; 307656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol); 308656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_printf(bio, "Content-Type: multipart/signed;"); 309656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_printf(bio, " protocol=\"%ssignature\";", mime_prefix); 310656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_puts(bio, " micalg=\""); 311656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project asn1_write_micalg(bio, mdalgs); 312656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_printf(bio, "\"; boundary=\"----%s\"%s%s", 313656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project bound, mime_eol, mime_eol); 314656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_printf(bio, "This is an S/MIME signed message%s%s", 315656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project mime_eol, mime_eol); 316656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* Now write out the first part */ 317656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_printf(bio, "------%s%s", bound, mime_eol); 318221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom if (!asn1_output_data(bio, data, val, flags, it)) 319656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return 0; 320656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_printf(bio, "%s------%s%s", mime_eol, bound, mime_eol); 321656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 322656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* Headers for signature */ 323656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 324656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_printf(bio, "Content-Type: %ssignature;", mime_prefix); 325656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_printf(bio, " name=\"smime.p7s\"%s", mime_eol); 326656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_printf(bio, "Content-Transfer-Encoding: base64%s", 327656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project mime_eol); 328656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_printf(bio, "Content-Disposition: attachment;"); 329656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_printf(bio, " filename=\"smime.p7s\"%s%s", 330656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project mime_eol, mime_eol); 331656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project B64_write_ASN1(bio, val, NULL, 0, it); 332656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_printf(bio,"%s------%s--%s%s", mime_eol, bound, 333656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project mime_eol, mime_eol); 334656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return 1; 335656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 336656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 337656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* Determine smime-type header */ 338656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 339656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (ctype_nid == NID_pkcs7_enveloped) 340656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project msg_type = "enveloped-data"; 341656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project else if (ctype_nid == NID_pkcs7_signed) 342656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project { 343656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (econt_nid == NID_id_smime_ct_receipt) 344656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project msg_type = "signed-receipt"; 345656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project else if (sk_X509_ALGOR_num(mdalgs) >= 0) 346656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project msg_type = "signed-data"; 347656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project else 348656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project msg_type = "certs-only"; 349656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 350656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project else if (ctype_nid == NID_id_smime_ct_compressedData) 351656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project { 352656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project msg_type = "compressed-data"; 353656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project cname = "smime.p7z"; 354656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 355656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* MIME headers */ 356656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol); 357656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_printf(bio, "Content-Disposition: attachment;"); 358656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_printf(bio, " filename=\"%s\"%s", cname, mime_eol); 359656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_printf(bio, "Content-Type: %smime;", mime_prefix); 360656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (msg_type) 361656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_printf(bio, " smime-type=%s;", msg_type); 362656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_printf(bio, " name=\"%s\"%s", cname, mime_eol); 363656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_printf(bio, "Content-Transfer-Encoding: base64%s%s", 364656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project mime_eol, mime_eol); 365656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (!B64_write_ASN1(bio, val, data, flags, it)) 366656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return 0; 367656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_printf(bio, "%s", mime_eol); 368656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return 1; 369656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 370656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 371656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* Handle output of ASN1 data */ 372656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 373656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 374656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags, 375656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project const ASN1_ITEM *it) 376656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project { 377656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO *tmpbio; 378656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project const ASN1_AUX *aux = it->funcs; 379656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ASN1_STREAM_ARG sarg; 38021c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom int rv = 1; 381656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 38221c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom /* If data is not deteched or resigning then the output BIO is 38321c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom * already set up to finalise when it is written through. 38421c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom */ 38521c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom if (!(flags & SMIME_DETACHED) || (flags & PKCS7_REUSE_DIGEST)) 386656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project { 387656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project SMIME_crlf_copy(data, out, flags); 388656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return 1; 389656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 390656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 391656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (!aux || !aux->asn1_cb) 392656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project { 393656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ASN1err(ASN1_F_ASN1_OUTPUT_DATA, 394656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ASN1_R_STREAMING_NOT_SUPPORTED); 395656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return 0; 396656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 397656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 398656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sarg.out = out; 399656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sarg.ndef_bio = NULL; 400656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sarg.boundary = NULL; 401656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 402656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* Let ASN1 code prepend any needed BIOs */ 403656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 404656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (aux->asn1_cb(ASN1_OP_DETACHED_PRE, &val, it, &sarg) <= 0) 405656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return 0; 406656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 407656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* Copy data across, passing through filter BIOs for processing */ 408656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project SMIME_crlf_copy(data, sarg.ndef_bio, flags); 409656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 410656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* Finalize structure */ 411656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (aux->asn1_cb(ASN1_OP_DETACHED_POST, &val, it, &sarg) <= 0) 41221c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom rv = 0; 413656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 414656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* Now remove any digests prepended to the BIO */ 415656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 416656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project while (sarg.ndef_bio != out) 417656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project { 418656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project tmpbio = BIO_pop(sarg.ndef_bio); 419656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_free(sarg.ndef_bio); 420656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sarg.ndef_bio = tmpbio; 421656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 422656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 42321c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom return rv; 424656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 425656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 426656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 427656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* SMIME reader: handle multipart/signed and opaque signing. 428656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * in multipart case the content is placed in a memory BIO 429656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * pointed to by "bcont". In opaque this is set to NULL 430656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */ 431656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 432656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it) 433656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{ 434656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO *asnin; 435656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project STACK_OF(MIME_HEADER) *headers = NULL; 436656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project STACK_OF(BIO) *parts = NULL; 437656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project MIME_HEADER *hdr; 438656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project MIME_PARAM *prm; 439656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ASN1_VALUE *val; 440656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project int ret; 441656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 442656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(bcont) *bcont = NULL; 443656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 444656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (!(headers = mime_parse_hdr(bio))) { 445656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_MIME_PARSE_ERROR); 446656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return NULL; 447656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 448656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 449656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) { 450656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sk_MIME_HEADER_pop_free(headers, mime_hdr_free); 451656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_CONTENT_TYPE); 452656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return NULL; 453656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 454656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 455656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* Handle multipart/signed */ 456656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 457656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(!strcmp(hdr->value, "multipart/signed")) { 458656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* Split into two parts */ 459656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project prm = mime_param_find(hdr, "boundary"); 460656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(!prm || !prm->param_value) { 461656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sk_MIME_HEADER_pop_free(headers, mime_hdr_free); 462656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BOUNDARY); 463656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return NULL; 464656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 465656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ret = multi_split(bio, prm->param_value, &parts); 466656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sk_MIME_HEADER_pop_free(headers, mime_hdr_free); 467656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(!ret || (sk_BIO_num(parts) != 2) ) { 468656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BODY_FAILURE); 469656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sk_BIO_pop_free(parts, BIO_vfree); 470656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return NULL; 471656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 472656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 473656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* Parse the signature piece */ 474656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project asnin = sk_BIO_value(parts, 1); 475656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 476656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (!(headers = mime_parse_hdr(asnin))) { 477656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_MIME_SIG_PARSE_ERROR); 478656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sk_BIO_pop_free(parts, BIO_vfree); 479656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return NULL; 480656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 481656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 482656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* Get content type */ 483656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 484656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(!(hdr = mime_hdr_find(headers, "content-type")) || 485656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project !hdr->value) { 486656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sk_MIME_HEADER_pop_free(headers, mime_hdr_free); 487656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_SIG_CONTENT_TYPE); 488656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return NULL; 489656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 490656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 491656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(strcmp(hdr->value, "application/x-pkcs7-signature") && 492656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project strcmp(hdr->value, "application/pkcs7-signature")) { 493656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_SIG_INVALID_MIME_TYPE); 494656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ERR_add_error_data(2, "type: ", hdr->value); 49521c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom sk_MIME_HEADER_pop_free(headers, mime_hdr_free); 496656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sk_BIO_pop_free(parts, BIO_vfree); 497656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return NULL; 498656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 499656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sk_MIME_HEADER_pop_free(headers, mime_hdr_free); 500656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* Read in ASN1 */ 501656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(!(val = b64_read_asn1(asnin, it))) { 502656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_ASN1_SIG_PARSE_ERROR); 503656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sk_BIO_pop_free(parts, BIO_vfree); 504656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return NULL; 505656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 506656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 507656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(bcont) { 508656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *bcont = sk_BIO_value(parts, 0); 509656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_free(asnin); 510656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sk_BIO_free(parts); 511656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } else sk_BIO_pop_free(parts, BIO_vfree); 512656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return val; 513656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 514656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 515656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* OK, if not multipart/signed try opaque signature */ 516656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 517656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (strcmp (hdr->value, "application/x-pkcs7-mime") && 518656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project strcmp (hdr->value, "application/pkcs7-mime")) { 519656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_INVALID_MIME_TYPE); 520656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ERR_add_error_data(2, "type: ", hdr->value); 521656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sk_MIME_HEADER_pop_free(headers, mime_hdr_free); 522656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return NULL; 523656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 524656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 525656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sk_MIME_HEADER_pop_free(headers, mime_hdr_free); 526656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 527656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(!(val = b64_read_asn1(bio, it))) { 528656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_PARSE_ERROR); 529656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return NULL; 530656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 531656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return val; 532656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 533656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 534656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 535656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* Copy text from one BIO to another making the output CRLF at EOL */ 536656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint SMIME_crlf_copy(BIO *in, BIO *out, int flags) 537656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{ 538656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO *bf; 539656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project char eol; 540656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project int len; 541656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project char linebuf[MAX_SMLEN]; 542656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* Buffer output so we don't write one line at a time. This is 543656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * useful when streaming as we don't end up with one OCTET STRING 544656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * per line. 545656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */ 546656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project bf = BIO_new(BIO_f_buffer()); 547656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (!bf) 548656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return 0; 549656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project out = BIO_push(bf, out); 550656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(flags & SMIME_BINARY) 551656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project { 552656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project while((len = BIO_read(in, linebuf, MAX_SMLEN)) > 0) 553656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_write(out, linebuf, len); 554656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 555656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project else 556656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project { 557656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(flags & SMIME_TEXT) 558656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_printf(out, "Content-Type: text/plain\r\n\r\n"); 559656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0) 560656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project { 561656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project eol = strip_eol(linebuf, &len); 562656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (len) 563656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_write(out, linebuf, len); 564656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(eol) BIO_write(out, "\r\n", 2); 565656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 566656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 567656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project (void)BIO_flush(out); 568656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_pop(out); 569656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_free(bf); 570656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return 1; 571656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 572656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 573656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* Strip off headers if they are text/plain */ 574656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint SMIME_text(BIO *in, BIO *out) 575656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{ 576656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project char iobuf[4096]; 577656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project int len; 578656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project STACK_OF(MIME_HEADER) *headers; 579656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project MIME_HEADER *hdr; 580656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 581656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (!(headers = mime_parse_hdr(in))) { 582656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ASN1err(ASN1_F_SMIME_TEXT,ASN1_R_MIME_PARSE_ERROR); 583656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return 0; 584656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 585656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) { 586656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ASN1err(ASN1_F_SMIME_TEXT,ASN1_R_MIME_NO_CONTENT_TYPE); 587656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sk_MIME_HEADER_pop_free(headers, mime_hdr_free); 588656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return 0; 589656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 590656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (strcmp (hdr->value, "text/plain")) { 591656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ASN1err(ASN1_F_SMIME_TEXT,ASN1_R_INVALID_MIME_TYPE); 592656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ERR_add_error_data(2, "type: ", hdr->value); 593656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sk_MIME_HEADER_pop_free(headers, mime_hdr_free); 594656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return 0; 595656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 596656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sk_MIME_HEADER_pop_free(headers, mime_hdr_free); 597656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project while ((len = BIO_read(in, iobuf, sizeof(iobuf))) > 0) 598656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_write(out, iobuf, len); 599e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu if (len < 0) 600e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu return 0; 601656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return 1; 602656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 603656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 604656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* Split a multipart/XXX message body into component parts: result is 605656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * canonical parts in a STACK of bios 606656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */ 607656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 608656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret) 609656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{ 610656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project char linebuf[MAX_SMLEN]; 611656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project int len, blen; 612656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project int eol = 0, next_eol = 0; 613656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO *bpart = NULL; 614656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project STACK_OF(BIO) *parts; 615656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project char state, part, first; 616656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 617656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project blen = strlen(bound); 618656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project part = 0; 619656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project state = 0; 620656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project first = 1; 621656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project parts = sk_BIO_new_null(); 622656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *ret = parts; 623656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) { 624656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project state = mime_bound_check(linebuf, len, bound, blen); 625656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(state == 1) { 626656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project first = 1; 627656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project part++; 628656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } else if(state == 2) { 629656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sk_BIO_push(parts, bpart); 630656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return 1; 631656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } else if(part) { 632656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* Strip CR+LF from linebuf */ 633656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project next_eol = strip_eol(linebuf, &len); 634656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(first) { 635656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project first = 0; 636656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(bpart) sk_BIO_push(parts, bpart); 637656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project bpart = BIO_new(BIO_s_mem()); 638656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_set_mem_eof_return(bpart, 0); 639656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } else if (eol) 640656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_write(bpart, "\r\n", 2); 641656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project eol = next_eol; 642656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (len) 643656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project BIO_write(bpart, linebuf, len); 644656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 645656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 646656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return 0; 647656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 648656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 649656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* This is the big one: parse MIME header lines up to message body */ 650656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 651656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#define MIME_INVALID 0 652656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#define MIME_START 1 653656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#define MIME_TYPE 2 654656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#define MIME_NAME 3 655656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#define MIME_VALUE 4 656656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#define MIME_QUOTE 5 657656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#define MIME_COMMENT 6 658656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 659656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 660656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio) 661656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{ 662656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project char *p, *q, c; 663656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project char *ntmp; 664656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project char linebuf[MAX_SMLEN]; 665656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project MIME_HEADER *mhdr = NULL; 666656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project STACK_OF(MIME_HEADER) *headers; 667656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project int len, state, save_state = 0; 668656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 669656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project headers = sk_MIME_HEADER_new(mime_hdr_cmp); 670c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root if (!headers) 671c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root return NULL; 672656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) { 673656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* If whitespace at line start then continuation line */ 674656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(mhdr && isspace((unsigned char)linebuf[0])) state = MIME_NAME; 675656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project else state = MIME_START; 676656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ntmp = NULL; 677656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* Go through all characters */ 678656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project for(p = linebuf, q = linebuf; (c = *p) && (c!='\r') && (c!='\n'); p++) { 679656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 680656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* State machine to handle MIME headers 681656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * if this looks horrible that's because it *is* 682656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */ 683656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 684656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project switch(state) { 685656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project case MIME_START: 686656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(c == ':') { 687656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project state = MIME_TYPE; 688656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *p = 0; 689656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ntmp = strip_ends(q); 690656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project q = p + 1; 691656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 692656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project break; 693656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 694656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project case MIME_TYPE: 695656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(c == ';') { 696656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project mime_debug("Found End Value\n"); 697656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *p = 0; 698656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project mhdr = mime_hdr_new(ntmp, strip_ends(q)); 699656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sk_MIME_HEADER_push(headers, mhdr); 700656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ntmp = NULL; 701656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project q = p + 1; 702656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project state = MIME_NAME; 703656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } else if(c == '(') { 704656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project save_state = state; 705656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project state = MIME_COMMENT; 706656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 707656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project break; 708656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 709656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project case MIME_COMMENT: 710656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(c == ')') { 711656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project state = save_state; 712656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 713656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project break; 714656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 715656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project case MIME_NAME: 716656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(c == '=') { 717656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project state = MIME_VALUE; 718656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *p = 0; 719656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ntmp = strip_ends(q); 720656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project q = p + 1; 721656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 722656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project break ; 723656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 724656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project case MIME_VALUE: 725656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(c == ';') { 726656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project state = MIME_NAME; 727656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *p = 0; 728656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project mime_hdr_addparam(mhdr, ntmp, strip_ends(q)); 729656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project ntmp = NULL; 730656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project q = p + 1; 731656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } else if (c == '"') { 732656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project mime_debug("Found Quote\n"); 733656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project state = MIME_QUOTE; 734656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } else if(c == '(') { 735656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project save_state = state; 736656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project state = MIME_COMMENT; 737656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 738656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project break; 739656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 740656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project case MIME_QUOTE: 741656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(c == '"') { 742656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project mime_debug("Found Match Quote\n"); 743656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project state = MIME_VALUE; 744656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 745656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project break; 746656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 747656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 748656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 749656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(state == MIME_TYPE) { 750656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project mhdr = mime_hdr_new(ntmp, strip_ends(q)); 751656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sk_MIME_HEADER_push(headers, mhdr); 752656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } else if(state == MIME_VALUE) 753656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project mime_hdr_addparam(mhdr, ntmp, strip_ends(q)); 754656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(p == linebuf) break; /* Blank line means end of headers */ 755656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 756656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 757656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectreturn headers; 758656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 759656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 760656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 761656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic char *strip_ends(char *name) 762656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{ 763656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return strip_end(strip_start(name)); 764656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 765656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 766656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* Strip a parameter of whitespace from start of param */ 767656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic char *strip_start(char *name) 768656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{ 769656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project char *p, c; 770656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* Look for first non white space or quote */ 771656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project for(p = name; (c = *p) ;p++) { 772656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(c == '"') { 773656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* Next char is start of string if non null */ 774656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(p[1]) return p + 1; 775656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* Else null string */ 776656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return NULL; 777656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 778656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(!isspace((unsigned char)c)) return p; 779656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 780656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return NULL; 781656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 782656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 783656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* As above but strip from end of string : maybe should handle brackets? */ 784656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic char *strip_end(char *name) 785656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{ 786656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project char *p, c; 787656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(!name) return NULL; 788656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* Look for first non white space or quote */ 789656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project for(p = name + strlen(name) - 1; p >= name ;p--) { 790656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project c = *p; 791656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(c == '"') { 792656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(p - 1 == name) return NULL; 793656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *p = 0; 794656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return name; 795656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 796656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(isspace((unsigned char)c)) *p = 0; 797656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project else return name; 798656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 799656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return NULL; 800656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 801656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 802656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic MIME_HEADER *mime_hdr_new(char *name, char *value) 803656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{ 804656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project MIME_HEADER *mhdr; 805656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project char *tmpname, *tmpval, *p; 806656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project int c; 807656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(name) { 808656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(!(tmpname = BUF_strdup(name))) return NULL; 809656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project for(p = tmpname ; *p; p++) { 8107d3d122363e2a85d516db314892f3d6112cb1377Brian Carlstrom c = (unsigned char)*p; 811656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(isupper(c)) { 812656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project c = tolower(c); 813656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *p = c; 814656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 815656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 816656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } else tmpname = NULL; 817656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(value) { 818656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(!(tmpval = BUF_strdup(value))) return NULL; 819656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project for(p = tmpval ; *p; p++) { 8207d3d122363e2a85d516db314892f3d6112cb1377Brian Carlstrom c = (unsigned char)*p; 821656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(isupper(c)) { 822656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project c = tolower(c); 823656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *p = c; 824656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 825656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 826656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } else tmpval = NULL; 827656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project mhdr = (MIME_HEADER *) OPENSSL_malloc(sizeof(MIME_HEADER)); 828656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(!mhdr) return NULL; 829656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project mhdr->name = tmpname; 830656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project mhdr->value = tmpval; 831656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(!(mhdr->params = sk_MIME_PARAM_new(mime_param_cmp))) return NULL; 832656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return mhdr; 833656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 834656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 835656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value) 836656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{ 837656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project char *tmpname, *tmpval, *p; 838656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project int c; 839656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project MIME_PARAM *mparam; 840656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(name) { 841656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project tmpname = BUF_strdup(name); 842656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(!tmpname) return 0; 843656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project for(p = tmpname ; *p; p++) { 8447d3d122363e2a85d516db314892f3d6112cb1377Brian Carlstrom c = (unsigned char)*p; 845656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(isupper(c)) { 846656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project c = tolower(c); 847656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *p = c; 848656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 849656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 850656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } else tmpname = NULL; 851656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(value) { 852656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project tmpval = BUF_strdup(value); 853656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(!tmpval) return 0; 854656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } else tmpval = NULL; 855656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* Parameter values are case sensitive so leave as is */ 856656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project mparam = (MIME_PARAM *) OPENSSL_malloc(sizeof(MIME_PARAM)); 857656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(!mparam) return 0; 858656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project mparam->param_name = tmpname; 859656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project mparam->param_value = tmpval; 860656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project sk_MIME_PARAM_push(mhdr->params, mparam); 861656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return 1; 862656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 863656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 864656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int mime_hdr_cmp(const MIME_HEADER * const *a, 865656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project const MIME_HEADER * const *b) 866656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{ 86721c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom if (!(*a)->name || !(*b)->name) 86821c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom return !!(*a)->name - !!(*b)->name; 86921c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom 870656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return(strcmp((*a)->name, (*b)->name)); 871656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 872656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 873656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int mime_param_cmp(const MIME_PARAM * const *a, 874656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project const MIME_PARAM * const *b) 875656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{ 87621c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom if (!(*a)->param_name || !(*b)->param_name) 87721c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom return !!(*a)->param_name - !!(*b)->param_name; 878656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return(strcmp((*a)->param_name, (*b)->param_name)); 879656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 880656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 881656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* Find a header with a given name (if possible) */ 882656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 883656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, char *name) 884656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{ 885656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project MIME_HEADER htmp; 886656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project int idx; 887656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project htmp.name = name; 888656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project idx = sk_MIME_HEADER_find(hdrs, &htmp); 889656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(idx < 0) return NULL; 890656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return sk_MIME_HEADER_value(hdrs, idx); 891656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 892656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 893656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name) 894656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{ 895656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project MIME_PARAM param; 896656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project int idx; 897656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project param.param_name = name; 898656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project idx = sk_MIME_PARAM_find(hdr->params, ¶m); 899656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(idx < 0) return NULL; 900656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return sk_MIME_PARAM_value(hdr->params, idx); 901656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 902656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 903656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic void mime_hdr_free(MIME_HEADER *hdr) 904656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{ 905656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(hdr->name) OPENSSL_free(hdr->name); 906656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(hdr->value) OPENSSL_free(hdr->value); 907656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(hdr->params) sk_MIME_PARAM_pop_free(hdr->params, mime_param_free); 908656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project OPENSSL_free(hdr); 909656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 910656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 911656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic void mime_param_free(MIME_PARAM *param) 912656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{ 913656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(param->param_name) OPENSSL_free(param->param_name); 914656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(param->param_value) OPENSSL_free(param->param_value); 915656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project OPENSSL_free(param); 916656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 917656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 918656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* Check for a multipart boundary. Returns: 919656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 0 : no boundary 920656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 1 : part boundary 921656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 2 : final boundary 922656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */ 923656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int mime_bound_check(char *line, int linelen, char *bound, int blen) 924656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{ 925656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(linelen == -1) linelen = strlen(line); 926656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(blen == -1) blen = strlen(bound); 927656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* Quickly eliminate if line length too short */ 928656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(blen + 2 > linelen) return 0; 929656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project /* Check for part boundary */ 930656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(!strncmp(line, "--", 2) && !strncmp(line + 2, bound, blen)) { 931656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if(!strncmp(line + blen + 2, "--", 2)) return 2; 932656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project else return 1; 933656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 934656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return 0; 935656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} 936656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project 937656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int strip_eol(char *linebuf, int *plen) 938656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project { 939656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project int len = *plen; 940656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project char *p, c; 941656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project int is_eol = 0; 942656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project p = linebuf + len - 1; 943656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project for (p = linebuf + len - 1; len > 0; len--, p--) 944656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project { 945656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project c = *p; 946656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project if (c == '\n') 947656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project is_eol = 1; 948656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project else if (c != '\r') 949656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project break; 950656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 951656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *plen = len; 952656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project return is_eol; 953656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project } 954