Fix indefinite length encoding so EOC correctly updates
[openssl.git] / crypto / pkcs7 / pk7_mime.c
index 0ba7d77462ab56417cd6e9a8c7c6cec07ef19d39..431aff94f0b0173870bab38ccb5fce6ac88b350e 100644 (file)
@@ -1,9 +1,9 @@
 /* pk7_mime.c */
 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
- * project 1999.
+ * project.
  */
 /* ====================================================================
- * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2003 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -75,37 +75,6 @@ char *param_value;                   /* Param value e.g. "sha1" */
 } MIME_PARAM;
 
 DECLARE_STACK_OF(MIME_PARAM)
-/* This block of defines is updated by a perl script, please do not touch! */
-#ifndef DEBUG_SAFESTACK
-       #define sk_MIME_PARAM_new(a) sk_new((int (*) \
-               (const char * const *, const char * const *))(a))
-       #define sk_MIME_PARAM_new_null() sk_new_null()
-       #define sk_MIME_PARAM_free(a) sk_free(a)
-       #define sk_MIME_PARAM_num(a) sk_num(a)
-       #define sk_MIME_PARAM_value(a,b) ((MIME_PARAM *) \
-               sk_value((a),(b)))
-       #define sk_MIME_PARAM_set(a,b,c) ((MIME_PARAM *) \
-               sk_set((a),(b),(char *)(c)))
-       #define sk_MIME_PARAM_zero(a) sk_zero(a)
-       #define sk_MIME_PARAM_push(a,b) sk_push((a),(char *)(b))
-       #define sk_MIME_PARAM_unshift(a,b) sk_unshift((a),(b))
-       #define sk_MIME_PARAM_find(a,b) sk_find((a), (char *)(b))
-       #define sk_MIME_PARAM_delete(a,b) ((MIME_PARAM *) \
-               sk_delete((a),(b)))
-       #define sk_MIME_PARAM_delete_ptr(a,b) ((MIME_PARAM *) \
-               sk_delete_ptr((a),(char *)(b)))
-       #define sk_MIME_PARAM_insert(a,b,c) sk_insert((a),(char *)(b),(c))
-       #define sk_MIME_PARAM_set_cmp_func(a,b) ((int (*) \
-               (const MIME_PARAM * const *,const MIME_PARAM * const *)) \
-               sk_set_cmp_func((a),(int (*) \
-               (const char * const *, const char * const *))(b)))
-       #define sk_MIME_PARAM_dup(a) sk_dup(a)
-       #define sk_MIME_PARAM_pop_free(a,b) sk_pop_free((a),(void (*)(void *))(b))
-       #define sk_MIME_PARAM_shift(a) ((MIME_PARAM *)sk_shift(a))
-       #define sk_MIME_PARAM_pop(a) ((MIME_PARAM *)sk_pop(a))
-       #define sk_MIME_PARAM_sort(a) sk_sort(a)
-#endif /* !DEBUG_SAFESTACK */
-/* End of perl script block, you may now edit :-) */
 IMPLEMENT_STACK_OF(MIME_PARAM)
 
 typedef struct {
@@ -115,39 +84,9 @@ STACK_OF(MIME_PARAM) *params;               /* Zero or more parameters */
 } MIME_HEADER;
 
 DECLARE_STACK_OF(MIME_HEADER)
-/* This block of defines is updated by a perl script, please do not touch! */
-#ifndef DEBUG_SAFESTACK
-       #define sk_MIME_HEADER_new(a) sk_new((int (*) \
-               (const char * const *, const char * const *))(a))
-       #define sk_MIME_HEADER_new_null() sk_new_null()
-       #define sk_MIME_HEADER_free(a) sk_free(a)
-       #define sk_MIME_HEADER_num(a) sk_num(a)
-       #define sk_MIME_HEADER_value(a,b) ((MIME_HEADER *) \
-               sk_value((a),(b)))
-       #define sk_MIME_HEADER_set(a,b,c) ((MIME_HEADER *) \
-               sk_set((a),(b),(char *)(c)))
-       #define sk_MIME_HEADER_zero(a) sk_zero(a)
-       #define sk_MIME_HEADER_push(a,b) sk_push((a),(char *)(b))
-       #define sk_MIME_HEADER_unshift(a,b) sk_unshift((a),(b))
-       #define sk_MIME_HEADER_find(a,b) sk_find((a), (char *)(b))
-       #define sk_MIME_HEADER_delete(a,b) ((MIME_HEADER *) \
-               sk_delete((a),(b)))
-       #define sk_MIME_HEADER_delete_ptr(a,b) ((MIME_HEADER *) \
-               sk_delete_ptr((a),(char *)(b)))
-       #define sk_MIME_HEADER_insert(a,b,c) sk_insert((a),(char *)(b),(c))
-       #define sk_MIME_HEADER_set_cmp_func(a,b) ((int (*) \
-               (const MIME_HEADER * const *,const MIME_HEADER * const *)) \
-               sk_set_cmp_func((a),(int (*) \
-               (const char * const *, const char * const *))(b)))
-       #define sk_MIME_HEADER_dup(a) sk_dup(a)
-       #define sk_MIME_HEADER_pop_free(a,b) sk_pop_free((a),(void (*)(void *))(b))
-       #define sk_MIME_HEADER_shift(a) ((MIME_HEADER *)sk_shift(a))
-       #define sk_MIME_HEADER_pop(a) ((MIME_HEADER *)sk_pop(a))
-       #define sk_MIME_HEADER_sort(a) sk_sort(a)
-#endif /* !DEBUG_SAFESTACK */
-/* End of perl script block, you may now edit :-) */
 IMPLEMENT_STACK_OF(MIME_HEADER)
 
+static int pkcs7_output_data(BIO *bio, BIO *data, PKCS7 *p7, int flags);
 static int B64_write_PKCS7(BIO *bio, PKCS7 *p7);
 static PKCS7 *B64_read_PKCS7(BIO *bio);
 static char * strip_ends(char *name);
@@ -212,7 +151,6 @@ static PKCS7 *B64_read_PKCS7(BIO *bio)
 
 int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags)
 {
-       char linebuf[MAX_SMLEN];
        char bound[33], c;
        int i;
        if((flags & PKCS7_DETACHED) && data) {
@@ -227,15 +165,15 @@ int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags)
                }
                bound[32] = 0;
                BIO_printf(bio, "MIME-Version: 1.0\n");
-               BIO_printf(bio, "Content-Type: multipart/signed ; ");
-               BIO_printf(bio, "protocol=\"application/x-pkcs7-signature\" ; ");
-               BIO_printf(bio, "micalg=sha1 ; boundary=\"----%s\"\n\n", bound);
+               BIO_printf(bio, "Content-Type: multipart/signed;");
+               BIO_printf(bio, " protocol=\"application/x-pkcs7-signature\";");
+               BIO_printf(bio, " micalg=sha1; boundary=\"----%s\"\n\n", bound);
                BIO_printf(bio, "This is an S/MIME signed message\n\n");
                /* Now write out the first part */
                BIO_printf(bio, "------%s\r\n", bound);
-               if(flags & PKCS7_TEXT) BIO_printf(bio, "Content-Type: text/plain\n\n");
-               while((i = BIO_read(data, linebuf, MAX_SMLEN)) > 0) 
-                                               BIO_write(bio, linebuf, i);
+
+               pkcs7_output_data(bio, data, p7, flags);
+
                BIO_printf(bio, "\n------%s\n", bound);
 
                /* Headers for signature */
@@ -257,6 +195,47 @@ int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags)
        return 1;
 }
 
+/* Handle output of PKCS#7 data */
+
+
+static int pkcs7_output_data(BIO *out, BIO *data, PKCS7 *p7, int flags)
+       {
+       BIO *tmpbio, *p7bio;
+
+       if (!(flags & PKCS7_STREAM))
+               {
+               SMIME_crlf_copy(data, out, flags);
+               return 1;
+               }
+
+       /* Partial sign operation */
+
+       /* Initialize sign operation */
+       p7bio = PKCS7_dataInit(p7, out);
+
+       /* Copy data across, computing digests etc */
+       SMIME_crlf_copy(data, p7bio, flags);
+
+       /* Must be detached */
+       PKCS7_set_detached(p7, 1);
+
+       /* Finalize signatures */
+       PKCS7_dataFinal(p7, p7bio);
+
+       /* Now remove any digests from output BIO */
+
+       while (1)
+               {
+               tmpbio = BIO_pop(p7bio);
+               if (tmpbio == out)
+                       break;
+               BIO_free(tmpbio);
+               }
+
+       return 1;
+
+       }
+
 /* SMIME reader: handle multipart/signed and opaque signing.
  * in multipart case the content is placed in a memory BIO
  * pointed to by "bcont". In opaque this is set to NULL
@@ -376,7 +355,8 @@ int SMIME_crlf_copy(BIO *in, BIO *out, int flags)
                                                BIO_write(out, linebuf, len);
                return 1;
        }
-       if(flags & PKCS7_TEXT) BIO_printf(out, "Content-Type: text/plain\r\n\r\n");
+       if(flags & PKCS7_TEXT)
+               BIO_printf(out, "Content-Type: text/plain\r\n\r\n");
        while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0) {
                eol = 0;
                while(iscrlf(linebuf[len - 1])) {
@@ -434,7 +414,7 @@ static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret)
        part = 0;
        state = 0;
        first = 1;
-       parts = sk_BIO_new(NULL);
+       parts = sk_BIO_new_null();
        *ret = parts;
        while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) {
                state = mime_bound_check(linebuf, len, bound, blen);
@@ -641,7 +621,7 @@ static MIME_HEADER *mime_hdr_new(char *name, char *value)
                        }
                }
        } else tmpval = NULL;
-       mhdr = (MIME_HEADER *) Malloc(sizeof(MIME_HEADER));
+       mhdr = (MIME_HEADER *) OPENSSL_malloc(sizeof(MIME_HEADER));
        if(!mhdr) return NULL;
        mhdr->name = tmpname;
        mhdr->value = tmpval;
@@ -670,7 +650,7 @@ static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value)
                if(!tmpval) return 0;
        } else tmpval = NULL;
        /* Parameter values are case sensitive so leave as is */
-       mparam = (MIME_PARAM *) Malloc(sizeof(MIME_PARAM));
+       mparam = (MIME_PARAM *) OPENSSL_malloc(sizeof(MIME_PARAM));
        if(!mparam) return 0;
        mparam->param_name = tmpname;
        mparam->param_value = tmpval;
@@ -714,17 +694,17 @@ static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name)
 
 static void mime_hdr_free(MIME_HEADER *hdr)
 {
-       if(hdr->name) Free(hdr->name);
-       if(hdr->value) Free(hdr->value);
+       if(hdr->name) OPENSSL_free(hdr->name);
+       if(hdr->value) OPENSSL_free(hdr->value);
        if(hdr->params) sk_MIME_PARAM_pop_free(hdr->params, mime_param_free);
-       Free(hdr);
+       OPENSSL_free(hdr);
 }
 
 static void mime_param_free(MIME_PARAM *param)
 {
-       if(param->param_name) Free(param->param_name);
-       if(param->param_value) Free(param->param_value);
-       Free(param);
+       if(param->param_name) OPENSSL_free(param->param_name);
+       if(param->param_value) OPENSSL_free(param->param_value);
+       OPENSSL_free(param);
 }
 
 /* Check for a multipart boundary. Returns: