From: Junio C Hamano <hidden> Date: 2016-06-15 22:52:10
Nguyễn Thái Ngọc Duy [off-list ref] writes:
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
Note that if a service fails, then "access denied" is printed too.
After run_service() returns with a failure, it is simply irresponsible to
append an "ERR" packet to the output channel without knowing what the
state of that channel is (e.g. it might be that the service wrote only
half a pkt_line it wanted to write, and you may be appending to it).
I think the earlier patch from Peff makes the division of responsibility
clearer. If the daemon's dispatch code notices it does not want to run it,
it is the daemon's job to report it. Otherwise the service can and should
report what it does, and after it starts running, the channel belongs to
the service.
The message is chosen to avoid leaking information, yet let users know
that they are deliberately not allowed to use the service, not a fault
in service configuration or the service itself.
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
OK let's try again. I don't send ERR when faults happen in
service->fn() (eventually run_service_command) because
- if it's start_command(), it's likely due to service configuration
fault (wrong --exec-path..)
- if it's finish_command(), the service may have run and sent
something back to users. We may break the protocol by sending ERR
daemon.c | 12 ++++++++----
1 files changed, 8 insertions(+), 4 deletions(-)
@@ -257,11 +257,11 @@ static int run_service(char *dir, struct daemon_service *service)if(!enabled&&!service->overridable){logerror("'%s': service not enabled.",service->name);errno=EACCES;-return-1;+gotofailed;}if(!(path=path_ok(dir)))-return-1;+gotofailed;/**Securityonthecheap.
@@ -277,7 +277,7 @@ static int run_service(char *dir, struct daemon_service *service)if(!export_all_trees&&access("git-daemon-export-ok",F_OK)){logerror("'%s': repository not exported.",path);errno=EACCES;-return-1;+gotofailed;}if(service->overridable){
@@ -291,7 +291,7 @@ static int run_service(char *dir, struct daemon_service *service)logerror("'%s': service not enabled for '%s'",service->name,path);errno=EACCES;-return-1;+gotofailed;}/*
From: Jeff King <hidden> Date: 2016-06-15 22:52:14
On Tue, Oct 04, 2011 at 08:55:09AM +1100, Nguyen Thai Ngoc Duy wrote:
The message is chosen to avoid leaking information, yet let users know
that they are deliberately not allowed to use the service, not a fault
in service configuration or the service itself.
I do think this is an improvement, but I wonder if the verbosity should
be configurable. Then open sites like kernel.org could be friendlier to
their users. Something like this instead:
---
daemon.c | 21 +++++++++++++++++----
1 files changed, 17 insertions(+), 4 deletions(-)
@@ -257,11 +266,11 @@ static int run_service(char *dir, struct daemon_service *service)if(!enabled&&!service->overridable){logerror("'%s': service not enabled.",service->name);errno=EACCES;-return-1;+returndaemon_error(dir,"service not enabled");}if(!(path=path_ok(dir)))-return-1;+returndaemon_error(dir,"no such repository");/**Securityonthecheap.
@@ -277,7 +286,7 @@ static int run_service(char *dir, struct daemon_service *service)if(!export_all_trees&&access("git-daemon-export-ok",F_OK)){logerror("'%s': repository not exported.",path);errno=EACCES;-return-1;+returndaemon_error(dir,"repository not exported");}if(service->overridable){
@@ -291,7 +300,7 @@ static int run_service(char *dir, struct daemon_service *service)logerror("'%s': service not enabled for '%s'",service->name,path);errno=EACCES;-return-1;+returndaemon_error(dir,"service not enabled");}/*
@@ -1167,6 +1176,10 @@ int main(int argc, char **argv)make_service_overridable(arg+18,0);continue;}+if(!prefixcmp(arg,"--informative-errors")){+informative_errors=1;+continue;+}if(!strcmp(arg,"--")){ok_paths=&argv[i+1];break;
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:52:14
(+cc: Andreas[*])
Jeff King wrote:
On Tue, Oct 04, 2011 at 08:55:09AM +1100, Nguyen Thai Ngoc Duy wrote:
quoted
The message is chosen to avoid leaking information, yet let users know
that they are deliberately not allowed to use the service, not a fault
in service configuration or the service itself.
I do think this is an improvement, but I wonder if the verbosity should
be configurable. Then open sites like kernel.org could be friendlier to
their users. Something like this instead:
FWIW the more verbose version you suggest also sounds fine to me. A
person trying to find the names of local users by checking for
repositories with names like "/home/user" would always receive the
error "no such repository", whether that user exists or not and
whether the actual error encountered was ENOENT, EACCES, lack of git
metadata, or the path running afoul of a whitelist or blacklist.
Either Duy's patch or this patch sounds very good to me. Thanks to
both of you for working on it.
[*] context:
http://thread.gmane.org/gmane.comp.version-control.git/182529/focus=183409
On Wed, Oct 12, 2011 at 04:09:16PM -0400, Jeff King wrote:
On Tue, Oct 04, 2011 at 08:55:09AM +1100, Nguyen Thai Ngoc Duy wrote:
quoted
The message is chosen to avoid leaking information, yet let users know
that they are deliberately not allowed to use the service, not a fault
in service configuration or the service itself.
I do think this is an improvement, but I wonder if the verbosity should
be configurable. Then open sites like kernel.org could be friendlier to
their users. Something like this instead:
How about allow users to select which messages they want to print? We
can even go further, allowing users to specify the messages themselves..
I don't know. I'm not a real server admin so maybe I'm just too
paranoid. Any admins care to speak up?
On the other hand, grouping all messages at one place may be easier to
audit, even if we don't allow customization.
Anyway, two cents on top of your patch..
-- 8< --
@@ -17,10 +17,25 @@#define initgroups(x, y) (0) /* nothing */#endif+/* Must match messages[] order below */+#define MSG_SERVICE_NOT_ENABLED 0+#define MSG_NO_SUCH_REPOSITORY 1+#define MSG_REPOSITORY_NOT_EXPORTED 2++staticstructdaemon_message+{+constchar*message;+constchar*config;+intenabled;+}messages[]={+{"service not enabled","message.serviceNotEnabled"},+{"no such repository","message.noSuchRepository"},+{"repository not exported","message.repositoryNotExported"},+};+staticintlog_syslog;staticintverbose;staticintreuseaddr;-staticintinformative_errors;staticconstchardaemon_usage[]="git daemon [--verbose] [--syslog] [--export-all]\n"
@@ -238,20 +253,31 @@ static int service_enabled;staticintgit_daemon_config(constchar*var,constchar*value,void*cb){+inti;+if(!prefixcmp(var,"daemon.")&&!strcmp(var+7,service_looking_at->config_name)){service_enabled=git_config_bool(var,value);return0;}+for(i=0;i<ARRAY_SIZE(messages);i++)+if(!strcmp(var,messages[i].config)){+messages[i].enabled=git_config_bool(var,value);+return0;+}+/* we are not interested in parsing any other configuration here */return0;}-staticintdaemon_error(constchar*dir,constchar*msg)+staticintdaemon_error(constchar*dir,intmsg_id){-if(!informative_errors)+constchar*msg;+if(!messages[msg_id].enabled)msg="access denied";+else+msg=messages[msg_id].message;packet_write(1,"ERR %s: %s",dir,msg);return-1;}
@@ -266,11 +292,11 @@ static int run_service(char *dir, struct daemon_service *service)if(!enabled&&!service->overridable){logerror("'%s': service not enabled.",service->name);errno=EACCES;-returndaemon_error(dir,"service not enabled");+returndaemon_error(dir,MSG_SERVICE_NOT_ENABLED);}if(!(path=path_ok(dir)))-returndaemon_error(dir,"no such repository");+returndaemon_error(dir,MSG_NO_SUCH_REPOSITORY);/**Securityonthecheap.
@@ -286,7 +312,7 @@ static int run_service(char *dir, struct daemon_service *service)if(!export_all_trees&&access("git-daemon-export-ok",F_OK)){logerror("'%s': repository not exported.",path);errno=EACCES;-returndaemon_error(dir,"repository not exported");+returndaemon_error(dir,MSG_REPOSITORY_NOT_EXPORTED);}if(service->overridable){
@@ -300,7 +326,7 @@ static int run_service(char *dir, struct daemon_service *service)logerror("'%s': service not enabled for '%s'",service->name,path);errno=EACCES;-returndaemon_error(dir,"service not enabled");+returndaemon_error(dir,MSG_SERVICE_NOT_ENABLED);}/*
@@ -1177,7 +1203,9 @@ int main(int argc, char **argv)continue;}if(!prefixcmp(arg,"--informative-errors")){-informative_errors=1;+inti;+for(i=0;i<ARRAY_SIZE(messages);i++)+messages[i].enabled=1;continue;}if(!strcmp(arg,"--")){--8<--
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:52:14
Nguyen Thai Ngoc Duy wrote:
How about allow users to select which messages they want to print? We
can even go further, allowing users to specify the messages themselves..
[...]
+ { "service not enabled", "message.serviceNotEnabled" },
+ { "no such repository", "message.noSuchRepository" },
+ { "repository not exported", "message.repositoryNotExported" },
I administer a private server that is only accessible as "localhost".
:) This much customization would leave me confused about what the
right choices are and what the choices mean (even if I were to make
the server public and start having security worries).
What is the intended use --- translation? The idealist in me thinks
that should be taken care of on the client side, if at all. (This
way, we would not be preventing especially friendly clients from
offering pertinent detailed advice for each error condition.
Alternatively, maybe some day the protocol will want to provide a way
for clients to indicate a preferred language and message verbosity.)
On Thu, Oct 13, 2011 at 4:59 PM, Jonathan Nieder [off-list ref] wrote:
Nguyen Thai Ngoc Duy wrote:
quoted
How about allow users to select which messages they want to print? We
can even go further, allowing users to specify the messages themselves..
[...]
quoted
+ { "service not enabled", "message.serviceNotEnabled" },
+ { "no such repository", "message.noSuchRepository" },
+ { "repository not exported", "message.repositoryNotExported" },
I administer a private server that is only accessible as "localhost".
:) This much customization would leave me confused about what the
right choices are and what the choices mean (even if I were to make
the server public and start having security worries).
--informative-errors is your friend. All errors are enabled.
What is the intended use --- translation? The idealist in me thinks
that should be taken care of on the client side, if at all. (This
way, we would not be preventing especially friendly clients from
offering pertinent detailed advice for each error condition.
Alternatively, maybe some day the protocol will want to provide a way
for clients to indicate a preferred language and message verbosity.)
Translation could be fun to do, but it's more about how much admins
want to reveal. For example, I may only want to show "service not
enabled" and "no such repository", not the last one, which simply
becomes "access denied".
Again I'm not real admin and this may be just bogus.
--
Duy
On Thu, Oct 13, 2011 at 5:56 PM, Nguyen Thai Ngoc Duy [off-list ref] wrote:
Translation could be fun to do
By translation, I don't mean inter-language translation. More like
personification. Instead of "service not enabled" you may want
"service is off, you want to attack me or what?"
--
Duy
From: Jeff King <hidden> Date: 2016-06-15 22:52:15
On Thu, Oct 13, 2011 at 03:45:44PM +1100, Nguyen Thai Ngoc Duy wrote:
On Wed, Oct 12, 2011 at 04:09:16PM -0400, Jeff King wrote:
quoted
On Tue, Oct 04, 2011 at 08:55:09AM +1100, Nguyen Thai Ngoc Duy wrote:
quoted
The message is chosen to avoid leaking information, yet let users know
that they are deliberately not allowed to use the service, not a fault
in service configuration or the service itself.
I do think this is an improvement, but I wonder if the verbosity should
be configurable. Then open sites like kernel.org could be friendlier to
their users. Something like this instead:
How about allow users to select which messages they want to print? We
can even go further, allowing users to specify the messages themselves..
I thought about that, but it just seemed like it was making things way
more complex than it needed to be. GitHub does do this kind of
customization, but we also have a custom layer that intercepts git://
connections, anyway, so we added the relevant code there.
I don't know if medium-sized sites (i.e., ones that aren't so big they
are running custom proxies on the frontend) would care about adding
custom messages here or not.
I don't know. I'm not a real server admin so maybe I'm just too
paranoid. Any admins care to speak up?
I doubt anybody would care that much about turning individual messages
on and off. I think the real value is in being able to say "don't push
by git://. The right way to push to this site is...".
But your patch kind of falls short of what people would want to do for
two reasons:
1. The message isn't dynamic at all. So I can't say:
You tried to push to git://host.tld/foo.git. The right way to do
that is:
git push https://host.tld/foo.git
That's what the GitHub message does if you try to push over git://;
it gives you a new remote name that will actually work, customized
to the repo you wanted to push to.
2. Tweaking just the message for anything but "service not enabled"
isn't all that useful. What do you say about "no such repository"
in a simple message, even with placeholders?
If you _really_ want to get fancy, a server could do a fuzzy
search on the available repos and say "did you mean...?".
But now we are talking about hooking arbitrary code into the
message.
So if we want to do anything, I would think it would be a hook. Except
that we may or may not have a repo, so it would not be a hook in
$GIT_DIR/hooks, but rather some script to be run passed on the command
line, like:
git daemon --informative-errors=/path/to/hook
-Peff