📄 dname.c
字号:
/****************************************************************************
*
* Copyright (c) 1998, Network Associates, Inc. and its affiliated Companies
*
****************************************************************************/
#include <string.h>
/* we don't want strings.h for WIN32, but for PGP use we should really check
PGP_WIN32, so we have the extra check in the #if */
#if !PGP_WIN32 && !defined(WIN32)
#include <strings.h>
#endif
#include "tc.h"
#include "cms.h"
#include "cms_proto.h"
typedef struct OIDentifier {
int oid_nelem; /* number of sub-identifiers */
unsigned long *oid_elements; /* the (ordered) list of sub-identifiers */
} OID_T, *OID_P;
/*****
* prototypes
*****/
static int HexStringToUchar(
unsigned char **der,
size_t *derlen,
const char *hexstr,
TC_MemoryMgr *mgr);
static int HexCharsToUchar(unsigned char *hex, char *string);
static char *AVAToString(
PKIAttributeTypeAndValue *ava,
TC_CONTEXT *context);
static int ParseStringRDNSeq(
PKIRDNSequence *rdnSeq,
const char *name,
TC_CONTEXT *context);
static int ParseStringAVA(
PKIAttributeTypeAndValue *ava,
const char *name,
TC_CONTEXT *context);
static int UndelimitString(
unsigned char **converted, size_t *length, const char *orig,
TC_MemoryMgr *mgr);
static int CreateAVADERFromString(
unsigned char *string,
size_t strLen,
TC_AVA_ENTRY *avaInfo,
unsigned char **der,
size_t *derLen,
TC_CONTEXT *context);
/*****
*
* Table to define the default printable tag value, the DER OID, and
* the value's data type for a distinguised name AVA. Some values
* for non-string types are currently commented out until we can
* handle them.
*
* Values for printable tags are based on the values in:
* RFC2256, "A Summary of the X.500(96) User Schema for use with LDAPv3"
*
* Values for DC came from:
* RFC2247, "Using Domains in LDAP/X.500"
*
* Values for email address, unstructured name, and unstructured address
* came from:
* PKCS #9 "Selected Attribute Types"
*
* Note: I have seen values for the following in print, but have not yet
* found the OID/type definitions
* userid
*
*****/
static struct {
const char *type; /* the attribute type for a name */
unsigned char oid[11];
int oidlen;
int tag; /* the base ASN.1 type (the default character set) */
} Types[] = {
/* common name */
{ "CN", { 0x55, 0x04, 0x03 }, 3, PKIID_PrintableString },
/* surname */
{ "SN", { 0x55, 0x04, 0x04 }, 3, PKIID_PrintableString },
{ "SerialNumber", { 0x55, 0x04, 0x05 }, 3, PKIID_PrintableString },
/* country name */
{ "C", { 0x55, 0x04, 0x06 }, 3, PKIID_PrintableString },
/* locality name */
{ "L", { 0x55, 0x04, 0x07 }, 3, PKIID_PrintableString },
/* state/province name */
{ "ST", { 0x55, 0x04, 0x08 }, 3, PKIID_PrintableString },
/* street address */
{ "STREET", { 0x55, 0x04, 0x09 }, 3, PKIID_PrintableString },
/* organization */
{ "O", { 0x55, 0x04, 0x0a }, 3, PKIID_PrintableString },
/* organization unit name */
{ "OU", { 0x55, 0x04, 0x0b }, 3, PKIID_PrintableString },
{ "title", { 0x55, 0x04, 0x0c }, 3, PKIID_PrintableString },
{ "description", { 0x55, 0x04, 0x0d }, 3, PKIID_PrintableString },
{ "businessCategory", { 55, 0x04, 0x0f }, 3, PKIID_PrintableString },
/* postal address */
/* SEQ OF { "PA", { 0x55, 0x04, 0x10 }, 3, ??? }, */
{ "postalCode", { 0x55, 0x04, 0x11 }, 3, PKIID_PrintableString },
/* postOfficebox */
{ "POBOX", { 0x55, 0x04, 0x12 }, 3, PKIID_PrintableString },
{ "physicalDeliveryOfficeName", { 0x55, 0x04, 0x13 }, 3, PKIID_PrintableString },
/* telephoneNumber */
{ "TN", { 0x55, 0x04, 0x14 }, 3, PKIID_PrintableString },
/* fax number */
/* SEQ { "FAX", { 0x55, 0x04, 0x17 }, 3, ??? }, */
{ "x121Address", { 0x55, 0x04, 0x18 }, 3, PKIID_NumericString },
/* international ISDN number */
{ "ISDN", { 0x55, 0x04, 0x19 }, 3, PKIID_NumericString },
{ "destinationIndicator", { 0x55, 0x04, 0x1b }, 3, PKIID_PrintableString },
/* BIT STRING { "userPassword", { 0x55, 0x04, 0x23 }, 3, ??? },*/
{ "name", { 0x55, 0x04, 0x29 }, 3, PKIID_PrintableString },
{ "givenName", { 0x55, 0x04, 0x2a }, 3, PKIID_PrintableString },
{ "initials", { 0x55, 0x04, 0x2b }, 3, PKIID_PrintableString },
/* eg., 3rd */
{ "generationQualifier", { 0x55, 0x04, 0x2c }, 3, PKIID_PrintableString },
/*{ "x500UniqueIdentifier", { 0x55, 0x04, 0x2d }, 3, PKIID_BIT_STRING },*/
/* distinquished name qualifier */
{ "dnQualifier", { 0x55, 0x04, 0x2e }, 3, PKIID_PrintableString },
{ "houseIdentifier", { 0x55, 0x04, 0x33 }, 3, PKIID_PrintableString },
/* directory management domain */
{ "dmdName", { 0x55, 0x04, 0x36 }, 3, PKIID_PrintableString },
/* domain component, 0.9.2342.19200300.100.1.25 */
{ "DC", { 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19 }, 10, PKIID_IA5String },
/* e-mail name from pkcs-9 */
{ "emailAddress", { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01 }, 9, PKIID_IA5String },
/* unstructued name from pkcs-9 */
{ "unstructuredName", { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x02 }, 9, PKIID_IA5String },
/* unstructed address from pkcs-9 */
{ "unstructuredAddress", { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x08 }, 9, PKIID_PrintableString },
{ NULL, { 0 }, 1, PKIID_NULL }
};
static int ValidASNType(int type)
{
switch(type) {
case TC_ASN_BOOLEAN:
case TC_ASN_INTEGER:
case TC_ASN_BIT_STRING :
case TC_ASN_OCTET_STRING :
case TC_ASN_NULL :
case TC_ASN_OBJECT_ID :
case TC_ASN_SEQUENCE :
case TC_ASN_SET :
case TC_ASN_NumericString :
case TC_ASN_PrintableString :
case TC_ASN_T61String :
case TC_ASN_VideotexString :
case TC_ASN_IA5String :
case TC_ASN_UTCTime :
case TC_ASN_GeneralizedTime :
case TC_ASN_GraphicString :
case TC_ASN_VisibleString :
case TC_ASN_GeneralString :
case TC_ASN_CHOICE :
return 0;
default:
return -1;
}
}
/*****
*
* InitAVAList
*
* Internal routine to set the default Dname AVA values in the
* context.
*
****/
int InitAVAList(TC_AVA_ENTRY **list, TC_MemoryMgr *memMgr)
{
TC_AVA_ENTRY *entry;
int i;
if (list == NULL)
return TC_E_INVARGS;
*list = NULL;
for (i = 0; Types[i].type; i++) {
entry = TC_Alloc(memMgr, sizeof(TC_AVA_ENTRY));
if (entry == NULL)
return TC_E_NOMEMORY;
entry->attributeType = TC_Alloc(memMgr, strlen(Types[i].type)+1 );
if (entry->attributeType == NULL) {
TC_Free(memMgr, entry);
return TC_E_NOMEMORY;
}
strcpy(entry->attributeType, Types[i].type);
entry->oid = TC_Alloc(memMgr, Types[i].oidlen);
if (entry->oid == NULL) {
/* TODO free whole list? */
TC_Free(memMgr, entry->attributeType);
TC_Free(memMgr, entry);
return TC_E_NOMEMORY;
}
memcpy(entry->oid, Types[i].oid, Types[i].oidlen);
entry->oidlen = Types[i].oidlen;
entry->asnType = Types[i].tag;
entry->next = *list;
*list = entry;
}
return 0;
} /* InitAVAList */
void FreeAVAList(TC_AVA_ENTRY *list, TC_MemoryMgr *memMgr)
{
TC_AVA_ENTRY *entry = list;
TC_AVA_ENTRY *tmp;
while (entry != NULL) {
if (entry->attributeType != NULL)
TC_Free(memMgr, entry->attributeType);
if (entry->oid != NULL)
TC_Free(memMgr, entry->oid);
tmp = entry->next;
TC_Free(memMgr, entry);
entry = tmp;
}
return;
} /* FreeAVAList */
/*****
*
* tc_change_ava_entry
*
* Allows the user to update the default ASN type for an AVA
* in the context's list.
*
* parameters
* input
* oid - the AVA's oid
* oidlen - length of above
* newASNType - the new type for the AVA
* context - pointer to an initialized context
*
* returns
* TC_E_INVARGS
* -1 (the provided oid is not in the list)
* 0
*****/
int tc_change_ava_entry(
unsigned char *oid,
size_t oidlen,
int newASNType,
TC_CONTEXT *context)
{
TC_AVA_ENTRY *listentry = NULL;
if (context == NULL || oid == NULL)
return TC_E_INVARGS;
if ( ValidASNType(newASNType) != 0)
return TC_E_INVARGS;
listentry = context->avaList;
while(listentry) {
if ((listentry->oidlen == oidlen) &&
(memcmp(listentry->oid, oid, oidlen) == 0))
break;
listentry = listentry->next;
}
if (listentry == NULL)
return -1;
listentry->asnType = newASNType;
return 0;
} /* tc_change_ava_entry */
/*****
*
* tc_add_avatype
*
* Allows the user to add a new AVA definition to the list in the context.
* Then the user can provide string representations of a Dname with
* that AVA when using tc_make_dname_fromstring. Also, Dname's containing
* that AVA will print successfully when using tc_extract_dname.
*
* parameters
* input
* oid - the oid for the AVA
* oidlen - length of above
* printableAttrName - the name to use for printable versions
* of this AVA (eg., "CN" or "unstructuredName")
* asnType - the ASN.1 type for this AVA
* context - pointer to an initialized context
*
* returns
* TC_E_INVARGS
* 0
*****/
int tc_add_avatype(
unsigned char *oid,
size_t oidlen,
const char *printableAttrName,
int asnType,
TC_CONTEXT *context)
{
TC_AVA_ENTRY *entry;
if (context == NULL || oid == NULL || oidlen == 0 ||
printableAttrName == NULL)
return TC_E_INVARGS;
if ( ValidASNType(asnType) != 0)
return TC_E_INVARGS;
entry = TC_Alloc(context->memMgr, sizeof(TC_AVA_ENTRY));
if (entry == NULL)
return TC_E_NOMEMORY;
entry->attributeType =
TC_Alloc(context->memMgr, strlen(printableAttrName)+1 );
if (entry->attributeType == NULL) {
TC_Free(context->memMgr, entry);
return TC_E_NOMEMORY;
}
strcpy(entry->attributeType, printableAttrName);
entry->oid = TC_Alloc(context->memMgr, oidlen);
if (entry->oid == NULL) {
TC_Free(context->memMgr, entry->attributeType);
TC_Free(context->memMgr, entry);
return TC_E_NOMEMORY;
}
memcpy(entry->oid, oid, oidlen);
entry->oidlen = oidlen;
entry->asnType = asnType;
entry->next = context->avaList;
context->avaList = entry;
return 0;
} /* tc_add_ava */
/*****
*
* Find the AVA entry in the context that has the printable
* name provided
*****/
static TC_AVA_ENTRY *lookupASNtype(
const char *name,
TC_CONTEXT *context)
{
TC_AVA_ENTRY *avaEntry = context->avaList;
while (avaEntry) {
if (strcasecmp (name, avaEntry->attributeType) == 0)
return avaEntry;
avaEntry = avaEntry->next;
}
return NULL;
}
/*****
*
* Find an AVA entry in the context give the OID
*
*****/
static TC_AVA_ENTRY *lookupAVAByOID(
PKIAttributeTypeAndValue *ava,
TC_CONTEXT *context)
{
TC_AVA_ENTRY *avaEntry = context->avaList;
while(avaEntry) {
if (ava->type.len == avaEntry->oidlen &&
memcmp(ava->type.val, avaEntry->oid, avaEntry->oidlen) == 0)
return avaEntry;
avaEntry = avaEntry->next;
}
return NULL;
} /* lookupAVAByOID */
/*****
*
* DERToOID
*
* a routine to convert from DER encoding to a list of integers
*
*****/
static OID_T *DERToOID(
unsigned char *derOid,
size_t derOidLen,
TC_MemoryMgr *mgr)
{
unsigned long i;
unsigned long *intElements;
unsigned char *dataPtr, *endPtr;
OID_T *oid = NULL;
dataPtr = derOid;
endPtr = dataPtr + derOidLen;
/* Count the number of integer elements are in the OID,
the first element will never be more than one byte
so start with second DER value */
for (i = 1; dataPtr < endPtr; i++) {
if (*dataPtr == 0x80) /* incorrect format */
return(oid);
while (*dataPtr++ & 0x80)
if (dataPtr > endPtr)
return(oid);
}
oid = TC_Alloc(mgr, sizeof(OID_T));
if (oid == NULL)
return NULL;
intElements = TC_Alloc(mgr, (i+1)*sizeof(unsigned long));
if (intElements == NULL) {
TC_Free(mgr, oid);
return NULL;
}
oid->oid_elements = intElements;
oid->oid_nelem = i;
for (dataPtr = derOid; dataPtr < endPtr; ) {
i = 0;
do {
i <<= 7;
i |= *dataPtr & 0x7f;
} while (*dataPtr++ & 0x80);
if (intElements == oid->oid_elements) {
*intElements++ = i / 40;
*intElements++ = i % 40;
}
else
*intElements++ = i;
}
return oid;
} /* DERToOID */
/*****
*
* OidToString
*
* Convert a DER (hex) representation of an OID into a dotted
* decimal string representataion. It's assumed that the provided
* string buffer is large enough.
*
*****/
static int OidToString(char *string, unsigned char *oid, size_t oidlen,
TC_MemoryMgr *mgr)
{
int i;
char temp[256];
OID_T *intOID;
if (!string)
return -1;
string[0] = '\0';
intOID = DERToOID(oid, oidlen, mgr);
if (intOID == NULL)
return -1;
for (i = 0; i < intOID->oid_nelem; i++) {
if (i == intOID->oid_nelem-1)
sprintf(temp, "%ld", intOID->oid_elements[i]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -