alg1485.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 971 行 · 第 1/2 页

C
971
字号
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is the Netscape security libraries. *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.  If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. */#include "cert.h"#include "xconst.h"#include "genname.h"#include "secitem.h"#include "secerr.h"struct NameToKind {    char *name;    SECOidTag kind;};static struct NameToKind name2kinds[] = {    { "CN",   		SEC_OID_AVA_COMMON_NAME, 		},    { "ST",   		SEC_OID_AVA_STATE_OR_PROVINCE, 		},    { "OU",   		SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME,	},    { "DC",   		SEC_OID_AVA_DC,	},    { "C",    		SEC_OID_AVA_COUNTRY_NAME, 		},    { "O",    		SEC_OID_AVA_ORGANIZATION_NAME, 		},    { "L",    		SEC_OID_AVA_LOCALITY, 			},    { "dnQualifier",	SEC_OID_AVA_DN_QUALIFIER, 		},    { "E",    		SEC_OID_PKCS9_EMAIL_ADDRESS, 		},    { "UID",  		SEC_OID_RFC1274_UID, 			},    { "MAIL", 		SEC_OID_RFC1274_MAIL, 			},    { 0,      		SEC_OID_UNKNOWN 			},};#define C_DOUBLE_QUOTE '\042'#define C_BACKSLASH '\134'#define C_EQUAL '='#define OPTIONAL_SPACE(c) \    (((c) == ' ') || ((c) == '\r') || ((c) == '\n'))#define SPECIAL_CHAR(c)						\    (((c) == ',') || ((c) == '=') || ((c) == C_DOUBLE_QUOTE) ||	\     ((c) == '\r') || ((c) == '\n') || ((c) == '+') ||		\     ((c) == '<') || ((c) == '>') || ((c) == '#') ||		\     ((c) == ';') || ((c) == C_BACKSLASH))#if 0/*** Find the start and end of a <string>. Strings can be wrapped in double** quotes to protect special characters.*/static int BracketThing(char **startp, char *end, char *result){    char *start = *startp;    char c;    /* Skip leading white space */    while (start < end) {	c = *start++;	if (!OPTIONAL_SPACE(c)) {	    start--;	    break;	}    }    if (start == end) return 0;    switch (*start) {      case '#':	/* Process hex thing */	start++;	*startp = start;	while (start < end) {	    c = *start++;	    if (((c >= '0') && (c <= '9')) ||		((c >= 'a') && (c <= 'f')) ||		((c >= 'A') && (c <= 'F'))) {		continue;	    }	    break;	}	rv = IS_HEX;	break;      case C_DOUBLE_QUOTE:	start++;	*startp = start;	while (start < end) {	    c = *start++;	    if (c == C_DOUBLE_QUOTE) {		break;	    }	    *result++ = c;	}	rv = IS_STRING;	break;      default:	while (start < end) {	    c = *start++;	    if (SPECIAL_CHAR(c)) {		start--;		break;	    }	    *result++ = c;	}	rv = IS_STRING;	break;    }    /* Terminate result string */    *result = 0;    return start;}static char *BracketSomething(char **startp, char* end, int spacesOK){    char *start = *startp;    char c;    int stopAtDQ;    /* Skip leading white space */    while (start < end) {	c = *start;	if (!OPTIONAL_SPACE(c)) {	    break;	}	start++;    }    if (start == end) return 0;    stopAtDQ = 0;    if (*start == C_DOUBLE_QUOTE) {	stopAtDQ = 1;    }    /*    ** Find the end of the something. The something is terminated most of    ** the time by a space. However, if spacesOK is true then it is    ** terminated by a special character only.    */    *startp = start;    while (start < end) {	c = *start;	if (stopAtDQ) {	    if (c == C_DOUBLE_QUOTE) {		*start = ' ';		break;	    }	} else {	if (SPECIAL_CHAR(c)) {	    break;	}	if (!spacesOK && OPTIONAL_SPACE(c)) {	    break;	}	}	start++;    }    return start;}#endif#define IS_PRINTABLE(c)						\    ((((c) >= 'a') && ((c) <= 'z')) ||				\     (((c) >= 'A') && ((c) <= 'Z')) ||				\     (((c) >= '0') && ((c) <= '9')) ||				\     ((c) == ' ') ||						\     ((c) == '\'') ||						\     ((c) == '\050') ||				/* ( */		\     ((c) == '\051') ||				/* ) */		\     (((c) >= '+') && ((c) <= '/')) ||		/* + , - . / */	\     ((c) == ':') ||						\     ((c) == '=') ||						\     ((c) == '?'))static PRBoolIsPrintable(unsigned char *data, unsigned len){    unsigned char ch, *end;    end = data + len;    while (data < end) {	ch = *data++;	if (!IS_PRINTABLE(ch)) {	    return PR_FALSE;	}    }    return PR_TRUE;}static PRBoolIs7Bit(unsigned char *data, unsigned len){    unsigned char ch, *end;    end = data + len;    while (data < end) {        ch = *data++;        if ((ch & 0x80)) {            return PR_FALSE;        }    }    return PR_TRUE;}static voidskipSpace(char **pbp, char *endptr){    char *bp = *pbp;    while (bp < endptr && OPTIONAL_SPACE(*bp)) {	bp++;    }    *pbp = bp;}static SECStatusscanTag(char **pbp, char *endptr, char *tagBuf, int tagBufSize){    char *bp, *tagBufp;    int taglen;    PORT_Assert(tagBufSize > 0);        /* skip optional leading space */    skipSpace(pbp, endptr);    if (*pbp == endptr) {	/* nothing left */	return SECFailure;    }        /* fill tagBuf */    taglen = 0;    bp = *pbp;    tagBufp = tagBuf;    while (bp < endptr && !OPTIONAL_SPACE(*bp) && (*bp != C_EQUAL)) {	if (++taglen >= tagBufSize) {	    *pbp = bp;	    return SECFailure;	}	*tagBufp++ = *bp++;    }    /* null-terminate tagBuf -- guaranteed at least one space left */    *tagBufp++ = 0;    *pbp = bp;        /* skip trailing spaces till we hit something - should be an equal sign */    skipSpace(pbp, endptr);    if (*pbp == endptr) {	/* nothing left */	return SECFailure;    }    if (**pbp != C_EQUAL) {	/* should be an equal sign */	return SECFailure;    }    /* skip over the equal sign */    (*pbp)++;        return SECSuccess;}static SECStatusscanVal(char **pbp, char *endptr, char *valBuf, int valBufSize)  {    char *bp, *valBufp;    int vallen;    PRBool isQuoted;        PORT_Assert(valBufSize > 0);        /* skip optional leading space */    skipSpace(pbp, endptr);    if(*pbp == endptr) {	/* nothing left */	return SECFailure;    }        bp = *pbp;        /* quoted? */    if (*bp == C_DOUBLE_QUOTE) {	isQuoted = PR_TRUE;	/* skip over it */	bp++;    } else {	isQuoted = PR_FALSE;    }        valBufp = valBuf;    vallen = 0;    while (bp < endptr) {	char c = *bp;	if (c == C_BACKSLASH) {	    /* escape character */	    bp++;	    if (bp >= endptr) {		/* escape charater must appear with paired char */		*pbp = bp;		return SECFailure;	    }	} else if (!isQuoted && SPECIAL_CHAR(c)) {	    /* unescaped special and not within quoted value */	    break;	} else if (c == C_DOUBLE_QUOTE) {	    /* reached unescaped double quote */	    break;	}	/* append character */        vallen++;	if (vallen >= valBufSize) {	    *pbp = bp;	    return SECFailure;	}	*valBufp++ = *bp++;    }        /* stip trailing spaces from unquoted values */    if (!isQuoted) {	if (valBufp > valBuf) {	    valBufp--;	    while ((valBufp > valBuf) && OPTIONAL_SPACE(*valBufp)) {		valBufp--;	    }	    valBufp++;	}    }        if (isQuoted) {	/* insist that we stopped on a double quote */	if (*bp != C_DOUBLE_QUOTE) {	    *pbp = bp;	    return SECFailure;	}	/* skip over the quote and skip optional space */	bp++;	skipSpace(&bp, endptr);    }        *pbp = bp;        if (valBufp == valBuf) {	/* empty value -- not allowed */	return SECFailure;    }        /* null-terminate valBuf -- guaranteed at least one space left */    *valBufp++ = 0;        return SECSuccess;}CERTAVA *CERT_ParseRFC1485AVA(PRArenaPool *arena, char **pbp, char *endptr,		    PRBool singleAVA) {    CERTAVA *a;    struct NameToKind *n2k;    int vt;    int valLen;    char *bp;    char tagBuf[32];    char valBuf[384];    if (scanTag(pbp, endptr, tagBuf, sizeof(tagBuf)) == SECFailure ||	scanVal(pbp, endptr, valBuf, sizeof(valBuf)) == SECFailure) {	PORT_SetError(SEC_ERROR_INVALID_AVA);	return 0;    }    /* insist that if we haven't finished we've stopped on a separator */    bp = *pbp;    if (bp < endptr) {	if (singleAVA || (*bp != ',' && *bp != ';')) {	    PORT_SetError(SEC_ERROR_INVALID_AVA);	    *pbp = bp;	    return 0;	}	/* ok, skip over separator */	bp++;    }    *pbp = bp;    for (n2k = name2kinds; n2k->name; n2k++) {	if (PORT_Strcasecmp(n2k->name, tagBuf) == 0) {	    valLen = PORT_Strlen(valBuf);	    if (n2k->kind == SEC_OID_AVA_COUNTRY_NAME) {		vt = SEC_ASN1_PRINTABLE_STRING;		if (valLen != 2) {		    PORT_SetError(SEC_ERROR_INVALID_AVA);		    return 0;		}		if (!IsPrintable((unsigned char*) valBuf, 2)) {		    PORT_SetError(SEC_ERROR_INVALID_AVA);		    return 0;		}	    } else if ((n2k->kind == SEC_OID_PKCS9_EMAIL_ADDRESS) ||		       (n2k->kind == SEC_OID_RFC1274_MAIL)) {		vt = SEC_ASN1_IA5_STRING;	    } else {		/* Hack -- for rationale see X.520 DirectoryString defn */		if (IsPrintable((unsigned char*)valBuf, valLen)) {		    vt = SEC_ASN1_PRINTABLE_STRING;                } else if (Is7Bit((unsigned char *)valBuf, valLen)) {                    vt = SEC_ASN1_T61_STRING;		} else {		    vt = SEC_ASN1_UNIVERSAL_STRING;		}	    }	    a = CERT_CreateAVA(arena, n2k->kind, vt, (char *) valBuf);	    return a;	}    }    /* matched no kind -- invalid tag */    PORT_SetError(SEC_ERROR_INVALID_AVA);    return 0;}static CERTName *ParseRFC1485Name(char *buf, int len){    SECStatus rv;    CERTName *name;    char *bp, *e;    CERTAVA *ava;    CERTRDN *rdn;    name = CERT_CreateName(NULL);    if (name == NULL) {	return NULL;    }        e = buf + len;    bp = buf;    while (bp < e) {	ava = CERT_ParseRFC1485AVA(name->arena, &bp, e, PR_FALSE);	if (ava == 0) goto loser;	rdn = CERT_CreateRDN(name->arena, ava, 0);	if (rdn == 0) goto loser;	rv = CERT_AddRDN(name, rdn);	if (rv) goto loser;	skipSpace(&bp, e);    }    if (name->rdns[0] == 0) {	/* empty name -- illegal */	goto loser;    }    /* Reverse order of RDNS to comply with RFC */    {	CERTRDN **firstRdn;	CERTRDN **lastRdn;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?