Check-in [e621b6dbe3]
Not logged in
Overview

SHA1 Hash:e621b6dbe310661d111e8caba43bdac40fd9693b
Date: 2007-07-30 14:28:17
User: drh
Comment:Use POST instead of GET for the /xfer method. Other bug fixes in the URL parser.
Timelines: ancestors | descendants | both | trunk
Other Links: files | ZIP archive | manifest

Tags And Properties
Changes
[hide diffs]

Modified src/http.c from [3b83a20834] to [a8e6ad7f13].

@@ -157,19 +157,34 @@
   Blob login, nonce, sig, pw, payload, hdr;
   const char *zSep;
   int i;
   int cnt = 0;
 
-  user_select();
   blob_zero(&nonce);
   blob_zero(&pw);
   db_blob(&nonce, "SELECT hex(randomblob(20))");
   blob_copy(&pw, &nonce);
-  db_blob(&pw, "SELECT pw FROM user WHERE uid=%d", g.userUid);
-  sha1sum_blob(&pw, &sig);
   blob_zero(&login);
-  blob_appendf(&login, "login %s %b %b\n", g.zLogin, &nonce, &sig);
+  if( g.urlUser==0 ){
+    user_select();
+    db_blob(&pw, "SELECT pw FROM user WHERE uid=%d", g.userUid);
+    sha1sum_blob(&pw, &sig);
+    blob_appendf(&login, "login %s %b %b\n", g.zLogin, &nonce, &sig);
+  }else{
+    if( g.urlPasswd==0 ){
+      if( strcmp(g.urlUser,"anonymous")!=0 ){
+        char *zPrompt = mprintf("password for %s", g.urlUser);
+        Blob x;
+        prompt_for_password(zPrompt, &x, 0);
+        free(zPrompt);
+        blob_append(&pw, blob_buffer(&x), blob_size(&x));
+        blob_reset(&x);
+      }
+    }
+    sha1sum_blob(&pw, &sig);
+    blob_appendf(&login, "login %s %b %b\n", g.urlUser, &nonce, &sig);
+  }
   blob_reset(&nonce);
   blob_reset(&pw);
   blob_reset(&sig);
   if( g.fHttpTrace ){
     payload = login;
@@ -183,11 +198,11 @@
   if( i>0 && g.urlPath[i-1]=='/' ){
     zSep = "";
   }else{
     zSep = "/";
   }
-  blob_appendf(&hdr, "GET %s%sxfer HTTP/1.1\r\n", g.urlPath, zSep);
+  blob_appendf(&hdr, "POST %s%sxfer HTTP/1.1\r\n", g.urlPath, zSep);
   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");
   }

Modified src/login.c from [c801bf1f9b] to [769bfdbb7f].

@@ -203,19 +203,23 @@
     g.isAnon = 0;
   }
 
   /* Check the login cookie to see if it matches a known valid user.
   */
-  if( uid==0 && (zCookie = P(login_cookie_name()))!=0 ){
-    uid = db_int(0,
-            "SELECT 1 FROM user"
-            " WHERE uid=%d"
-            "   AND cookie=%Q"
-            "   AND ipaddr=%Q"
-            "   AND cexpire>julianday('now')",
-            atoi(zCookie), zCookie, zRemoteAddr
-         );
+  if( uid==0 ){
+    if( (zCookie = P(login_cookie_name()))!=0 ){
+      uid = db_int(0,
+              "SELECT uid FROM user"
+              " WHERE uid=%d"
+              "   AND cookie=%Q"
+              "   AND ipaddr=%Q"
+              "   AND cexpire>julianday('now')",
+              atoi(zCookie), zCookie, zRemoteAddr
+           );
+    }else{
+      uid = db_int(0, "SELECT uid FROM user WHERE login='anonymous'");
+    }
   }
 
   if( uid==0 ){
     g.isAnon = 1;
     g.zLogin = "";

Modified src/main.c from [66d6462906] to [fa34f0baa1].

@@ -69,10 +69,12 @@
 
   int urlIsFile;          /* True if a "file:" url */
   char *urlName;          /* Hostname for http: or filename for file: */
   int urlPort;            /* TCP port number for http: */
   char *urlPath;          /* Pathname for http: */
+  char *urlUser;          /* User id for http: */
+  char *urlPasswd;        /* Password for http: */
   char *urlCanonical;     /* Canonical representation of the URL */
 
   const char *zLogin;     /* Login name.  "" if not logged in. */
   int isAnon;             /* True if logged in anoymously */
   int noPswd;             /* Logged in without password (on 127.0.0.1) */

Modified src/url.c from [f3bcafe705] to [6f5bc8946f].

@@ -31,20 +31,38 @@
 **
 **      g.urlIsFile      True if this is a file URL
 **      g.urlName        Hostname for HTTP:.  Filename for FILE:
 **      g.urlPort        Port name for HTTP.
 **      g.urlPath        Path name for HTTP.
+**      g.urlUser        Userid.
+**      g.urlPasswd      Password.
 **      g.urlCanonical   The URL in canonical form
+**
+** HTTP url format is:
+**
+**     http://userid:password@host:port/path?query#fragment
 **
 */
 void url_parse(const char *zUrl){
   int i, j, c;
-  char *zFile;
+  char *zFile = 0;
   if( strncmp(zUrl, "http:", 5)==0 ){
     g.urlIsFile = 0;
-    for(i=7; (c=zUrl[i])!=0 && c!=':' && c!='/'; i++){}
-    g.urlName = mprintf("%.*s", i-7, &zUrl[7]);
+    for(i=7; (c=zUrl[i])!=0 && c!='/' && c!='@'; i++){}
+    if( c=='@' ){
+      for(j=7; j<i && zUrl[j]!=':'; j++){}
+      g.urlUser = mprintf("%.*s", j-7, &zUrl[7]);
+      if( j<i ){
+        g.urlPasswd = mprintf("%.*s", i-j-1, &zUrl[j+1]);
+      }
+      for(j=i+1; (c=zUrl[j])!=0 && c!='/' && c!=':'; j++){}
+      g.urlName = mprintf("%.*s", j-i-1, &zUrl[i+1]);
+      i = j;
+    }else{
+      for(i=7; (c=zUrl[i])!=0 && c!='/' && c!=':'; i++){}
+      g.urlName = mprintf("%.*s", i-7, &zUrl[7]);
+    }
     for(j=0; g.urlName[j]; j++){ g.urlName[j] = tolower(g.urlName[j]); }
     if( c==':' ){
       g.urlPort = 0;
       i++;
       while( (c = zUrl[i])!=0 && isdigit(c) ){
@@ -87,6 +105,23 @@
     free(zFile);
     g.urlName = mprintf("%b", &cfile);
     g.urlCanonical = mprintf("file://%T", g.urlName);
     blob_reset(&cfile);
   }
+}
+
+/*
+** COMMAND: test-urlparser
+*/
+void cmd_test_urlparser(void){
+  if( g.argc!=3 ){
+    usage("URL");
+  }
+  url_parse(g.argv[2]);
+  printf("g.urlIsFile    = %d\n", g.urlIsFile);
+  printf("g.urlName      = %s\n", g.urlName);
+  printf("g.urlPort      = %d\n", g.urlPort);
+  printf("g.urlPath      = %s\n", g.urlPath);
+  printf("g.urlUser      = %s\n", g.urlUser);
+  printf("g.urlPasswd    = %s\n", g.urlPasswd);
+  printf("g.urlCanonical = %s\n", g.urlCanonical);
 }

Modified src/user.c from [f41abe0610] to [47ac33e64a].

@@ -54,12 +54,12 @@
   char *z = getpass(zPrompt);
   strip_string(pPassphrase, z);
 }
 
 /*
-** Prompt the user for a passphrase used to encrypt the private key
-** portion of an RSA key pair.
+** Prompt the user for a password.  Store the result in the pPassphrase
+** blob.
 **
 ** Behavior is controlled by the verify parameter:
 **
 **     0     Just ask once.
 **
@@ -66,11 +66,15 @@
 **     1     If the first answer is a non-empty string, ask for
 **           verification.  Repeat if the two strings do not match.
 **
 **     2     Ask twice, repeat if the strings do not match.
 */
-static void get_passphrase(const char *zPrompt, Blob *pPassphrase, int verify){
+void prompt_for_password(
+  const char *zPrompt,
+  Blob *pPassphrase,
+  int verify
+){
   Blob secondTry;
   blob_zero(pPassphrase);
   blob_zero(&secondTry);
   while(1){
     prompt_for_passphrase(zPrompt, pPassphrase);
@@ -117,11 +121,11 @@
   if( n>=2 && strncmp(g.argv[2],"new",n)==0 ){
     Blob passwd, login, contact;
 
     prompt_user("login: ", &login);
     prompt_user("contact-info: ", &contact);
-    get_passphrase("password: ", &passwd, 1);
+    prompt_for_password("password: ", &passwd, 1);
     db_multi_exec(
       "INSERT INTO user(login,pw,cap,info)"
       "VALUES(%B,%B,'jnor',%B)",
       &login, &passwd, &contact
     );
@@ -149,11 +153,11 @@
     uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", g.argv[3]);
     if( uid==0 ){
       fossil_fatal("no such user: %s", g.argv[3]);
     }
     zPrompt = mprintf("new passwd for %s: ", g.argv[3]);
-    get_passphrase(zPrompt, &pw, 1);
+    prompt_for_password(zPrompt, &pw, 1);
     if( blob_size(&pw)==0 ){
       printf("password unchanged\n");
     }else{
       db_multi_exec("UPDATE user SET pw=%B WHERE uid=%d", &pw, uid);
     }

Modified src/xfer.c from [1d5b7d85e6] to [a734598a7e].

@@ -360,10 +360,11 @@
         cgi_reset_content();
         @ error wrong\sproject
         nErr++;
         break;
       }
+      login_check_credentials();
       if( blob_eq(&aToken[0], "pull") ){
         if( !g.okRead ){
           cgi_reset_content();
           @ error not\sauthorized\sto\sread
           nErr++;
@@ -385,10 +386,11 @@
     /*    clone
     **
     ** The client knows nothing.  Tell all.
     */
     if( blob_eq(&aToken[0], "clone") ){
+      login_check_credentials();
       if( !g.okRead ){
         cgi_reset_content();
         @ error not\sauthorized\sto\sread
         nErr++;
         break;