{"schema":"libjg2-1",
"vpath":"/git/",
"avatar":"/git/avatar/",
"alang":"",
"gen_ut":1756236721,
"reponame":"openssl",
"desc":"OpenSSL",
"owner": { "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" },"url":"https://warmcat.com/repo/openssl",
"f":3,
"items": [
{"schema":"libjg2-1",
"cid":"750c751b5fcf41e13a316286f8c1815e",
"commit": {"type":"commit",
"time": 1456411368,
"time_ofs": 60,
"oid_tree": { "oid": "83e686e480f176176595a3b2f388be366b774b08", "alias": []},
"oid":{ "oid": "380f18ed5f140e0ae1b68f3ab8f4f7c395658d9e", "alias": []},
"msg": "CVE-2016-0798: avoid memory leak in SRP",
"sig_commit": { "git_time": { "time": 1456411368, "offset": 60 }, "name": "Emilia Kasper", "email": "emilia@openssl.org", "md5": "ed7c7cd0bbbda5ebcb1a10a4000e62ce" },
"sig_author": { "git_time": { "time": 1456315199, "offset": 60 }, "name": "Emilia Kasper", "email": "emilia@openssl.org", "md5": "ed7c7cd0bbbda5ebcb1a10a4000e62ce" }},
"body": "CVE-2016-0798: avoid memory leak in SRP\n\nThe SRP user database lookup method SRP_VBASE_get_by_user had confusing\nmemory management semantics; the returned pointer was sometimes newly\nallocated, and sometimes owned by the callee. The calling code has no\nway of distinguishing these two cases.\n\nSpecifically, SRP servers that configure a secret seed to hide valid\nlogin information are vulnerable to a memory leak: an attacker\nconnecting with an invalid username can cause a memory leak of around\n300 bytes per connection.\n\nServers that do not configure SRP, or configure SRP but do not configure\na seed are not vulnerable.\n\nIn Apache, the seed directive is known as SSLSRPUnknownUserSeed.\n\nTo mitigate the memory leak, the seed handling in SRP_VBASE_get_by_user\nis now disabled even if the user has configured a seed.\n\nApplications are advised to migrate to SRP_VBASE_get1_by_user. However,\nnote that OpenSSL makes no strong guarantees about the\nindistinguishability of valid and invalid logins. In particular,\ncomputations are currently not carried out in constant time.\n\nReviewed-by: Rich Salz \u003crsalz@openssl.org\u003e\n"
,
"diff": "diff --git a/CHANGES b/CHANGES\nindex d849648..51e7b08 100644\n--- a/CHANGES\n+++ b/CHANGES\n@@ -4,6 +4,21 @@\n \n Changes between 1.0.2f and 1.1.0 [xx XXX xxxx]\n \n+ *) Deprecate SRP_VBASE_get_by_user.\n+ SRP_VBASE_get_by_user had inconsistent memory management behaviour.\n+ In order to fix an unavoidable memory leak (CVE-2016-0798),\n+ SRP_VBASE_get_by_user was changed to ignore the \u0022fake user\u0022 SRP\n+ seed, even if the seed is configured.\n+\n+ Users should use SRP_VBASE_get1_by_user instead. Note that in\n+ SRP_VBASE_get1_by_user, caller must free the returned value. Note\n+ also that even though configuring the SRP seed attempts to hide\n+ invalid usernames by continuing the handshake with fake\n+ credentials, this behaviour is not constant time and no strong\n+ guarantees are made that the handshake is indistinguishable from\n+ that of a valid user.\n+ [Emilia Käsper]\n+\n *) Configuration change; it's now possible to build dynamic engines\n without having to build shared libraries and vice versa. This\n only applies to the engines in engines/, those in crypto/engine/\ndiff --git a/apps/s_server.c b/apps/s_server.c\nindex 1380628..6645dc8 100644\n--- a/apps/s_server.c\n+++ b/apps/s_server.c\n@@ -352,6 +352,8 @@ typedef struct srpsrvparm_st {\n static int ssl_srp_server_param_cb(SSL *s, int *ad, void *arg)\n {\n srpsrvparm *p \u003d (srpsrvparm *) arg;\n+ int ret \u003d SSL3_AL_FATAL;\n+\n if (p-\u003elogin \u003d\u003d NULL \u0026\u0026 p-\u003euser \u003d\u003d NULL) {\n p-\u003elogin \u003d SSL_get_srp_username(s);\n BIO_printf(bio_err, \u0022SRP username \u003d \u005c\u0022%s\u005c\u0022\u005cn\u0022, p-\u003elogin);\n@@ -360,21 +362,25 @@ static int ssl_srp_server_param_cb(SSL *s, int *ad, void *arg)\n \n if (p-\u003euser \u003d\u003d NULL) {\n BIO_printf(bio_err, \u0022User %s doesn't exist\u005cn\u0022, p-\u003elogin);\n- return SSL3_AL_FATAL;\n+ goto err;\n }\n+\n if (SSL_set_srp_server_param\n (s, p-\u003euser-\u003eN, p-\u003euser-\u003eg, p-\u003euser-\u003es, p-\u003euser-\u003ev,\n p-\u003euser-\u003einfo) \u003c 0) {\n *ad \u003d SSL_AD_INTERNAL_ERROR;\n- return SSL3_AL_FATAL;\n+ goto err;\n }\n BIO_printf(bio_err,\n \u0022SRP parameters set: username \u003d \u005c\u0022%s\u005c\u0022 info\u003d\u005c\u0022%s\u005c\u0022 \u005cn\u0022,\n p-\u003elogin, p-\u003euser-\u003einfo);\n- /* need to check whether there are memory leaks */\n+ ret \u003d SSL_ERROR_NONE;\n+\n+err:\n+ SRP_user_pwd_free(p-\u003euser);\n p-\u003euser \u003d NULL;\n p-\u003elogin \u003d NULL;\n- return SSL_ERROR_NONE;\n+ return ret;\n }\n \n #endif\n@@ -2325,9 +2331,10 @@ static int sv_body(int s, int stype, unsigned char *context)\n #ifndef OPENSSL_NO_SRP\n while (SSL_get_error(con, k) \u003d\u003d SSL_ERROR_WANT_X509_LOOKUP) {\n BIO_printf(bio_s_out, \u0022LOOKUP renego during write\u005cn\u0022);\n+ SRP_user_pwd_free(srp_callback_parm.user);\n srp_callback_parm.user \u003d\n- SRP_VBASE_get_by_user(srp_callback_parm.vb,\n- srp_callback_parm.login);\n+ SRP_VBASE_get1_by_user(srp_callback_parm.vb,\n+ srp_callback_parm.login);\n if (srp_callback_parm.user)\n BIO_printf(bio_s_out, \u0022LOOKUP done %s\u005cn\u0022,\n srp_callback_parm.user-\u003einfo);\n@@ -2393,9 +2400,10 @@ static int sv_body(int s, int stype, unsigned char *context)\n #ifndef OPENSSL_NO_SRP\n while (SSL_get_error(con, i) \u003d\u003d SSL_ERROR_WANT_X509_LOOKUP) {\n BIO_printf(bio_s_out, \u0022LOOKUP renego during read\u005cn\u0022);\n+ SRP_user_pwd_free(srp_callback_parm.user);\n srp_callback_parm.user \u003d\n- SRP_VBASE_get_by_user(srp_callback_parm.vb,\n- srp_callback_parm.login);\n+ SRP_VBASE_get1_by_user(srp_callback_parm.vb,\n+ srp_callback_parm.login);\n if (srp_callback_parm.user)\n BIO_printf(bio_s_out, \u0022LOOKUP done %s\u005cn\u0022,\n srp_callback_parm.user-\u003einfo);\n@@ -2520,9 +2528,10 @@ static int init_ssl_connection(SSL *con)\n while (i \u003c\u003d 0 \u0026\u0026 SSL_get_error(con, i) \u003d\u003d SSL_ERROR_WANT_X509_LOOKUP) {\n BIO_printf(bio_s_out, \u0022LOOKUP during accept %s\u005cn\u0022,\n srp_callback_parm.login);\n+ SRP_user_pwd_free(srp_callback_parm.user);\n srp_callback_parm.user \u003d\n- SRP_VBASE_get_by_user(srp_callback_parm.vb,\n- srp_callback_parm.login);\n+ SRP_VBASE_get1_by_user(srp_callback_parm.vb,\n+ srp_callback_parm.login);\n if (srp_callback_parm.user)\n BIO_printf(bio_s_out, \u0022LOOKUP done %s\u005cn\u0022,\n srp_callback_parm.user-\u003einfo);\n@@ -2732,9 +2741,10 @@ static int www_body(int s, int stype, unsigned char *context)\n if (BIO_should_io_special(io)\n \u0026\u0026 BIO_get_retry_reason(io) \u003d\u003d BIO_RR_SSL_X509_LOOKUP) {\n BIO_printf(bio_s_out, \u0022LOOKUP renego during read\u005cn\u0022);\n+ SRP_user_pwd_free(srp_callback_parm.user);\n srp_callback_parm.user \u003d\n- SRP_VBASE_get_by_user(srp_callback_parm.vb,\n- srp_callback_parm.login);\n+ SRP_VBASE_get1_by_user(srp_callback_parm.vb,\n+ srp_callback_parm.login);\n if (srp_callback_parm.user)\n BIO_printf(bio_s_out, \u0022LOOKUP done %s\u005cn\u0022,\n srp_callback_parm.user-\u003einfo);\n@@ -3093,9 +3103,10 @@ static int rev_body(int s, int stype, unsigned char *context)\n if (BIO_should_io_special(io)\n \u0026\u0026 BIO_get_retry_reason(io) \u003d\u003d BIO_RR_SSL_X509_LOOKUP) {\n BIO_printf(bio_s_out, \u0022LOOKUP renego during accept\u005cn\u0022);\n+ SRP_user_pwd_free(srp_callback_parm.user);\n srp_callback_parm.user \u003d\n- SRP_VBASE_get_by_user(srp_callback_parm.vb,\n- srp_callback_parm.login);\n+ SRP_VBASE_get1_by_user(srp_callback_parm.vb,\n+ srp_callback_parm.login);\n if (srp_callback_parm.user)\n BIO_printf(bio_s_out, \u0022LOOKUP done %s\u005cn\u0022,\n srp_callback_parm.user-\u003einfo);\n@@ -3121,9 +3132,10 @@ static int rev_body(int s, int stype, unsigned char *context)\n if (BIO_should_io_special(io)\n \u0026\u0026 BIO_get_retry_reason(io) \u003d\u003d BIO_RR_SSL_X509_LOOKUP) {\n BIO_printf(bio_s_out, \u0022LOOKUP renego during read\u005cn\u0022);\n+ SRP_user_pwd_free(srp_callback_parm.user);\n srp_callback_parm.user \u003d\n- SRP_VBASE_get_by_user(srp_callback_parm.vb,\n- srp_callback_parm.login);\n+ SRP_VBASE_get1_by_user(srp_callback_parm.vb,\n+ srp_callback_parm.login);\n if (srp_callback_parm.user)\n BIO_printf(bio_s_out, \u0022LOOKUP done %s\u005cn\u0022,\n srp_callback_parm.user-\u003einfo);\ndiff --git a/crypto/srp/srp_vfy.c b/crypto/srp/srp_vfy.c\nindex 0a9de14..0d3da7e 100644\n--- a/crypto/srp/srp_vfy.c\n+++ b/crypto/srp/srp_vfy.c\n@@ -184,7 +184,7 @@ static char *t_tob64(char *dst, const unsigned char *src, int size)\n return olddst;\n }\n \n-static void SRP_user_pwd_free(SRP_user_pwd *user_pwd)\n+void SRP_user_pwd_free(SRP_user_pwd *user_pwd)\n {\n if (user_pwd \u003d\u003d NULL)\n return;\n@@ -246,6 +246,24 @@ static int SRP_user_pwd_set_sv_BN(SRP_user_pwd *vinfo, BIGNUM *s, BIGNUM *v)\n return (vinfo-\u003es !\u003d NULL \u0026\u0026 vinfo-\u003ev !\u003d NULL);\n }\n \n+static SRP_user_pwd *srp_user_pwd_dup(SRP_user_pwd *src)\n+{\n+ SRP_user_pwd *ret;\n+\n+ if (src \u003d\u003d NULL)\n+ return NULL;\n+ if ((ret \u003d SRP_user_pwd_new()) \u003d\u003d NULL)\n+ return NULL;\n+\n+ SRP_user_pwd_set_gN(ret, src-\u003eg, src-\u003eN);\n+ if (!SRP_user_pwd_set_ids(ret, src-\u003eid, src-\u003einfo)\n+ || !SRP_user_pwd_set_sv_BN(ret, BN_dup(src-\u003es), BN_dup(src-\u003ev))) {\n+ SRP_user_pwd_free(ret);\n+ return NULL;\n+ }\n+ return ret;\n+}\n+\n SRP_VBASE *SRP_VBASE_new(char *seed_key)\n {\n SRP_VBASE *vb \u003d OPENSSL_malloc(sizeof(*vb));\n@@ -467,21 +485,51 @@ int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file)\n \n }\n \n-SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username)\n+static SRP_user_pwd *find_user(SRP_VBASE *vb, char *username)\n {\n int i;\n SRP_user_pwd *user;\n- unsigned char digv[SHA_DIGEST_LENGTH];\n- unsigned char digs[SHA_DIGEST_LENGTH];\n- EVP_MD_CTX *ctxt \u003d NULL;\n \n if (vb \u003d\u003d NULL)\n return NULL;\n+\n for (i \u003d 0; i \u003c sk_SRP_user_pwd_num(vb-\u003eusers_pwd); i++) {\n user \u003d sk_SRP_user_pwd_value(vb-\u003eusers_pwd, i);\n if (strcmp(user-\u003eid, username) \u003d\u003d 0)\n return user;\n }\n+\n+ return NULL;\n+}\n+\n+/*\n+ * DEPRECATED: use SRP_VBASE_get1_by_user instead.\n+ * This method ignores the configured seed and fails for an unknown user.\n+ * Ownership of the returned pointer is not released to the caller.\n+ * In other words, caller must not free the result.\n+ */\n+SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username)\n+{\n+ return find_user(vb, username);\n+}\n+\n+/*\n+ * Ownership of the returned pointer is released to the caller.\n+ * In other words, caller must free the result once done.\n+ */\n+SRP_user_pwd *SRP_VBASE_get1_by_user(SRP_VBASE *vb, char *username)\n+{\n+ SRP_user_pwd *user;\n+ unsigned char digv[SHA_DIGEST_LENGTH];\n+ unsigned char digs[SHA_DIGEST_LENGTH];\n+ EVP_MD_CTX *ctxt \u003d NULL;\n+\n+ if (vb \u003d\u003d NULL)\n+ return NULL;\n+\n+ if ((user \u003d find_user(vb, username)) !\u003d NULL)\n+ return srp_user_pwd_dup(user);\n+\n if ((vb-\u003eseed_key \u003d\u003d NULL) ||\n (vb-\u003edefault_g \u003d\u003d NULL) || (vb-\u003edefault_N \u003d\u003d NULL))\n return NULL;\ndiff --git a/include/openssl/srp.h b/include/openssl/srp.h\nindex 83a3293..4111d51 100644\n--- a/include/openssl/srp.h\n+++ b/include/openssl/srp.h\n@@ -85,14 +85,19 @@ typedef struct SRP_gN_cache_st {\n DEFINE_STACK_OF(SRP_gN_cache)\n \n typedef struct SRP_user_pwd_st {\n+ /* Owned by us. */\n char *id;\n BIGNUM *s;\n BIGNUM *v;\n+ /* Not owned by us. */\n const BIGNUM *g;\n const BIGNUM *N;\n+ /* Owned by us. */\n char *info;\n } SRP_user_pwd;\n \n+void SRP_user_pwd_free(SRP_user_pwd *user_pwd);\n+\n DEFINE_STACK_OF(SRP_user_pwd)\n \n typedef struct SRP_VBASE_st {\n@@ -118,7 +123,12 @@ DEFINE_STACK_OF(SRP_gN)\n SRP_VBASE *SRP_VBASE_new(char *seed_key);\n void SRP_VBASE_free(SRP_VBASE *vb);\n int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file);\n-SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username);\n+\n+/* This method ignores the configured seed and fails for an unknown user. */\n+DEPRECATEDIN_1_1_0(SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username))\n+/* NOTE: unlike in SRP_VBASE_get_by_user, caller owns the returned pointer.*/\n+SRP_user_pwd *SRP_VBASE_get1_by_user(SRP_VBASE *vb, char *username);\n+\n char *SRP_create_verifier(const char *user, const char *pass, char **salt,\n char **verifier, const char *N, const char *g);\n int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt,\ndiff --git a/util/libeay.num b/util/libeay.num\nindex ca8e9ec..ad7ad9d 100755\n--- a/util/libeay.num\n+++ b/util/libeay.num\n@@ -4073,7 +4073,7 @@ OPENSSL_memcmp 4565\t1_1_0\tEXIST::FUNCTION:\n OPENSSL_strncasecmp 4566\t1_1_0\tEXIST::FUNCTION:\n OPENSSL_gmtime 4567\t1_1_0\tEXIST::FUNCTION:\n OPENSSL_gmtime_adj 4568\t1_1_0\tEXIST::FUNCTION:\n-SRP_VBASE_get_by_user 4569\t1_1_0\tEXIST::FUNCTION:SRP\n+SRP_VBASE_get_by_user 4569\t1_1_0\tEXIST::FUNCTION:DEPRECATEDIN_1_1_0,SRP\n SRP_Calc_server_key 4570\t1_1_0\tEXIST::FUNCTION:SRP\n SRP_create_verifier 4571\t1_1_0\tEXIST::FUNCTION:SRP\n SRP_create_verifier_BN 4572\t1_1_0\tEXIST::FUNCTION:SRP\n@@ -4711,3 +4711,5 @@ OPENSSL_thread_stop 5213\t1_1_0\tEXIST::FUNCTION:\n OPENSSL_INIT_new 5215\t1_1_0\tEXIST::FUNCTION:\n OPENSSL_INIT_free 5216\t1_1_0\tEXIST::FUNCTION:\n OPENSSL_INIT_set_config_filename 5217\t1_1_0\tEXIST::FUNCTION:\n+SRP_user_pwd_free 5218\t1_1_0\tEXIST::FUNCTION:SRP\n+SRP_VBASE_get1_by_user 5219\t1_1_0\tEXIST::FUNCTION:SRP\n","s":{"c":1756165180,"u": 35146}}
],"g": 1763,"chitpc": 0,"ehitpc": 0,"indexed":0
,
"ab": 0, "si": 0, "db":0, "di":0, "sat":0, "lfc": "7d0a"}