43
static int auto_update_server_info;
44
static int auto_gc = 1;
45
static int fix_thin = 1;
46
+static int stateless_rpc;
47
+static const char *service_dir;
48
static const char *head_name;
49
static void *head_name_to_free;
50
static int sent_capabilities;
60
static const char *NONCE_BAD = "BAD";
61
static const char *NONCE_MISSING = "MISSING";
62
static const char *NONCE_OK = "OK";
63
+static const char *NONCE_SLOP = "SLOP";
64
static const char *nonce_status;
65
+static long nonce_stamp_slop;
66
+static unsigned long nonce_stamp_slop_limit;
67
68
static enum deny_action parse_deny_action(const char *var, const char *value)
69
{
150
if (strcmp(var, "receive.certnonceseed") == 0)
151
return git_config_string(&cert_nonce_seed, var, value);
152
153
+ if (strcmp(var, "receive.certnonceslop") == 0) {
154
+ nonce_stamp_slop_limit = git_config_ulong(var, value);
155
+ return 0;
156
+ }
157
+
158
return git_default_config(var, value, cb);
159
}
160
369
static const char *check_nonce(const char *buf, size_t len)
370
{
371
char *nonce = find_header(buf, len, "nonce");
372
+ unsigned long stamp, ostamp;
373
+ char *bohmac, *expect = NULL;
374
const char *retval = NONCE_BAD;
375
376
if (!nonce) {
384
goto leave;
385
}
386
375
- /* returned nonce MUST match what we gave out earlier */
376
- retval = NONCE_BAD;
387
+ if (!stateless_rpc) {
388
+ /* returned nonce MUST match what we gave out earlier */
389
+ retval = NONCE_BAD;
390
+ goto leave;
391
+ }
392
+
393
+ /*
394
+ * In stateless mode, we may be receiving a nonce issued by
395
+ * another instance of the server that serving the same
396
+ * repository, and the timestamps may not match, but the
397
+ * nonce-seed and dir should match, so we can recompute and
398
+ * report the time slop.
399
+ *
400
+ * In addition, when a nonce issued by another instance has
401
+ * timestamp within receive.certnonceslop seconds, we pretend
402
+ * as if we issued that nonce when reporting to the hook.
403
+ */
404
+
405
+ /* nonce is concat(<seconds-since-epoch>, "-", <hmac>) */
406
+ if (*nonce <= '0' || '9' < *nonce) {
407
+ retval = NONCE_BAD;
408
+ goto leave;
409
+ }
410
+ stamp = strtoul(nonce, &bohmac, 10);
411
+ if (bohmac == nonce || bohmac[0] != '-') {
412
+ retval = NONCE_BAD;
413
+ goto leave;
414
+ }
415
+
416
+ expect = prepare_push_cert_nonce(service_dir, stamp);
417
+ if (strcmp(expect, nonce)) {
418
+ /* Not what we would have signed earlier */
419
+ retval = NONCE_BAD;
420
+ goto leave;
421
+ }
422
+
423
+ /*
424
+ * By how many seconds is this nonce stale? Negative value
425
+ * would mean it was issued by another server with its clock
426
+ * skewed in the future.
427
+ */
428
+ ostamp = strtoul(push_cert_nonce, NULL, 10);
429
+ nonce_stamp_slop = (long)ostamp - (long)stamp;
430
+
431
+ if (nonce_stamp_slop_limit &&
432
+ abs(nonce_stamp_slop) <= nonce_stamp_slop_limit) {
433
+ /*
434
+ * Pretend as if the received nonce (which passes the
435
+ * HMAC check, so it is not a forged by third-party)
436
+ * is what we issued.
437
+ */
438
+ free((void *)push_cert_nonce);
439
+ push_cert_nonce = xstrdup(nonce);
440
+ retval = NONCE_OK;
441
+ } else {
442
+ retval = NONCE_SLOP;
443
+ }
444
445
leave:
446
free(nonce);
447
+ free(expect);
448
return retval;
449
}
450
494
if (push_cert_nonce) {
495
argv_array_pushf(&env, "GIT_PUSH_CERT_NONCE=%s", push_cert_nonce);
496
argv_array_pushf(&env, "GIT_PUSH_CERT_NONCE_STATUS=%s", nonce_status);
497
+ if (nonce_status == NONCE_SLOP)
498
+ argv_array_pushf(&env, "GIT_PUSH_CERT_NONCE_SLOP=%ld",
499
+ nonce_stamp_slop);
500
}
501
proc->env = env.argv;
502
}
1432
int cmd_receive_pack(int argc, const char **argv, const char *prefix)
1433
{
1434
int advertise_refs = 0;
1364
- int stateless_rpc = 0;
1435
int i;
1366
- const char *dir = NULL;
1436
struct command *commands;
1437
struct sha1_array shallow = SHA1_ARRAY_INIT;
1438
struct sha1_array ref = SHA1_ARRAY_INIT;
1465
1466
usage(receive_pack_usage);
1467
}
1399
- if (dir)
1468
+ if (service_dir)
1469
usage(receive_pack_usage);
1401
- dir = arg;
1470
+ service_dir = arg;
1471
}
1403
- if (!dir)
1472
+ if (!service_dir)
1473
usage(receive_pack_usage);
1474
1475
setup_path();
1476
1408
- if (!enter_repo(dir, 0))
1409
- die("'%s' does not appear to be a git repository", dir);
1477
+ if (!enter_repo(service_dir, 0))
1478
+ die("'%s' does not appear to be a git repository", service_dir);
1479
1480
git_config(receive_pack_config, NULL);
1481
if (cert_nonce_seed)
1413
- push_cert_nonce = prepare_push_cert_nonce(dir, time(NULL));
1482
+ push_cert_nonce = prepare_push_cert_nonce(service_dir, time(NULL));
1483
1484
if (0 <= transfer_unpack_limit)
1485
unpack_limit = transfer_unpack_limit;