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
- branch=trunk inherited from [a28c83647d]
- sym-trunk inherited from [a28c83647d]
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;