X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=transport.c;h=f50c31a572f35964cb12c2d88ee5748858908cd1;hb=a768a02265f3b8f43e37f66a0a3affba92c830c7;hp=be4a63ec1952f7eeb59ea24cdc6835e7d0ba70f9;hpb=a52fb9b8f3e30b5b5e743cae91c3b2e1f729eb5d;p=thirdparty%2Fgit.git diff --git a/transport.c b/transport.c index be4a63ec19..f50c31a572 100644 --- a/transport.c +++ b/transport.c @@ -321,11 +321,6 @@ static void print_ref_status(char flag, const char *summary, struct ref *to, str } } -static const char *status_abbrev(unsigned char sha1[20]) -{ - return find_unique_abbrev(sha1, DEFAULT_ABBREV); -} - static void print_ok_ref_status(struct ref *ref, int porcelain) { if (ref->deletion) @@ -340,7 +335,8 @@ static void print_ok_ref_status(struct ref *ref, int porcelain) char type; const char *msg; - strbuf_addstr(&quickref, status_abbrev(ref->old_oid.hash)); + strbuf_add_unique_abbrev(&quickref, ref->old_oid.hash, + DEFAULT_ABBREV); if (ref->forced_update) { strbuf_addstr(&quickref, "..."); type = '+'; @@ -350,7 +346,8 @@ static void print_ok_ref_status(struct ref *ref, int porcelain) type = ' '; msg = NULL; } - strbuf_addstr(&quickref, status_abbrev(ref->new_oid.hash)); + strbuf_add_unique_abbrev(&quickref, ref->new_oid.hash, + DEFAULT_ABBREV); print_ref_status(type, quickref.buf, ref, ref->peer_ref, msg, porcelain); strbuf_release(&quickref); @@ -620,21 +617,89 @@ static const struct string_list *protocol_whitelist(void) return enabled ? &allowed : NULL; } -int is_transport_allowed(const char *type) +enum protocol_allow_config { + PROTOCOL_ALLOW_NEVER = 0, + PROTOCOL_ALLOW_USER_ONLY, + PROTOCOL_ALLOW_ALWAYS +}; + +static enum protocol_allow_config parse_protocol_config(const char *key, + const char *value) { - const struct string_list *allowed = protocol_whitelist(); - return !allowed || string_list_has_string(allowed, type); + if (!strcasecmp(value, "always")) + return PROTOCOL_ALLOW_ALWAYS; + else if (!strcasecmp(value, "never")) + return PROTOCOL_ALLOW_NEVER; + else if (!strcasecmp(value, "user")) + return PROTOCOL_ALLOW_USER_ONLY; + + die("unknown value for config '%s': %s", key, value); } -void transport_check_allowed(const char *type) +static enum protocol_allow_config get_protocol_config(const char *type) { - if (!is_transport_allowed(type)) - die("transport '%s' not allowed", type); + char *key = xstrfmt("protocol.%s.allow", type); + char *value; + + /* first check the per-protocol config */ + if (!git_config_get_string(key, &value)) { + enum protocol_allow_config ret = + parse_protocol_config(key, value); + free(key); + free(value); + return ret; + } + free(key); + + /* if defined, fallback to user-defined default for unknown protocols */ + if (!git_config_get_string("protocol.allow", &value)) { + enum protocol_allow_config ret = + parse_protocol_config("protocol.allow", value); + free(value); + return ret; + } + + /* fallback to built-in defaults */ + /* known safe */ + if (!strcmp(type, "http") || + !strcmp(type, "https") || + !strcmp(type, "git") || + !strcmp(type, "ssh") || + !strcmp(type, "file")) + return PROTOCOL_ALLOW_ALWAYS; + + /* known scary; err on the side of caution */ + if (!strcmp(type, "ext")) + return PROTOCOL_ALLOW_NEVER; + + /* unknown; by default let them be used only directly by the user */ + return PROTOCOL_ALLOW_USER_ONLY; +} + +int is_transport_allowed(const char *type, int from_user) +{ + const struct string_list *whitelist = protocol_whitelist(); + if (whitelist) + return string_list_has_string(whitelist, type); + + switch (get_protocol_config(type)) { + case PROTOCOL_ALLOW_ALWAYS: + return 1; + case PROTOCOL_ALLOW_NEVER: + return 0; + case PROTOCOL_ALLOW_USER_ONLY: + if (from_user < 0) + from_user = git_env_bool("GIT_PROTOCOL_FROM_USER", 1); + return from_user; + } + + die("BUG: invalid protocol_allow_config type"); } -int transport_restrict_protocols(void) +void transport_check_allowed(const char *type) { - return !!protocol_whitelist(); + if (!is_transport_allowed(type, -1)) + die("transport '%s' not allowed", type); } struct transport *transport_get(struct remote *remote, const char *url)