pcertdb.c

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

C
2,743
字号
    /* copy the options date */    if ( optionsDate ) {	rv = SECITEM_CopyItem(arena, &entry->optionsDate, optionsDate);	if ( rv != SECSuccess ) {	    goto loser;	}    } else {	PORT_Assert(smimeOptions == NULL);	entry->optionsDate.data = NULL;	entry->optionsDate.len = 0;    }        return(entry);loser:    if ( arena ) {	PORT_FreeArena(arena, PR_FALSE);    }        return(NULL);}/* * delete a SMIME entry */static SECStatusDeleteDBSMimeEntry(CERTCertDBHandle *handle, char *emailAddr){    PRArenaPool *arena = NULL;    SECStatus rv;    SECItem dbkey;        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);    if ( arena == NULL ) {	goto loser;    }    rv = EncodeDBSMimeKey(emailAddr, arena, &dbkey);    if ( rv != SECSuccess ) {	goto loser;    }    rv = DeleteDBEntry(handle, certDBEntryTypeSMimeProfile, &dbkey);    if ( rv == SECFailure ) {	goto loser;    }    PORT_FreeArena(arena, PR_FALSE);    return(SECSuccess);loser:    if ( arena ) {	PORT_FreeArena(arena, PR_FALSE);    }        return(SECFailure);}/* * Read a SMIME entry */static certDBEntrySMime *ReadDBSMimeEntry(CERTCertDBHandle *handle, char *emailAddr){    PRArenaPool *arena = NULL;    PRArenaPool *tmparena = NULL;    certDBEntrySMime *entry;    SECItem dbkey;    SECItem dbentry;    SECStatus rv;        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);    if ( arena == NULL ) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }    tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);    if ( tmparena == NULL ) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }        entry = (certDBEntrySMime *)PORT_ArenaAlloc(arena,						sizeof(certDBEntrySMime));    if ( entry == NULL ) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }    entry->common.arena = arena;    entry->common.type = certDBEntryTypeSMimeProfile;    rv = EncodeDBSMimeKey(emailAddr, tmparena, &dbkey);    if ( rv != SECSuccess ) {	goto loser;    }        rv = ReadDBEntry(handle, &entry->common, &dbkey, &dbentry, tmparena);    if ( rv == SECFailure ) {	goto loser;    }    /* is record long enough for header? */    if ( dbentry.len < DB_SMIME_ENTRY_HEADER_LEN ) {	PORT_SetError(SEC_ERROR_BAD_DATABASE);	goto loser;    }    rv = DecodeDBSMimeEntry(entry, &dbentry, emailAddr);    if ( rv != SECSuccess ) {	goto loser;    }        PORT_FreeArena(tmparena, PR_FALSE);    return(entry);    loser:    if ( tmparena ) {	PORT_FreeArena(tmparena, PR_FALSE);    }    if ( arena ) {	PORT_FreeArena(arena, PR_FALSE);    }        return(NULL);}/* * Encode a SMIME entry into byte stream suitable for * the database */static SECStatusWriteDBSMimeEntry(CERTCertDBHandle *handle, certDBEntrySMime *entry){    SECItem dbitem, dbkey;    PRArenaPool *tmparena = NULL;    SECStatus rv;        tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);    if ( tmparena == NULL ) {	goto loser;    }        rv = EncodeDBSMimeEntry(entry, tmparena, &dbitem);    if ( rv != SECSuccess ) {	goto loser;    }    rv = EncodeDBSMimeKey(entry->emailAddr, tmparena, &dbkey);    if ( rv != SECSuccess ) {	goto loser;    }    /* now write it to the database */    rv = WriteDBEntry(handle, &entry->common, &dbkey, &dbitem);    if ( rv != SECSuccess ) {	goto loser;    }        PORT_FreeArena(tmparena, PR_FALSE);    return(SECSuccess);loser:    if ( tmparena ) {	PORT_FreeArena(tmparena, PR_FALSE);    }    return(SECFailure);    }/* * Encode a database subject record */static SECStatusEncodeDBSubjectEntry(certDBEntrySubject *entry, PRArenaPool *arena,		     SECItem *dbitem){    unsigned char *buf;    int len;    unsigned int ncerts;    unsigned int i;    unsigned char *tmpbuf;    unsigned int nnlen = 0;    unsigned int eaddrlen = 0;    int keyidoff;    SECItem *certKeys;    SECItem *keyIDs;        if ( entry->nickname ) {	nnlen = PORT_Strlen(entry->nickname) + 1;    }    if ( entry->emailAddr ) {	eaddrlen = PORT_Strlen(entry->emailAddr) + 1;    }        ncerts = entry->ncerts;        /* compute the length of the entry */    keyidoff = DB_SUBJECT_ENTRY_HEADER_LEN + nnlen + eaddrlen;    len = keyidoff + 4 * ncerts;    for ( i = 0; i < ncerts; i++ ) {	len += entry->certKeys[i].len;	len += entry->keyIDs[i].len;    }        /* allocate space for encoded database record, including space     * for low level header     */    dbitem->len = len + SEC_DB_ENTRY_HEADER_LEN;        dbitem->data = (unsigned char *)PORT_ArenaAlloc(arena, dbitem->len);    if ( dbitem->data == NULL) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }        /* fill in database record */    buf = &dbitem->data[SEC_DB_ENTRY_HEADER_LEN];        buf[0] = ( ncerts >> 8 ) & 0xff;    buf[1] = ncerts & 0xff;    buf[2] = ( nnlen >> 8 ) & 0xff;    buf[3] = nnlen & 0xff;    buf[4] = ( eaddrlen >> 8 ) & 0xff;    buf[5] = eaddrlen & 0xff;    PORT_Memcpy(&buf[DB_SUBJECT_ENTRY_HEADER_LEN], entry->nickname, nnlen);    PORT_Memcpy(&buf[DB_SUBJECT_ENTRY_HEADER_LEN+nnlen], entry->emailAddr,		eaddrlen);        for ( i = 0; i < ncerts; i++ ) {	certKeys = entry->certKeys;	keyIDs = entry->keyIDs;	buf[keyidoff+i*2] = ( certKeys[i].len >> 8 ) & 0xff;	buf[keyidoff+1+i*2] = certKeys[i].len & 0xff;	buf[keyidoff+ncerts*2+i*2] = ( keyIDs[i].len >> 8 ) & 0xff;	buf[keyidoff+1+ncerts*2+i*2] = keyIDs[i].len & 0xff;    }        /* temp pointer used to stuff certkeys and keyids into the buffer */    tmpbuf = &buf[keyidoff+ncerts*4];    for ( i = 0; i < ncerts; i++ ) {	certKeys = entry->certKeys;	PORT_Memcpy(tmpbuf, certKeys[i].data, certKeys[i].len);	tmpbuf = tmpbuf + certKeys[i].len;    }        for ( i = 0; i < ncerts; i++ ) {	keyIDs = entry->keyIDs;	PORT_Memcpy(tmpbuf, keyIDs[i].data, keyIDs[i].len);	tmpbuf = tmpbuf + keyIDs[i].len;    }    PORT_Assert(tmpbuf == &buf[len]);        return(SECSuccess);loser:    return(SECFailure);}/* * Encode a database key for a subject record */static SECStatusEncodeDBSubjectKey(SECItem *derSubject, PRArenaPool *arena,		   SECItem *dbkey){    dbkey->len = derSubject->len + SEC_DB_KEY_HEADER_LEN;    dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey->len);    if ( dbkey->data == NULL ) {	goto loser;    }    PORT_Memcpy(&dbkey->data[SEC_DB_KEY_HEADER_LEN], derSubject->data,	      derSubject->len);    dbkey->data[0] = certDBEntryTypeSubject;    return(SECSuccess);loser:    return(SECFailure);}static SECStatusDecodeDBSubjectEntry(certDBEntrySubject *entry, SECItem *dbentry,		     SECItem *derSubject){    unsigned int ncerts;    PRArenaPool *arena;    unsigned int len, itemlen;    unsigned char *tmpbuf;    unsigned int i;    SECStatus rv;    unsigned int keyidoff;    unsigned int nnlen, eaddrlen;        arena = entry->common.arena;    rv = SECITEM_CopyItem(arena, &entry->derSubject, derSubject);    if ( rv != SECSuccess ) {	goto loser;    }    /* is record long enough for header? */    if ( dbentry->len < DB_SUBJECT_ENTRY_HEADER_LEN ) {	PORT_SetError(SEC_ERROR_BAD_DATABASE);	goto loser;    }        entry->ncerts = ncerts = ( ( dbentry->data[0] << 8 ) | dbentry->data[1] );    nnlen = ( ( dbentry->data[2] << 8 ) | dbentry->data[3] );    eaddrlen = ( ( dbentry->data[4] << 8 ) | dbentry->data[5] );    if ( dbentry->len < ( ncerts * 4 + DB_SUBJECT_ENTRY_HEADER_LEN +			 nnlen + eaddrlen) ) {	PORT_SetError(SEC_ERROR_BAD_DATABASE);	goto loser;    }        entry->certKeys = (SECItem *)PORT_ArenaAlloc(arena,						 sizeof(SECItem) * ncerts);    entry->keyIDs = (SECItem *)PORT_ArenaAlloc(arena,					       sizeof(SECItem) * ncerts);    if ( ( entry->certKeys == NULL ) || ( entry->keyIDs == NULL ) ) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }    if ( nnlen > 1 ) { /* null terminator is stored */	entry->nickname = (char *)PORT_ArenaAlloc(arena, nnlen);	if ( entry->nickname == NULL ) {	    PORT_SetError(SEC_ERROR_NO_MEMORY);	    goto loser;	}	PORT_Memcpy(entry->nickname,		    &dbentry->data[DB_SUBJECT_ENTRY_HEADER_LEN],		    nnlen);    } else {	entry->nickname = NULL;    }        if ( eaddrlen > 1 ) { /* null terminator is stored */	entry->emailAddr = (char *)PORT_ArenaAlloc(arena, eaddrlen);	if ( entry->emailAddr == NULL ) {	    PORT_SetError(SEC_ERROR_NO_MEMORY);	    goto loser;	}	PORT_Memcpy(entry->emailAddr,		    &dbentry->data[DB_SUBJECT_ENTRY_HEADER_LEN+nnlen],		    eaddrlen);    } else {	entry->emailAddr = NULL;    }        /* collect the lengths of the certKeys and keyIDs, and total the     * overall length.     */    keyidoff = DB_SUBJECT_ENTRY_HEADER_LEN + nnlen + eaddrlen;    len = keyidoff + 4 * ncerts;    tmpbuf = &dbentry->data[0];        for ( i = 0; i < ncerts; i++ ) {	itemlen = ( tmpbuf[keyidoff + 2*i] << 8 ) | tmpbuf[keyidoff + 1 + 2*i] ;	len += itemlen;	entry->certKeys[i].len = itemlen;	itemlen = ( tmpbuf[keyidoff + 2*ncerts + 2*i] << 8 ) |	    tmpbuf[keyidoff + 1 + 2*ncerts + 2*i] ;	len += itemlen;	entry->keyIDs[i].len = itemlen;    }        /* is database entry correct length? */    if ( len != dbentry->len ){	PORT_SetError(SEC_ERROR_BAD_DATABASE);	goto loser;    }        tmpbuf = &tmpbuf[keyidoff + 4*ncerts];    for ( i = 0; i < ncerts; i++ ) {	entry->certKeys[i].data =	    (unsigned char *)PORT_ArenaAlloc(arena, entry->certKeys[i].len);	if ( entry->certKeys[i].data == NULL ) {	    PORT_SetError(SEC_ERROR_NO_MEMORY);	    goto loser;	}	PORT_Memcpy(entry->certKeys[i].data, tmpbuf, entry->certKeys[i].len);	tmpbuf = &tmpbuf[entry->certKeys[i].len];    }    for ( i = 0; i < ncerts; i++ ) {	entry->keyIDs[i].data =	    (unsigned char *)PORT_ArenaAlloc(arena, entry->keyIDs[i].len);	if ( entry->keyIDs[i].data == NULL ) {	    PORT_SetError(SEC_ERROR_NO_MEMORY);	    goto loser;	}	PORT_Memcpy(entry->keyIDs[i].data, tmpbuf, entry->keyIDs[i].len);	tmpbuf = &tmpbuf[entry->keyIDs[i].len];    }        PORT_Assert(tmpbuf == &dbentry->data[dbentry->len]);        return(SECSuccess);loser:    return(SECFailure);}/* * create a new subject entry with a single cert */static certDBEntrySubject *NewDBSubjectEntry(SECItem *derSubject, SECItem *certKey,		  SECItem *keyID, char *nickname, char *emailAddr,		  unsigned int flags){    PRArenaPool *arena = NULL;    certDBEntrySubject *entry;    SECStatus rv;    unsigned int nnlen;    unsigned int eaddrlen;        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);    if ( arena == NULL ) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }    entry = (certDBEntrySubject *)PORT_ArenaAlloc(arena,						  sizeof(certDBEntrySubject));    if ( entry == NULL ) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	goto loser;    }    /* init common fields */    entry->common.arena = arena;    entry->common.type = certDBEntryTypeSubject;    entry->common.version = CERT_DB_FILE_VERSION;    entry->common.flags = flags;    /* copy the subject */    rv = SECITEM_CopyItem(arena, &entry->derSubject, derSubject);    if ( rv != SECSuccess ) {	goto loser;    }        entry->ncerts = 1;    /* copy nickname */    if ( nickname && ( *nickname != '\0' ) ) {	nnlen = PORT_Strlen(nickname) + 1;	entry->nickname = (char *)PORT_ArenaAlloc(arena, nnlen);	if ( entry->nickname == NULL ) {	    goto loser;	}						  	PORT_Memcpy(entry->nickname, nickname, nnlen);    } else {	entry->nickname = NULL;    }        /* copy email addr */    if ( emailAddr && ( *emailAddr != '\0' ) ) {	emailAddr = CERT_FixupEmailAddr(emailAddr);	if ( emailAddr == NULL ) {	    entry->emailAddr = NULL;	    goto loser;	}		eaddrlen = PORT_Strlen(emailAddr) + 1;	entry->emailAddr = (char *)PORT_ArenaAlloc(arena, eaddrlen);	if ( entry->emailAddr == NULL ) {	    PORT_Free(emailAddr);	    goto loser;	}		PORT_Memcpy(entry->emailAddr, emailAddr, eaddrlen);	PORT_Free(emailAddr);    } else {	entry->emailAddr = NULL;    }        /* allocate space for certKeys and keyIDs */    entry->certKeys = (SECItem *)PORT_ArenaAlloc(arena, sizeof(SECItem));    entry->keyIDs = (SECItem *)PORT_ArenaAlloc(arena, sizeof(SECItem));    if ( ( entry->certKeys == NULL ) || ( entry->keyIDs == NULL ) ) {	goto loser;    }    /* copy the certKey and keyID */    rv = SECITEM_CopyItem(arena, &entry->certKeys[0], certKey);    if ( rv != SECSuccess ) {	goto loser;    }    rv = SECITEM_CopyItem(arena, &entry->keyIDs[0], keyID);    if ( rv != SECSuccess ) {	goto loser;    }        return(entry);loser:    if ( arena ) {	PORT_FreeArena(arena, PR_FALSE);    }        return(NULL);}/* * delete a subject entry */static SECStatusDeleteDBSubjectEntry(CERTCertDBHandle *handle, SECItem *derSubject){    SECItem dbkey;    PRArenaPool *arena = NULL;    SECStatus rv;        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);    if ( arena == NULL ) {	goto loser;    }        rv = EncodeDBSubjectKey(derSubject, arena, &dbkey);    if ( rv != SECSuccess ) {	goto loser;    }        rv = DeleteDBEntry(handle, certDBEntryTypeSubject, &dbkey);    if ( rv == SECFailure ) {	goto loser;    }    PORT_FreeArena(arena, PR_FALSE);    return(SECSuccess);loser:    if ( arena ) {	PORT_FreeArena(arena, PR_FALSE);    }        return(SECFailure);}

⌨️ 快捷键说明

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