summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2001-08-02 18:42:14 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2001-08-02 18:42:14 +0000
commit7f3662750ef4941e9e75647dcfb2634c7cc8aa33 (patch)
tree466e0abb409e6ccd4bf07745d671fccd0ce05be6
parentaf73a46729f6ebbb8546bf3c3125767e86c5c8ae (diff)
downloadgnutls-7f3662750ef4941e9e75647dcfb2634c7cc8aa33.tar.gz
added some kind of support for X509 Extensions
-rw-r--r--lib/auth_rsa.c6
-rw-r--r--lib/auth_x509.h1
-rw-r--r--lib/cert_verify.c5
-rw-r--r--lib/cert_verify.h2
-rw-r--r--lib/gnutls.h.in24
-rw-r--r--lib/gnutls_auth.c17
-rw-r--r--lib/gnutls_cert.c128
-rw-r--r--lib/gnutls_cert.h1
-rw-r--r--lib/gnutls_errors.c1
-rw-r--r--lib/gnutls_errors_int.h1
-rw-r--r--lib/gnutls_int.h10
-rw-r--r--lib/gnutls_record.c4
-rw-r--r--src/cli.c15
13 files changed, 167 insertions, 48 deletions
diff --git a/lib/auth_rsa.c b/lib/auth_rsa.c
index 1a410b4c6e..8fe746f037 100644
--- a/lib/auth_rsa.c
+++ b/lib/auth_rsa.c
@@ -455,11 +455,15 @@ int proc_rsa_certificate(GNUTLS_KEY key, opaque * data, int data_size)
ret = GNUTLS_CERT_NOT_TRUSTED;
ret = gnutls_verify_certificate( peer_certificate_list, peer_certificate_list_size,
- cred->ca_list, cred->ncas, NULL, 0, key->x509_cn);
+ cred->ca_list, cred->ncas, NULL, 0);
info->peer_certificate_status = ret;
info->peer_certificate_version = peer_certificate_list[0].version;
+
+ if ( peer_certificate_list[0].subjectAltName[0]!=0)
+ strcpy( info->subjectAltName, peer_certificate_list[0].subjectAltName);
+
info->peer_certificate_expiration_time = peer_certificate_list[0].expiration_time;
info->peer_certificate_activation_time = peer_certificate_list[0].activation_time;
diff --git a/lib/auth_x509.h b/lib/auth_x509.h
index d5ff1ec5ac..af120000a9 100644
--- a/lib/auth_x509.h
+++ b/lib/auth_x509.h
@@ -40,6 +40,7 @@ typedef struct {
int peer_certificate_version;
time_t peer_certificate_activation_time;
time_t peer_certificate_expiration_time;
+ char subjectAltName[X509_CN_SIZE];
} X509PKI_CLIENT_AUTH_INFO;
diff --git a/lib/cert_verify.c b/lib/cert_verify.c
index 024f2d984b..b58cbf74fb 100644
--- a/lib/cert_verify.c
+++ b/lib/cert_verify.c
@@ -306,7 +306,7 @@ int gnutls_verify_certificate2(gnutls_cert * cert, gnutls_cert * trusted_cas, in
int gnutls_verify_certificate( gnutls_cert * certificate_list,
int clist_size, gnutls_cert * trusted_cas, int tcas_size, void *CRLs,
- int crls_size, char* cn)
+ int crls_size)
{
int i = 0;
int expired = 0;
@@ -339,9 +339,6 @@ int gnutls_verify_certificate( gnutls_cert * certificate_list,
if (ret != GNUTLS_CERT_TRUSTED)
return ret;
- if ( strcmp( certificate_list[0].cert_info.common_name, cn) != 0)
- return GNUTLS_CERT_WRONG_CN;
-
if (expired != 0)
return GNUTLS_CERT_EXPIRED;
diff --git a/lib/cert_verify.h b/lib/cert_verify.h
index 878bda875a..99c88e3251 100644
--- a/lib/cert_verify.h
+++ b/lib/cert_verify.h
@@ -1,5 +1,5 @@
int gnutls_verify_certificate(gnutls_cert * certificate_list,
int clist_size, gnutls_cert * trusted_cas, int tcas_size, void *CRLs,
- int crls_size, char* cn);
+ int crls_size);
time_t _gnutls_utcTime2gtime(char *ttime);
time_t _gnutls_generalTime2gtime(char *ttime);
diff --git a/lib/gnutls.h.in b/lib/gnutls.h.in
index 6b6c6d2c89..d2570ca327 100644
--- a/lib/gnutls.h.in
+++ b/lib/gnutls.h.in
@@ -142,8 +142,6 @@ int gnutls_ext_set_dnsname( GNUTLS_STATE, const char* dnsname);
* authentication. This will be used while verifying the
* certificate
*/
-int gnutls_x509_set_cn( GNUTLS_STATE, const char* cn);
-
/* Credential structures for SRP - used in gnutls_set_cred(); */
@@ -185,15 +183,22 @@ typedef struct {
char username[256];
} SRP_SERVER_AUTH_INFO;
-typedef enum CertificateStatus { GNUTLS_CERT_TRUSTED=1, GNUTLS_CERT_NOT_TRUSTED, GNUTLS_CERT_EXPIRED, GNUTLS_CERT_WRONG_CN, GNUTLS_CERT_INVALID } CertificateStatus;
+typedef enum CertificateStatus { GNUTLS_CERT_TRUSTED=1, GNUTLS_CERT_NOT_TRUSTED, GNUTLS_CERT_EXPIRED, GNUTLS_CERT_INVALID } CertificateStatus;
+
+#define X509_CN_SIZE 256
+#define X509_C_SIZE 3
+#define X509_O_SIZE 256
+#define X509_OU_SIZE 256
+#define X509_L_SIZE 256
+#define X509_S_SIZE 256
typedef struct {
- char common_name[256];
- char country[3];
- char organization[256];
- char organizational_unit_name[256];
- char locality_name[256];
- char state_or_province_name[256];
+ char common_name[X509_CN_SIZE];
+ char country[X509_C_SIZE];
+ char organization[X509_O_SIZE];
+ char organizational_unit_name[X509_OU_SIZE];
+ char locality_name[X509_L_SIZE];
+ char state_or_province_name[X509_S_SIZE];
} gnutls_DN;
typedef struct {
@@ -203,6 +208,7 @@ typedef struct {
int peer_certificate_version;
time_t peer_certificate_activation_time;
time_t peer_certificate_expiration_time;
+ char subjectAltName[X509_CN_SIZE];
} X509PKI_CLIENT_AUTH_INFO;
diff --git a/lib/gnutls_auth.c b/lib/gnutls_auth.c
index b8abab6ccd..e9dfd0fcd1 100644
--- a/lib/gnutls_auth.c
+++ b/lib/gnutls_auth.c
@@ -182,20 +182,3 @@ const void* gnutls_get_auth_info( GNUTLS_STATE state) {
return state->gnutls_key->auth_info;
}
-/**
- * gnutls_x509_set_cn - Used to set the CN for X509 authentication
- * @state: is a &GNUTLS_STATE structure.
- * @cn: is a null terminated string that contains the peer's CN.
- *
- * This function is to be used by clients that want to verify
- * also the peer's Common Name (ie. the certificate may be verified,
- * but it may have been issued for someone else).
- **/
-int gnutls_x509_set_cn( GNUTLS_STATE state, const char* cn) {
-
- if (strlen( cn) >= X509_CN_SIZE) return GNUTLS_E_MEMORY_ERROR;
-
- strcpy( state->gnutls_key->x509_cn, cn);
-
- return 0;
-}
diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c
index add48fdaf3..3d2fa568a6 100644
--- a/lib/gnutls_cert.c
+++ b/lib/gnutls_cert.c
@@ -499,6 +499,7 @@ static int _read_rsa_params(opaque * der, int dersize, MPI ** params)
/* this function will convert up to 3 digit
* numbers to characters.
*/
+#define MAX_INT_DIGITS 4
void _gnutls_int2str(int k, char* data) {
if (k > 999) data[0] = 0;
else sprintf( data, "%d", k);
@@ -506,12 +507,14 @@ void _gnutls_int2str(int k, char* data) {
/* This function will attempt to read a Name
* ASN.1 structure. (Taken from Fabio's samples!)
+ *
+ * FIXME: These functions need carefull auditing
* --nmav
*/
static int _get_Name_type( node_asn *rasn, char *root, gnutls_DN * dn)
{
int k, k2, result, len;
- char name[128], str[1024], name2[128], counter[5], name3[128];
+ char name[128], str[1024], name2[128], counter[MAX_INT_DIGITS], name3[128];
k = 0;
do {
@@ -586,6 +589,121 @@ static int _get_Name_type( node_asn *rasn, char *root, gnutls_DN * dn)
return GNUTLS_E_ASN1_PARSING_ERROR;
}
+
+static int _parse_extension( gnutls_cert* cert, char* extnID, char* critical, char* extnValue, int extnValueLen) {
+ fprintf(stderr, "Extension: %s, %s\n", extnID, critical);
+
+ if (strcmp( extnID, "2 5 29 14")==0) { /* subject Key ID */
+ /* we don't use it */
+ return 0;
+ }
+
+ if (strcmp( extnID, "2 5 29 19")==0) { /* Basic Constraints */
+ /* we don't use it */
+ return 0;
+ }
+
+ if (strcmp( extnID, "2 5 29 17")==0) { /* subjectAltName */
+ strncpy( cert->subjectAltName, extnValue, sizeof( cert->subjectAltName)-1);
+ return 0;
+ }
+
+
+ if (strcmp( critical, "TRUE")==0) {
+ gnutls_assert();
+ return GNUTLS_E_X509_UNSUPPORTED_CRITICAL_EXTENSION;
+ }
+ return 0;
+
+}
+
+/* This function will attempt to parse Extensions in
+ * an X509v3 certificate
+ */
+static int _get_Ext_type( node_asn *rasn, char *root, gnutls_cert *cert)
+{
+ int k, result, len;
+ char name[128], name2[128], counter[MAX_INT_DIGITS];
+ char str[1024];
+ char critical[10];
+ char extnID[128];
+ char extnValue[128];
+
+ k = 0;
+ do {
+ k++;
+
+ strcpy(name, root);
+ strcat(name, ".?");
+ _gnutls_int2str(k, counter);
+ strcat(name, counter);
+
+ len = sizeof(str) - 1;
+ result = asn1_read_value( rasn, name, str, &len);
+
+ /* move to next
+ */
+
+ if (result==ASN_ELEMENT_NOT_FOUND) break;
+
+ do {
+
+ strcpy(name2, name);
+ strcat(name2, ".extnID");
+
+ len = sizeof(extnID) - 1;
+ result = asn1_read_value( rasn, name2, extnID, &len);
+
+ if (result==ASN_ELEMENT_NOT_FOUND) break;
+ else
+ if (result != ASN_OK) {
+ gnutls_assert();
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ strcpy(name2, name);
+ strcat(name2, ".critical");
+
+ len = sizeof(critical) - 1;
+ result = asn1_read_value( rasn, name2, critical, &len);
+
+ if (result==ASN_ELEMENT_NOT_FOUND) break;
+ else
+ if (result != ASN_OK) {
+ gnutls_assert();
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ strcpy(name2, name);
+ strcat(name2, ".extnValue");
+
+ len = sizeof( extnValue) - 1;
+ result = asn1_read_value( rasn, name2, extnValue, &len);
+
+ if (result==ASN_ELEMENT_NOT_FOUND) break;
+ else
+ if (result != ASN_OK) {
+ gnutls_assert();
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ /* Handle Extension */
+ if ( (result=_parse_extension( cert, extnID, critical, extnValue, len)) < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+
+ } while (0);
+ } while (1);
+
+ if (result==ASN_ELEMENT_NOT_FOUND)
+ return 0;
+ else
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+}
+
+
#define MAX_TIME 1024
static time_t _gnutls_get_time( node_asn* c2, char* root, char* when) {
opaque ttime[MAX_TIME];
@@ -754,12 +872,20 @@ return GNUTLS_E_UNIMPLEMENTED_FEATURE;
}
if ((result =
+ _get_Ext_type( c2, "certificate2.tbsCertificate.extensions", gCert)) < 0) {
+ gnutls_assert();
+ asn1_delete_structure(c2);
+ return result;
+ }
+
+ if ((result =
_get_Name_type( c2, "certificate2.tbsCertificate.issuer", &gCert->issuer_info)) < 0) {
gnutls_assert();
asn1_delete_structure(c2);
return result;
}
+
gCert->expiration_time = _gnutls_get_time( c2, "certificate2", "notAfter");
gCert->activation_time = _gnutls_get_time( c2, "certificate2", "notBefore");
diff --git a/lib/gnutls_cert.h b/lib/gnutls_cert.h
index 5e015229aa..fc7eb34bed 100644
--- a/lib/gnutls_cert.h
+++ b/lib/gnutls_cert.h
@@ -21,6 +21,7 @@ typedef struct {
gnutls_DN cert_info;
gnutls_DN issuer_info;
+ opaque subjectAltName[X509_CN_SIZE];
opaque signature[1024];
int signature_size;
diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c
index 5f4b5f953d..5d5324559e 100644
--- a/lib/gnutls_errors.c
+++ b/lib/gnutls_errors.c
@@ -77,6 +77,7 @@ static gnutls_error_entry error_algorithms[] = {
GNUTLS_ERROR_ENTRY( GNUTLS_E_ASN1_PARSING_ERROR, 1),
GNUTLS_ERROR_ENTRY( GNUTLS_E_ASN1_ERROR, 1),
GNUTLS_ERROR_ENTRY( GNUTLS_E_X509_CERTIFICATE_ERROR, 1),
+ GNUTLS_ERROR_ENTRY( GNUTLS_E_X509_UNSUPPORTED_CRITICAL_EXTENSION, 1),
GNUTLS_ERROR_ENTRY( GNUTLS_E_AGAIN, 0),
GNUTLS_ERROR_ENTRY( GNUTLS_E_GOT_HELLO_REQUEST, 0),
GNUTLS_ERROR_ENTRY( GNUTLS_E_GOT_APPLICATION_DATA, 0),
diff --git a/lib/gnutls_errors_int.h b/lib/gnutls_errors_int.h
index d186b2db61..0ab5dffea1 100644
--- a/lib/gnutls_errors_int.h
+++ b/lib/gnutls_errors_int.h
@@ -44,5 +44,6 @@
#define GNUTLS_E_PK_ENCRYPTION_FAILED -44
#define GNUTLS_E_PK_DECRYPTION_FAILED -45
#define GNUTLS_E_PK_SIGNATURE_FAILED -46
+#define GNUTLS_E_X509_UNSUPPORTED_CRITICAL_EXTENSION -47
#define GNUTLS_E_UNIMPLEMENTED_FEATURE -250
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 78dfdff428..3f13411865 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -29,10 +29,10 @@
#define WRITE_DEBUG
#define HARD_DEBUG
#define BUFFERS_DEBUG
-#define RECORD_DEBUG
+#define RECORD_DEBUG*/
#define HANDSHAKE_DEBUG
#define DEBUG
-*/
+
#define SOCKET int
#define LIST ...
@@ -62,7 +62,7 @@
#define HEADER_SIZE 5
#define MAX_RECV_SIZE 18432+HEADER_SIZE /* 2^14+2048+HEADER_SIZE */
-/* X509 */
+/* X509 - also in gnutls.h.in */
#define X509_CN_SIZE 256
#define X509_C_SIZE 3
#define X509_O_SIZE 256
@@ -108,7 +108,7 @@ typedef enum AlertDescription { GNUTLS_CLOSE_NOTIFY, GNUTLS_UNEXPECTED_MESSAGE=1
GNUTLS_INSUFFICIENT_SECURITY, GNUTLS_INTERNAL_ERROR=80, GNUTLS_USER_CANCELED=90,
GNUTLS_NO_RENEGOTIATION=100
} AlertDescription;
-typedef enum CertificateStatus { GNUTLS_CERT_TRUSTED=1, GNUTLS_CERT_NOT_TRUSTED, GNUTLS_CERT_EXPIRED, GNUTLS_CERT_WRONG_CN, GNUTLS_CERT_INVALID } CertificateStatus;
+typedef enum CertificateStatus { GNUTLS_CERT_TRUSTED=1, GNUTLS_CERT_NOT_TRUSTED, GNUTLS_CERT_EXPIRED, GNUTLS_CERT_INVALID } CertificateStatus;
typedef enum HandshakeType { GNUTLS_HELLO_REQUEST, GNUTLS_CLIENT_HELLO, GNUTLS_SERVER_HELLO,
GNUTLS_CERTIFICATE=11, GNUTLS_SERVER_KEY_EXCHANGE,
@@ -197,8 +197,6 @@ typedef struct {
opaque client_random[TLS_RANDOM_SIZE];
ProtocolVersion version;
- opaque x509_cn[X509_CN_SIZE];
-
AUTH_CRED* cred; /* used to specify keys/certificates etc */
} GNUTLS_KEY_A;
typedef GNUTLS_KEY_A* GNUTLS_KEY;
diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c
index de5638e1dc..3cdcd6e17d 100644
--- a/lib/gnutls_record.c
+++ b/lib/gnutls_record.c
@@ -359,6 +359,10 @@ int _gnutls_send_alert(SOCKET cd, GNUTLS_STATE state, AlertLevel level, AlertDes
* have been initiated using gnutls_handshake() or similar function.
* If 'wait' is non-zero then we will not wait for the other peer to
* close the TLS connection.
+ *
+ * This function actually sends the peer a closure alert, and if 'wait'
+ * is zero, will wait for the peer to reply (with a closure alert too).
+ *
**/
int gnutls_bye(SOCKET cd, GNUTLS_STATE state, int wait)
{
diff --git a/src/cli.c b/src/cli.c
index 61d0b9ecc3..6ed2da4162 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -46,8 +46,9 @@
PRINTX( "O:", x509_info->X.organization); \
PRINTX( "L:", x509_info->X.locality_name); \
PRINTX( "S:", x509_info->X.state_or_province_name); \
- PRINTX( "C:", x509_info->X.country);
-
+ PRINTX( "C:", x509_info->X.country); \
+ PRINTX( "SAN:", x509_info->subjectAltName);
+
static int print_info( GNUTLS_STATE state) {
const char *tmp;
const ANON_CLIENT_AUTH_INFO *dh_info;
@@ -75,9 +76,6 @@ const X509PKI_CLIENT_AUTH_INFO *x509_info;
case GNUTLS_CERT_TRUSTED:
printf("- Peer's X509 Certificate was verified\n");
break;
- case GNUTLS_CERT_WRONG_CN:
- printf("- Peer's X509 Certificate was verified but it does not match the server's name\n");
- break;
case GNUTLS_CERT_INVALID:
default:
printf("- Peer's X509 Certificate was invalid\n");
@@ -172,7 +170,7 @@ int main(int argc, char** argv)
gnutls_init(&state, GNUTLS_CLIENT);
gnutls_set_protocol_priority( state, GNUTLS_TLS1, GNUTLS_SSL3, 0);
- gnutls_set_cipher_priority( state, GNUTLS_3DES_CBC, GNUTLS_ARCFOUR, GNUTLS_RIJNDAEL_CBC, 0);
+ gnutls_set_cipher_priority( state, GNUTLS_3DES_CBC, GNUTLS_RIJNDAEL_CBC, 0);
gnutls_set_compression_priority( state, GNUTLS_ZLIB, GNUTLS_NULL_COMPRESSION, 0);
gnutls_set_kx_priority( state, GNUTLS_KX_RSA, GNUTLS_KX_SRP, GNUTLS_KX_DH_ANON, 0);
gnutls_set_mac_priority( state, GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0);
@@ -181,8 +179,7 @@ int main(int argc, char** argv)
gnutls_set_cred( state, GNUTLS_SRP, cred);
gnutls_set_cred( state, GNUTLS_X509PKI, xcred);
- gnutls_ext_set_dnsname( state, "localhost");
- gnutls_x509_set_cn( state, "localhost");
+// gnutls_ext_set_dnsname( state, "localhost");
ret = gnutls_handshake(sd, state);
@@ -225,7 +222,7 @@ int main(int argc, char** argv)
gnutls_init(&state, GNUTLS_CLIENT);
gnutls_set_protocol_priority( state, GNUTLS_TLS1, GNUTLS_SSL3, 0);
- gnutls_set_cipher_priority( state, GNUTLS_3DES_CBC, GNUTLS_TWOFISH_CBC, GNUTLS_RIJNDAEL_CBC, GNUTLS_ARCFOUR, 0);
+ gnutls_set_cipher_priority( state, GNUTLS_3DES_CBC, GNUTLS_TWOFISH_CBC, GNUTLS_RIJNDAEL_CBC, 0);
gnutls_set_compression_priority( state, GNUTLS_NULL_COMPRESSION, 0);
gnutls_set_kx_priority( state, GNUTLS_KX_RSA, GNUTLS_KX_SRP, GNUTLS_KX_DH_ANON, 0);