From 7a71af86ce75751f3cb2e9e9e3f2e0715b39b101 Mon Sep 17 00:00:00 2001 From: Ben Laurie Date: Thu, 7 Jun 2012 13:20:47 +0000 Subject: [PATCH] Rearrange and test authz extension. --- apps/s_server.c | 33 +------------ ssl/ssl.h | 10 ++++ ssl/ssl_err.c | 2 + ssl/ssl_rsa.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 139 insertions(+), 32 deletions(-) diff --git a/apps/s_server.c b/apps/s_server.c index 58c70afca0..7881083c2e 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -316,8 +316,6 @@ static int cert_chain = 0; #ifndef OPENSSL_NO_TLSEXT static BIO *authz_in = NULL; static const char *s_authz_file = NULL; -static unsigned char *authz = NULL; -static size_t authz_length; #endif #ifndef OPENSSL_NO_PSK @@ -1501,33 +1499,6 @@ bad: next_proto.data = NULL; } # endif - if (s_authz_file != NULL) - { - /* Allow authzs up to 64KB bytes. */ - static const size_t authz_limit = 65536; - - authz_in = BIO_new(BIO_s_file_internal()); - if (authz_in == NULL) - { - ERR_print_errors(bio_err); - goto end; - } - - if (BIO_read_filename(authz_in, s_authz_file) <= 0) - { - ERR_print_errors(bio_err); - goto end; - } - authz = OPENSSL_malloc(authz_limit); - authz_length = BIO_read(authz_in, authz, authz_limit); - if (authz_length == authz_limit || authz_length <= 0) - { - BIO_printf(bio_err, "authz too large\n"); - goto end; - } - BIO_free(authz_in); - authz_in = NULL; - } #endif /* OPENSSL_NO_TLSEXT */ } @@ -1828,7 +1799,7 @@ bad: if (!set_cert_key_stuff(ctx, s_cert, s_key, s_chain)) goto end; #ifndef OPENSSL_NO_TLSEXT - if (authz != NULL && !SSL_CTX_use_authz(ctx, authz, authz_length)) + if (s_authz_file != NULL && !SSL_CTX_use_authz_file(ctx, s_authz_file)) goto end; #endif #ifndef OPENSSL_NO_TLSEXT @@ -2025,8 +1996,6 @@ end: X509_free(s_cert2); if (s_key2) EVP_PKEY_free(s_key2); - if (authz != NULL) - OPENSSL_free(authz); if (authz_in != NULL) BIO_free(authz_in); #endif diff --git a/ssl/ssl.h b/ssl/ssl.h index 4a9fa89cd6..42bc51ea40 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -1782,8 +1782,16 @@ int SSL_use_certificate(SSL *ssl, X509 *x); int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len); #ifndef OPENSSL_NO_TLSEXT +/* Set authz data for the current active cert. */ int SSL_CTX_use_authz(SSL_CTX *ctx, unsigned char *authz, size_t authz_length); int SSL_use_authz(SSL *ssl, unsigned char *authz, size_t authz_length); +/* Get the authz of type 'type' associated with the current active cert. */ +const unsigned char *SSL_CTX_get_authz_data(SSL_CTX *ctx, unsigned char type, + size_t *data_length); +#ifndef OPENSSL_NO_STDIO +int SSL_CTX_use_authz_file(SSL_CTX *ctx, const char *file); +int SSL_use_authz_file(SSL *ssl, const char *file); +#endif #endif #ifndef OPENSSL_NO_STDIO @@ -2137,6 +2145,7 @@ void ERR_load_SSL_strings(void); /* Error codes for the SSL functions. */ /* Function codes. */ +#define SSL_F_AUTHZ_FIND_DATA 330 #define SSL_F_AUTHZ_VALIDATE 323 #define SSL_F_CLIENT_CERTIFICATE 100 #define SSL_F_CLIENT_FINISHED 167 @@ -2180,6 +2189,7 @@ void ERR_load_SSL_strings(void); #define SSL_F_GET_SERVER_HELLO 109 #define SSL_F_GET_SERVER_VERIFY 110 #define SSL_F_I2D_SSL_SESSION 111 +#define SSL_F_READ_AUTHZ 329 #define SSL_F_READ_N 112 #define SSL_F_REQUEST_CERTIFICATE 113 #define SSL_F_SERVER_FINISH 239 diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index ce004558a2..e6736fb101 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -70,6 +70,7 @@ static ERR_STRING_DATA SSL_str_functs[]= { +{ERR_FUNC(SSL_F_AUTHZ_FIND_DATA), "AUTHZ_FIND_DATA"}, {ERR_FUNC(SSL_F_AUTHZ_VALIDATE), "AUTHZ_VALIDATE"}, {ERR_FUNC(SSL_F_CLIENT_CERTIFICATE), "CLIENT_CERTIFICATE"}, {ERR_FUNC(SSL_F_CLIENT_FINISHED), "CLIENT_FINISHED"}, @@ -113,6 +114,7 @@ static ERR_STRING_DATA SSL_str_functs[]= {ERR_FUNC(SSL_F_GET_SERVER_HELLO), "GET_SERVER_HELLO"}, {ERR_FUNC(SSL_F_GET_SERVER_VERIFY), "GET_SERVER_VERIFY"}, {ERR_FUNC(SSL_F_I2D_SSL_SESSION), "i2d_SSL_SESSION"}, +{ERR_FUNC(SSL_F_READ_AUTHZ), "READ_AUTHZ"}, {ERR_FUNC(SSL_F_READ_N), "READ_N"}, {ERR_FUNC(SSL_F_REQUEST_CERTIFICATE), "REQUEST_CERTIFICATE"}, {ERR_FUNC(SSL_F_SERVER_FINISH), "SERVER_FINISH"}, diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c index 855952d54c..1babdef3c6 100644 --- a/ssl/ssl_rsa.c +++ b/ssl/ssl_rsa.c @@ -855,6 +855,46 @@ static char authz_validate(const unsigned char *authz, size_t length) } } +static const unsigned char *authz_find_data(const unsigned char *authz, + size_t authz_length, + unsigned char data_type, + size_t *data_length) + { + if (authz == NULL) return NULL; + if (!authz_validate(authz, authz_length)) + { + SSLerr(SSL_F_AUTHZ_FIND_DATA,SSL_R_INVALID_AUTHZ_DATA); + return NULL; + } + + for (;;) + { + unsigned char type; + unsigned short len; + if (!authz_length) + return NULL; + + type = *(authz++); + authz_length--; + + /* We've validated the authz data, so we don't have to + * check again that we have enough bytes left. */ + len = ((unsigned short) authz[0]) << 8 | + ((unsigned short) authz[1]); + authz += 2; + authz_length -= 2; + if (type == data_type) + { + *data_length = len; + return authz; + } + authz += len; + authz_length -= len; + } + /* No match */ + return NULL; + } + static int ssl_set_authz(CERT *c, unsigned char *authz, size_t authz_length) { CERT_PKEY *current_key = c->key; @@ -901,4 +941,90 @@ int SSL_use_authz(SSL *ssl, unsigned char *authz, size_t authz_length) } return ssl_set_authz(ssl->cert, authz, authz_length); } + +const unsigned char *SSL_CTX_get_authz_data(SSL_CTX *ctx, unsigned char type, + size_t *data_length) + { + CERT_PKEY *current_key; + + if (ctx->cert == NULL) + return NULL; + current_key = ctx->cert->key; + if (current_key->authz == NULL) + return NULL; + return authz_find_data(current_key->authz, + current_key->authz_length, type, data_length); + } + +#ifndef OPENSSL_NO_STDIO +/* read_authz returns a newly allocated buffer with authz data */ +static unsigned char *read_authz(const char *file, size_t *authz_length) + { + BIO *authz_in = NULL; + unsigned char *authz = NULL; + /* Allow authzs up to 64KB. */ + static const size_t authz_limit = 65536; + size_t read_length; + unsigned char *ret = NULL; + + authz_in = BIO_new(BIO_s_file_internal()); + if (authz_in == NULL) + { + SSLerr(SSL_F_READ_AUTHZ,ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(authz_in,file) <= 0) + { + SSLerr(SSL_F_READ_AUTHZ,ERR_R_SYS_LIB); + goto end; + } + + authz = OPENSSL_malloc(authz_limit); + read_length = BIO_read(authz_in, authz, authz_limit); + if (read_length == authz_limit || read_length <= 0) + { + SSLerr(SSL_F_READ_AUTHZ,SSL_R_AUTHZ_DATA_TOO_LARGE); + OPENSSL_free(authz); + goto end; + } + *authz_length = read_length; + ret = authz; +end: + if (authz_in != NULL) BIO_free(authz_in); + return ret; + } + +int SSL_CTX_use_authz_file(SSL_CTX *ctx, const char *file) + { + unsigned char *authz = NULL; + size_t authz_length = 0; + int ret; + + authz = read_authz(file, &authz_length); + if (authz == NULL) + return 0; + + ret = SSL_CTX_use_authz(ctx, authz, authz_length); + /* SSL_CTX_use_authz makes a local copy of the authz. */ + OPENSSL_free(authz); + return ret; + } + +int SSL_use_authz_file(SSL *ssl, const char *file) + { + unsigned char *authz = NULL; + size_t authz_length = 0; + int ret; + + authz = read_authz(file, &authz_length); + if (authz == NULL) + return 0; + + ret = SSL_use_authz(ssl, authz, authz_length); + /* SSL_use_authz makes a local copy of the authz. */ + OPENSSL_free(authz); + return ret; + } +#endif /* OPENSSL_NO_STDIO */ #endif /* OPENSSL_NO_TLSEXT */ -- 2.34.1