Browse Source

add HttpProxyAuthenticator config option too

svn:r4272
Roger Dingledine 20 years ago
parent
commit
f0e309e5bd
5 changed files with 65 additions and 20 deletions
  1. 8 0
      src/or/config.c
  2. 22 0
      src/or/connection.c
  3. 6 15
      src/or/connection_or.c
  4. 25 3
      src/or/directory.c
  5. 4 2
      src/or/or.h

+ 8 - 0
src/or/config.c

@@ -133,6 +133,7 @@ static config_var_t config_vars[] = {
   VAR("Group",               STRING,   Group,                NULL),
   VAR("HashedControlPassword",STRING,  HashedControlPassword, NULL),
   VAR("HttpProxy",           STRING,   HttpProxy,            NULL),
+  VAR("HttpProxyAuthenticator",STRING, HttpProxyAuthenticator,NULL),
   VAR("HttpsProxy",          STRING,   HttpsProxy,           NULL),
   VAR("HttpsProxyAuthenticator",STRING,HttpsProxyAuthenticator,NULL),
   VAR("HiddenServiceOptions",LINELIST_V, RendConfigLines,    NULL),
@@ -1527,6 +1528,13 @@ options_validate(or_options_t *options)
     }
   }
 
+  if (options->HttpProxyAuthenticator) {
+    if (strlen(options->HttpProxyAuthenticator) >= 48) {
+      log(LOG_WARN, "HttpProxyAuthenticator is too long (>= 48 chars).");
+      result = -1;
+    }
+  }
+
   if (options->HttpsProxy) { /* parse it now */
     if (parse_addr_port(options->HttpsProxy, NULL,
                         &options->HttpsProxyAddr, &options->HttpsProxyPort) < 0) {

+ 22 - 0
src/or/connection.c

@@ -1559,6 +1559,28 @@ int connection_send_destroy(uint16_t circ_id, connection_t *conn) {
   return 0;
 }
 
+/** Alloocates a base64'ed authenticator for use in http or https
+ * auth, based on the input string <b>authenticator</b>. Returns it
+ * if success, else returns NULL. */
+char *
+alloc_http_authenticator(const char *authenticator) {
+  /* an authenticator in Basic authentication
+   * is just the string "username:password" */
+  const int authenticator_length = strlen(authenticator);
+  /* The base64_encode function needs a minimum buffer length
+   * of 66 bytes. */
+  const int base64_authenticator_length = (authenticator_length/48+1)*66;
+  char *base64_authenticator = tor_malloc(base64_authenticator_length);
+  if (base64_encode(base64_authenticator, base64_authenticator_length,
+                    authenticator, authenticator_length) < 0) {
+    tor_free(base64_authenticator); /* free and set to null */
+  } else {
+    /* remove extra \n at end of encoding */
+    base64_authenticator[strlen(base64_authenticator) - 1] = 0;
+  }
+  return base64_authenticator;
+}
+
 /** Process new bytes that have arrived on conn-\>inbuf.
  *
  * This function just passes conn to the connection-specific

+ 6 - 15
src/or/connection_or.c

@@ -169,27 +169,18 @@ int connection_or_finished_connecting(connection_t *conn)
     char buf[1024];
     char addrbuf[INET_NTOA_BUF_LEN];
     struct in_addr in;
+    char *base64_authenticator=NULL;
     const char *authenticator = get_options()->HttpsProxyAuthenticator;
 
     in.s_addr = htonl(conn->addr);
     tor_inet_ntoa(&in, addrbuf, sizeof(addrbuf));
 
     if (authenticator) {
-      /* an authenticator in Basic authentication
-       * is just the string "username:password" */
-      const int authenticator_length = strlen(authenticator);
-      /* The base64_encode function needs a minimum buffer length
-       * of 66 bytes. */
-      const int base64_authenticator_length = (authenticator_length/48+1)*66;
-      char *base64_authenticator = tor_malloc(base64_authenticator_length);
-      if (base64_encode(base64_authenticator, base64_authenticator_length,
-                        authenticator, authenticator_length) < 0) {
-        log_fn(LOG_WARN, "Encoding authenticator failed");
-        base64_authenticator[0] = 0;
-      } else {
-        /* remove extra \n at end of encoding */
-        base64_authenticator[strlen(base64_authenticator) - 1] = 0;
-      }
+      base64_authenticator = alloc_http_authenticator(authenticator);
+      if (!base64_authenticator)
+        log_fn(LOG_WARN, "Encoding https authenticator failed");
+    }
+    if (base64_authenticator) {
       tor_snprintf(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.1\r\n"
                    "Proxy-Authorization: Basic %s\r\n\r\n", addrbuf,
                    conn->port, base64_authenticator);

+ 25 - 3
src/or/directory.c

@@ -363,7 +363,8 @@ directory_send_command(connection_t *conn, const char *platform,
                        int purpose, const char *resource,
                        const char *payload, size_t payload_len) {
   char tmp[8192];
-  char proxystring[128];
+  char proxystring[256];
+  char proxyauthstring[256];
   char hoststring[128];
   char url[128];
   const char *httpcommand = NULL;
@@ -371,15 +372,35 @@ directory_send_command(connection_t *conn, const char *platform,
   tor_assert(conn);
   tor_assert(conn->type == CONN_TYPE_DIR);
 
+  /* come up with a string for which Host: we want */
   if (conn->port == 80) {
     strlcpy(hoststring, conn->address, sizeof(hoststring));
   } else {
     tor_snprintf(hoststring, sizeof(hoststring),"%s:%d",conn->address, conn->port);
   }
+
+  /* come up with some proxy lines, if we're using one. */
   if (get_options()->HttpProxy) {
+    char *base64_authenticator=NULL;
+    const char *authenticator = get_options()->HttpProxyAuthenticator;
+
     tor_snprintf(proxystring, sizeof(proxystring),"http://%s", hoststring);
+    if (authenticator) {
+      base64_authenticator = alloc_http_authenticator(authenticator);
+      if (!base64_authenticator)
+        log_fn(LOG_WARN, "Encoding http authenticator failed");
+    }
+    if (base64_authenticator) {
+      tor_snprintf(proxyauthstring, sizeof(proxyauthstring),
+                   "\r\nProxy-Authorization: Basic %s",
+                   base64_authenticator);
+      tor_free(base64_authenticator);
+    } else {
+      proxyauthstring[0] = 0;
+    }
   } else {
     proxystring[0] = 0;
+    proxyauthstring[0] = 0;
   }
 
   switch (purpose) {
@@ -424,12 +445,13 @@ directory_send_command(connection_t *conn, const char *platform,
       break;
   }
 
-  tor_snprintf(tmp, sizeof(tmp), "%s %s%s HTTP/1.0\r\nContent-Length: %lu\r\nHost: %s\r\n\r\n",
+  tor_snprintf(tmp, sizeof(tmp), "%s %s%s HTTP/1.0\r\nContent-Length: %lu\r\nHost: %s%s\r\n\r\n",
            httpcommand,
            proxystring,
            url,
            payload ? (unsigned long)payload_len : 0,
-           hoststring);
+           hoststring,
+           proxyauthstring);
   connection_write_to_buf(tmp, strlen(tmp), conn);
 
   if (payload) {

+ 4 - 2
src/or/or.h

@@ -1059,11 +1059,12 @@ typedef struct {
   char *HttpProxy; /**< hostname[:port] to use as http proxy, if any */
   uint32_t HttpProxyAddr; /**< Parsed IPv4 addr for http proxy, if any */
   uint16_t HttpProxyPort; /**< Parsed port for http proxy, if any */
+  char *HttpProxyAuthenticator; /**< username:password string, if any */
 
   char *HttpsProxy; /**< hostname[:port] to use as https proxy, if any */
   uint32_t HttpsProxyAddr; /**< Parsed IPv4 addr for https proxy, if any */
   uint16_t HttpsProxyPort; /**< Parsed port for https proxy, if any */
-  char *HttpsProxyAuthenticator; /** username:password string, if any */
+  char *HttpsProxyAuthenticator; /**< username:password string, if any */
 
   struct config_line_t *DirServers; /**< List of configuration lines
                                      * for directory servers. */
@@ -1075,7 +1076,7 @@ typedef struct {
   smartlist_t *RedirectExitList; /**< List of exit_redirect_t */
   int _MonthlyAccountingStart; /**< Deprecated: day of month when accounting
                                 * interval starts */
-  char *AccountingStart; /** How long is the accounting interval, and when
+  char *AccountingStart; /**< How long is the accounting interval, and when
                           * does it start? */
   uint64_t AccountingMax; /**< How many bytes do we allow per accounting
                            * interval before hibernation?  0 for "never
@@ -1317,6 +1318,7 @@ int connection_state_is_open(connection_t *conn);
 int connection_state_is_connecting(connection_t *conn);
 
 int connection_send_destroy(uint16_t circ_id, connection_t *conn);
+char *alloc_http_authenticator(const char *authenticator);
 
 void assert_connection_ok(connection_t *conn, time_t now);
 int connection_or_nonopen_was_started_here(connection_t *conn);