From 852aa5ad351ea53e5f01d2f44b5b4370c2bf5425 Mon Sep 17 00:00:00 2001
From: Patrick Monnerat <patrick@monnerat.net>
Date: Mon, 25 Apr 2022 11:44:05 +0200
Subject: [PATCH] url: check sasl additional parameters for connection reuse.

Also move static function safecmp() as non-static Curl_safecmp() since
its purpose is needed at several places.

Bug: https://curl.se/docs/CVE-2022-22576.html

CVE-2022-22576

Closes #8746
---
 lib/strcase.c   | 10 ++++++++++
 lib/strcase.h   |  2 ++
 lib/url.c       | 13 ++++++++++++-
 lib/urldata.h   |  1 +
 lib/vtls/vtls.c | 21 ++++++---------------
 5 files changed, 31 insertions(+), 16 deletions(-)

CVE: CVE-2022-22576
Upstream-Status: Backport [https://github.com/curl/curl/commit/852aa5ad351ea53e5f01d2f44b5b4370c2bf5425.patch]
Comment: Refreshed patch
Signed-off-by: Sana.Kazi <Sana.Kazi@kpit.com>

diff --git a/lib/strcase.c b/lib/strcase.c
index dd46ca1ba0e5..692a3f14aee7 100644
--- a/lib/strcase.c
+++ b/lib/strcase.c
@@ -251,6 +251,16 @@
   } while(*src++ && --n);
 }
 
+/* Compare case-sensitive NUL-terminated strings, taking care of possible
+ * null pointers. Return true if arguments match.
+ */
+bool Curl_safecmp(char *a, char *b)
+{
+  if(a && b)
+    return !strcmp(a, b);
+  return !a && !b;
+}
+
 /* --- public functions --- */
 
 int curl_strequal(const char *first, const char *second)
diff --git a/lib/strcase.h b/lib/strcase.h
index b234d3815220..2635f5117e99 100644
--- a/lib/strcase.h
+++ b/lib/strcase.h
@@ -48,4 +48,6 @@
 void Curl_strntoupper(char *dest, const char *src, size_t n);
 void Curl_strntolower(char *dest, const char *src, size_t n);
 
+bool Curl_safecmp(char *a, char *b);
+
 #endif /* HEADER_CURL_STRCASE_H */
diff --git a/lib/url.c b/lib/url.c
index 9a988b4d58d8..e1647b133854 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -730,6 +730,7 @@
   Curl_safefree(conn->allocptr.host);
   Curl_safefree(conn->allocptr.cookiehost);
   Curl_safefree(conn->allocptr.rtsp_transport);
+  Curl_safefree(conn->oauth_bearer);  
   Curl_safefree(conn->trailer);
   Curl_safefree(conn->host.rawalloc); /* host name buffer */
   Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */
@@ -1251,7 +1252,9 @@
         /* This protocol requires credentials per connection,
            so verify that we're using the same name and password as well */
         if(strcmp(needle->user, check->user) ||
-           strcmp(needle->passwd, check->passwd)) {
+           strcmp(needle->passwd, check->passwd) ||
+           !Curl_safecmp(needle->sasl_authzid, check->sasl_authzid) ||
+           !Curl_safecmp(needle->oauth_bearer, check->oauth_bearer)) {			
           /* one of them was different */
           continue;
         }
@@ -3392,6 +3395,14 @@
       result = CURLE_OUT_OF_MEMORY;
       goto out;
     }
+  }
+
+  if(data->set.str[STRING_BEARER]) {
+    conn->oauth_bearer = strdup(data->set.str[STRING_BEARER]);
+    if(!conn->oauth_bearer) {
+      result = CURLE_OUT_OF_MEMORY;
+      goto out;
+    }
   }
 
 #ifdef USE_UNIX_SOCKETS
diff --git a/lib/urldata.h b/lib/urldata.h
index 07eb19b87034..1d89b8d7fa68 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -949,6 +949,8 @@
 
   char *sasl_authzid;     /* authorisation identity string, allocated */
 
+  char *oauth_bearer; /* OAUTH2 bearer, allocated */
+
   int httpversion;        /* the HTTP version*10 reported by the server */
   int rtspversion;        /* the RTSP version*10 reported by the server */
 
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index 03b85ba065e5..a40ac06f684f 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -82,15 +82,6 @@
   else                                       \
     dest->var = NULL;
 
-static bool safecmp(char *a, char *b)
-{
-  if(a && b)
-    return !strcmp(a, b);
-  else if(!a && !b)
-    return TRUE; /* match */
-  return FALSE; /* no match */
-}
-
 
 bool
 Curl_ssl_config_matches(struct ssl_primary_config* data,
@@ -101,12 +101,12 @@
      (data->verifypeer == needle->verifypeer) &&
      (data->verifyhost == needle->verifyhost) &&
      (data->verifystatus == needle->verifystatus) &&
-     safecmp(data->CApath, needle->CApath) &&
-     safecmp(data->CAfile, needle->CAfile) &&
-     safecmp(data->issuercert, needle->issuercert) &&
-     safecmp(data->clientcert, needle->clientcert) &&
-     safecmp(data->random_file, needle->random_file) &&
-     safecmp(data->egdsocket, needle->egdsocket) &&
+     Curl_safecmp(data->CApath, needle->CApath) &&
+     Curl_safecmp(data->CAfile, needle->CAfile) &&
+     Curl_safecmp(data->issuercert, needle->issuercert) &&
+     Curl_safecmp(data->clientcert, needle->clientcert) &&
+     Curl_safecmp(data->random_file, needle->random_file) &&
+     Curl_safecmp(data->egdsocket, needle->egdsocket) &&     
      Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) &&
      Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13) &&
      Curl_safe_strcasecompare(data->pinned_key, needle->pinned_key))
