Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Factor the sync password out of the last-sync-url configuration setting. Store the password separately. Prompt the user for the password if it is missing. |
|---|---|
| Timelines: | family | ancestors | descendants | both | experimental |
| Files: | files | file ages | folders |
| SHA1: |
59002d5e35918d83a54b07c9a3982467 |
| User & Date: | drh 2010-01-21 18:13:33.000 |
Context
|
2010-01-21
| ||
| 19:51 | Better reporting of failed logins by the server back to the client. check-in: b030521c42 user: drh tags: experimental | |
| 18:13 | Factor the sync password out of the last-sync-url configuration setting. Store the password separately. Prompt the user for the password if it is missing. check-in: 59002d5e35 user: drh tags: experimental | |
|
2010-01-20
| ||
| 21:51 | Fix a bug in file change detection introduced by check-in [d7a583e697]. Don't use that check-in, nor [30f23e3f5c]. check-in: 1abc8a940e user: drh tags: trunk | |
Changes
Changes to src/configure.c.
| ︙ | ︙ | |||
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 |
db_multi_exec("%s", blob_str(&in));
configure_finalize_receive();
db_end_transaction(0);
}else
if( strncmp(zMethod, "pull", n)==0 || strncmp(zMethod, "push", n)==0 ){
int mask;
const char *zServer;
url_proxy_options();
if( g.argc!=4 && g.argc!=5 ){
usage("pull AREA ?URL?");
}
mask = find_area(g.argv[3]);
if( g.argc==5 ){
zServer = g.argv[4];
}else{
zServer = db_get("last-sync-url", 0);
if( zServer==0 ){
fossil_fatal("no server specified");
}
}
url_parse(zServer);
user_select();
if( strncmp(zMethod, "push", n)==0 ){
client_sync(0,0,0,0,mask);
}else{
client_sync(0,0,0,mask,0);
}
}else
| > > > > > | 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 |
db_multi_exec("%s", blob_str(&in));
configure_finalize_receive();
db_end_transaction(0);
}else
if( strncmp(zMethod, "pull", n)==0 || strncmp(zMethod, "push", n)==0 ){
int mask;
const char *zServer;
const char *zPw;
url_proxy_options();
if( g.argc!=4 && g.argc!=5 ){
usage("pull AREA ?URL?");
}
mask = find_area(g.argv[3]);
if( g.argc==5 ){
zServer = g.argv[4];
zPw = 0;
g.dontKeepUrl = 1;
}else{
zServer = db_get("last-sync-url", 0);
if( zServer==0 ){
fossil_fatal("no server specified");
}
zPw = db_get("last-sync-pw", 0);
}
url_parse(zServer);
if( g.urlPasswd==0 && zPw ) g.urlPasswd = mprintf("%s", zPw);
user_select();
if( strncmp(zMethod, "push", n)==0 ){
client_sync(0,0,0,0,mask);
}else{
client_sync(0,0,0,mask,0);
}
}else
|
| ︙ | ︙ |
Changes to src/http.c.
| ︙ | ︙ | |||
42 43 44 45 46 47 48 49 50 51 52 |
static void http_build_login_card(Blob *pPayload, Blob *pLogin){
Blob nonce; /* The nonce */
const char *zLogin; /* The user login name */
const char *zPw; /* The user password */
Blob pw; /* The nonce with user password appended */
Blob sig; /* The signature field */
blob_zero(&nonce);
blob_zero(&pw);
sha1sum_blob(pPayload, &nonce);
blob_copy(&pw, &nonce);
| > > > > | | < < | < < | | | | | | | < < < < | 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 71 72 73 74 |
static void http_build_login_card(Blob *pPayload, Blob *pLogin){
Blob nonce; /* The nonce */
const char *zLogin; /* The user login name */
const char *zPw; /* The user password */
Blob pw; /* The nonce with user password appended */
Blob sig; /* The signature field */
blob_zero(pLogin);
if( g.urlUser==0 || strcmp(g.urlUser, "anonymous")==0 ){
return; /* If no login card for users "nobody" and "anonymous" */
}
blob_zero(&nonce);
blob_zero(&pw);
sha1sum_blob(pPayload, &nonce);
blob_copy(&pw, &nonce);
zLogin = g.urlUser;
if( g.urlPasswd ){
zPw = g.urlPasswd;
}else{
char *zPrompt = mprintf("password for %s: ", g.urlUser);
Blob x;
prompt_for_password(zPrompt, &x, 0);
free(zPrompt);
zPw = blob_str(&x);
if( !g.dontKeepUrl ) db_set("last-sync-pw", zPw, 0);
g.urlPasswd = mprintf("%s", zPw);
}
/* The login card wants the SHA1 hash of the password, so convert the
** password to its SHA1 hash it it isn't already a SHA1 hash.
**
** Except, if the password begins with "*" then use the characters
** after the "*" as a cleartext password. Put an "*" at the beginning
|
| ︙ | ︙ |
Changes to src/main.c.
| ︙ | ︙ | |||
99 100 101 102 103 104 105 106 107 108 109 110 111 112 | int urlPort; /* TCP port number for http: or https: */ int urlDfltPort; /* The default port for the given protocol */ char *urlPath; /* Pathname for http: */ char *urlUser; /* User id for http: */ char *urlPasswd; /* Password for http: */ char *urlCanonical; /* Canonical representation of the URL */ char *urlProxyAuth; /* Proxy-Authorizer: string */ const char *zLogin; /* Login name. "" if not logged in. */ int noPswd; /* Logged in without password (on 127.0.0.1) */ int userUid; /* Integer user id */ /* Information used to populate the RCVFROM table */ int rcvid; /* The rcvid. 0 if not yet defined. */ | > | 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | int urlPort; /* TCP port number for http: or https: */ int urlDfltPort; /* The default port for the given protocol */ char *urlPath; /* Pathname for http: */ char *urlUser; /* User id for http: */ char *urlPasswd; /* Password for http: */ char *urlCanonical; /* Canonical representation of the URL */ char *urlProxyAuth; /* Proxy-Authorizer: string */ int dontKeepUrl; /* Do not persist the URL */ const char *zLogin; /* Login name. "" if not logged in. */ int noPswd; /* Logged in without password (on 127.0.0.1) */ int userUid; /* Integer user id */ /* Information used to populate the RCVFROM table */ int rcvid; /* The rcvid. 0 if not yet defined. */ |
| ︙ | ︙ |
Changes to src/sync.c.
| ︙ | ︙ | |||
77 78 79 80 81 82 83 84 |
** This routine processes the command-line argument for push, pull,
** and sync. If a command-line argument is given, that is the URL
** of a server to sync against. If no argument is given, use the
** most recently synced URL. Remember the current URL for next time.
*/
void process_sync_args(void){
const char *zUrl = 0;
int urlOptional = find_option("autourl",0,0)!=0;
| > | > | | > > > > < | < < < < | 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
** This routine processes the command-line argument for push, pull,
** and sync. If a command-line argument is given, that is the URL
** of a server to sync against. If no argument is given, use the
** most recently synced URL. Remember the current URL for next time.
*/
void process_sync_args(void){
const char *zUrl = 0;
const char *zPw = 0;
int urlOptional = find_option("autourl",0,0)!=0;
g.dontKeepUrl = find_option("once",0,0)!=0;
url_proxy_options();
db_find_and_open_repository(1);
if( g.argc==2 ){
zUrl = db_get("last-sync-url", 0);
zPw = db_get("last-sync-pw", 0);
}else if( g.argc==3 ){
zUrl = g.argv[2];
}
if( zUrl==0 ){
if( urlOptional ) exit(0);
usage("URL");
}
url_parse(zUrl);
if( !g.dontKeepUrl ){
db_set("last-sync-url", g.urlCanonical, 0);
if( g.urlPasswd ) db_set("last-sync-pw", g.urlPasswd, 0);
}
if( g.urlUser!=0 && g.urlPasswd==0 ){
g.urlPasswd = mprintf("%s", zPw);
}
user_select();
if( g.argc==2 ){
printf("Server: %s\n", g.urlCanonical);
}
url_enable_proxy("via proxy: ");
}
/*
** COMMAND: pull
**
|
| ︙ | ︙ | |||
187 188 189 190 191 192 193 | process_sync_args(); client_sync(1,1,0,0,0); } /* ** COMMAND: remote-url ** | | < < < | > > > > > > > > > > > > | > > > > > < < < | | > | 188 189 190 191 192 193 194 195 196 197 198 199 200 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 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
process_sync_args();
client_sync(1,1,0,0,0);
}
/*
** COMMAND: remote-url
**
** Usage: %fossil remote-url ?URL|off? ?--password PASSWORD?
**
** Query and/or change the default server URL used by the "pull", "push",
** and "sync" commands.
**
** The remote-url is set automatically by a "clone" command or by any
** "sync", "push", or "pull" command that specifies an explicit URL.
** The default remote-url is used by auto-syncing and by "sync", "push",
** "pull" that omit the server URL.
**
** See also: clone, push, pull, sync
*/
void remote_url_cmd(void){
char *zUrl;
const char *zPw = find_option("password", 0, 1);
db_find_and_open_repository(1);
if( g.argc!=2 && g.argc!=3 ){
usage("remote-url ?URL|off?");
}
if( g.argc==3 ){
if( strcmp(g.argv[2],"off")==0 ){
db_unset("last-sync-url", 0);
db_unset("last-sync-pw", 0);
}else{
url_parse(g.argv[2]);
if( g.urlUser && g.urlPasswd==0 ){
if( zPw ){
g.urlPasswd = mprintf("%s", zPw);
}else{
char *zPrompt = mprintf("password for %s: ", g.urlUser);
Blob x;
prompt_for_password(zPrompt, &x, 0);
free(zPrompt);
g.urlPasswd = blob_str(&x);
}
}
db_set("last-sync-url", g.urlCanonical, 0);
if( g.urlPasswd ){
db_set("last-sync-pw", g.urlPasswd, 0);
}else{
db_unset("last-sync-pw", 0);
}
}
}
zUrl = db_get("last-sync-url", 0);
if( zUrl==0 ){
printf("off\n");
return;
}else{
url_parse(zUrl);
printf("%s\n", g.urlCanonical);
}
}
|
Changes to src/url.c.
| ︙ | ︙ | |||
35 36 37 38 39 40 41 | ** g.urlName Hostname for HTTP: or HTTPS:. Filename for FILE: ** g.urlPort TCP port number for HTTP or HTTPS. ** g.urlDfltPort Default TCP port number (80 or 443). ** g.urlPath Path name for HTTP or HTTPS. ** g.urlUser Userid. ** g.urlPasswd Password. ** g.urlHostname HOST:PORT or just HOST if port is the default. | | > | 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 |
** g.urlName Hostname for HTTP: or HTTPS:. Filename for FILE:
** g.urlPort TCP port number for HTTP or HTTPS.
** g.urlDfltPort Default TCP port number (80 or 443).
** g.urlPath Path name for HTTP or HTTPS.
** g.urlUser Userid.
** g.urlPasswd Password.
** g.urlHostname HOST:PORT or just HOST if port is the default.
** g.urlCanonical The URL in canonical form, omitting password
**
** 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://", 7)==0 || strncmp(zUrl, "https://", 8)==0 ){
int iStart;
char *zLogin;
g.urlIsFile = 0;
if( zUrl[4]=='s' ){
g.urlIsHttps = 1;
g.urlProtocol = "https";
g.urlDfltPort = 443;
iStart = 8;
}else{
|
| ︙ | ︙ | |||
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
if( j<i ){
g.urlPasswd = mprintf("%.*s", i-j-1, &zUrl[j+1]);
dehttpize(g.urlPasswd);
}
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=iStart; (c=zUrl[i])!=0 && c!='/' && c!=':'; i++){}
g.urlName = mprintf("%.*s", i-iStart, &zUrl[iStart]);
}
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++;
}
g.urlHostname = mprintf("%s:%d", g.urlName, g.urlPort);
}else{
g.urlPort = g.urlDfltPort;
g.urlHostname = g.urlName;
}
g.urlPath = mprintf(&zUrl[i]);
dehttpize(g.urlName);
dehttpize(g.urlPath);
if( g.urlDfltPort==g.urlPort ){
| > > | > | > | > | > > | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
if( j<i ){
g.urlPasswd = mprintf("%.*s", i-j-1, &zUrl[j+1]);
dehttpize(g.urlPasswd);
}
for(j=i+1; (c=zUrl[j])!=0 && c!='/' && c!=':'; j++){}
g.urlName = mprintf("%.*s", j-i-1, &zUrl[i+1]);
i = j;
zLogin = mprintf("%t@", g.urlUser);
}else{
for(i=iStart; (c=zUrl[i])!=0 && c!='/' && c!=':'; i++){}
g.urlName = mprintf("%.*s", i-iStart, &zUrl[iStart]);
zLogin = mprintf("");
}
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++;
}
g.urlHostname = mprintf("%s:%d", g.urlName, g.urlPort);
}else{
g.urlPort = g.urlDfltPort;
g.urlHostname = g.urlName;
}
g.urlPath = mprintf(&zUrl[i]);
dehttpize(g.urlName);
dehttpize(g.urlPath);
if( g.urlDfltPort==g.urlPort ){
g.urlCanonical = mprintf(
"%s://%s%T%T",
g.urlProtocol, zLogin, g.urlName, g.urlPath
);
}else{
g.urlCanonical = mprintf(
"%s://%s%T:%d%T",
g.urlProtocol, zLogin, g.urlName, g.urlPort, g.urlPath
);
}
free(zLogin);
}else if( strncmp(zUrl, "file:", 5)==0 ){
g.urlIsFile = 1;
if( zUrl[5]=='/' && zUrl[6]=='/' ){
i = 7;
}else{
i = 5;
}
|
| ︙ | ︙ |
Changes to src/xfer.c.
| ︙ | ︙ | |||
430 431 432 433 434 435 436 437 438 439 440 441 442 443 |
login_set_capabilities(zCap);
g.userUid = db_column_int(&q, 2);
g.zLogin = mprintf("%b", pLogin);
g.zNonce = mprintf("%b", pNonce);
if( g.fHttpTrace ){
fprintf(stderr, "# login [%s] with capabilities [%s]\n", g.zLogin,zCap);
}
}
}
db_finalize(&q);
if( rc==0 ){
/* If the login was successful. */
login_set_anon_nobody_capabilities();
| > > | 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 |
login_set_capabilities(zCap);
g.userUid = db_column_int(&q, 2);
g.zLogin = mprintf("%b", pLogin);
g.zNonce = mprintf("%b", pNonce);
if( g.fHttpTrace ){
fprintf(stderr, "# login [%s] with capabilities [%s]\n", g.zLogin,zCap);
}
}else{
@ message login\sfailed
}
}
db_finalize(&q);
if( rc==0 ){
/* If the login was successful. */
login_set_anon_nobody_capabilities();
|
| ︙ | ︙ | |||
1206 1207 1208 1209 1210 1211 1212 |
*/
if( blob_eq(&xfer.aToken[0], "cookie") && xfer.nToken==2 ){
db_set("cookie", blob_str(&xfer.aToken[1]), 0);
}else
/* message MESSAGE
**
| | > > > > > > > > > > > | | 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 |
*/
if( blob_eq(&xfer.aToken[0], "cookie") && xfer.nToken==2 ){
db_set("cookie", blob_str(&xfer.aToken[1]), 0);
}else
/* message MESSAGE
**
** Print a message. Similar to "error" but does not stop processing.
**
** If the "login failed" message is seen, clear the sync password prior
** to the next cycle.
*/
if( blob_eq(&xfer.aToken[0],"message") && xfer.nToken==2 ){
char *zMsg = blob_terminate(&xfer.aToken[1]);
defossilize(zMsg);
if( strcmp(zMsg, "login failed")==0 ){
if( cloneFlag && nCycle==0 ){
zMsg = 0;
}else{
if( !g.dontKeepUrl ) db_unset("last-sync-pw", 0);
g.urlPasswd = 0;
}
}
if( zMsg ) printf("\rServer says: %s\n", zMsg);
}else
/* error MESSAGE
**
** Report an error and abandon the sync session.
**
** Except, when cloning we will sometimes get an error on the
|
| ︙ | ︙ |