| ︙ | | |
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
|
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
|
-
+
|
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
|| fossil_strcmp(zLogin,"anonymous")==0
|| fossil_strcmp(zLogin, "anonymous")==0
){
return 0; /* Anybody is allowed to sync as "nobody" or "anonymous" */
}
if( fossil_strcmp(P("REMOTE_USER"), zLogin)==0
&& db_get_boolean("remote_user_ok",0) ){
return 0; /* Accept Basic Authorization */
}
|
| ︙ | | |
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
|
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
|
-
+
|
** again with the SHA1 password.
*/
const char *zPw = db_column_text(&q, 0);
char *zSecret = sha1_shared_secret(zPw, blob_str(pLogin), 0);
blob_zero(&combined);
blob_copy(&combined, pNonce);
blob_append(&combined, zSecret, -1);
free(zSecret);
fossil_free(zSecret);
sha1sum_blob(&combined, &hash);
rc = blob_constant_time_cmp(&hash, pSig);
blob_reset(&hash);
blob_reset(&combined);
}
if( rc==0 ){
const char *zCap;
|
| ︙ | | |
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
|
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
}
/*
** If this variable is set, disable login checks. Used for debugging
** only.
*/
static int disableLogin = 0;
/*
** Must be passed the version info from pragmas
** client-version/server-version cards. If the version info is "new
** enough" then the loginCardMode is ORd into the X-Fossil-Xfer-Login
** card flag, else this is a no-op.
*/
static void xfer_xflc_check(int iRemoteVersion, int iDate, int iTime,
int fLoginCardMode){
if( iRemoteVersion>=22700
&& (iDate > 20250727
|| (iDate == 20250727 && iTime >= 110500)) ){
g.syncInfo.fLoginCardMode |= fLoginCardMode;
}
}
/*
** The CGI/HTTP preprocessor always redirects requests with a content-type
** of application/x-fossil or application/x-fossil-debug to this page,
** regardless of what path was specified in the HTTP header. This allows
** clone clients to specify a URL that omits default pathnames, such
** as "http://fossil-scm.org/" instead of "http://fossil-scm.org/index.cgi".
|
| ︙ | | |
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
|
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
|
+
|
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
|
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
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
@ 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 Cookie header */
assert( g.syncInfo.fLoginCardMode && "Set via HTTP cookie" );
blob_zero(&xfer.line);
blob_append(&xfer.line, g.syncInfo.zLoginCard, -1);
xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken,
count(xfer.aToken));
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
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
|
1578
1579
1580
1581
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
|
+
+
-
+
+
+
+
+
+
+
+
+
+
|
@ 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
** The client can send multiple logins. Permissions are cumulative.
** cumulative permissions. But that feature was never used. Hence
** it is now prohibited. Any login card after the first generates
** a fatal error.
*/
if( blob_eq(&xfer.aToken[0], "login")
&& xfer.nToken==4
){
handle_login_card:
nLogin++;
if( disableLogin ){
g.perm.Read = g.perm.Write = g.perm.Private = g.perm.Admin = 1;
}else if( nLogin > 1 ){
cgi_reset_content();
@ error multiple\slogin\cards
nErr++;
break;
}else{
if( check_tail_hash(&xfer.aToken[2], xfer.pIn)
|| check_login(&xfer.aToken[1], &xfer.aToken[2], &xfer.aToken[3])
){
cgi_reset_content();
@ error login\sfailed
nErr++;
|
| ︙ | | |
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
|
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
|
-
|
if( !g.perm.Private ){
server_private_xfer_not_authorized();
}else{
xfer.nextIsPrivate = 1;
}
}else
/* pragma NAME VALUE...
**
** The client issues pragmas to try to influence the behavior of the
** server. These are requests only. Unknown pragmas are silently
** ignored.
*/
if( blob_eq(&xfer.aToken[0], "pragma") && xfer.nToken>=2 ){
|
| ︙ | | |
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
|
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
|
+
-
+
+
+
|
/* pragma client-version VERSION ?DATE? ?TIME?
**
** 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 = g.syncInfo.remoteVersion =
xfer.remoteVersion = atoi(blob_str(&xfer.aToken[2]));
atoi(blob_str(&xfer.aToken[2]));
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)
}
xfer_xflc_check( xfer.remoteVersion, xfer.remoteDate,
xfer.remoteTime, 0x04 );
}else
/* pragma uv-hash HASH
**
** The client wants to make sure that unversioned files are all synced.
** If the HASH does not match, send a complete catalog of
** "uvigot" cards.
|
| ︙ | | |
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
|
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
|
-
-
+
|
db_lset("client-id", zClientId);
}
blob_appendf(&send, "pragma ci-lock %s %s\n", zCkinLock, zClientId);
zCkinLock = 0;
}else if( zClientId ){
blob_appendf(&send, "pragma ci-unlock %s\n", zClientId);
}
/* Append randomness to the end of the uplink message. This makes all
** messages unique so that that the login-card nonce will always
** be unique.
*/
zRandomness = db_text(0, "SELECT hex(randomblob(20))");
blob_appendf(&send, "# %s\n", zRandomness);
free(zRandomness);
fossil_free(zRandomness);
if( (syncFlags & SYNC_VERBOSE)!=0
&& (syncFlags & SYNC_XVERBOSE)==0
){
fossil_print("waiting for server...");
}
fflush(stdout);
|
| ︙ | | |
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
|
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
|
-
-
-
|
}
}else
/* message MESSAGE
**
** A message is received from the server. Print it.
** 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( (syncFlags & SYNC_PUSH) && zMsg
&& sqlite3_strglob("pull only *", zMsg)==0 ){
syncFlags &= ~SYNC_PUSH;
|
| ︙ | | |
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
|
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
|
+
-
+
+
+
|
/* pragma server-version VERSION ?DATE? ?TIME?
**
** 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 = g.syncInfo.remoteVersion =
xfer.remoteVersion = atoi(blob_str(&xfer.aToken[2]));
atoi(blob_str(&xfer.aToken[2]));
if( xfer.nToken>=5 ){
xfer.remoteDate = atoi(blob_str(&xfer.aToken[3]));
xfer.remoteTime = atoi(blob_str(&xfer.aToken[4]));
}
xfer_xflc_check( xfer.remoteVersion, xfer.remoteDate,
xfer.remoteTime, 0x08 );
}
/* pragma uv-pull-only
** pragma uv-push-ok
**
** If the server is unwilling to accept new unversioned content (because
** this client lacks the necessary permissions) then it sends a
|
| ︙ | | |
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
|
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
|
-
+
|
fossil_warning(
"server replies with HTML instead of fossil sync protocol:\n%b",
&recv
);
nErr++;
break;
}
blob_appendf(&xfer.err, "unknown command: [%b]\n", &xfer.aToken[0]);
blob_appendf(&xfer.err, "unknown command: [%b]\n", &xfer.line);
}
if( blob_size(&xfer.err) ){
fossil_force_newline();
fossil_warning("%b", &xfer.err);
nErr++;
break;
|
| ︙ | | |
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
|
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
|
-
+
|
if( go ){
manifest_crosslink_end(MC_PERMIT_HOOKS);
}else{
manifest_crosslink_end(MC_PERMIT_HOOKS);
content_enable_dephantomize(1);
}
db_end_transaction(0);
};
}; /* while(go) */
transport_stats(&nSent, &nRcvd, 1);
if( pnRcvd ) *pnRcvd = nArtifactRcvd;
if( (rSkew*24.0*3600.0) > 10.0 ){
fossil_warning("*** time skew *** server is fast by %s",
db_timespan_name(rSkew));
g.clockSkewSeen = 1;
}else if( rSkew*24.0*3600.0 < -10.0 ){
|
| ︙ | | |