diff options
author | Daniel Stenberg <daniel@haxx.se> | 2021-12-17 23:40:11 +0100 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2021-12-20 10:51:44 +0100 |
commit | 556a42edfb9b3fcd744f2e032e59498bc8af4841 (patch) | |
tree | e2a1ea2487febdc404ffcba8a3c860439e493d3e /lib | |
parent | 7a92f865b43aac942ae5755a7a3a06775751fdea (diff) | |
download | curl-556a42edfb9b3fcd744f2e032e59498bc8af4841.tar.gz |
nss:set_cipher don't clobber the cipher list
The string is set by the user and needs to remain intact for proper
connection reuse etc.
Reported-by: Eric Musser
Fixes #8160
Closes #8161
Diffstat (limited to 'lib')
-rw-r--r-- | lib/vtls/nss.c | 78 |
1 files changed, 40 insertions, 38 deletions
diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c index 1897b9ab1..260ff0b04 100644 --- a/lib/vtls/nss.c +++ b/lib/vtls/nss.c @@ -304,13 +304,14 @@ static char *nss_sslver_to_name(PRUint16 nssver) } } -static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc * model, - char *cipher_list) +/* the longest cipher name this supports */ +#define MAX_CIPHER_LENGTH 128 + +static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc *model, + const char *cipher_list) { unsigned int i; - PRBool cipher_state[NUM_OF_CIPHERS]; - PRBool found; - char *cipher; + const char *cipher; /* use accessors to avoid dynamic linking issues after an update of NSS */ const PRUint16 num_implemented_ciphers = SSL_GetNumImplementedCiphers(); @@ -326,51 +327,52 @@ static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc * model, SSL_CipherPrefSet(model, implemented_ciphers[i], PR_FALSE); } - /* Set every entry in our list to false */ - for(i = 0; i < NUM_OF_CIPHERS; i++) { - cipher_state[i] = PR_FALSE; - } - cipher = cipher_list; - while(cipher_list && (cipher_list[0])) { + while(cipher && cipher[0]) { + const char *end; + char name[MAX_CIPHER_LENGTH + 1]; + size_t len; + bool found = FALSE; while((*cipher) && (ISSPACE(*cipher))) ++cipher; - cipher_list = strpbrk(cipher, ":, "); - if(cipher_list) { - *cipher_list++ = '\0'; - } - - found = PR_FALSE; - - for(i = 0; i<NUM_OF_CIPHERS; i++) { - if(strcasecompare(cipher, cipherlist[i].name)) { - cipher_state[i] = PR_TRUE; - found = PR_TRUE; - break; - } - } + end = strpbrk(cipher, ":, "); + if(end) + len = end - cipher; + else + len = strlen(cipher); - if(found == PR_FALSE) { - failf(data, "Unknown cipher in list: %s", cipher); + if(len > MAX_CIPHER_LENGTH) { + failf(data, "Bad cipher list"); return SECFailure; } - - if(cipher_list) { - cipher = cipher_list; + else if(len) { + memcpy(name, cipher, len); + name[len] = 0; + + for(i = 0; i<NUM_OF_CIPHERS; i++) { + if(strcasecompare(name, cipherlist[i].name)) { + /* Enable the selected cipher */ + if(SSL_CipherPrefSet(model, cipherlist[i].num, PR_TRUE) != + SECSuccess) { + failf(data, "cipher-suite not supported by NSS: %s", name); + return SECFailure; + } + found = TRUE; + break; + } + } } - } - /* Finally actually enable the selected ciphers */ - for(i = 0; i<NUM_OF_CIPHERS; i++) { - if(!cipher_state[i]) - continue; - - if(SSL_CipherPrefSet(model, cipherlist[i].num, PR_TRUE) != SECSuccess) { - failf(data, "cipher-suite not supported by NSS: %s", cipherlist[i].name); + if(!found && len) { + failf(data, "Unknown cipher: %s", name); return SECFailure; } + if(end) + cipher = ++end; + else + break; } return SECSuccess; |