diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2001-08-02 18:42:14 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2001-08-02 18:42:14 +0000 |
commit | 7f3662750ef4941e9e75647dcfb2634c7cc8aa33 (patch) | |
tree | 466e0abb409e6ccd4bf07745d671fccd0ce05be6 | |
parent | af73a46729f6ebbb8546bf3c3125767e86c5c8ae (diff) | |
download | gnutls-7f3662750ef4941e9e75647dcfb2634c7cc8aa33.tar.gz |
added some kind of support for X509 Extensions
-rw-r--r-- | lib/auth_rsa.c | 6 | ||||
-rw-r--r-- | lib/auth_x509.h | 1 | ||||
-rw-r--r-- | lib/cert_verify.c | 5 | ||||
-rw-r--r-- | lib/cert_verify.h | 2 | ||||
-rw-r--r-- | lib/gnutls.h.in | 24 | ||||
-rw-r--r-- | lib/gnutls_auth.c | 17 | ||||
-rw-r--r-- | lib/gnutls_cert.c | 128 | ||||
-rw-r--r-- | lib/gnutls_cert.h | 1 | ||||
-rw-r--r-- | lib/gnutls_errors.c | 1 | ||||
-rw-r--r-- | lib/gnutls_errors_int.h | 1 | ||||
-rw-r--r-- | lib/gnutls_int.h | 10 | ||||
-rw-r--r-- | lib/gnutls_record.c | 4 | ||||
-rw-r--r-- | src/cli.c | 15 |
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) { @@ -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); |