summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2021-12-17 23:40:11 +0100
committerDaniel Stenberg <daniel@haxx.se>2021-12-20 10:51:44 +0100
commit556a42edfb9b3fcd744f2e032e59498bc8af4841 (patch)
treee2a1ea2487febdc404ffcba8a3c860439e493d3e
parent7a92f865b43aac942ae5755a7a3a06775751fdea (diff)
downloadcurl-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
-rw-r--r--lib/vtls/nss.c78
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;