@@ -30,6 +30,7 @@ static const char daemon_usage[] =
3030" [--interpolated-path=<path>]\n"
3131" [--reuseaddr] [--pid-file=<file>]\n"
3232" [--(enable|disable|allow-override|forbid-override)=<service>]\n"
33+ " [--access-hook=<path>]\n"
3334" [--inetd | [--listen=<host_or_ipaddr>] [--port=<n>]\n"
3435" [--detach] [--user=<user> [--group=<group>]]\n"
3536" [<directory>...]" ;
@@ -256,6 +257,71 @@ static int daemon_error(const char *dir, const char *msg)
256257 return -1 ;
257258}
258259
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+
259325static int run_service (char * dir , struct daemon_service * service )
260326{
261327 const char * path ;
@@ -303,6 +369,13 @@ static int run_service(char *dir, struct daemon_service *service)
303369 return daemon_error (dir , "service not enabled" );
304370 }
305371
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+
306379 /*
307380 * We'll ignore SIGTERM from now on, we have a
308381 * good client.
@@ -1142,6 +1215,10 @@ int main(int argc, char **argv)
11421215 export_all_trees = 1 ;
11431216 continue ;
11441217 }
1218+ if (!prefixcmp (arg , "--access-hook=" )) {
1219+ access_hook = arg + 14 ;
1220+ continue ;
1221+ }
11451222 if (!prefixcmp (arg , "--timeout=" )) {
11461223 timeout = atoi (arg + 10 );
11471224 continue ;
0 commit comments