]> sjero.net Git - wget/commitdiff
[svn] Remember that the NTLM-authorized TCP connections stay authorized.
authorhniksic <devnull@localhost>
Sat, 23 Apr 2005 02:03:19 +0000 (19:03 -0700)
committerhniksic <devnull@localhost>
Sat, 23 Apr 2005 02:03:19 +0000 (19:03 -0700)
src/ChangeLog
src/cmpt.c
src/http.c

index f9f4b4f16ce3258dfd469f4249d0dbb3e575fe46..eb496ec99efdd0758a571583321567fbbc8a4994 100644 (file)
@@ -1,3 +1,14 @@
+2005-04-23  Hrvoje Niksic  <hniksic@xemacs.org>
+
+       * cmpt.c: Reenable the memmove implementation for systems that
+       lack it.
+
+       * http.c (gethttp): Store the "authorized" state of the persistent
+       connection.
+       (request_remove_header): New function.
+       (gethttp): Don't send the "Basic" authentication if the connection
+       is already authorized.
+
 2005-04-23  Hrvoje Niksic  <hniksic@xemacs.org>
 
        * utils.c (base64_encode): Treat input as unsigned chars.
index 99cbbb8ab82e112c023fd94e6587350413eeb2b0..daa1460225fd68cef6ab75919f331306aa01b592 100644 (file)
@@ -1435,10 +1435,6 @@ const unsigned short int __mon_yday[2][13] =
   };
 #endif
 
-/* Currently unused in Wget.  Uncomment if we start using memmove
-   again. */
-#if 0
-
 #ifndef HAVE_MEMMOVE
 void *
 memmove (char *dest, const char *source, unsigned length)
@@ -1458,8 +1454,6 @@ memmove (char *dest, const char *source, unsigned length)
 }
 #endif /* not HAVE_MEMMOVE */
 
-#endif /* 0 */
-
 /* fnmatch is a POSIX function, but we include an implementation for
    the sake of systems that don't have it.  Furthermore, according to
    anecdotal evidence, historical implementations of fnmatch are buggy
index 7f7fb3f71e34dd6bdf2349de97ac3de608d39674..6a5cf1f9f5d3261995e84e1cc31eae9eab6d27a2 100644 (file)
@@ -202,7 +202,7 @@ release_header (struct request_header *hdr)
 /* Set the request named NAME to VALUE.  Specifically, this means that
    a "NAME: VALUE\r\n" header line will be used in the request.  If a
    header with the same name previously existed in the request, its
-   value will be replaced by this one.
+   value will be replaced by this one.  A NULL value means do nothing.
 
    RELEASE_POLICY determines whether NAME and VALUE should be released
    (freed) with request_free.  Allowed values are:
@@ -233,6 +233,7 @@ request_set_header (struct request *req, char *name, char *value,
 {
   struct request_header *hdr;
   int i;
+
   if (!value)
     {
       /* A NULL value is a no-op; if freeing the name is requested,
@@ -241,6 +242,7 @@ request_set_header (struct request *req, char *name, char *value,
        xfree (name);
       return;
     }
+
   for (i = 0; i < req->hcount; i++)
     {
       hdr = &req->headers[i];
@@ -260,8 +262,7 @@ request_set_header (struct request *req, char *name, char *value,
   if (req->hcount >= req->hcapacity)
     {
       req->hcapacity <<= 1;
-      req->headers = xrealloc (req->headers,
-                              req->hcapacity * sizeof (struct request_header));
+      req->headers = xrealloc (req->headers, req->hcapacity * sizeof (*hdr));
     }
   hdr = &req->headers[req->hcount++];
   hdr->name = name;
@@ -288,6 +289,29 @@ request_set_user_header (struct request *req, const char *header)
   request_set_header (req, xstrdup (name), (char *) p, rel_name);
 }
 
+/* Remove the header with specified name from REQ.  Returns 1 if the
+   header was actually removed, 0 otherwise.  */
+
+static int
+request_remove_header (struct request *req, char *name)
+{
+  int i;
+  for (i = 0; i < req->hcount; i++)
+    {
+      struct request_header *hdr = &req->headers[i];
+      if (0 == strcasecmp (name, hdr->name))
+       {
+         release_header (hdr);
+         /* Move the remaining headers by one. */
+         if (i < req->hcount - 1)
+           memmove (hdr, hdr + 1, (req->hcount - i - 1) * sizeof (*hdr));
+         --req->hcount;
+         return 1;
+       }
+    }
+  return 0;
+}
+
 #define APPEND(p, str) do {                    \
   int A_len = strlen (str);                    \
   memcpy (p, str, A_len);                      \
@@ -855,6 +879,12 @@ static struct {
   /* Whether a ssl handshake has occoured on this connection.  */
   int ssl;
 
+  /* Whether the connection was authorized.  This is only done by
+     NTLM, which authorizes *connections* rather than individual
+     requests.  (That practice is peculiar for HTTP, but it is a
+     useful optimization.)  */
+  int authorized;
+
 #ifdef ENABLE_NTLM
   /* NTLM data of the current connection.  */
   struct ntlmdata ntlm;
@@ -909,6 +939,7 @@ register_persistent (const char *host, int port, int fd, int ssl)
   pconn.host = xstrdup (host);
   pconn.port = port;
   pconn.ssl = ssl;
+  pconn.authorized = 0;
 
   DEBUGP (("Registered socket %d for persistent reuse.\n", fd));
 }
@@ -1113,6 +1144,9 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
      not be tried again. */
   int auth_finished = 0;
 
+  /* Whether NTLM authentication is used for this request. */
+  int ntlm_seen = 0;
+
   /* Whether our connection to the remote host is through SSL.  */
   int using_ssl = 0;
 
@@ -1381,6 +1415,11 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
          logprintf (LOG_VERBOSE, _("Reusing existing connection to %s:%d.\n"),
                     escnonprint (pconn.host), pconn.port);
          DEBUGP (("Reusing fd %d.\n", sock));
+         if (pconn.authorized)
+           /* If the connection is already authorized, the "Basic"
+              authorization added by code above is unnecessary and
+              only hurts us.  */
+           request_remove_header (req, "Authorization");
        }
     }
 
@@ -1587,6 +1626,7 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
        CLOSE_FINISH (sock);
       else
        CLOSE_INVALIDATE (sock);
+      pconn.authorized = 0;
       if (auth_finished || !(user && passwd))
        {
          /* If we have tried it already, then there is not point
@@ -1631,6 +1671,8 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
                                                             pth,
                                                             &auth_finished),
                                  rel_value);
+             if (BEGINS_WITH (www_authenticate, "NTLM"))
+               ntlm_seen = 1;
              xfree (pth);
              xfree (www_authenticate);
              goto retry_with_auth;
@@ -1639,6 +1681,12 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
       request_free (req);
       return AUTHFAILED;
     }
+  else /* statcode != HTTP_STATUS_UNAUTHORIZED */
+    {
+      /* Kludge: if NTLM is used, mark the TCP connection as authorized. */
+      if (ntlm_seen)
+       pconn.authorized = 1;
+    }
   request_free (req);
 
   hs->statcode = statcode;