]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
More Digest changes.
authorMichael R Sweet <michael.r.sweet@gmail.com>
Fri, 14 Sep 2018 18:58:35 +0000 (14:58 -0400)
committerMichael R Sweet <michael.r.sweet@gmail.com>
Fri, 14 Sep 2018 18:58:35 +0000 (14:58 -0400)
cups/auth.c
cups/getputfile.c
cups/http-private.h
cups/http-support.c
cups/request.c
cups/testhttp.c

index a2651527baf4e9cf9c12aed1b351f9b62728755a..47e14168e4be74655e6fb04529f700d706860bd8 100644 (file)
@@ -266,15 +266,7 @@ cupsDoAuthentication(
       cups_auth_param(schemedata, "nonce", nonce, sizeof(nonce));
       cups_auth_param(schemedata, "realm", http->realm, sizeof(http->realm));
 
-      if (strcmp(nonce, http->nonce))
-      {
-        strlcpy(http->nonce, nonce, sizeof(http->nonce));
-        http->nonce_count = 1;
-      }
-      else
-        http->nonce_count ++;
-
-      if (_httpSetDigestAuthString(http, method, resource))
+      if (_httpSetDigestAuthString(http, nonce, method, resource))
         break;
     }
   }
index ba88973c005f950dda8d72e19f5a3d7f303f764d..2cdb9cb0999440f7c260aec009b890aa30607e4d 100644 (file)
@@ -92,16 +92,7 @@ cupsGetFd(http_t     *http,          /* I - Connection to server or @code CUPS_HTTP_DEFA
       * Update the Digest authentication string...
       */
 
-      if (http->nextnonce[0])
-      {
-        strlcpy(http->nonce, http->nextnonce, sizeof(http->nonce));
-        http->nonce_count = 1;
-        http->nextnonce[0] = '\0';
-      }
-      else
-        http->nonce_count ++;
-
-      _httpSetDigestAuthString(http, "GET", resource);
+      _httpSetDigestAuthString(http, http->nextnonce, "GET", resource);
     }
 
 #ifdef HAVE_GSSAPI
@@ -356,16 +347,7 @@ cupsPutFd(http_t     *http,                /* I - Connection to server or @code CUPS_HTTP_DEFA
       * Update the Digest authentication string...
       */
 
-      if (http->nextnonce[0])
-      {
-        strlcpy(http->nonce, http->nextnonce, sizeof(http->nonce));
-        http->nonce_count = 1;
-        http->nextnonce[0] = '\0';
-      }
-      else
-        http->nonce_count ++;
-
-      _httpSetDigestAuthString(http, "PUT", resource);
+      _httpSetDigestAuthString(http, http->nextnonce, "PUT", resource);
     }
 
 #ifdef HAVE_GSSAPI
index db71ede28c1fd98bd0db06d12e623eccc38f2351..e7f7e445fe936d4be3c85bd583fdb4ec479d43f5 100644 (file)
@@ -440,7 +440,7 @@ extern const char   *_httpResolveURI(const char *uri, char *resolved_uri,
                                         size_t resolved_size, int options,
                                         int (*cb)(void *context),
                                         void *context);
-extern int             _httpSetDigestAuthString(http_t *http, const char *method, const char *resource);
+extern int             _httpSetDigestAuthString(http_t *http, const char *nonce, const char *method, const char *resource);
 extern const char      *_httpStatus(cups_lang_t *lang, http_status_t status);
 extern void            _httpTLSInitialize(void);
 extern size_t          _httpTLSPending(http_t *http);
index cd423aefd9fcbc95ecf4ce63788e30271a53c8ec..3834dbef8470bab2d04716fa7a2ef245c223f4a4 100644 (file)
@@ -661,139 +661,6 @@ httpDecode64_2(char       *out,           /* I  - String to write to */
 }
 
 
-/*
- * '_httpSetDigestAuthString()' - Calculate a Digest authentication response
- *                                using the appropriate RFC 2068/2617/7616
- *                                algorithm.
- */
-
-int                                    /* O - 1 on success, 0 on failure */
-_httpSetDigestAuthString(
-    http_t     *http,                  /* I - HTTP connection */
-    const char *method,                        /* I - HTTP method */
-    const char *resource)              /* I - HTTP resource path */
-{
-  char         kd[65],                 /* Final MD5/SHA-256 digest */
-               ha1[65],                /* Hash of username:realm:password */
-               ha2[65],                /* Hash of method:request-uri */
-               username[HTTP_MAX_VALUE],
-                                       /* username:password */
-               *password,              /* Pointer to password */
-               temp[1024],             /* Temporary string */
-               digest[1024];           /* Digest auth data */
-  unsigned char        hash[32];               /* Hash buffer */
-  size_t       hashsize;               /* Size of hash */
-
-
-  DEBUG_printf(("2_httpSetDigestAuthString(http=%p, method=\"%s\", resource=\"%s\")", http, method, resource));
-
-  strlcpy(username, http->userpass, sizeof(username));
-  if ((password = strchr(username, ':')) != NULL)
-    *password++ = '\0';
-  else
-    return (0);
-
-  if (http->algorithm[0])
-  {
-   /*
-    * Follow RFC 2617/7616...
-    */
-
-    int                i;                      /* Looping var */
-    char       cnonce[65];             /* cnonce value */
-    const char *hashalg;               /* Hashing algorithm */
-
-    for (i = 0; i < 64; i ++)
-      cnonce[i] = "0123456789ABCDEF"[CUPS_RAND() & 15];
-    cnonce[64] = '\0';
-
-    if (!_cups_strcasecmp(http->algorithm, "MD5"))
-    {
-     /*
-      * RFC 2617 Digest with MD5
-      */
-
-      hashalg = "md5";
-    }
-    else if (!_cups_strcasecmp(http->algorithm, "SHA-256"))
-    {
-     /*
-      * RFC 7616 Digest with SHA-256
-      */
-
-      hashalg = "sha2-256";
-    }
-    else
-    {
-     /*
-      * Some other algorithm we don't support, skip this one...
-      */
-
-      return (0);
-    }
-
-   /*
-    * Calculate digest value...
-    */
-
-    /* H(A1) = H(username:realm:password) */
-    snprintf(temp, sizeof(temp), "%s:%s:%s", username, http->realm, password);
-    hashsize = (size_t)cupsHashData(hashalg, (unsigned char *)temp, strlen(temp), hash, sizeof(hash));
-    cupsHashString(hash, hashsize, ha1, sizeof(ha1));
-
-    /* H(A2) = H(method:uri) */
-    snprintf(temp, sizeof(temp), "%s:%s", method, resource);
-    hashsize = (size_t)cupsHashData(hashalg, (unsigned char *)temp, strlen(temp), hash, sizeof(hash));
-    cupsHashString(hash, hashsize, ha2, sizeof(ha2));
-
-    /* KD = H(H(A1):nonce:nc:cnonce:qop:H(A2)) */
-    snprintf(temp, sizeof(temp), "%s:%s:%08x:%s:%s:%s", ha1, http->nonce, http->nonce_count, cnonce, "auth", ha2);
-    hashsize = (size_t)cupsHashData(hashalg, (unsigned char *)temp, strlen(temp), hash, sizeof(hash));
-    cupsHashString(hash, hashsize, kd, sizeof(kd));
-
-   /*
-    * Pass the RFC 2617/7616 WWW-Authenticate header...
-    */
-
-    if (http->opaque[0])
-      snprintf(digest, sizeof(digest), "username=\"%s\", realm=\"%s\", nonce=\"%s\", algorithm=%s, qop=auth, opaque=\"%s\", cnonce=\"%s\", nc=%08x, uri=\"%s\", response=\"%s\"", cupsUser(), http->realm, http->nonce, http->algorithm, http->opaque, cnonce, http->nonce_count, resource, kd);
-    else
-      snprintf(digest, sizeof(digest), "username=\"%s\", realm=\"%s\", nonce=\"%s\", algorithm=%s, qop=auth, cnonce=\"%s\", nc=%08x, uri=\"%s\", response=\"%s\"", username, http->realm, http->nonce, http->algorithm, cnonce, http->nonce_count, resource, kd);
-  }
-  else
-  {
-   /*
-    * Use old RFC 2069 Digest method...
-    */
-
-    /* H(A1) = H(username:realm:password) */
-    snprintf(temp, sizeof(temp), "%s:%s:%s", username, http->realm, password);
-    hashsize = (size_t)cupsHashData("md5", (unsigned char *)temp, strlen(temp), hash, sizeof(hash));
-    cupsHashString(hash, hashsize, ha1, sizeof(ha1));
-
-    /* H(A2) = H(method:uri) */
-    snprintf(temp, sizeof(temp), "%s:%s", method, resource);
-    hashsize = (size_t)cupsHashData("md5", (unsigned char *)temp, strlen(temp), hash, sizeof(hash));
-    cupsHashString(hash, hashsize, ha2, sizeof(ha2));
-
-    /* KD = H(H(A1):nonce:H(A2)) */
-    snprintf(temp, sizeof(temp), "%s:%s:%s", ha1, http->nonce, ha2);
-    hashsize = (size_t)cupsHashData("md5", (unsigned char *)temp, strlen(temp), hash, sizeof(hash));
-    cupsHashString(hash, hashsize, kd, sizeof(kd));
-
-   /*
-    * Pass the old RFC 2069 WWW-Authenticate header...
-    */
-
-    snprintf(digest, sizeof(digest), "username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"", username, http->realm, http->nonce, resource, kd);
-  }
-
-  httpSetAuthString(http, "Digest", digest);
-
-  return (1);
-}
-
-
 /*
  * 'httpEncode64()' - Base64-encode a string.
  *
@@ -1430,6 +1297,152 @@ httpSeparateURI(
 }
 
 
+/*
+ * '_httpSetDigestAuthString()' - Calculate a Digest authentication response
+ *                                using the appropriate RFC 2068/2617/7616
+ *                                algorithm.
+ */
+
+int                                    /* O - 1 on success, 0 on failure */
+_httpSetDigestAuthString(
+    http_t     *http,                  /* I - HTTP connection */
+    const char *nonce,                 /* I - Nonce value */
+    const char *method,                        /* I - HTTP method */
+    const char *resource)              /* I - HTTP resource path */
+{
+  char         kd[65],                 /* Final MD5/SHA-256 digest */
+               ha1[65],                /* Hash of username:realm:password */
+               ha2[65],                /* Hash of method:request-uri */
+               username[HTTP_MAX_VALUE],
+                                       /* username:password */
+               *password,              /* Pointer to password */
+               temp[1024],             /* Temporary string */
+               digest[1024];           /* Digest auth data */
+  unsigned char        hash[32];               /* Hash buffer */
+  size_t       hashsize;               /* Size of hash */
+
+
+  DEBUG_printf(("2_httpSetDigestAuthString(http=%p, nonce=\"%s\", method=\"%s\", resource=\"%s\")", http, nonce, method, resource));
+
+  if (nonce && *nonce && strcmp(nonce, http->nonce))
+  {
+    strlcpy(http->nonce, nonce, sizeof(http->nonce));
+
+    if (nonce == http->nextnonce)
+      http->nextnonce[0] = '\0';
+
+    http->nonce_count = 1;
+  }
+  else
+    http->nonce_count ++;
+
+  strlcpy(username, http->userpass, sizeof(username));
+  if ((password = strchr(username, ':')) != NULL)
+    *password++ = '\0';
+  else
+    return (0);
+
+  if (http->algorithm[0])
+  {
+   /*
+    * Follow RFC 2617/7616...
+    */
+
+    int                i;                      /* Looping var */
+    char       cnonce[65];             /* cnonce value */
+    const char *hashalg;               /* Hashing algorithm */
+
+    for (i = 0; i < 64; i ++)
+      cnonce[i] = "0123456789ABCDEF"[CUPS_RAND() & 15];
+    cnonce[64] = '\0';
+
+    if (!_cups_strcasecmp(http->algorithm, "MD5"))
+    {
+     /*
+      * RFC 2617 Digest with MD5
+      */
+
+      hashalg = "md5";
+    }
+    else if (!_cups_strcasecmp(http->algorithm, "SHA-256"))
+    {
+     /*
+      * RFC 7616 Digest with SHA-256
+      */
+
+      hashalg = "sha2-256";
+    }
+    else
+    {
+     /*
+      * Some other algorithm we don't support, skip this one...
+      */
+
+      return (0);
+    }
+
+   /*
+    * Calculate digest value...
+    */
+
+    /* H(A1) = H(username:realm:password) */
+    snprintf(temp, sizeof(temp), "%s:%s:%s", username, http->realm, password);
+    hashsize = (size_t)cupsHashData(hashalg, (unsigned char *)temp, strlen(temp), hash, sizeof(hash));
+    cupsHashString(hash, hashsize, ha1, sizeof(ha1));
+
+    /* H(A2) = H(method:uri) */
+    snprintf(temp, sizeof(temp), "%s:%s", method, resource);
+    hashsize = (size_t)cupsHashData(hashalg, (unsigned char *)temp, strlen(temp), hash, sizeof(hash));
+    cupsHashString(hash, hashsize, ha2, sizeof(ha2));
+
+    /* KD = H(H(A1):nonce:nc:cnonce:qop:H(A2)) */
+    snprintf(temp, sizeof(temp), "%s:%s:%08x:%s:%s:%s", ha1, http->nonce, http->nonce_count, cnonce, "auth", ha2);
+    hashsize = (size_t)cupsHashData(hashalg, (unsigned char *)temp, strlen(temp), hash, sizeof(hash));
+    cupsHashString(hash, hashsize, kd, sizeof(kd));
+
+   /*
+    * Pass the RFC 2617/7616 WWW-Authenticate header...
+    */
+
+    if (http->opaque[0])
+      snprintf(digest, sizeof(digest), "username=\"%s\", realm=\"%s\", nonce=\"%s\", algorithm=%s, qop=auth, opaque=\"%s\", cnonce=\"%s\", nc=%08x, uri=\"%s\", response=\"%s\"", cupsUser(), http->realm, http->nonce, http->algorithm, http->opaque, cnonce, http->nonce_count, resource, kd);
+    else
+      snprintf(digest, sizeof(digest), "username=\"%s\", realm=\"%s\", nonce=\"%s\", algorithm=%s, qop=auth, cnonce=\"%s\", nc=%08x, uri=\"%s\", response=\"%s\"", username, http->realm, http->nonce, http->algorithm, cnonce, http->nonce_count, resource, kd);
+  }
+  else
+  {
+   /*
+    * Use old RFC 2069 Digest method...
+    */
+
+    /* H(A1) = H(username:realm:password) */
+    snprintf(temp, sizeof(temp), "%s:%s:%s", username, http->realm, password);
+    hashsize = (size_t)cupsHashData("md5", (unsigned char *)temp, strlen(temp), hash, sizeof(hash));
+    cupsHashString(hash, hashsize, ha1, sizeof(ha1));
+
+    /* H(A2) = H(method:uri) */
+    snprintf(temp, sizeof(temp), "%s:%s", method, resource);
+    hashsize = (size_t)cupsHashData("md5", (unsigned char *)temp, strlen(temp), hash, sizeof(hash));
+    cupsHashString(hash, hashsize, ha2, sizeof(ha2));
+
+    /* KD = H(H(A1):nonce:H(A2)) */
+    snprintf(temp, sizeof(temp), "%s:%s:%s", ha1, http->nonce, ha2);
+    hashsize = (size_t)cupsHashData("md5", (unsigned char *)temp, strlen(temp), hash, sizeof(hash));
+    cupsHashString(hash, hashsize, kd, sizeof(kd));
+
+   /*
+    * Pass the old RFC 2069 WWW-Authenticate header...
+    */
+
+    snprintf(digest, sizeof(digest), "username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"", username, http->realm, http->nonce, resource, kd);
+  }
+
+  httpSetAuthString(http, "Digest", digest);
+
+  return (1);
+}
+
+
 /*
  * 'httpStateString()' - Return the string describing a HTTP state value.
  *
index 924bb6fc008102b2b43a9bec2f039f0b2bd19a8f..e58beceeba59044c4f069ee6545a8dc0460b3ce0 100644 (file)
@@ -686,16 +686,7 @@ cupsSendRequest(http_t     *http,  /* I - Connection to server or @code CUPS_HTTP
       * Update the Digest authentication string...
       */
 
-      if (http->nextnonce[0])
-      {
-        strlcpy(http->nonce, http->nextnonce, sizeof(http->nonce));
-        http->nonce_count = 1;
-        http->nextnonce[0] = '\0';
-      }
-      else
-        http->nonce_count ++;
-
-      _httpSetDigestAuthString(http, "POST", resource);
+      _httpSetDigestAuthString(http, http->nextnonce, "POST", resource);
     }
 
 #ifdef HAVE_GSSAPI
index 1480d04b5ba6e186fbc85b66d530109b28bc4fc9..dfb767c89e7be994d3a462b45bd55df7c57286cf 100644 (file)
@@ -628,6 +628,8 @@ main(int  argc,                             /* I - Number of command-line arguments */
 
   for (i = 1; i < argc; i ++)
   {
+    int new_auth;
+
     if (!strcmp(argv[i], "-o"))
     {
       i ++;
@@ -711,6 +713,8 @@ main(int  argc,                             /* I - Number of command-line arguments */
 
     printf("Checking file \"%s\"...\n", resource);
 
+    new_auth = 0;
+
     do
     {
       if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_CONNECTION), "close"))
@@ -723,9 +727,13 @@ main(int  argc,                            /* I - Number of command-line arguments */
        }
       }
 
+      if (http->authstring && !strncmp(http->authstring, "Digest ", 7) && !new_auth)
+        _httpSetDigestAuthString(http, http->nextnonce, "HEAD", resource);
+
       httpClearFields(http);
       httpSetField(http, HTTP_FIELD_AUTHORIZATION, httpGetAuthString(http));
       httpSetField(http, HTTP_FIELD_ACCEPT_LANGUAGE, "en");
+
       if (httpHead(http, resource))
       {
         if (httpReconnect2(http, 30000, NULL))
@@ -742,6 +750,8 @@ main(int  argc,                             /* I - Number of command-line arguments */
 
       while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE);
 
+      new_auth = 0;
+
       if (status == HTTP_STATUS_UNAUTHORIZED)
       {
        /*
@@ -754,6 +764,8 @@ main(int  argc,                             /* I - Number of command-line arguments */
        * See if we can do authentication...
        */
 
+        new_auth = 1;
+
        if (cupsDoAuthentication(http, "HEAD", resource))
        {
          status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
@@ -802,6 +814,8 @@ main(int  argc,                             /* I - Number of command-line arguments */
     printf("Requesting file \"%s\" (Accept-Encoding: %s)...\n", resource,
            encoding ? encoding : "identity");
 
+    new_auth = 0;
+
     do
     {
       if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_CONNECTION), "close"))
@@ -814,6 +828,9 @@ main(int  argc,                             /* I - Number of command-line arguments */
        }
       }
 
+      if (http->authstring && !strncmp(http->authstring, "Digest ", 7) && !new_auth)
+        _httpSetDigestAuthString(http, http->nextnonce, "GET", resource);
+
       httpClearFields(http);
       httpSetField(http, HTTP_FIELD_AUTHORIZATION, httpGetAuthString(http));
       httpSetField(http, HTTP_FIELD_ACCEPT_LANGUAGE, "en");
@@ -835,6 +852,8 @@ main(int  argc,                             /* I - Number of command-line arguments */
 
       while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE);
 
+      new_auth = 0;
+
       if (status == HTTP_STATUS_UNAUTHORIZED)
       {
        /*
@@ -847,6 +866,8 @@ main(int  argc,                             /* I - Number of command-line arguments */
        * See if we can do authentication...
        */
 
+        new_auth = 1;
+
        if (cupsDoAuthentication(http, "GET", resource))
        {
          status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;