@@ -30,6 +30,7 @@ static const char daemon_usage[] =
30
30
" [--interpolated-path=<path>]\n"
31
31
" [--reuseaddr] [--pid-file=<file>]\n"
32
32
" [--(enable|disable|allow-override|forbid-override)=<service>]\n"
33
+ " [--access-hook=<path>]\n"
33
34
" [--inetd | [--listen=<host_or_ipaddr>] [--port=<n>]\n"
34
35
" [--detach] [--user=<user> [--group=<group>]]\n"
35
36
" [<directory>...]" ;
@@ -256,6 +257,71 @@ static int daemon_error(const char *dir, const char *msg)
256
257
return -1 ;
257
258
}
258
259
260
+ static char * access_hook ;
261
+
262
+ static int run_access_hook (struct daemon_service * service , const char * dir , const char * path )
263
+ {
264
+ struct child_process child ;
265
+ struct strbuf buf = STRBUF_INIT ;
266
+ const char * argv [8 ];
267
+ const char * * arg = argv ;
268
+ char * eol ;
269
+ int seen_errors = 0 ;
270
+
271
+ #define STRARG (x ) ((x) ? (x) : "")
272
+ * arg ++ = access_hook ;
273
+ * arg ++ = service -> name ;
274
+ * arg ++ = path ;
275
+ * arg ++ = STRARG (hostname );
276
+ * arg ++ = STRARG (canon_hostname );
277
+ * arg ++ = STRARG (ip_address );
278
+ * arg ++ = STRARG (tcp_port );
279
+ * arg = NULL ;
280
+ #undef STRARG
281
+
282
+ memset (& child , 0 , sizeof (child ));
283
+ child .use_shell = 1 ;
284
+ child .argv = argv ;
285
+ child .no_stdin = 1 ;
286
+ child .no_stderr = 1 ;
287
+ child .out = -1 ;
288
+ if (start_command (& child )) {
289
+ logerror ("daemon access hook '%s' failed to start" ,
290
+ access_hook );
291
+ goto error_return ;
292
+ }
293
+ if (strbuf_read (& buf , child .out , 0 ) < 0 ) {
294
+ logerror ("failed to read from pipe to daemon access hook '%s'" ,
295
+ access_hook );
296
+ strbuf_reset (& buf );
297
+ seen_errors = 1 ;
298
+ }
299
+ if (close (child .out ) < 0 ) {
300
+ logerror ("failed to close pipe to daemon access hook '%s'" ,
301
+ access_hook );
302
+ seen_errors = 1 ;
303
+ }
304
+ if (finish_command (& child ))
305
+ seen_errors = 1 ;
306
+
307
+ if (!seen_errors ) {
308
+ strbuf_release (& buf );
309
+ return 0 ;
310
+ }
311
+
312
+ error_return :
313
+ strbuf_ltrim (& buf );
314
+ if (!buf .len )
315
+ strbuf_addstr (& buf , "service rejected" );
316
+ eol = strchr (buf .buf , '\n' );
317
+ if (eol )
318
+ * eol = '\0' ;
319
+ errno = EACCES ;
320
+ daemon_error (dir , buf .buf );
321
+ strbuf_release (& buf );
322
+ return -1 ;
323
+ }
324
+
259
325
static int run_service (char * dir , struct daemon_service * service )
260
326
{
261
327
const char * path ;
@@ -303,6 +369,13 @@ static int run_service(char *dir, struct daemon_service *service)
303
369
return daemon_error (dir , "service not enabled" );
304
370
}
305
371
372
+ /*
373
+ * Optionally, a hook can choose to deny access to the
374
+ * repository depending on the phase of the moon.
375
+ */
376
+ if (access_hook && run_access_hook (service , dir , path ))
377
+ return -1 ;
378
+
306
379
/*
307
380
* We'll ignore SIGTERM from now on, we have a
308
381
* good client.
@@ -1142,6 +1215,10 @@ int main(int argc, char **argv)
1142
1215
export_all_trees = 1 ;
1143
1216
continue ;
1144
1217
}
1218
+ if (!prefixcmp (arg , "--access-hook=" )) {
1219
+ access_hook = arg + 14 ;
1220
+ continue ;
1221
+ }
1145
1222
if (!prefixcmp (arg , "--timeout=" )) {
1146
1223
timeout = atoi (arg + 10 );
1147
1224
continue ;
0 commit comments