⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 x509.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 5 页
字号:
    *next = rdn->len > 0;    return NULL;}/* *  Fetches the next RDN in a DN */static err_tget_next_rdn(chunk_t *rdn, chunk_t * attribute, chunk_t *oid, chunk_t *value, asn1_t *type, bool *next){    chunk_t body;    /* initialize return values */    *oid   = empty_chunk;    *value = empty_chunk;    /* if all attributes have been parsed, get next rdn */    if (attribute->len <= 0)    {	/* an RDN is a SET OF attributeTypeAndValue */	if (*rdn->ptr != ASN1_SET)	    return "RDN is not a SET";	attribute->len = asn1_length(rdn);        if (attribute->len == ASN1_INVALID_LENGTH)            return "Invalid attribute length";	attribute->ptr = rdn->ptr;	/* advance to start of next RDN */	rdn->ptr += attribute->len;	rdn->len -= attribute->len;    }    /* an attributeTypeAndValue is a SEQUENCE */    if (*attribute->ptr != ASN1_SEQUENCE) 	return "attributeTypeAndValue is not a SEQUENCE";    /* extract the attribute body */    body.len = asn1_length(attribute);    if (body.len == ASN1_INVALID_LENGTH)        return "Invalid attribute body length";    body.ptr = attribute->ptr;        /* advance to start of next attribute */    attribute->ptr += body.len;    attribute->len -= body.len;    /* attribute type is an OID */    if (*body.ptr != ASN1_OID)	return "attributeType is not an OID";    /* extract OID */    oid->len = asn1_length(&body);     if (oid->len == ASN1_INVALID_LENGTH)        return "Invalid attribute OID length";   oid->ptr = body.ptr;    /* advance to the attribute value */    body.ptr += oid->len;    body.len -= oid->len;    /* extract string type */    *type = *body.ptr;    /* extract string value */    value->len = asn1_length(&body);    if (value->len == ASN1_INVALID_LENGTH)        return "Invalid attribute string length";    value->ptr = body.ptr;    /* are there any RDNs left? */    *next = rdn->len > 0 || attribute->len > 0;    return NULL;}/* *  Parses an ASN.1 distinguished name int its OID/value pairs */static err_tdn_parse(chunk_t dn, chunk_t *str){    chunk_t rdn, oid, attribute, value;    asn1_t type;    int oid_code;    bool next;    bool first = TRUE;    err_t ugh;    if(dn.ptr == NULL) {	const char *e = "(empty)";	strncpy(str->ptr, e, str->len);	update_chunk(str, strlen(e));	return NULL;    }    ugh = init_rdn(dn, &rdn, &attribute, &next);    if (ugh != NULL) /* a parsing error has occured */        return ugh;    while (next)    {	ugh = get_next_rdn(&rdn, &attribute, &oid, &value, &type, &next);	if (ugh != NULL) /* a parsing error has occured */	    return ugh;	if (first)		/* first OID/value pair */	    first = FALSE;	else			/* separate OID/value pair by a comma */	    update_chunk(str, snprintf(str->ptr,str->len,", "));	/* print OID */	oid_code = known_oid(oid);	if (oid_code == OID_UNKNOWN)	/* OID not found in list */	    hex_str(oid, str);	else	    update_chunk(str, snprintf(str->ptr,str->len,"%s",			      oid_names[oid_code].name));	/* print value */	update_chunk(str, snprintf(str->ptr,str->len,"=%.*s",			      (int)value.len,value.ptr));    }    return NULL;}/* *  Count the number of wildcard RDNs in a distinguished name */intdn_count_wildcards(chunk_t dn){    chunk_t rdn, attribute, oid, value;    asn1_t type;    bool next;    int wildcards = 0;    err_t ugh = init_rdn(dn, &rdn, &attribute, &next);    if (ugh != NULL) /* a parsing error has occured */        return -1;    while (next)    {	ugh = get_next_rdn(&rdn, &attribute, &oid, &value, &type, &next);		if (ugh != NULL) /* a parsing error has occured */	    return -1;	if (value.len == 1 && *value.ptr == '*')	    wildcards++; /* we have found a wildcard RDN */    }    return wildcards;}/* * Prints a binary string in hexadecimal form */voidhex_str(chunk_t bin, chunk_t *str){    u_int i;    update_chunk(str, snprintf(str->ptr,str->len,"0x"));    for (i=0; i < bin.len; i++)	update_chunk(str, snprintf(str->ptr,str->len,"%02X",*bin.ptr++));}/*  Converts a binary DER-encoded ASN.1 distinguished name *  into LDAP-style human-readable ASCII format */intdntoa(char *dst, size_t dstlen, chunk_t dn){    err_t ugh = NULL;    chunk_t str;    str.ptr = dst;    str.len = dstlen;    ugh = dn_parse(dn, &str);    if (ugh != NULL) /* error, print DN as hex string */    {	DBG(DBG_PARSING,	    DBG_log("error in DN parsing: %s", ugh)	)	str.ptr = dst;	str.len = dstlen;	hex_str(dn, &str);    }    return (int)(dstlen - str.len);}/* * Same as dntoa but prints a special string for a null dn */intdntoa_or_null(char *dst, size_t dstlen, chunk_t dn, const char* null_dn){    if (dn.ptr == NULL)	return snprintf(dst, dstlen, "%s", null_dn);    else	return dntoa(dst, dstlen, dn);}/*  Converts an LDAP-style human-readable ASCII-encoded *  ASN.1 distinguished name into binary DER-encoded format */err_tatodn(char *src, chunk_t *dn){  /* finite state machine for atodn */    typedef enum {	SEARCH_OID =	0,	READ_OID =	1,	SEARCH_NAME =	2,	READ_NAME =	3,        UNKNOWN_OID =	4    } state_t;    u_char oid_len_buf[3];    u_char name_len_buf[3];    u_char rdn_seq_len_buf[3];    u_char rdn_set_len_buf[3];    u_char dn_seq_len_buf[3];    chunk_t asn1_oid_len     = { oid_len_buf,     0 };    chunk_t asn1_name_len    = { name_len_buf,    0 };    chunk_t asn1_rdn_seq_len = { rdn_seq_len_buf, 0 };    chunk_t asn1_rdn_set_len = { rdn_set_len_buf, 0 };    chunk_t asn1_dn_seq_len  = { dn_seq_len_buf,  0 };    chunk_t oid  = empty_chunk;    chunk_t name = empty_chunk;    int whitespace  = 0;    int rdn_seq_len = 0;    int rdn_set_len = 0;    int dn_seq_len  = 0;    int pos         = 0;    err_t ugh = NULL;    u_char *dn_ptr = dn->ptr + 4;    state_t state = SEARCH_OID;    do    {        switch (state)	{	case SEARCH_OID:	    if (*src != ' ' && *src != '/' && *src !=  ',')	    {		oid.ptr = src;		oid.len = 1;		state = READ_OID;	    }	    break;	case READ_OID:	    if (*src != ' ' && *src != '=')		oid.len++;	    else	    {		for (pos = 0; pos < X501_RDN_ROOF; pos++)		{		    if (strlen(x501rdns[pos].name) == oid.len &&			strncasecmp(x501rdns[pos].name, oid.ptr, oid.len) == 0)			break; /* found a valid OID */		}		if (pos == X501_RDN_ROOF)		{		    ugh = "unknown OID in ID_DER_ASN1_DN";		    state = UNKNOWN_OID;		    break;		}		code_asn1_length(x501rdns[pos].oid.len, &asn1_oid_len);		/* reset oid and change state */		oid = empty_chunk;		state = SEARCH_NAME;	    }	    break;	case SEARCH_NAME:	    if (*src != ' ' && *src != '=')	    {		name.ptr = src;		name.len = 1;		whitespace = 0;		state = READ_NAME;	    }	    break;	case READ_NAME:	    if (*src != ',' && *src != '/' && *src != '\0')	    {		name.len++;		if (*src == ' ')		    whitespace++;		else		    whitespace = 0;	    }	    else	    {		name.len -= whitespace;		code_asn1_length(name.len, &asn1_name_len);		/* compute the length of the relative distinguished name sequence */		rdn_seq_len = 1 + asn1_oid_len.len + x501rdns[pos].oid.len +			      1 + asn1_name_len.len + name.len;		code_asn1_length(rdn_seq_len, &asn1_rdn_seq_len);		/* compute the length of the relative distinguished name set */		rdn_set_len = 1 + asn1_rdn_seq_len.len + rdn_seq_len;		code_asn1_length(rdn_set_len, &asn1_rdn_set_len);		/* encode the relative distinguished name */		*dn_ptr++ = ASN1_SET;		chunkcpy(dn_ptr, asn1_rdn_set_len);		*dn_ptr++ = ASN1_SEQUENCE;		chunkcpy(dn_ptr, asn1_rdn_seq_len);		*dn_ptr++ = ASN1_OID;		chunkcpy(dn_ptr, asn1_oid_len);		chunkcpy(dn_ptr, x501rdns[pos].oid);		/* encode the ASN.1 character string type of the name */		*dn_ptr++ = (x501rdns[pos].type == ASN1_PRINTABLESTRING		    && !is_printablestring(name))? ASN1_T61STRING : x501rdns[pos].type;		chunkcpy(dn_ptr, asn1_name_len);		chunkcpy(dn_ptr, name);		/* accumulate the length of the distinguished name sequence */		dn_seq_len += 1 + asn1_rdn_set_len.len + rdn_set_len;		/* reset name and change state */		name = empty_chunk;		state = SEARCH_OID;	    }	    break;	case UNKNOWN_OID:	    break;	}    } while (*src++ != '\0');    /* complete the distinguished name sequence*/    code_asn1_length(dn_seq_len, &asn1_dn_seq_len);    dn->ptr += 3 - asn1_dn_seq_len.len;    dn->len =  1 + asn1_dn_seq_len.len + dn_seq_len;    dn_ptr = dn->ptr;    *dn_ptr++ = ASN1_SEQUENCE;    chunkcpy(dn_ptr, asn1_dn_seq_len);    return ugh;}/*  compare two distinguished names by *  comparing the individual RDNs */boolsame_dn(chunk_t a, chunk_t b){    chunk_t rdn_a, rdn_b, attribute_a, attribute_b;    chunk_t oid_a, oid_b, value_a, value_b;    asn1_t type_a, type_b;    bool next_a, next_b;    /* same lengths for the DNs */    if (a.len != b.len)	return FALSE;    /* try a binary comparison first */    if (memcmp(a.ptr, b.ptr, b.len) == 0)       return TRUE;     /* initialize DN parsing */    if (init_rdn(a, &rdn_a, &attribute_a, &next_a) != NULL    ||  init_rdn(b, &rdn_b, &attribute_b, &next_b) != NULL)	return FALSE;    /* fetch next RDN pair */    while (next_a && next_b)    {	/* parse next RDNs and check for errors */	if (get_next_rdn(&rdn_a, &attribute_a, &oid_a, &value_a, &type_a, &next_a) != NULL	||  get_next_rdn(&rdn_b, &attribute_b, &oid_b, &value_b, &type_b, &next_b) != NULL)	{	    return FALSE;	}	/* OIDs must agree */	if (oid_a.len != oid_b.len || memcmp(oid_a.ptr, oid_b.ptr, oid_b.len) != 0)	    return FALSE;	/* same lengths for values */	if (value_a.len != value_b.len)	    return FALSE;	/* printableStrings and email RDNs require uppercase comparison */	if (type_a == type_b && (type_a == ASN1_PRINTABLESTRING ||	   (type_a == ASN1_IA5STRING && known_oid(oid_a) == OID_PKCS9_EMAIL)))	{	    if (strncasecmp(value_a.ptr, value_b.ptr, value_b.len) != 0)		return FALSE;	}	else	{	    if (strncmp(value_a.ptr, value_b.ptr, value_b.len) != 0)		return FALSE;	}    }    /* both DNs must have same number of RDNs */    if (next_a || next_b)	return FALSE;    /* the two DNs are equal! */    return TRUE;}/*  compare two distinguished names by comparing the individual RDNs. *  A single'*' character designates a wildcard RDN in DN b. */boolmatch_dn(chunk_t a, chunk_t b, int *wildcards){    chunk_t rdn_a, rdn_b, attribute_a, attribute_b;    chunk_t oid_a, oid_b, value_a, value_b;    asn1_t type_a,  type_b;    bool next_a, next_b;    /* initialize wildcard counter */    *wildcards = 0;    /* initialize DN parsing */    if (init_rdn(a, &rdn_a, &attribute_a, &next_a) != NULL    ||  init_rdn(b, &rdn_b, &attribute_b, &next_b) != NULL)    	return FALSE;    /* fetch next RDN pair */    while (next_a && next_b)    {	/* parse next RDNs and check for errors */	if (get_next_rdn(&rdn_a, &attribute_a, &oid_a, &value_a, &type_a, &next_a) != NULL	||  get_next_rdn(&rdn_b, &attribute_b, &oid_b, &value_b, &type_b, &next_b) != NULL)	{	    return FALSE;	}	/* OIDs must agree */	if (oid_a.len != oid_b.len || memcmp(oid_a.ptr, oid_b.ptr, oid_b.len) != 0)	    return FALSE;	/* does rdn_b contain a wildcard? */	if (value_b.len == 1 && *value_b.ptr == '*')	{	    (*wildcards)++;	    continue;	}	/* same lengths for values */	if (value_a.len != value_b.len)	    return FALSE;	/* printableStrings and email RDNs require uppercase comparison */	if (type_a == type_b && (type_a == ASN1_PRINTABLESTRING ||	   (type_a == ASN1_IA5STRING && known_oid(oid_a) == OID_PKCS9_EMAIL)))	{	    if (strncasecmp(value_a.ptr, value_b.ptr, value_b.len) != 0)		return FALSE;	}	else	{	    if (strncmp(value_a.ptr, value_b.ptr, value_b.len) != 0)		return FALSE;	}    }    /* both DNs must have same number of RDNs */    if (next_a || next_b) {	if(*wildcards) {	    char abuf[BUF_LEN];	    char bbuf[BUF_LEN];	    	    dntoa(abuf, BUF_LEN, a);	    dntoa(bbuf, BUF_LEN, b);	    	    openswan_log("while comparing A='%s'<=>'%s'=B with a wildcard count of %d, %s had too few RDNs",			 abuf, bbuf, *wildcards, (next_a ? "B" : "A"));	}	return FALSE;    }    /* the two DNs match! */    return TRUE;}/* *  compare two X.509 certificates by comparing their signatures */static bool

⌨️ 快捷键说明

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