Diff
Not logged in

Differences From:

File src/http.c part of check-in [5468ec7c5e] - Incremental changes toward encrypting sync traffic. The changes are incomplete, but all legacy functionality appears to still works. by drh on 2009-03-26 15:32:43. [view]

To:

File src/http.c part of check-in [9a23c348b1] - Infrastructure in place on the client side to encrypt sync traffic. This is mostly untested so far because we do not yet have a server that understands encrypted traffic. by drh on 2009-03-27 14:32:33. [view]

@@ -173,14 +173,35 @@
 }
 #endif
 
 /*
+** zLine is a line from the header of an HTTP reply.  Find the
+** "argument" to this header line.  The argument is the first non-whitespace
+** character following the first ":" in the line.  The argument consists of
+** non-whitespace and non-semicolon characters.  Zero-terminate the argument
+** before returning.
+*/
+static char *header_arg(char *zIn){
+  char *z;
+  while( *zIn && *zIn!=':' ){ zIn++; }
+  if( *zIn==':' ){ zIn++; }
+  while( isspace(*zIn) ){ zIn++; }
+  for(z=zIn; *z && *z!=';' && !isspace(*z); z++){}
+  *z = 0;
+  return zIn;
+}
+
+/*
 ** Make a single attempt to talk to the server.  Return TRUE on success
 ** and FALSE on a failure.
 **
 ** pHeader contains the HTTP header.  pPayload contains the content.
 ** The content of the reply is written into pReply.  pReply is assumed
 ** to be uninitialized prior to this call.
+**
+** pPayload has already been compressed and/or encrypted prior to being
+** passed into this function.  pReply will be decrypted and/or decompressed
+** as required by this function, based on the Content-Type of the reply.
 **
 ** If an error occurs, this routine return false, resets pReply and
 ** closes the persistent connection, if any.
 */
@@ -190,8 +211,10 @@
   int iLength;
   int iHttpVersion;
   int i;
   int nRead;
+  int needDecrypt = 0;
+  int needDecompress = 0;
   char zLine[2000];
 
   if( pSocket==0 && http_open_socket() ){
     return 0;
@@ -220,16 +243,25 @@
         closeConnection = 1;
       }else{
         closeConnection = 0;
       }
-    } else if( strncasecmp(zLine, "content-length:", 15)==0 ){
-      iLength = atoi(&zLine[16]);
+    }else if( strncasecmp(zLine,"content-length:",15)==0 ){
+      iLength = atoi(header_arg(zLine));
     }else if( strncasecmp(zLine, "connection:", 11)==0 ){
-      for(i=12; isspace(zLine[i]); i++){}
-      if( zLine[i]=='c' || zLine[i]=='C' ){
-        closeConnection = 1;
-      }else if( zLine[i]=='k' || zLine[i]=='K' ){
-        closeConnection = 0;
+      int c = header_arg(zLine)[0];
+      if( c=='c' || c=='C' ){
+        closeConnection = 1;   /* Connection: close */
+      }else if( c=='k' || c=='K' ){
+        closeConnection = 0;   /* Connection: keep-alive */
+      }
+    }else if( strncasecmp(zLine, "content-type:", 13)==0 ){
+      const char *zType = header_arg(zLine);
+      if( strcmp(zType, "application/x-fossil")==0 ){
+        needDecompress = 1;
+        needDecrypt = 0;
+      }else if( strcmp(zType, "application/x-fossil-secure")==0 ){
+        needDecompress = 1;
+        needDecrypt = 1;
       }
     }
   }
   if( iLength<0 ) goto write_err;
@@ -252,15 +284,24 @@
     for(i=0; zLine[i] && zLine[i]!='\n' && zLine[i]!='\r'; i++){}
     if( i==0 ) break;
     zLine[i] = 0;
     if( strncasecmp(zLine,"content-length:",15)==0 ){
-      iLength = atoi(&zLine[16]);
+      iLength = atoi(header_arg(zLine));
     }else if( strncasecmp(zLine, "connection:", 11)==0 ){
-      for(i=12; isspace(zLine[i]); i++){}
-      if( zLine[i]=='c' || zLine[i]=='C' ){
+      int c = header_arg(zLine)[0];
+      if( c=='c' || c=='C' ){
         closeConnection = 1;   /* Connection: close */
-      }else if( zLine[i]=='k' || zLine[i]=='K' ){
+      }else if( c=='k' || c=='K' ){
         closeConnection = 0;   /* Connection: keep-alive */
+      }
+    }else if( strncasecmp(zLine, "content-type:", 13)==0 ){
+      const char *zType = header_arg(zLine);
+      if( strcmp(zType, "application/x-fossil")==0 ){
+        needDecompress = 1;
+        needDecrypt = 0;
+      }else if( strcmp(zType, "application/x-fossil-secure")==0 ){
+        needDecompress = 1;
+        needDecrypt = 1;
       }
     }
   }
   if( iLength<0 ) goto write_err;
@@ -271,8 +312,14 @@
     goto write_err;
   }
   if( closeConnection ){
     http_close();
+  }
+  if( needDecrypt ){
+    blob_decrypt(pReply, g.urlPasswd, pReply);
+  }
+  if( needDecompress ){
+    blob_uncompress(pReply, pReply);
   }
   return 1;
 
 write_err:
@@ -342,9 +389,13 @@
   blob_reset(&sig);
 
   /* Construct the payload, which includes the login card.
   */
-  if( g.fHttpTrace ){
+  if( g.fHttpSecure && g.urlPasswd[0] ){
+    blob_compress(pSend, pSend);
+    payload = login;
+    blob_encrypt(pSend, g.urlPasswd, &payload);
+  }else if( g.fHttpTrace ){
     payload = login;
     blob_append(&payload, blob_buffer(pSend), blob_size(pSend));
   }else{
     blob_compress2(&login, pSend, &payload);
@@ -362,9 +413,11 @@
   }
   blob_appendf(&hdr, "POST %s%sxfer HTTP/1.1\r\n", g.urlPath, zSep);
   blob_appendf(&hdr, "Host: %s\r\n", g.urlHostname);
   blob_appendf(&hdr, "User-Agent: Fossil/" MANIFEST_VERSION "\r\n");
-  if( g.fHttpTrace ){
+  if( g.fHttpSecure && g.urlPasswd[0] ){
+    blob_appendf(&hdr, "Content-Type: application/x-fossil-secure\r\n");
+  }else if( g.fHttpTrace ){
     blob_appendf(&hdr, "Content-Type: application/x-fossil-debug\r\n");
   }else{
     blob_appendf(&hdr, "Content-Type: application/x-fossil\r\n");
   }
@@ -404,14 +457,13 @@
   blob_reset(&hdr);
   blob_reset(&payload);
 
   /* Process the reply.  pRecv contains only the payload of the
-  ** reply message, not the header.
+  ** reply message, not the header.  pRecv has already been decrypted
+  ** and decompressed
   */
   if( g.fHttpTrace ){
     printf("HTTP RECEIVE:\n%s\n=======================\n", blob_str(pRecv));
-  }else{
-    blob_uncompress(pRecv, pRecv);
   }
 }