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

📄 x509v3.c

📁 WLAN无线网络管理的最新程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * X.509v3 certificate parsing and processing (RFC 3280 profile) * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */#include "includes.h"#include "common.h"#ifdef CONFIG_INTERNAL_X509#include "asn1.h"#include "crypto.h"#include "x509v3.h"static void x509_free_name(struct x509_name *name){	os_free(name->cn);	os_free(name->c);	os_free(name->l);	os_free(name->st);	os_free(name->o);	os_free(name->ou);	os_free(name->email);	name->cn = name->c = name->l = name->st = name->o = name->ou = NULL;	name->email = NULL;}/** * x509_certificate_free - Free an X.509 certificate * @cert: Certificate to be freed */void x509_certificate_free(struct x509_certificate *cert){	if (cert == NULL)		return;	if (cert->next) {		wpa_printf(MSG_DEBUG, "X509: x509_certificate_free: cer=%p "			   "was still on a list (next=%p)\n",			   cert, cert->next);	}	x509_free_name(&cert->issuer);	x509_free_name(&cert->subject);	os_free(cert->public_key);	os_free(cert->sign_value);	os_free(cert);}/** * x509_certificate_free - Free an X.509 certificate chain * @cert: Pointer to the first certificate in the chain */void x509_certificate_chain_free(struct x509_certificate *cert){	struct x509_certificate *next;	while (cert) {		next = cert->next;		cert->next = NULL;		x509_certificate_free(cert);		cert = next;	}}static int x509_whitespace(char c){	return c == ' ' || c == '\t';}static void x509_str_strip_whitespace(char *a){	char *ipos, *opos;	int remove_whitespace = 1;	ipos = opos = a;	while (*ipos) {		if (remove_whitespace && x509_whitespace(*ipos))			ipos++;		else {			remove_whitespace = x509_whitespace(*ipos);			*opos++ = *ipos++;		}	}	*opos-- = '\0';	if (opos > a && x509_whitespace(*opos))		*opos = '\0';}static int x509_str_compare(const char *a, const char *b){	char *aa, *bb;	int ret;	if (!a && b)		return -1;	if (a && !b)		return 1;	if (!a && !b)		return 0;	aa = os_strdup(a);	bb = os_strdup(b);	if (aa == NULL || bb == NULL) {		os_free(aa);		os_free(bb);		return os_strcasecmp(a, b);	}	x509_str_strip_whitespace(aa);	x509_str_strip_whitespace(bb);	ret = os_strcasecmp(aa, bb);	os_free(aa);	os_free(bb);	return ret;}/** * x509_name_compare - Compare X.509 certificate names * @a: Certificate name * @b: Certificate name * Returns: <0, 0, or >0 based on whether a is less than, equal to, or * greater than b */int x509_name_compare(struct x509_name *a, struct x509_name *b){	int res;	if (!a && b)		return -1;	if (a && !b)		return 1;	if (!a && !b)		return 0;	res = x509_str_compare(a->cn, b->cn);	if (res)		return res;	res = x509_str_compare(a->c, b->c);	if (res)		return res;	res = x509_str_compare(a->l, b->l);	if (res)		return res;	res = x509_str_compare(a->st, b->st);	if (res)		return res;	res = x509_str_compare(a->o, b->o);	if (res)		return res;	res = x509_str_compare(a->ou, b->ou);	if (res)		return res;	res = x509_str_compare(a->email, b->email);	if (res)		return res;	return 0;}static int x509_parse_algorithm_identifier(	const u8 *buf, size_t len,	struct x509_algorithm_identifier *id, const u8 **next){	struct asn1_hdr hdr;	const u8 *pos, *end;	/*	 * AlgorithmIdentifier ::= SEQUENCE {	 *     algorithm            OBJECT IDENTIFIER,	 *     parameters           ANY DEFINED BY algorithm OPTIONAL	 * }	 */	if (asn1_get_next(buf, len, &hdr) < 0 ||	    hdr.class != ASN1_CLASS_UNIVERSAL ||	    hdr.tag != ASN1_TAG_SEQUENCE) {		wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE "			   "(AlgorithmIdentifier) - found class %d tag 0x%x",			   hdr.class, hdr.tag);		return -1;	}	pos = hdr.payload;	end = pos + hdr.length;	if (end > buf + len)		return -1;	*next = end;	if (asn1_get_oid(pos, end - pos, &id->oid, &pos))		return -1;	/* TODO: optional parameters */	return 0;}static int x509_parse_public_key(const u8 *buf, size_t len,				 struct x509_certificate *cert,				 const u8 **next){	struct asn1_hdr hdr;	const u8 *pos, *end;	/*	 * SubjectPublicKeyInfo ::= SEQUENCE {	 *     algorithm            AlgorithmIdentifier,	 *     subjectPublicKey     BIT STRING	 * }	 */	pos = buf;	end = buf + len;	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||	    hdr.class != ASN1_CLASS_UNIVERSAL ||	    hdr.tag != ASN1_TAG_SEQUENCE) {		wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE "			   "(SubjectPublicKeyInfo) - found class %d tag 0x%x",			   hdr.class, hdr.tag);		return -1;	}	pos = hdr.payload;	if (pos + hdr.length > end)		return -1;	end = pos + hdr.length;	*next = end;	if (x509_parse_algorithm_identifier(pos, end - pos,					    &cert->public_key_alg, &pos))		return -1;	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||	    hdr.class != ASN1_CLASS_UNIVERSAL ||	    hdr.tag != ASN1_TAG_BITSTRING) {		wpa_printf(MSG_DEBUG, "X509: Expected BITSTRING "			   "(subjectPublicKey) - found class %d tag 0x%x",			   hdr.class, hdr.tag);		return -1;	}	if (hdr.length < 1)		return -1;	pos = hdr.payload;	if (*pos) {		wpa_printf(MSG_DEBUG, "X509: BITSTRING - %d unused bits",			   *pos);		/*		 * TODO: should this be rejected? X.509 certificates are		 * unlikely to use such a construction. Now we would end up		 * including the extra bits in the buffer which may also be		 * ok.		 */	}	os_free(cert->public_key);	cert->public_key = os_malloc(hdr.length - 1);	if (cert->public_key == NULL) {		wpa_printf(MSG_DEBUG, "X509: Failed to allocate memory for "			   "public key");		return -1;	}	os_memcpy(cert->public_key, pos + 1, hdr.length - 1);	cert->public_key_len = hdr.length - 1;	wpa_hexdump(MSG_MSGDUMP, "X509: subjectPublicKey",		    cert->public_key, cert->public_key_len);	return 0;}static int x509_parse_name(const u8 *buf, size_t len, struct x509_name *name,			   const u8 **next){	struct asn1_hdr hdr;	const u8 *pos, *end, *set_pos, *set_end, *seq_pos, *seq_end;	struct asn1_oid oid;	char **fieldp;	/*	 * Name ::= CHOICE { RDNSequence }	 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName	 * RelativeDistinguishedName ::= SET OF AttributeTypeAndValue	 * AttributeTypeAndValue ::= SEQUENCE {	 *     type     AttributeType,	 *     value    AttributeValue	 * }	 * AttributeType ::= OBJECT IDENTIFIER	 * AttributeValue ::= ANY DEFINED BY AttributeType	 */	if (asn1_get_next(buf, len, &hdr) < 0 ||	    hdr.class != ASN1_CLASS_UNIVERSAL ||	    hdr.tag != ASN1_TAG_SEQUENCE) {		wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE "			   "(Name / RDNSequencer) - found class %d tag 0x%x",			   hdr.class, hdr.tag);		return -1;	}	pos = hdr.payload;	if (pos + hdr.length > buf + len)		return -1;	end = *next = pos + hdr.length;	while (pos < end) {		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||		    hdr.class != ASN1_CLASS_UNIVERSAL ||		    hdr.tag != ASN1_TAG_SET) {			wpa_printf(MSG_DEBUG, "X509: Expected SET "				   "(RelativeDistinguishedName) - found class "				   "%d tag 0x%x", hdr.class, hdr.tag);			x509_free_name(name);			return -1;		}		set_pos = hdr.payload;		pos = set_end = hdr.payload + hdr.length;		if (asn1_get_next(set_pos, set_end - set_pos, &hdr) < 0 ||		    hdr.class != ASN1_CLASS_UNIVERSAL ||		    hdr.tag != ASN1_TAG_SEQUENCE) {			wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE "				   "(AttributeTypeAndValue) - found class %d "				   "tag 0x%x", hdr.class, hdr.tag);			x509_free_name(name);			return -1;		}		seq_pos = hdr.payload;		seq_end = hdr.payload + hdr.length;		if (asn1_get_oid(seq_pos, seq_end - seq_pos, &oid, &seq_pos)) {			x509_free_name(name);			return -1;		}		if (asn1_get_next(seq_pos, seq_end - seq_pos, &hdr) < 0 ||		    hdr.class != ASN1_CLASS_UNIVERSAL) {			wpa_printf(MSG_DEBUG, "X509: Failed to parse "				   "AttributeValue");			x509_free_name(name);			return -1;		}		/* RFC 3280:		 * MUST: country, organization, organizational-unit,		 * distinguished name qualifier, state or province name,		 * common name, serial number.		 * SHOULD: locality, title, surname, given name, initials,		 * pseudonym, generation qualifier.		 * MUST: domainComponent (RFC 2247).		 */		fieldp = NULL;		if (oid.len == 4 &&		    oid.oid[0] == 2 && oid.oid[1] == 5 && oid.oid[2] == 4) {			/* id-at ::= 2.5.4 */			switch (oid.oid[3]) {			case 3:				/* commonName */				fieldp = &name->cn;				break;			case 6:				/*  countryName */				fieldp = &name->c;				break;			case 7:				/* localityName */				fieldp = &name->l;				break;			case 8:				/* stateOrProvinceName */				fieldp = &name->st;				break;			case 10:				/* organizationName */				fieldp = &name->o;				break;			case 11:				/* organizationalUnitName */				fieldp = &name->ou;				break;			}		} else if (oid.len == 7 &&			   oid.oid[0] == 1 && oid.oid[1] == 2 &&			   oid.oid[2] == 840 && oid.oid[3] == 113549 &&			   oid.oid[4] == 1 && oid.oid[5] == 9 &&			   oid.oid[6] == 1) {			/* 1.2.840.113549.1.9.1 - e-mailAddress */			fieldp = &name->email;		}		if (fieldp == NULL) {			wpa_hexdump(MSG_DEBUG, "X509: Unrecognized OID",				    (u8 *) oid.oid,				    oid.len * sizeof(oid.oid[0]));			wpa_hexdump_ascii(MSG_MSGDUMP, "X509: Attribute Data",					  hdr.payload, hdr.length);			continue;		}		os_free(*fieldp);		*fieldp = os_malloc(hdr.length + 1);		if (*fieldp == NULL) {			x509_free_name(name);			return -1;		}		os_memcpy(*fieldp, hdr.payload, hdr.length);		(*fieldp)[hdr.length] = '\0';	}	return 0;}/** * x509_name_string - Convert an X.509 certificate name into a string * @name: Name to convert * @buf: Buffer for the string * @len: Maximum buffer length */void x509_name_string(struct x509_name *name, char *buf, size_t len){	char *pos, *end;	int ret;	if (len == 0)		return;	pos = buf;	end = buf + len;	if (name->c) {		ret = os_snprintf(pos, end - pos, "C=%s, ", name->c);		if (ret < 0 || ret >= end - pos)			goto done;		pos += ret;	}	if (name->st) {		ret = os_snprintf(pos, end - pos, "ST=%s, ", name->st);		if (ret < 0 || ret >= end - pos)			goto done;		pos += ret;	}	if (name->l) {		ret = os_snprintf(pos, end - pos, "L=%s, ", name->l);		if (ret < 0 || ret >= end - pos)			goto done;		pos += ret;	}	if (name->o) {		ret = os_snprintf(pos, end - pos, "O=%s, ", name->o);		if (ret < 0 || ret >= end - pos)			goto done;		pos += ret;	}	if (name->ou) {		ret = os_snprintf(pos, end - pos, "OU=%s, ", name->ou);		if (ret < 0 || ret >= end - pos)			goto done;		pos += ret;	}	if (name->cn) {		ret = os_snprintf(pos, end - pos, "CN=%s, ", name->cn);		if (ret < 0 || ret >= end - pos)			goto done;		pos += ret;	}	if (pos > buf + 1 && pos[-1] == ' ' && pos[-2] == ',') {		*pos-- = '\0';		*pos-- = '\0';	}	if (name->email) {		ret = os_snprintf(pos, end - pos, "/emailAddress=%s",				  name->email);		if (ret < 0 || ret >= end - pos)			goto done;		pos += ret;	}done:	end[-1] = '\0';}static int x509_parse_time(const u8 *buf, size_t len, u8 asn1_tag,			   os_time_t *val){	const char *pos;	int year, month, day, hour, min, sec;	/*	 * Time ::= CHOICE {	 *     utcTime        UTCTime,	 *     generalTime    GeneralizedTime	 * }	 *	 * UTCTime: YYMMDDHHMMSSZ	 * GeneralizedTime: YYYYMMDDHHMMSSZ	 */	pos = (const char *) buf;	switch (asn1_tag) {	case ASN1_TAG_UTCTIME:		if (len != 13 || buf[12] != 'Z') {			wpa_hexdump_ascii(MSG_DEBUG, "X509: Unrecognized "					  "UTCTime format", buf, len);			return -1;		}		if (sscanf(pos, "%02d", &year) != 1) {			wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse "					  "UTCTime year", buf, len);			return -1;		}		if (year < 50)			year += 2000;		else			year += 1900;		pos += 2;		break;	case ASN1_TAG_GENERALIZEDTIME:		if (len != 15 || buf[14] != 'Z') {			wpa_hexdump_ascii(MSG_DEBUG, "X509: Unrecognized "					  "GeneralizedTime format", buf, len);			return -1;		}		if (sscanf(pos, "%04d", &year) != 1) {			wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse "					  "GeneralizedTime year", buf, len);			return -1;		}		pos += 4;

⌨️ 快捷键说明

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