Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch xfer-login-card Through [2250a684cc] Excluding Merge-Ins
This is equivalent to a diff from c6f0d7aecd to 2250a684cc
|
2025-07-23
| ||
| 15:58 | Minor optimization: replace calls to mprintf("%s", X) with fossil_strdup(X). check-in: 4c3e1728e1 user: danield tags: trunk | |
|
2025-07-22
| ||
| 17:52 | Remove lots of debug output. Replace a couple of mprintf() with fossil_strdup() and a couple free() with fossil_free(). Milestone: libfossil has successfully logged in to this version of fossil. check-in: 1078a123c1 user: stephan tags: xfer-login-card | |
| 15:53 | Doc typo fixes. check-in: 2250a684cc user: stephan tags: xfer-login-card | |
| 15:51 | Set g.syncInfo.bLoginCardHeader=1 if that inbound header is detected, rather than delaying it until the /xfer handling. Internal doc additions. check-in: 4fc13c5c88 user: stephan tags: xfer-login-card | |
|
2025-07-21
| ||
| 18:38 | Enable an /xfer login card to be delivered via the X-Fossil-Xfer-Login HTTP header, which is expected to be in the same format as the sync protocol's login card. The purpose of this is to simplify generation of the login card from non-fossil(1) clients, namely libfossil. This is untested until libfossil can generate such cards (it's just missing a ... check-in: cfddded40e user: stephan tags: xfer-login-card | |
| 17:16 | Account for [638b7e094b899a] when building with --json, as reported in [forum:9acc3d0022407bfe | forum post 9acc3d0022]. check-in: c6f0d7aecd user: stephan tags: trunk | |
| 13:20 | Remove FossilUserPerms::Query, as it's unused and its designated capabilities letter 'q' collides with ModTkt. It's been there since 2011-09-14 but went unnoticed until today when that struct was emacs-macro-reformatted into libfossil and triggered a duplicate case value for the letter 'q'. check-in: 638b7e094b user: stephan tags: trunk | |
Changes to VERSION.
| 1 | - + |
|
Changes to src/cgi.c.
| ︙ | |||
2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 | 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 | + + + + |
}else if( fossil_strcmp(zFieldName,"range:")==0 ){
int x1 = 0;
int x2 = 0;
if( sscanf(zVal,"bytes=%d-%d",&x1,&x2)==2 && x1>=0 && x1<=x2 ){
rangeStart = x1;
rangeEnd = x2+1;
}
}else if( fossil_strcmp(zFieldName, "x-fossil-xfer-login:")==0 ){
g.syncInfo.zLoginCard = fossil_strdup(zVal);
g.syncInfo.bLoginCardHeader = 1;
/*fprintf(stderr, "X-Fossil-Xfer-Login: %s\n", g.syncInfo.zLoginCard);*/
}
}
cgi_setenv("REQUEST_SCHEME",zScheme);
cgi_init();
cgi_trace(0);
}
|
| ︙ |
Changes to src/http.c.
| ︙ | |||
50 51 52 53 54 55 56 | 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 75 76 77 78 79 80 81 82 83 84 85 86 | - - - + + + + + - - + + + - + - + - + | /* ** Construct the "login" card with the client credentials. ** ** login LOGIN NONCE SIGNATURE ** ** The LOGIN is the user id of the client. NONCE is the sha1 checksum |
| ︙ | |||
117 118 119 120 121 122 123 | 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | - + - + + + + + + |
}
fossil_free(g.url.passwd);
g.url.passwd = fossil_strdup(zPw);
}
blob_append(&pw, zPw, -1);
sha1sum_blob(&pw, &sig);
|
| ︙ | |||
457 458 459 460 461 462 463 464 465 466 | 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 | + - + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - + |
if( transport_open(&g.url) ){
fossil_warning("%s", transport_errmsg(&g.url));
return 1;
}
/* Construct the login card and prepare the complete payload */
blob_zero(&login);
if( blob_size(pSend)==0 ){
blob_zero(&payload);
}else{
|
| ︙ |
Changes to src/main.c.
| ︙ | |||
286 287 288 289 290 291 292 293 294 295 296 297 298 299 | 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | + + + + + + + + + + + |
const char **azAuxOpt[MX_AUX]; /* Options of each option() value */
int anAuxCols[MX_AUX]; /* Number of columns for option() values */
int allowSymlinks; /* Cached "allow-symlinks" option */
int mainTimerId; /* Set to fossil_timer_start() */
int nPendingRequest; /* # of HTTP requests in "fossil server" */
int nRequest; /* Total # of HTTP request */
int bAvoidDeltaManifests; /* Avoid using delta manifests if true */
/* State for communicating specific details between the inbound HTTP
** header parser (cgi.c), xfer.c, and http.c. */
struct {
char *zLoginCard; /* Inbound X-Fossil-Xfer-Login request header */
int bLoginCardHeader; /* If true, emit login cards in outbound
** requests as HTTP headers instead of as
** part of the payload. Gets activated
** on-demand based on xfer traffic
** contents. */
} syncInfo;
#ifdef FOSSIL_ENABLE_JSON
struct FossilJsonBits {
int isJsonMode; /* True if running in JSON mode, else
false. This changes how errors are
reported. In JSON mode we try to
always output JSON-form error
responses and always (in CGI mode)
|
| ︙ | |||
756 757 758 759 760 761 762 763 764 765 766 767 768 769 | 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 | + + + + + |
#ifdef FOSSIL_ENABLE_TCL
memset(&g.tcl, 0, sizeof(TclContext));
g.tcl.argc = g.argc;
g.tcl.argv = copy_args(g.argc, g.argv); /* save full arguments */
#endif
g.mainTimerId = fossil_timer_start();
capture_case_sensitive_option();
g.syncInfo.bLoginCardHeader =
/* This is only for facilitating development of the
** xfer-login-card branch. It will be removed or re-imagined at
** some point. */
!!find_option("login-card-header","lch", 0);
g.zVfsName = find_option("vfs",0,1);
if( g.zVfsName==0 ){
g.zVfsName = fossil_getenv("FOSSIL_VFS");
}
if( g.zVfsName ){
sqlite3_vfs *pVfs = sqlite3_vfs_find(g.zVfsName);
if( pVfs ){
|
| ︙ |
Changes to src/user.c.
| ︙ | |||
463 464 465 466 467 468 469 | 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 | - + |
fossil_print("password unchanged\n");
}else{
char *zSecret = sha1_shared_secret(blob_str(&pw), g.argv[3], 0);
db_unprotect(PROTECT_USER);
db_multi_exec("UPDATE user SET pw=%Q, mtime=now() WHERE uid=%d",
zSecret, uid);
db_protect_pop();
|
| ︙ |
Changes to src/xfer.c.
| ︙ | |||
788 789 790 791 792 793 794 795 796 797 798 799 800 801 | 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 | + + + + + |
** the length of the input hash in pHash.
*/
static int check_tail_hash(Blob *pHash, Blob *pMsg){
Blob tail;
int rc;
blob_tail(pMsg, &tail);
rc = hname_verify_hash(&tail, blob_buffer(pHash), blob_size(pHash));
#if 0
fprintf(stderr, "check tail=%d hash=[%.*s]\ntail=<<%.*s>>\n", rc,
blob_size(pHash), blob_str(pHash),
blob_size(&tail), blob_str(&tail));
#endif
blob_reset(&tail);
return rc==HNAME_ERROR;
}
/*
** Check the signature on an application/x-fossil payload received by
** the HTTP server. The signature is a line of the following form:
|
| ︙ | |||
825 826 827 828 829 830 831 | 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 | - + |
static int check_login(Blob *pLogin, Blob *pNonce, Blob *pSig){
Stmt q;
int rc = -1;
char *zLogin = blob_terminate(pLogin);
defossilize(zLogin);
if( fossil_strcmp(zLogin, "nobody")==0
|
| ︙ | |||
852 853 854 855 856 857 858 859 860 861 862 863 864 865 | 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 | + + + + + + + + + |
szPw = blob_size(&pw);
blob_zero(&combined);
blob_copy(&combined, pNonce);
blob_append(&combined, blob_buffer(&pw), szPw);
sha1sum_blob(&combined, &hash);
assert( blob_size(&hash)==40 );
rc = blob_constant_time_cmp(&hash, pSig);
#if 0
fprintf(stderr,
"check login rc=%d nonce=[%.*s] pSig=[%.*s] .hash=[%.*s]\n",
rc,
blob_size(pNonce), blob_str(pNonce),
blob_size(pSig), blob_str(pSig),
blob_size(&hash), blob_str(&hash));
#endif
blob_reset(&hash);
blob_reset(&combined);
if( rc!=0 && szPw!=40 ){
/* If this server stores cleartext passwords and the password did not
** match, then perhaps the client is sending SHA1 passwords. Try
** again with the SHA1 password.
*/
|
| ︙ | |||
1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 | 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 | + |
const char *zScript = 0;
char *zUuidList = 0;
int nUuidList = 0;
char **pzUuidList = 0;
int *pnUuidList = 0;
int uvCatalogSent = 0;
int bSendLinks = 0;
int nLogin = 0;
if( fossil_strcmp(PD("REQUEST_METHOD","POST"),"POST") ){
fossil_redirect_home();
}
g.zLogin = "anonymous";
login_set_anon_nobody_capabilities();
login_check_credentials();
|
| ︙ | |||
1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 | 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 | + + + + + + + + + + + + + + + + + + + |
@ error common\sscript\sfailed:\s%F(g.zErrMsg)
nErr++;
}
zScript = xfer_push_code();
if( zScript ){ /* NOTE: Are TH1 transfer hooks enabled? */
pzUuidList = &zUuidList;
pnUuidList = &nUuidList;
}
if( g.syncInfo.zLoginCard ){
/* Login card received via HTTP header X-Fossil-Xfer-Login */
blob_zero(&xfer.line);
blob_append(&xfer.line, g.syncInfo.zLoginCard, -1);
xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken,
count(xfer.aToken));
#if 0
fprintf(stderr,"%s:%d: g.syncInfo.zLoginCard=[%s]\nnToken=%d tok[0]=%s line=%s\n",
__FILE__, __LINE__, g.syncInfo.zLoginCard,
xfer.nToken, xfer.nToken ? blob_str(&xfer.aToken[0]) : "<NULL>",
blob_str(&xfer.line));
#endif
fossil_free( g.syncInfo.zLoginCard );
g.syncInfo.zLoginCard = 0;
if( xfer.nToken==4
&& blob_eq(&xfer.aToken[0], "login") ){
goto handle_login_card;
}
}
while( blob_line(xfer.pIn, &xfer.line) ){
if( blob_buffer(&xfer.line)[0]=='#' ) continue;
if( blob_size(&xfer.line)==0 ) continue;
xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken));
/* file HASH SIZE \n CONTENT
|
| ︙ | |||
1548 1549 1550 1551 1552 1553 1554 | 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 | + + - + + + + + + + + + + + + + + + + + + + + |
@ push %s(db_get("server-code", "x")) %s(db_get("project-code", "x"))
}else
/* login USER NONCE SIGNATURE
**
** The client has sent login credentials to the server.
** Validate the login. This has to happen before anything else.
**
** For many years, Fossil would accept multiple login cards with
|
| ︙ | |||
1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 | 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 | + + |
**
** The client announces to the server what version of Fossil it
** is running. The DATE and TIME are a pure numeric ISO8601 time
** for the specific check-in of the client.
*/
if( xfer.nToken>=3 && blob_eq(&xfer.aToken[1], "client-version") ){
xfer.remoteVersion = atoi(blob_str(&xfer.aToken[2]));
g.syncInfo.bLoginCardHeader =
xfer.remoteVersion>=RELEASE_VERSION_NUMBER;
if( xfer.nToken>=5 ){
xfer.remoteDate = atoi(blob_str(&xfer.aToken[3]));
xfer.remoteTime = atoi(blob_str(&xfer.aToken[4]));
@ pragma server-version %d(RELEASE_VERSION_NUMBER) \
@ %d(MANIFEST_NUMERIC_DATE) %d(MANIFEST_NUMERIC_TIME)
}
}else
|
| ︙ | |||
2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 | 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 | + + |
**
** The server announces to the server what version of Fossil it
** is running. The DATE and TIME are a pure numeric ISO8601 time
** for the specific check-in of the client.
*/
if( xfer.nToken>=3 && blob_eq(&xfer.aToken[1], "server-version") ){
xfer.remoteVersion = atoi(blob_str(&xfer.aToken[2]));
g.syncInfo.bLoginCardHeader =
xfer.remoteVersion>=RELEASE_VERSION_NUMBER;
if( xfer.nToken>=5 ){
xfer.remoteDate = atoi(blob_str(&xfer.aToken[3]));
xfer.remoteTime = atoi(blob_str(&xfer.aToken[4]));
}
}
/* pragma uv-pull-only
|
| ︙ |
Changes to www/sync.wiki.
| ︙ | |||
224 225 226 227 228 229 230 | 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | - - - + + + - - - + + + - - - + + + | The userid is the name of the user that is requesting service from the server. The nonce is the SHA1 hash of the remainder of the message - all text that follows the newline character that terminates the login card. The signature is the SHA1 hash of the concatenation of the nonce and the users password. |
| ︙ |