pk7_mime.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/* pk7_mime.c */
/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
* project 1999.
*/
/* ====================================================================
* 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
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#include <stdio.h>
#include <ctype.h>
#include "cryptlib.h"
/* MIME and related routines */
/* MIME format structures
* Note that all are translated to lower case apart from
* parameter values. Quotes are stripped off
*/
typedef struct {
char *param_name; /* Param name e.g. "micalg" */
char *param_value; /* Param value e.g. "sha1" */
} MIME_PARAM;
typedef struct {
char *name; /* Name of line e.g. "content-type" */
} MIME_HEADER;
static char * strip_ends(char *name);
static char * strip_start(char *name);
static int mime_hdr_cmp(const MIME_HEADER * const *a,
const MIME_HEADER * const *b);
static int mime_param_cmp(const MIME_PARAM * const *a,
const MIME_PARAM * const *b);
#define MAX_SMLEN 1024
#define mime_debug(x) /* x */
typedef void (*stkfree)();
/* Base 64 read and write of PKCS#7 structure */
{
return 0;
}
return 1;
}
{
return 0;
}
return p7;
}
/* SMIME sender */
{
char bound[33], c;
int i;
char *mime_prefix, *mime_eol;
if (flags & PKCS7_NOOLDMIMETYPE)
mime_prefix = "application/pkcs7-";
else
mime_prefix = "application/x-pkcs7-";
if (flags & PKCS7_CRLFEOL)
mime_eol = "\r\n";
else
mime_eol = "\n";
/* Generate a random boundary */
for(i = 0; i < 32; i++) {
c = bound[i] & 0xf;
if(c < 10) c += '0';
else c += 'A' - 10;
bound[i] = c;
}
bound[32] = 0;
/* Now write out the first part */
/* Headers for signature */
mime_eol);
return 1;
}
/* MIME headers */
return 1;
}
* in multipart case the content is placed in a memory BIO
* pointed to by "bcont". In opaque this is set to NULL
*/
{
int ret;
return NULL;
}
return NULL;
}
/* Split into two parts */
return NULL;
}
return NULL;
}
/* Parse the signature piece */
return NULL;
}
/* Get content type */
return NULL;
}
return NULL;
}
/* Read in PKCS#7 */
return NULL;
}
if(bcont) {
return p7;
}
return NULL;
}
return NULL;
}
return p7;
}
/* Copy text from one BIO to another making the output CRLF at EOL */
{
char eol;
int len;
if(flags & PKCS7_BINARY) {
return 1;
}
if (len)
}
return 1;
}
{
char iobuf[4096];
int len;
return 0;
}
return 0;
}
return 0;
}
return 1;
}
* canonical parts in a STACK of bios
*/
{
part = 0;
state = 0;
first = 1;
parts = sk_BIO_new_null();
if(state == 1) {
first = 1;
part++;
} else if(state == 2) {
return 1;
} else if(part) {
/* Strip CR+LF from linebuf */
if(first) {
first = 0;
} else if (eol)
if (len)
}
}
return 0;
}
/* This is the big one: parse MIME header lines up to message body */
#define MIME_INVALID 0
#define MIME_START 1
#define MIME_TYPE 2
#define MIME_NAME 3
#define MIME_VALUE 4
#define MIME_QUOTE 5
#define MIME_COMMENT 6
{
char *p, *q, c;
char *ntmp;
/* If whitespace at line start then continuation line */
else state = MIME_START;
/* Go through all characters */
/* State machine to handle MIME headers
* if this looks horrible that's because it *is*
*/
switch(state) {
case MIME_START:
if(c == ':') {
*p = 0;
ntmp = strip_ends(q);
q = p + 1;
}
break;
case MIME_TYPE:
if(c == ';') {
mime_debug("Found End Value\n");
*p = 0;
q = p + 1;
} else if(c == '(') {
save_state = state;
}
break;
case MIME_COMMENT:
if(c == ')') {
state = save_state;
}
break;
case MIME_NAME:
if(c == '=') {
state = MIME_VALUE;
*p = 0;
ntmp = strip_ends(q);
q = p + 1;
}
break ;
case MIME_VALUE:
if(c == ';') {
*p = 0;
q = p + 1;
} else if (c == '"') {
mime_debug("Found Quote\n");
state = MIME_QUOTE;
} else if(c == '(') {
save_state = state;
}
break;
case MIME_QUOTE:
if(c == '"') {
mime_debug("Found Match Quote\n");
state = MIME_VALUE;
}
break;
}
}
} else if(state == MIME_VALUE)
if(p == linebuf) break; /* Blank line means end of headers */
}
return headers;
}
static char *strip_ends(char *name)
{
}
/* Strip a parameter of whitespace from start of param */
static char *strip_start(char *name)
{
char *p, c;
/* Look for first non white space or quote */
for(p = name; (c = *p) ;p++) {
if(c == '"') {
/* Next char is start of string if non null */
if(p[1]) return p + 1;
/* Else null string */
return NULL;
}
if(!isspace((unsigned char)c)) return p;
}
return NULL;
}
/* As above but strip from end of string : maybe should handle brackets? */
{
char *p, c;
/* Look for first non white space or quote */
c = *p;
if(c == '"') {
*p = 0;
return name;
}
if(isspace((unsigned char)c)) *p = 0;
else return name;
}
return NULL;
}
{
int c;
if(name) {
for(p = tmpname ; *p; p++) {
c = *p;
if(isupper(c)) {
c = tolower(c);
*p = c;
}
}
if(value) {
for(p = tmpval ; *p; p++) {
c = *p;
if(isupper(c)) {
c = tolower(c);
*p = c;
}
}
return mhdr;
}
{
int c;
if(name) {
if(!tmpname) return 0;
for(p = tmpname ; *p; p++) {
c = *p;
if(isupper(c)) {
c = tolower(c);
*p = c;
}
}
if(value) {
if(!tmpval) return 0;
/* Parameter values are case sensitive so leave as is */
if(!mparam) return 0;
return 1;
}
static int mime_hdr_cmp(const MIME_HEADER * const *a,
const MIME_HEADER * const *b)
{
}
static int mime_param_cmp(const MIME_PARAM * const *a,
const MIME_PARAM * const *b)
{
}
/* Find a header with a given name (if possible) */
{
int idx;
}
{
int idx;
}
{
}
{
}
/* Check for a multipart boundary. Returns:
* 0 : no boundary
* 1 : part boundary
* 2 : final boundary
*/
{
/* Quickly eliminate if line length too short */
/* Check for part boundary */
else return 1;
}
return 0;
}
{
char *p, c;
int is_eol = 0;
{
c = *p;
if (c == '\n')
is_eol = 1;
else if (c != '\r')
break;
}
return is_eol;
}