[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#189261: [PATCH] support HTTP proxy basic access authenication



This patch implements basic access authentication against HTTP proxies.
The changes are done without touching the external interface, requiring
no SONAME change (and hopefully no ABI breakage.)

Still, more testing is needed.

Debian Bug #189261

Signed-off-by: Zak B. Elep <zakame@zakame.net>

---
 src/base64.c |   11 ++++
 src/cddb.c   |  148 ++++++++++++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 135 insertions(+), 24 deletions(-)

diff --git a/src/base64.c b/src/base64.c
index e4b627d..53a4c1c 100644
--- a/src/base64.c
+++ b/src/base64.c
@@ -105,6 +105,10 @@ WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
 static unsigned char oddity_64[] =
 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-";
 
+/* Regular base64 encoding set */
+static unsigned char regular_64[] =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+
 int
 cd_basis_encode64(unsigned char *outbuffer, unsigned char *inbuffer,
 		  int inlen, int outlen, unsigned char *basis)
@@ -153,3 +157,10 @@ cdindex_encode64(unsigned char *outbuffer, unsigned char *inbuffer,
 {
    return cd_basis_encode64(outbuffer, inbuffer, inlen, outlen, oddity_64);
 }
+
+int
+regular_encode64(unsigned char *outbuffer, unsigned char *inbuffer,
+		 int inlen, int outlen)
+{
+   return cd_basis_encode64(outbuffer, inbuffer, inlen, outlen, regular_64);
+}
diff --git a/src/cddb.c b/src/cddb.c
index 3dabe31..3c3739a 100644
--- a/src/cddb.c
+++ b/src/cddb.c
@@ -54,6 +54,9 @@ Boston, MA  02111-1307, USA.
 extern int
 __internal_cdindex_discid (struct disc_info disc,
 			   char *discid, int len);
+extern int
+regular_encode64 (unsigned char *outbuffer, unsigned char *inbuffer,
+                  int inlen, int outlen);
 
 /* Static function prototypes */
 static int cddb_sum (long val);
@@ -77,8 +80,8 @@ int use_cddb_message = 1;
 int parse_disc_artist = 1;
 int cddb_submit_method = CDDB_SUBMIT_EMAIL;
 char *cddb_submit_email_address = CDDB_EMAIL_SUBMIT_ADDRESS;
-char *proxy_auth_username = NULL;
-char *proxy_auth_password = NULL;
+char proxy_auth_username[256];
+char proxy_auth_password[256];
 
 /* CDDB sum function */
 static int
@@ -360,6 +363,34 @@ cddb_process_url(struct cddb_host *host, const char *url)
 
   url += 3;
 
+  if(strchr(url, '@')) {
+    index = 0;
+    while(url[index] != ':' && url[index] != '\0' &&
+          url[index] != '@' && index < 527) {
+      index++;
+      if(index > 256)
+        return -1;
+    }
+
+    memset(proxy_auth_username, '\0', index + 1);
+    strncpy(proxy_auth_username, url, index);
+
+    if(url[index] == ':') {
+      url += (index + 1);
+      index = 0;
+      while(url[index] != '\0' && url[index] != '@' && index < 527) {
+        index++;
+        if(index > 256)
+          return -1;
+      }
+
+      memset(proxy_auth_password, '\0', index + 1);
+      strncpy(proxy_auth_password, url, index);
+    }
+
+    url += (index + 1);
+  }
+
   index = 0;
   while(url[index] != ':' && url[index] != '\0' &&
 	url[index] != '/' && index < 527) {
@@ -564,8 +595,13 @@ cddb_write_serverlist(struct cddb_conf conf,
     fputs("ACCESS=LOCAL\n", cddbconf);
   
   if(conf.conf_proxy == CDDB_PROXY_ENABLED)
-    fprintf(cddbconf, "PROXY=http://%s:%d/\n";,
-	    proxy.server_name, proxy.server_port);
+    if(proxy_auth_username && proxy_auth_password)
+      fprintf(cddbconf, "PROXY=http://%s:%s@%s:%d/\n";,
+              proxy_auth_username, proxy_auth_password,
+              proxy.server_name, proxy.server_port);
+    else
+      fprintf(cddbconf, "PROXY=http://%s:%d/\n";,
+              proxy.server_name, proxy.server_port);
   for(index = 0; index < list.list_len; index++) {
     switch(list.list_host[index].host_protocol) {
     case CDDB_MODE_HTTP:
@@ -698,6 +734,47 @@ cddb_connect(struct cddb_server *server)
 
   return sock;
 }
+
+/* Generate an HTTP header for HTTP proxy auth if needed */
+static int
+__internal_generate_proxy_auth(char *outbuffer, const char *username,
+                               const char *password, int outbuffer_len)
+{
+  int index, inbuffer_len, userpass_len;
+  char *inbuffer, *userpass;
+  char proxy_auth_tag[] = "Proxy-Authorization: Basic ";
+
+  userpass_len = strlen(username) + strlen(password) + 1;
+  
+  if((userpass = malloc(userpass_len + 1)) == NULL)
+    return -1;
+
+  memset(userpass, '\0', userpass_len + 1);
+  snprintf(userpass, userpass_len + 1, "%s:%s", username, password);
+
+  inbuffer_len = 128;
+
+  if((inbuffer = malloc(inbuffer_len + 1)) == NULL)
+    return -1;
+
+  memset(inbuffer, '\0', inbuffer_len + 1);
+  if(regular_encode64(inbuffer, userpass, userpass_len, inbuffer_len) < 0)
+    return -1;
+
+  free(userpass);
+
+  index = strlen(proxy_auth_tag);
+  if(index > outbuffer_len)
+    return -1;
+
+  strncpy(outbuffer, proxy_auth_tag, index);
+  outbuffer += index;
+  strncpy(outbuffer, inbuffer, inbuffer_len);
+
+  free(inbuffer);
+
+  return 0;
+}
 		  
 /* Connect to a CDDB server and say hello */
 int
@@ -705,8 +782,8 @@ cddb_connect_server(struct cddb_host host,
 		    struct cddb_server *proxy,
 		    struct cddb_hello hello, ...)
 {
-  int sock, token[3], http_string_len;
-  char *outbuffer, *http_string;
+  int sock, token[3], http_string_len, proxy_auth_len;
+  char *outbuffer, *http_string, *proxy_auth;
   va_list arglist;
 
   va_start(arglist, hello);
@@ -722,18 +799,32 @@ cddb_connect_server(struct cddb_host host,
   if(host.host_protocol == CDDB_MODE_HTTP) {
     http_string = va_arg(arglist, char *);
     http_string_len = va_arg(arglist, int);
-    if(proxy != NULL)
+    if(proxy != NULL) {
+      if(proxy_auth_username && proxy_auth_password) {
+        proxy_auth_len = 527;
+        if((proxy_auth = malloc(proxy_auth_len + 1)) == NULL)
+          return -1;
+        memset(proxy_auth, '\0', proxy_auth_len + 1);
+        if(__internal_generate_proxy_auth(proxy_auth, proxy_auth_username,
+                                          proxy_auth_password, proxy_auth_len)
+           < 0)
+          return -1;
+        http_string_len += strlen(proxy_auth);
+      }
       snprintf(http_string, http_string_len,
-	       "GET http://%s:%d/%s?";
-	       "hello=anonymous+anonymous+%s+%s&proto=%d "
-	       "HTTP/1.0\n\n",
-	       host.host_server.server_name,
-	       host.host_server.server_port,
-	       host.host_addressing,
-	       hello.hello_program,
-	       hello.hello_version,
-	       CDDB_PROTOCOL_LEVEL);
-    else
+               "GET http://%s:%d/%s?";
+               "hello=anonymous+anonymous+%s+%s&proto=%d "
+               "HTTP/1.0\n"
+               "%s\n\n",
+               host.host_server.server_name,
+               host.host_server.server_port,
+               host.host_addressing,
+               hello.hello_program,
+               hello.hello_version,
+               CDDB_PROTOCOL_LEVEL,
+               (proxy_auth != NULL ? proxy_auth : ""));
+      free(proxy_auth);
+    } else
       snprintf(http_string, http_string_len,
 	       "GET /%s?hello=anonymous+anonymous+%s+%s&proto=%d "
 	       "HTTP/1.0\n\n",
@@ -2226,7 +2317,7 @@ cddb_http_submit(int cd_desc, struct cddb_host host,
   FILE *cddb_entry;
   int sock, index, changed_artist = 0,
     changed_track[MAX_TRACKS], token[3], error = 0;
-  char inbuffer[512], outbuffer[512], cddb_file[512], *home;
+  char inbuffer[512], outbuffer[512], cddb_file[512], proxy_auth[512], *home;
   struct stat st;
   struct cddb_entry entry;
   struct disc_info disc;
@@ -2302,12 +2393,21 @@ cddb_http_submit(int cd_desc, struct cddb_host host,
     return 0;
   }
    
-  if(proxy != NULL)
-    snprintf(outbuffer, 512, "POST http://%s:%d%s HTTP/1.0\n",
-	     host.host_server.server_name,
-	     host.host_server.server_port,
-	     HTTP_SUBMIT_CGI);
-  else
+  if(proxy != NULL) {
+    if(proxy_auth_username && proxy_auth_password) {
+      memset(proxy_auth, '\0', 512);
+      if(__internal_generate_proxy_auth(proxy_auth, proxy_auth_username,
+                                          proxy_auth_password, 512)
+         < 0)
+        return -1;
+    }
+    snprintf(outbuffer, 512, "POST http://%s:%d%s HTTP/1.0\n"
+             "%s\n",
+             host.host_server.server_name,
+             host.host_server.server_port,
+             HTTP_SUBMIT_CGI,
+             (strlen(proxy_auth) > 0 ? proxy_auth : ""));
+  } else
     snprintf(outbuffer, 512, "POST %s HTTP/1.0\n",
 	     HTTP_SUBMIT_CGI);
   send(sock, outbuffer, strlen(outbuffer), 0);
-- 
tg: (9f407de..) bugs/189261-http-proxy-auth (depends on: upstream)



Reply to: