Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Use POST instead of GET for the /xfer method. Other bug fixes in the URL parser. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA1: |
e621b6dbe310661d111e8caba43bdac4 |
| User & Date: | drh 2007-07-30 14:28:17.000 |
Context
|
2007-07-30
| ||
| 16:35 | Only request the password one time on a push or pull. ... (check-in: 3a25b68390 user: drh tags: trunk) | |
| 16:31 | Merge in clone and sync changes. Fix a bug in undelta. ... (check-in: e3c529c2f0 user: dan tags: trunk) | |
| 14:28 | Use POST instead of GET for the /xfer method. Other bug fixes in the URL parser. ... (check-in: e621b6dbe3 user: drh tags: trunk) | |
| 13:34 | When errors occur during CGI, make sure the error is returned in a correct CGI reply. ... (check-in: 396cc2a4eb user: drh tags: trunk) | |
Changes
Changes to src/http.c.
| ︙ | ︙ | |||
155 156 157 158 159 160 161 |
*/
void http_exchange(Blob *pSend, Blob *pRecv){
Blob login, nonce, sig, pw, payload, hdr;
const char *zSep;
int i;
int cnt = 0;
| < > > > | | > > > > > > > > > | > > > | > | | 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
*/
void http_exchange(Blob *pSend, Blob *pRecv){
Blob login, nonce, sig, pw, payload, hdr;
const char *zSep;
int i;
int cnt = 0;
blob_zero(&nonce);
blob_zero(&pw);
db_blob(&nonce, "SELECT hex(randomblob(20))");
blob_copy(&pw, &nonce);
blob_zero(&login);
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;
blob_append(&payload, blob_buffer(pSend), blob_size(pSend));
}else{
blob_compress2(&login, pSend, &payload);
blob_reset(&login);
}
blob_zero(&hdr);
i = strlen(g.urlPath);
if( i>0 && g.urlPath[i-1]=='/' ){
zSep = "";
}else{
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");
}
blob_appendf(&hdr, "Content-Length: %d\r\n\r\n", blob_size(&payload));
|
| ︙ | ︙ |
Changes to src/login.c.
| ︙ | ︙ | |||
201 202 203 204 205 206 207 |
zCap = "s";
g.noPswd = 1;
g.isAnon = 0;
}
/* Check the login cookie to see if it matches a known valid user.
*/
| > | | | | | | | | | > > > | 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
zCap = "s";
g.noPswd = 1;
g.isAnon = 0;
}
/* Check the login cookie to see if it matches a known valid user.
*/
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 = "";
zCap = db_get("nologin-cap","onrj");
}else if( zCap==0 ){
|
| ︙ | ︙ |
Changes to src/main.c.
| ︙ | ︙ | |||
67 68 69 70 71 72 73 74 75 76 77 78 79 80 | Blob cgiIn; /* Input to an xfer www method */ int cgiPanic; /* Write error messages to CGI */ 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 *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) */ int userUid; /* Integer user id */ | > > | 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | Blob cgiIn; /* Input to an xfer www method */ int cgiPanic; /* Write error messages to CGI */ 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) */ int userUid; /* Integer user id */ |
| ︙ | ︙ |
Changes to src/url.c.
| ︙ | ︙ | |||
29 30 31 32 33 34 35 36 37 38 39 40 |
/*
** Parse the given URL. Populate variables in the global "g" structure.
**
** 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.urlCanonical The URL in canonical form
**
*/
void url_parse(const char *zUrl){
int i, j, c;
| > > > > > > | | > > > > > > > > > > > | > | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
/*
** Parse the given URL. Populate variables in the global "g" structure.
**
** 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 = 0;
if( strncmp(zUrl, "http:", 5)==0 ){
g.urlIsFile = 0;
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) ){
g.urlPort = g.urlPort*10 + c - '0';
i++;
|
| ︙ | ︙ | |||
86 87 88 89 90 91 92 |
file_canonical_name(zFile, &cfile);
free(zFile);
g.urlName = mprintf("%b", &cfile);
g.urlCanonical = mprintf("file://%T", g.urlName);
blob_reset(&cfile);
}
}
| > > > > > > > > > > > > > > > > > | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
file_canonical_name(zFile, &cfile);
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);
}
|
Changes to src/user.c.
| ︙ | ︙ | |||
52 53 54 55 56 57 58 |
*/
static void prompt_for_passphrase(const char *zPrompt, Blob *pPassphrase){
char *z = getpass(zPrompt);
strip_string(pPassphrase, z);
}
/*
| | | > | > > > | 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
*/
static void prompt_for_passphrase(const char *zPrompt, Blob *pPassphrase){
char *z = getpass(zPrompt);
strip_string(pPassphrase, z);
}
/*
** Prompt the user for a password. Store the result in the pPassphrase
** blob.
**
** Behavior is controlled by the verify parameter:
**
** 0 Just ask once.
**
** 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.
*/
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);
if( verify==0 ) break;
if( verify==1 && blob_size(pPassphrase)==0 ) break;
|
| ︙ | ︙ | |||
115 116 117 118 119 120 121 |
}
n = strlen(g.argv[2]);
if( n>=2 && strncmp(g.argv[2],"new",n)==0 ){
Blob passwd, login, contact;
prompt_user("login: ", &login);
prompt_user("contact-info: ", &contact);
| | | 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
}
n = strlen(g.argv[2]);
if( n>=2 && strncmp(g.argv[2],"new",n)==0 ){
Blob passwd, login, contact;
prompt_user("login: ", &login);
prompt_user("contact-info: ", &contact);
prompt_for_password("password: ", &passwd, 1);
db_multi_exec(
"INSERT INTO user(login,pw,cap,info)"
"VALUES(%B,%B,'jnor',%B)",
&login, &passwd, &contact
);
}else if( n>=2 && strncmp(g.argv[2],"default",n)==0 ){
user_select();
|
| ︙ | ︙ | |||
147 148 149 150 151 152 153 |
Blob pw;
if( g.argc!=4 ) usage("user password USERNAME");
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]);
| | | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
Blob pw;
if( g.argc!=4 ) usage("user password USERNAME");
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]);
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);
}
}else if( n>=2 && strncmp(g.argv[2],"capabilities",2)==0 ){
int uid;
|
| ︙ | ︙ |
Changes to src/xfer.c.
| ︙ | ︙ | |||
358 359 360 361 362 363 364 365 366 367 368 369 370 371 |
}
if( !blob_eq_str(&aToken[2], zPCode, -1) ){
cgi_reset_content();
@ error wrong\sproject
nErr++;
break;
}
if( blob_eq(&aToken[0], "pull") ){
if( !g.okRead ){
cgi_reset_content();
@ error not\sauthorized\sto\sread
nErr++;
break;
}
| > | 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 |
}
if( !blob_eq_str(&aToken[2], zPCode, -1) ){
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++;
break;
}
|
| ︙ | ︙ | |||
383 384 385 386 387 388 389 390 391 392 393 394 395 396 |
}else
/* clone
**
** The client knows nothing. Tell all.
*/
if( blob_eq(&aToken[0], "clone") ){
if( !g.okRead ){
cgi_reset_content();
@ error not\sauthorized\sto\sread
nErr++;
break;
}
isPull = 1;
| > | 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 |
}else
/* 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;
}
isPull = 1;
|
| ︙ | ︙ |