| ︙ | | |
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
|
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
|
-
+
-
-
+
|
pXfer->nGimmeSent++;
}
db_finalize(&q);
}
/*
** Compute an SHA1 hash on the tail of pMsg. Verify that it matches the
** the hash given in pHash. Return 1 on a successful match. Return 0
** the hash given in pHash. Return non-zero for an error and 0 on success.
** if there is a mismatch.
*/
static int check_tail_hash(Blob *pHash, Blob *pMsg){
Blob tail;
Blob h2;
int rc;
blob_tail(pMsg, &tail);
sha1sum_blob(&tail, &h2);
rc = blob_compare(pHash, &h2);
blob_reset(&h2);
blob_reset(&tail);
return rc==0;
return rc;
}
/*
** Check the signature on an application/x-fossil payload received by
** the HTTP server. The signature is a line of the following form:
**
** login LOGIN NONCE SIGNATURE
|
| ︙ | | |
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
|
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
|
+
+
-
+
|
** If everything checks out, the USER.CAP column for the USER table
** is consulted to set privileges in the global g variable.
**
** If anything fails to check out, no changes are made to privileges.
**
** Signature generation on the client side is handled by the
** http_exchange() routine.
**
** Return non-zero for a login failure and zero for success.
*/
void check_login(Blob *pLogin, Blob *pNonce, Blob *pSig){
int check_login(Blob *pLogin, Blob *pNonce, Blob *pSig){
Stmt q;
int rc = -1;
char *zLogin = blob_terminate(pLogin);
defossilize(zLogin);
db_prepare(&q,
"SELECT pw, cap, uid FROM user"
|
| ︙ | | |
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
|
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
|
-
-
-
+
|
}
}
db_finalize(&q);
if( rc==0 ){
/* If the login was successful. */
login_set_anon_nobody_capabilities();
}else{
/* Login failed */
@ message login\sfailed
}
return rc;
}
/*
** Send the content of all files in the unsent table.
**
** This is really just an optimization. If you clear the
** unsent table, all the right files will still get transferred.
|
| ︙ | | |
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
|
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
|
+
-
-
+
+
+
+
+
+
+
+
|
** The client can send multiple logins. Permissions are cumulative.
*/
if( blob_eq(&xfer.aToken[0], "login")
&& xfer.nToken==4
){
if( disableLogin ){
g.okRead = g.okWrite = 1;
}else{
}else if( check_tail_hash(&xfer.aToken[2], xfer.pIn) ){
check_login(&xfer.aToken[1], &xfer.aToken[2], &xfer.aToken[3]);
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++;
break;
}
}
}else
/* reqconfig NAME
**
** Request a configuration value
*/
|
| ︙ | | |
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
|
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
|
+
|
blob_appendf(&send, "pull %s %s\n", zSCode, zPCode);
nCardSent++;
}
if( pushFlag ){
blob_appendf(&send, "push %s %s\n", zSCode, zPCode);
nCardSent++;
}
go = 0;
/* Process the reply that came back from the server */
while( blob_line(&recv, &xfer.line) ){
if( blob_buffer(&xfer.line)[0]=='#' ){
continue;
}
xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken));
|
| ︙ | | |
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
|
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
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
|
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
+
+
+
|
**
** 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
** first message exchange because the project-code is unknown
** and so the login card on the request was invalid. The project-code
** is returned in the reply before the error card, so second and
** subsequent messages should be OK. Nevertheless, we need to ignore
** the error card on the first message of a clone.
*/
if( blob_eq(&xfer.aToken[0],"error") && xfer.nToken==2 ){
if( !cloneFlag || nCycle>0 ){
char *zMsg = blob_terminate(&xfer.aToken[1]);
defossilize(zMsg);
if( strcmp(zMsg, "login failed")==0 ){
if( !g.dontKeepUrl ) db_unset("last-sync-pw", 0);
g.urlPasswd = 0;
if( nCycle<2 ) go = 1;
}else{
blob_appendf(&xfer.err, "server says: %s", zMsg);
printf("Server Error: %s\n", zMsg);
blob_appendf(&xfer.err, "\rserver says: %s", zMsg);
}
printf("\rServer Error: %s\n", zMsg);
}
}else
/* Unknown message */
{
if( blob_str(&xfer.aToken[0])[0]=='<' ){
fossil_fatal(
|
| ︙ | | |
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
|
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
|
-
|
if( nCardRcvd>0 ){
printf(zValueFormat, "Received:",
blob_size(&recv), nCardRcvd,
xfer.nFileRcvd, xfer.nDeltaRcvd + xfer.nDanglingFile);
}
blob_reset(&recv);
nCycle++;
go = 0;
/* If we received one or more files on the previous exchange but
** there are still phantoms, then go another round.
*/
nFileRecv = xfer.nFileRcvd + xfer.nDeltaRcvd + xfer.nDanglingFile;
if( (nFileRecv>0 || newPhantom) && db_exists("SELECT 1 FROM phantom") ){
go = 1;
|
| ︙ | | |