Search
j0ke.net Open Build Service
>
Projects
>
home:netmax
:
monitoring
>
openssl1
> openssl-CVE-2016-0798-101.patch
Sign Up
|
Log In
Username
Password
Cancel
Overview
Repositories
Revisions
Requests
Users
Advanced
Attributes
Meta
File openssl-CVE-2016-0798-101.patch of Package openssl1
commit 59a908f1e8380412a81392c468b83bf6071beb2a Author: Emilia Kasper <emilia@openssl.org> Date: Wed Feb 24 12:59:59 2016 +0100 CVE-2016-0798: avoid memory leak in SRP The SRP user database lookup method SRP_VBASE_get_by_user had confusing memory management semantics; the returned pointer was sometimes newly allocated, and sometimes owned by the callee. The calling code has no way of distinguishing these two cases. Specifically, SRP servers that configure a secret seed to hide valid login information are vulnerable to a memory leak: an attacker connecting with an invalid username can cause a memory leak of around 300 bytes per connection. Servers that do not configure SRP, or configure SRP but do not configure a seed are not vulnerable. In Apache, the seed directive is known as SSLSRPUnknownUserSeed. To mitigate the memory leak, the seed handling in SRP_VBASE_get_by_user is now disabled even if the user has configured a seed. Applications are advised to migrate to SRP_VBASE_get1_by_user. However, note that OpenSSL makes no strong guarantees about the indistinguishability of valid and invalid logins. In particular, computations are currently not carried out in constant time. Reviewed-by: Rich Salz <rsalz@openssl.org> Index: openssl-1.0.1i/apps/s_server.c =================================================================== --- openssl-1.0.1i.orig/apps/s_server.c 2016-02-26 09:45:21.967034547 +0100 +++ openssl-1.0.1i/apps/s_server.c 2016-02-26 09:55:55.582705403 +0100 @@ -413,6 +413,8 @@ static int MS_CALLBACK ssl_srp_server_param_cb(SSL *s, int *ad, void *arg) { srpsrvparm *p = (srpsrvparm *)arg; + int ret = SSL3_AL_FATAL; + if (p->login == NULL && p->user == NULL ) { p->login = SSL_get_srp_username(s); @@ -423,19 +425,23 @@ if (p->user == NULL) { BIO_printf(bio_err, "User %s doesn't exist\n", p->login); - return SSL3_AL_FATAL; + goto err; } + if (SSL_set_srp_server_param(s, p->user->N, p->user->g, p->user->s, p->user->v, p->user->info) < 0) { *ad = SSL_AD_INTERNAL_ERROR; - return SSL3_AL_FATAL; + goto err; } BIO_printf(bio_err, "SRP parameters set: username = \"%s\" info=\"%s\" \n", p->login,p->user->info); - /* need to check whether there are memory leaks */ + ret = SSL_ERROR_NONE; + +err: + SRP_user_pwd_free(p->user); p->user = NULL; p->login = NULL; - return SSL_ERROR_NONE; + return ret; } #endif @@ -2300,7 +2306,8 @@ while (SSL_get_error(con,k) == SSL_ERROR_WANT_X509_LOOKUP) { BIO_printf(bio_s_out,"LOOKUP renego during write\n"); - srp_callback_parm.user = SRP_VBASE_get_by_user(srp_callback_parm.vb, srp_callback_parm.login); + SRP_user_pwd_free(srp_callback_parm.user); + srp_callback_parm.user = SRP_VBASE_get1_by_user(srp_callback_parm.vb, srp_callback_parm.login); if (srp_callback_parm.user) BIO_printf(bio_s_out,"LOOKUP done %s\n",srp_callback_parm.user->info); else @@ -2359,7 +2366,8 @@ while (SSL_get_error(con,i) == SSL_ERROR_WANT_X509_LOOKUP) { BIO_printf(bio_s_out,"LOOKUP renego during read\n"); - srp_callback_parm.user = SRP_VBASE_get_by_user(srp_callback_parm.vb, srp_callback_parm.login); + SRP_user_pwd_free(srp_callback_parm.user); + srp_callback_parm.user = SRP_VBASE_get1_by_user(srp_callback_parm.vb, srp_callback_parm.login); if (srp_callback_parm.user) BIO_printf(bio_s_out,"LOOKUP done %s\n",srp_callback_parm.user->info); else @@ -2448,7 +2456,8 @@ while (i <= 0 && SSL_get_error(con,i) == SSL_ERROR_WANT_X509_LOOKUP) { BIO_printf(bio_s_out,"LOOKUP during accept %s\n",srp_callback_parm.login); - srp_callback_parm.user = SRP_VBASE_get_by_user(srp_callback_parm.vb, srp_callback_parm.login); + SRP_user_pwd_free(srp_callback_parm.user); + srp_callback_parm.user = SRP_VBASE_get1_by_user(srp_callback_parm.vb, srp_callback_parm.login); if (srp_callback_parm.user) BIO_printf(bio_s_out,"LOOKUP done %s\n",srp_callback_parm.user->info); else @@ -2690,7 +2699,8 @@ while (i <= 0 && SSL_get_error(con,i) == SSL_ERROR_WANT_X509_LOOKUP) { BIO_printf(bio_s_out,"LOOKUP during accept %s\n",srp_callback_parm.login); - srp_callback_parm.user = SRP_VBASE_get_by_user(srp_callback_parm.vb, srp_callback_parm.login); + SRP_user_pwd_free(srp_callback_parm.user); + srp_callback_parm.user = SRP_VBASE_get1_by_user(srp_callback_parm.vb, srp_callback_parm.login); if (srp_callback_parm.user) BIO_printf(bio_s_out,"LOOKUP done %s\n",srp_callback_parm.user->info); else Index: openssl-1.0.1i/crypto/srp/srp.h =================================================================== --- openssl-1.0.1i.orig/crypto/srp/srp.h 2016-02-26 09:45:21.967034547 +0100 +++ openssl-1.0.1i/crypto/srp/srp.h 2016-02-26 09:59:30.355828026 +0100 @@ -83,16 +83,21 @@ typedef struct SRP_user_pwd_st { + /* Owned by us. */ char *id; BIGNUM *s; BIGNUM *v; + /* Not owned by us. */ const BIGNUM *g; const BIGNUM *N; + /* Owned by us. */ char *info; } SRP_user_pwd; DECLARE_STACK_OF(SRP_user_pwd) +void SRP_user_pwd_free(SRP_user_pwd *user_pwd); + typedef struct SRP_VBASE_st { STACK_OF(SRP_user_pwd) *users_pwd; @@ -117,7 +122,12 @@ SRP_VBASE *SRP_VBASE_new(char *seed_key); int SRP_VBASE_free(SRP_VBASE *vb); int SRP_VBASE_init(SRP_VBASE *vb, char * verifier_file); + +/* This method ignores the configured seed and fails for an unknown user. */ SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username); +/* NOTE: unlike in SRP_VBASE_get_by_user, caller owns the returned pointer.*/ +SRP_user_pwd *SRP_VBASE_get1_by_user(SRP_VBASE *vb, char *username); + char *SRP_create_verifier(const char *user, const char *pass, char **salt, char **verifier, const char *N, const char *g); int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt, BIGNUM **verifier, BIGNUM *N, BIGNUM *g); Index: openssl-1.0.1i/crypto/srp/srp_vfy.c =================================================================== --- openssl-1.0.1i.orig/crypto/srp/srp_vfy.c 2016-02-26 09:45:14.998989106 +0100 +++ openssl-1.0.1i/crypto/srp/srp_vfy.c 2016-02-26 10:01:19.740387786 +0100 @@ -182,7 +182,7 @@ return olddst; } -static void SRP_user_pwd_free(SRP_user_pwd *user_pwd) +void SRP_user_pwd_free(SRP_user_pwd *user_pwd) { if (user_pwd == NULL) return; @@ -244,6 +244,24 @@ return (vinfo->s != NULL && vinfo->v != NULL) ; } +static SRP_user_pwd *srp_user_pwd_dup(SRP_user_pwd *src) +{ + SRP_user_pwd *ret; + + if (src == NULL) + return NULL; + if ((ret = SRP_user_pwd_new()) == NULL) + return NULL; + + SRP_user_pwd_set_gN(ret, src->g, src->N); + if (!SRP_user_pwd_set_ids(ret, src->id, src->info) + || !SRP_user_pwd_set_sv_BN(ret, BN_dup(src->s), BN_dup(src->v))) { + SRP_user_pwd_free(ret); + return NULL; + } + return ret; +} + SRP_VBASE *SRP_VBASE_new(char *seed_key) { SRP_VBASE *vb = (SRP_VBASE *) OPENSSL_malloc(sizeof(SRP_VBASE)); @@ -474,23 +492,51 @@ } - -SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username) +static SRP_user_pwd *find_user(SRP_VBASE *vb, char *username) { int i; SRP_user_pwd *user; - unsigned char digv[SHA_DIGEST_LENGTH]; - unsigned char digs[SHA_DIGEST_LENGTH]; - EVP_MD_CTX ctxt; if (vb == NULL) return NULL; + for(i = 0; i < sk_SRP_user_pwd_num(vb->users_pwd); i++) { user = sk_SRP_user_pwd_value(vb->users_pwd, i); if (strcmp(user->id,username)==0) return user; } + + return NULL; +} + +/* + * This method ignores the configured seed and fails for an unknown user. + * Ownership of the returned pointer is not released to the caller. + * In other words, caller must not free the result. + */ +SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username) +{ + return find_user(vb, username); +} + +/* + * Ownership of the returned pointer is released to the caller. + * In other words, caller must free the result once done. + */ +SRP_user_pwd *SRP_VBASE_get1_by_user(SRP_VBASE *vb, char *username) +{ + SRP_user_pwd *user; + unsigned char digv[SHA_DIGEST_LENGTH]; + unsigned char digs[SHA_DIGEST_LENGTH]; + EVP_MD_CTX ctxt; + + if (vb == NULL) + return NULL; + + if ((user = find_user(vb, username)) != NULL) + return srp_user_pwd_dup(user); + if ((vb->seed_key == NULL) || (vb->default_g == NULL) || (vb->default_N == NULL)) Index: openssl-1.0.1i/util/libeay.num =================================================================== --- openssl-1.0.1i.orig/util/libeay.num 2016-02-26 09:45:21.967034547 +0100 +++ openssl-1.0.1i/util/libeay.num 2016-02-26 09:58:37.423554553 +0100 @@ -1806,6 +1806,8 @@ ASN1_UTCTIME_get 2350 NOEXIST::FUNCTION: X509_REQ_digest 2362 EXIST::FUNCTION:EVP X509_CRL_digest 2391 EXIST::FUNCTION:EVP +SRP_VBASE_get1_by_user 2393 EXIST::FUNCTION:SRP +SRP_user_pwd_free 2394 EXIST::FUNCTION:SRP d2i_ASN1_SET_OF_PKCS7 2397 NOEXIST::FUNCTION: EVP_CIPHER_CTX_set_key_length 2399 EXIST::FUNCTION: EVP_CIPHER_CTX_ctrl 2400 EXIST::FUNCTION: