secname.c

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

C
640
字号
/* * 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 "secoid.h"#include "secder.h"	/* XXX remove this when remove the DERTemplates */#include "secasn1.h"#include "secitem.h"#include <stdarg.h>#include "secerr.h"static const SEC_ASN1Template cert_AVATemplate[] = {    { SEC_ASN1_SEQUENCE,	  0, NULL, sizeof(CERTAVA) },    { SEC_ASN1_OBJECT_ID,	  offsetof(CERTAVA,type), },    { SEC_ASN1_ANY,	  offsetof(CERTAVA,value), },    { 0, }};const SEC_ASN1Template CERT_RDNTemplate[] = {    { SEC_ASN1_SET_OF,	  offsetof(CERTRDN,avas), cert_AVATemplate, sizeof(CERTRDN) }};static intCountArray(void **array){    int count = 0;    if (array) {	while (*array++) {	    count++;	}    }    return count;}static void**AddToArray(PRArenaPool *arena, void **array, void *element){    unsigned count;    void **ap;    /* Count up number of slots already in use in the array */    count = 0;    ap = array;    if (ap) {	while (*ap++) {	    count++;	}    }    if (array) {	array = (void**) PORT_ArenaGrow(arena, array,					(count + 1) * sizeof(void *),					(count + 2) * sizeof(void *));    } else {	array = (void**) PORT_ArenaAlloc(arena, (count + 2) * sizeof(void *));    }    if (array) {	array[count] = element;	array[count+1] = 0;    }    return array;}#if 0static void**RemoveFromArray(void **array, void *element){    unsigned count;    void **ap;    int slot;    /* Look for element */    ap = array;    if (ap) {	count = 1;			/* count the null at the end */	slot = -1;	for (; *ap; ap++, count++) {	    if (*ap == element) {		/* Found it */		slot = ap - array;	    }	}	if (slot >= 0) {	    /* Found it. Squish array down */	    PORT_Memmove((void*) (array + slot), (void*) (array + slot + 1),		       (count - slot - 1) * sizeof(void*));	    /* Don't bother reallocing the memory */	}    }    return array;}#endif /* 0 */SECOidTagCERT_GetAVATag(CERTAVA *ava){    SECOidData *oid;    if (!ava->type.data) return (SECOidTag)-1;    oid = SECOID_FindOID(&ava->type);        if ( oid ) {	return(oid->offset);    }    return (SECOidTag)-1;}static SECStatusSetupAVAType(PRArenaPool *arena, SECOidTag type, SECItem *it, unsigned *maxLenp){    unsigned char *oid;    unsigned oidLen;    unsigned char *cp;    unsigned maxLen;    SECOidData *oidrec;    oidrec = SECOID_FindOIDByTag(type);    if (oidrec == NULL)	return SECFailure;    oid = oidrec->oid.data;    oidLen = oidrec->oid.len;    switch (type) {      case SEC_OID_AVA_COUNTRY_NAME:	maxLen = 2;	break;      case SEC_OID_AVA_ORGANIZATION_NAME:	maxLen = 64;	break;      case SEC_OID_AVA_COMMON_NAME:	maxLen = 64;	break;      case SEC_OID_AVA_LOCALITY:	maxLen = 128;	break;      case SEC_OID_AVA_STATE_OR_PROVINCE:	maxLen = 128;	break;      case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME:	maxLen = 64;	break;      case SEC_OID_AVA_DC:	maxLen = 128;	break;      case SEC_OID_AVA_DN_QUALIFIER:	maxLen = 0x7fff;	break;      case SEC_OID_PKCS9_EMAIL_ADDRESS:	maxLen = 128;	break;      case SEC_OID_RFC1274_UID:	maxLen = 256;  /* RFC 1274 specifies 256 */	break;      case SEC_OID_RFC1274_MAIL:	maxLen = 256;  /* RFC 1274 specifies 256 */	break;       default:	PORT_SetError(SEC_ERROR_INVALID_ARGS);	return SECFailure;    }    it->data = cp = (unsigned char*) PORT_ArenaAlloc(arena, oidLen);    if (cp == NULL) {	return SECFailure;    }    it->len = oidLen;    PORT_Memcpy(cp, oid, oidLen);    *maxLenp = maxLen;    return SECSuccess;}static SECStatusSetupAVAValue(PRArenaPool *arena, int valueType, char *value, SECItem *it,	      unsigned maxLen){    unsigned valueLen, valueLenLen, total;    unsigned ucs4Len = 0, ucs4MaxLen;    unsigned char *cp, *ucs4Val;    switch (valueType) {      case SEC_ASN1_PRINTABLE_STRING:      case SEC_ASN1_IA5_STRING:      case SEC_ASN1_T61_STRING:	valueLen = PORT_Strlen(value);	break;      case SEC_ASN1_UNIVERSAL_STRING:	valueLen = PORT_Strlen(value);	ucs4Val = (unsigned char *)PORT_ArenaZAlloc(arena, 						    PORT_Strlen(value) * 6);	ucs4MaxLen = PORT_Strlen(value) * 6;	if(!ucs4Val || !PORT_UCS4_UTF8Conversion(PR_TRUE, (unsigned char *)value, valueLen,					ucs4Val, ucs4MaxLen, &ucs4Len)) {	    PORT_SetError(SEC_ERROR_INVALID_ARGS);	    return SECFailure;	}	value = (char *)ucs4Val;	valueLen = ucs4Len;	break;      default:	PORT_SetError(SEC_ERROR_INVALID_ARGS);	return SECFailure;    }    if (((valueType != SEC_ASN1_UNIVERSAL_STRING) && (valueLen > maxLen)) ||	(valueType == SEC_ASN1_UNIVERSAL_STRING) && (valueLen > (maxLen * 4))) {	PORT_SetError(SEC_ERROR_INVALID_ARGS);	return SECFailure;    }     valueLenLen = DER_LengthLength(valueLen);    total = 1 + valueLenLen + valueLen;    it->data = cp = (unsigned char*) PORT_ArenaAlloc(arena, total);    if (!cp) {	return SECFailure;    }    it->len = total;    cp = (unsigned char*) DER_StoreHeader(cp, valueType, valueLen);    PORT_Memcpy(cp, value, valueLen);    return SECSuccess;}CERTAVA *CERT_CreateAVA(PRArenaPool *arena, SECOidTag kind, int valueType, char *value){    CERTAVA *ava;    int rv;    unsigned maxLen;    ava = (CERTAVA*) PORT_ArenaZAlloc(arena, sizeof(CERTAVA));    if (ava) {	rv = SetupAVAType(arena, kind, &ava->type, &maxLen);	if (rv) {	    /* Illegal AVA type */	    return 0;	}	rv = SetupAVAValue(arena, valueType, value, &ava->value, maxLen);	if (rv) {	    /* Illegal value type */	    return 0;	}    }    return ava;}CERTAVA *CERT_CopyAVA(PRArenaPool *arena, CERTAVA *from){    CERTAVA *ava;    int rv;    ava = (CERTAVA*) PORT_ArenaZAlloc(arena, sizeof(CERTAVA));    if (ava) {	rv = SECITEM_CopyItem(arena, &ava->type, &from->type);	if (rv) goto loser;	rv = SECITEM_CopyItem(arena, &ava->value, &from->value);	if (rv) goto loser;    }    return ava;  loser:    return 0;}/************************************************************************//* XXX This template needs to go away in favor of the new SEC_ASN1 version. */static const SEC_ASN1Template cert_RDNTemplate[] = {    { SEC_ASN1_SET_OF,	  offsetof(CERTRDN,avas), cert_AVATemplate, sizeof(CERTRDN) }};CERTRDN *CERT_CreateRDN(PRArenaPool *arena, CERTAVA *ava0, ...){    CERTAVA *ava;    CERTRDN *rdn;    va_list ap;    unsigned count;    CERTAVA **avap;    rdn = (CERTRDN*) PORT_ArenaAlloc(arena, sizeof(CERTRDN));    if (rdn) {	/* Count number of avas going into the rdn */	count = 1;	va_start(ap, ava0);	while ((ava = va_arg(ap, CERTAVA*)) != 0) {	    count++;	}	va_end(ap);	/* Now fill in the pointers */	rdn->avas = avap =	    (CERTAVA**) PORT_ArenaAlloc( arena, (count + 1)*sizeof(CERTAVA*));	if (!avap) {	    return 0;	}	*avap++ = ava0;	va_start(ap, ava0);	while ((ava = va_arg(ap, CERTAVA*)) != 0) {	    *avap++ = ava;	}	va_end(ap);	*avap++ = 0;    }    return rdn;}SECStatusCERT_AddAVA(PRArenaPool *arena, CERTRDN *rdn, CERTAVA *ava){    rdn->avas = (CERTAVA**) AddToArray(arena, (void**) rdn->avas, ava);    return rdn->avas ? SECSuccess : SECFailure;}SECStatusCERT_CopyRDN(PRArenaPool *arena, CERTRDN *to, CERTRDN *from){    CERTAVA **avas, *fava, *tava;    SECStatus rv;    /* Copy each ava from from */    avas = from->avas;    while ((fava = *avas++) != 0) {	tava = CERT_CopyAVA(arena, fava);	if (!tava) return SECFailure;	rv = CERT_AddAVA(arena, to, tava);	if (rv) return rv;    }    return SECSuccess;}/************************************************************************/const SEC_ASN1Template CERT_NameTemplate[] = {    { SEC_ASN1_SEQUENCE_OF,	  offsetof(CERTName,rdns), CERT_RDNTemplate, sizeof(CERTName) }};CERTName *CERT_CreateName(CERTRDN *rdn0, ...){    CERTRDN *rdn;    CERTName *name;    va_list ap;    unsigned count;    CERTRDN **rdnp;    PRArenaPool *arena;        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);    if ( !arena ) {	return(0);    }        name = (CERTName*) PORT_ArenaAlloc(arena, sizeof(CERTName));    if (name) {	name->arena = arena;		/* Count number of RDNs going into the Name */	if (!rdn0) {	    count = 0;	} else {	    count = 1;	    va_start(ap, rdn0);	    while ((rdn = va_arg(ap, CERTRDN*)) != 0) {		count++;	    }	    va_end(ap);	}	/* Allocate space (including space for terminal null ptr) */	name->rdns = rdnp =	    (CERTRDN**) PORT_ArenaAlloc(arena, (count + 1) * sizeof(CERTRDN*));	if (!name->rdns) {	    goto loser;	}	/* Now fill in the pointers */	if (count > 0) {	    *rdnp++ = rdn0;	    va_start(ap, rdn0);	    while ((rdn = va_arg(ap, CERTRDN*)) != 0) {		*rdnp++ = rdn;	    }	    va_end(ap);	}	/* null terminate the list */	*rdnp++ = 0;    }    return name;loser:    PORT_FreeArena(arena, PR_FALSE);    return(0);}voidCERT_DestroyName(CERTName *name){    if (name)    {        PRArenaPool *arena = name->arena;        name->rdns = NULL;	name->arena = NULL;	if (arena) PORT_FreeArena(arena, PR_FALSE);    }}SECStatusCERT_AddRDN(CERTName *name, CERTRDN *rdn){    name->rdns = (CERTRDN**) AddToArray(name->arena, (void**) name->rdns, rdn);    return name->rdns ? SECSuccess : SECFailure;}SECStatusCERT_CopyName(PRArenaPool *arena, CERTName *to, CERTName *from){    CERTRDN **rdns, *frdn, *trdn;    SECStatus rv;    CERT_DestroyName(to);    to->arena = arena;    /* Copy each rdn from from */    rdns = from->rdns;    while ((frdn = *rdns++) != 0) {	trdn = CERT_CreateRDN(arena, 0);	if ( trdn == NULL ) {	    return(SECFailure);	}	rv = CERT_CopyRDN(arena, trdn, frdn);	if (rv) return rv;	rv = CERT_AddRDN(to, trdn);	if (rv) return rv;    }    return SECSuccess;}/************************************************************************/SECComparisonCERT_CompareAVA(CERTAVA *a, CERTAVA *b){    SECComparison rv;    rv = SECITEM_CompareItem(&a->type, &b->type);    if (rv) {	/*	** XXX for now we are going to just assume that a bitwise	** comparison of the value codes will do the trick.	*/    }    rv = SECITEM_CompareItem(&a->value, &b->value);    return rv;}SECComparisonCERT_CompareRDN(CERTRDN *a, CERTRDN *b){    CERTAVA **aavas, *aava;    CERTAVA **bavas, *bava;    int ac, bc;    SECComparison rv = SECEqual;    aavas = a->avas;    bavas = b->avas;    /*    ** Make sure array of ava's are the same length. If not, then we are    ** not equal    */    ac = CountArray((void**) aavas);    bc = CountArray((void**) bavas);    if (ac < bc) return SECLessThan;    if (ac > bc) return SECGreaterThan;    for (;;) {	aava = *aavas++;	bava = *bavas++;	if (!aava) {	    break;	}	rv = CERT_CompareAVA(aava, bava);	if (rv) return rv;    }    return rv;}SECComparisonCERT_CompareName(CERTName *a, CERTName *b){    CERTRDN **ardns, *ardn;    CERTRDN **brdns, *brdn;    int ac, bc;    SECComparison rv = SECEqual;    ardns = a->rdns;    brdns = b->rdns;    /*    ** Make sure array of rdn's are the same length. If not, then we are    ** not equal    */    ac = CountArray((void**) ardns);    bc = CountArray((void**) brdns);    if (ac < bc) return SECLessThan;    if (ac > bc) return SECGreaterThan;    for (;;) {	ardn = *ardns++;	brdn = *brdns++;	if (!ardn) {	    break;	}	rv = CERT_CompareRDN(ardn, brdn);	if (rv) return rv;    }    return rv;}/* Moved from certhtml.c */SECItem *CERT_DecodeAVAValue(SECItem *derAVAValue){          SECItem          *retItem;     const SEC_ASN1Template *theTemplate       = NULL;          PRBool            convertUCS4toUTF8 = PR_FALSE;          PRBool            convertUCS2toUTF8 = PR_FALSE;          SECItem           avaValue          = {siBuffer, 0};     if(!derAVAValue) {	return NULL;    }    switch(derAVAValue->data[0]) {	case SEC_ASN1_UNIVERSAL_STRING:	    convertUCS4toUTF8 = PR_TRUE;	    theTemplate = SEC_UniversalStringTemplate;	    break;	case SEC_ASN1_IA5_STRING:	    theTemplate = SEC_IA5StringTemplate;	    break;	case SEC_ASN1_PRINTABLE_STRING:	    theTemplate = SEC_PrintableStringTemplate;	    break;	case SEC_ASN1_T61_STRING:	    theTemplate = SEC_T61StringTemplate;	    break;	case SEC_ASN1_BMP_STRING:	    convertUCS2toUTF8 = PR_TRUE;	    theTemplate = SEC_BMPStringTemplate;	    break;	case SEC_ASN1_UTF8_STRING:	    /* No conversion needed ! */	    theTemplate = SEC_UTF8StringTemplate;	    break;	default:	    return NULL;    }    PORT_Memset(&avaValue, 0, sizeof(SECItem));    if(SEC_ASN1DecodeItem(NULL, &avaValue, theTemplate, derAVAValue) 				!= SECSuccess) {	return NULL;    }    if (convertUCS4toUTF8) {	unsigned int   utf8ValLen = avaValue.len * 3;	unsigned char *utf8Val    = (unsigned char*)PORT_ZAlloc(utf8ValLen);	if(!PORT_UCS4_UTF8Conversion(PR_FALSE, avaValue.data, avaValue.len,				     utf8Val, utf8ValLen, &utf8ValLen)) {	    PORT_Free(utf8Val);	    PORT_Free(avaValue.data);	    return NULL;	}	PORT_Free(avaValue.data);	avaValue.data = utf8Val;	avaValue.len = utf8ValLen;    } else if (convertUCS2toUTF8) {	unsigned int   utf8ValLen = avaValue.len * 3;	unsigned char *utf8Val    = (unsigned char*)PORT_ZAlloc(utf8ValLen);	if(!PORT_UCS2_UTF8Conversion(PR_FALSE, avaValue.data, avaValue.len,				     utf8Val, utf8ValLen, &utf8ValLen)) {	    PORT_Free(utf8Val);	    PORT_Free(avaValue.data);	    return NULL;	}	PORT_Free(avaValue.data);	avaValue.data = utf8Val;	avaValue.len = utf8ValLen;    }    retItem = SECITEM_DupItem(&avaValue);    PORT_Free(avaValue.data);    return retItem;}

⌨️ 快捷键说明

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