{"thread":{"id":"17431","subject":"[PATCH] Support various HTTP authentication methods","startedAt":"2009-01-29T09:32:12Z","lastAt":"2009-02-05T08:11:09Z","messageCount":16,"participants":["Moriyoshi Koizumi","Junio C Hamano","Johannes Sixt","Aristotle Pagaltzis","Daniel Stenberg"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"102423","messageId":"1233221532.21518.1.camel@lena.gsc.riken.jp","threadId":"17431","inReplyTo":null,"subject":"[PATCH] Support various HTTP authentication methods","fromName":"Moriyoshi Koizumi","fromEmail":"mozo@mozo.jp","sentAt":"2009-01-29T09:32:12Z","receivedAt":"2009-01-29T09:32:12Z","isPatch":true,"sender":{"key":"mozo@mozo.jp","avatar":"https://gravatar.com/avatar/65cac99f5cbc06fe8937f550174c11584ea57e8b831310ca4d8046b3bd0ca752?d=mp&s=160"},"body":"Currently there is no way to specify the preferred authentication\nmethod for the HTTP backend and it always ends up with the CURL's\ndefault\nsettings.\n\nThis patch enables it if supported by CURL, adding a couple of new\nsettings\nand config environment variables listed below (the names within the\nparentheses indicate the latter.)\n\n- http.auth (GIT_HTTP_AUTH)\n  Specifies the preferred authentication method for HTTP.  This can\n  be a method name or the combination of those separated by comma. Valid\n  values are \"basic\", \"digest\", \"gss\" and \"ntlm\". You can also specify\n  \"any\" (all of the above), \"anysafe\" (all of the above except \"basic\").\n\n  Note that the strings are treated case-insensitive.\n\n- http.proxy_auth (GIT_HTTP_PROXY_AUTH)\n  Specifies the preferred authentication method method for HTTP proxy.\n  The same thing as above applies to this setting.\n\nSigned-off-by: Moriyoshi Koizumi <mozo@mozo.jp>\n---\n http.c |  105\n++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 1 files changed, 105 insertions(+), 0 deletions(-)\n\ndiff --git a/http.c b/http.c\nindex ee58799..889135f 100644\n--- a/http.c\n+++ b/http.c\n@@ -25,6 +25,12 @@ static long curl_low_speed_limit = -1;\n static long curl_low_speed_time = -1;\n static int curl_ftp_no_epsv = 0;\n static const char *curl_http_proxy = NULL;\n+#if LIBCURL_VERSION_NUM >= 0x070a06\n+static const char *curl_http_auth = NULL;\n+#endif\n+#if LIBCURL_VERSION_NUM >= 0x070a07\n+static const char *curl_http_proxy_auth = NULL;\n+#endif\n \n static struct curl_slist *pragma_header;\n \n@@ -153,11 +159,67 @@ static int http_options(const char *var, const\nchar *value, void *cb)\n \t\t\treturn git_config_string(&curl_http_proxy, var, value);\n \t\treturn 0;\n \t}\n+#if LIBCURL_VERSION_NUM >= 0x070a06\n+\tif (!strcmp(\"http.auth\", var)) {\n+\t\tif (curl_http_auth == NULL)\n+\t\t\treturn git_config_string(&curl_http_auth, var, value);\n+\t\treturn 0;\n+\t}\n+#endif\n+#if LIBCURL_VERSION_NUM >= 0x070a07\n+\tif (!strcmp(\"http.proxy_auth\", var)) {\n+\t\tif (curl_http_proxy_auth == NULL)\n+\t\t\treturn git_config_string(&curl_http_proxy_auth, var, value);\n+\t\treturn 0;\n+\t}\n+#endif\n \n \t/* Fall back on the default ones */\n \treturn git_default_config(var, value, cb);\n }\n \n+#if LIBCURL_VERSION_NUM >= 0x070a06\n+static long get_curl_auth_bitmask(const char* auth_method)\n+{\n+\tchar *buf = xmalloc(strlen(auth_method) + 1);\n+\tconst unsigned char *p = (const unsigned char *)auth_method;\n+\tlong mask = CURLAUTH_NONE;\n+\n+\tfor (;;) {\n+\t\tchar *q = buf;\n+\t\twhile (*p && isspace(*p))\n+\t\t\t++p;\n+\n+\t\twhile (*p && *p != ',')\n+\t\t\t*q++ = tolower(*p++);\n+\n+\t\twhile (--q >= buf && isspace(*(unsigned char *)q));\n+\t\t++q;\n+\n+\t\t*q = '\\0';\n+\n+\t\tif (strcmp(buf, \"basic\") == 0)\n+\t\t\tmask |= CURLAUTH_BASIC;\n+\t\telse if (strcmp(buf, \"digest\") == 0)\n+\t\t\tmask |= CURLAUTH_DIGEST;\n+\t\telse if (strcmp(buf, \"gss\") == 0)\n+\t\t\tmask |= CURLAUTH_GSSNEGOTIATE;\n+\t\telse if (strcmp(buf, \"ntlm\") == 0)\n+\t\t\tmask |= CURLAUTH_NTLM;\n+\t\telse if (strcmp(buf, \"any\") == 0)\n+\t\t\tmask |= CURLAUTH_ANY;\n+\t\telse if (strcmp(buf, \"anysafe\") == 0)\n+\t\t\tmask |= CURLAUTH_ANYSAFE;\n+\n+\t\tif (!*p)\n+\t\t\tbreak;\n+\t\t++p;\n+\t}\n+\n+\treturn mask;\n+}\n+#endif\n+\n static CURL* get_curl_handle(void)\n {\n \tCURL* result = curl_easy_init();\n@@ -210,6 +272,20 @@ static CURL* get_curl_handle(void)\n \tif (curl_http_proxy)\n \t\tcurl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);\n \n+\tif (curl_http_auth) {\n+\t\tlong n = get_curl_auth_bitmask(curl_http_auth);\n+\t\tcurl_easy_setopt(result, CURLOPT_HTTPAUTH, n);\n+\t}\n+\n+\tif (curl_http_proxy) {\n+\t\tcurl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);\n+\n+\t\tif (curl_http_proxy_auth) {\n+\t\t\tlong n = get_curl_auth_bitmask(curl_http_proxy_auth);\n+\t\t\tcurl_easy_setopt(result, CURLOPT_PROXYAUTH, n);\n+\t\t}\n+\t}\n+\n \treturn result;\n }\n \n@@ -258,6 +334,21 @@ void http_init(struct remote *remote)\n \tif (low_speed_time != NULL)\n \t\tcurl_low_speed_time = strtol(low_speed_time, NULL, 10);\n \n+#if LIBCURL_VERSION_NUM >= 0x070a06\n+\t{\n+\t\tchar *http_auth = getenv(\"GIT_HTTP_AUTH\");\n+\t\tif (http_auth)\n+\t\t\tcurl_http_auth = xstrdup(http_auth);\n+\t}\n+#endif\n+#if LIBCURL_VERSION_NUM >= 0x070a07\n+\t{\n+\t\tchar *http_proxy_auth = getenv(\"GIT_HTTP_PROXY_AUTH\");\n+\t\tif (http_proxy_auth)\n+\t\t\tcurl_http_proxy_auth = xstrdup(http_proxy_auth);\n+\t}\n+#endif\n+\n \tgit_config(http_options, NULL);\n \n \tif (curl_ssl_verify == -1)\n@@ -309,6 +400,20 @@ void http_cleanup(void)\n \t\tfree((void *)curl_http_proxy);\n \t\tcurl_http_proxy = NULL;\n \t}\n+\n+#if LIBCURL_VERSION_NUM >= 0x070a06\n+\tif (curl_http_auth) {\n+\t\tfree((void *)curl_http_auth);\n+\t\tcurl_http_auth = NULL;\n+\t}\n+#endif\n+\n+#if LIBCURL_VERSION_NUM >= 0x070a07\n+\tif (curl_http_proxy_auth) {\n+\t\tfree((void *)curl_http_proxy_auth);\n+\t\tcurl_http_proxy_auth = NULL;\n+\t}\n+#endif\n }\n \n struct active_request_slot *get_active_slot(void)\n-- \n1.5.6.3\n"},{"id":"102424","messageId":"7v3af2h1b0.fsf@gitster.siamese.dyndns.org","threadId":"17431","inReplyTo":"1233221532.21518.1.camel@lena.gsc.riken.jp","subject":"Re: [PATCH] Support various HTTP authentication methods","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-01-29T10:08:35Z","receivedAt":"2009-01-29T10:08:35Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Moriyoshi Koizumi <mozo@mozo.jp> writes:\n\n> Currently there is no way to specify the preferred authentication\n> method for the HTTP backend and it always ends up with the CURL's\n> default\n> settings.\n>\n> This patch enables it if supported by CURL, adding a couple of new\n\n\"it\" in \"enables it\" is a bit unclear...\n\n> Signed-off-by: Moriyoshi Koizumi <mozo@mozo.jp>\n> ---\n>  http.c |  105\n> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n>  1 files changed, 105 insertions(+), 0 deletions(-)\n\nLinewrapped and whitespace damaged patch that would not apply.\n\n> diff --git a/http.c b/http.c\n> index ee58799..889135f 100644\n> --- a/http.c\n> +++ b/http.c\n> @@ -25,6 +25,12 @@ static long curl_low_speed_limit = -1;\n>  static long curl_low_speed_time = -1;\n>  static int curl_ftp_no_epsv = 0;\n>  static const char *curl_http_proxy = NULL;\n> +#if LIBCURL_VERSION_NUM >= 0x070a06\n> +static const char *curl_http_auth = NULL;\n> +#endif\n> +#if LIBCURL_VERSION_NUM >= 0x070a07\n> +static const char *curl_http_proxy_auth = NULL;\n> +#endif\n\nI am not a cURL expert, so I'd take your word for these version\ndependencies.\n\nWe do not initialize static scope pointers to \"= NULL\" nor variables to 0,\ninstead we let BSS take care of that for us.  ftp_no_epsv we can see in\nthe context is doing unnecessary initialization that should be fixed.\n\n>  static struct curl_slist *pragma_header;\n>  \n> @@ -153,11 +159,67 @@ static int http_options(const char *var, const\n> char *value, void *cb)\n>  \t\t\treturn git_config_string(&curl_http_proxy, var, value);\n>  \t\treturn 0;\n>  \t}\n> +#if LIBCURL_VERSION_NUM >= 0x070a06\n> +\tif (!strcmp(\"http.auth\", var)) {\n> +\t\tif (curl_http_auth == NULL)\n\nWe tend to say \"if (!pointer)\".\n\nI see you implemented \"the first one wins\" rule with this test, but I do\nnot think you want that.  We first read $HOME/.gitconfig and then\nrepository specific $GIT_DIR/config, so it is often more useful to use\n\"the last one wins\" rule.\n\n> +\t\t\treturn git_config_string(&curl_http_auth, var, value);\n> +\t\treturn 0;\n> +\t}\n> +#endif\n> +#if LIBCURL_VERSION_NUM >= 0x070a07\n> +\tif (!strcmp(\"http.proxy_auth\", var)) {\n> +\t\tif (curl_http_proxy_auth == NULL)\n> +\t\t\treturn git_config_string(&curl_http_proxy_auth, var, value);\n> +\t\treturn 0;\n> +\t}\n> +#endif\n>  \n>  \t/* Fall back on the default ones */\n>  \treturn git_default_config(var, value, cb);\n>  }\n>  \n> +#if LIBCURL_VERSION_NUM >= 0x070a06\n> +static long get_curl_auth_bitmask(const char* auth_method)\n> +{\n> +\tchar *buf = xmalloc(strlen(auth_method) + 1);\n> +\tconst unsigned char *p = (const unsigned char *)auth_method;\n> +\tlong mask = CURLAUTH_NONE;\n\nOur isspace() is a sane_isspace(), so you do not have to play casting\ngames between signed vs unsigned char.\n\n> +\tfor (;;) {\n> +\t\tchar *q = buf;\n> +\t\twhile (*p && isspace(*p))\n> +\t\t\t++p;\n> +\n> +\t\twhile (*p && *p != ',')\n> +\t\t\t*q++ = tolower(*p++);\n> +\n> +\t\twhile (--q >= buf && isspace(*(unsigned char *)q));\n> +\t\t++q;\n> +\n> +\t\t*q = '\\0';\n> +\n> +\t\tif (strcmp(buf, \"basic\") == 0)\n\nSay !strcmp(buf, \"literal\") like you did in the configuration parsing part\nearlier.\n\n> +\t\t\tmask |= CURLAUTH_BASIC;\n> +\t\telse if (strcmp(buf, \"digest\") == 0)\n> +\t\t\tmask |= CURLAUTH_DIGEST;\n> +\t\telse if (strcmp(buf, \"gss\") == 0)\n> +\t\t\tmask |= CURLAUTH_GSSNEGOTIATE;\n> +\t\telse if (strcmp(buf, \"ntlm\") == 0)\n> +\t\t\tmask |= CURLAUTH_NTLM;\n> +\t\telse if (strcmp(buf, \"any\") == 0)\n> +\t\t\tmask |= CURLAUTH_ANY;\n> +\t\telse if (strcmp(buf, \"anysafe\") == 0)\n> +\t\t\tmask |= CURLAUTH_ANYSAFE;\n> +\n> +\t\tif (!*p)\n> +\t\t\tbreak;\n> +\t\t++p;\n> +\t}\n\nYou leak \"buf\" here you forgot to free.  The string you can possibly\naccept is a known set with some maximum length, so you can use a on-stack\nbuf[] and reject any token longer than that maximum, right?\n\n> +\treturn mask;\n> +}\n> +#endif\n> +\n>  static CURL* get_curl_handle(void)\n>  {\n>  \tCURL* result = curl_easy_init();\n> @@ -210,6 +272,20 @@ static CURL* get_curl_handle(void)\n>  \tif (curl_http_proxy)\n>  \t\tcurl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);\n>  \n> +\tif (curl_http_auth) {\n> +\t\tlong n = get_curl_auth_bitmask(curl_http_auth);\n> +\t\tcurl_easy_setopt(result, CURLOPT_HTTPAUTH, n);\n> +\t}\n> +\n> +\tif (curl_http_proxy) {\n> +\t\tcurl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);\n> +\n> +\t\tif (curl_http_proxy_auth) {\n> +\t\t\tlong n = get_curl_auth_bitmask(curl_http_proxy_auth);\n> +\t\t\tcurl_easy_setopt(result, CURLOPT_PROXYAUTH, n);\n> +\t\t}\n> +\t}\n> +\n\nThis part does not have to be protected with the LIBCURL_VERSION_NUM\nconditional?  I somehow find it unlikely...\n\nInstead of parsing the string every time a curl handle is asked for, how\nabout parsing them once and store the masks in two file scope static longs\nin http_init() and use that value to easy_setopt() call here?\n\nThat way you can free the two strings much early without waiting for\nhttp_cleanup(), too, right?\n"},{"id":"102426","messageId":"4981826D.507@viscovery.net","threadId":"17431","inReplyTo":"1233221532.21518.1.camel@lena.gsc.riken.jp","subject":"Re: [PATCH] Support various HTTP authentication methods","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2009-01-29T10:18:21Z","receivedAt":"2009-01-29T10:18:21Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Moriyoshi Koizumi schrieb:\n> @@ -210,6 +272,20 @@ static CURL* get_curl_handle(void)\n>  \tif (curl_http_proxy)\n>  \t\tcurl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);\n\nCURLOPT_PROXY is set here...\n\n>  \n> +\tif (curl_http_auth) {\n> +\t\tlong n = get_curl_auth_bitmask(curl_http_auth);\n> +\t\tcurl_easy_setopt(result, CURLOPT_HTTPAUTH, n);\n> +\t}\n> +\n> +\tif (curl_http_proxy) {\n> +\t\tcurl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);\n\n... and here again. Is that necessary?\n\n-- Hannes\n"},{"id":"102448","messageId":"4981B63F.4040100@mozo.jp","threadId":"17431","inReplyTo":"7v3af2h1b0.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Support various HTTP authentication methods","fromName":"Moriyoshi Koizumi","fromEmail":"mozo@mozo.jp","sentAt":"2009-01-29T13:59:27Z","receivedAt":"2009-01-29T13:59:27Z","isPatch":true,"sender":{"key":"mozo@mozo.jp","avatar":"https://gravatar.com/avatar/65cac99f5cbc06fe8937f550174c11584ea57e8b831310ca4d8046b3bd0ca752?d=mp&s=160"},"body":"First thank you for the advice. I am not familiar to the code base and\ndefinitely doing something wrong.\n\nJunio C Hamano wrote:\n> Moriyoshi Koizumi <mozo@mozo.jp> writes:\n>> This patch enables it if supported by CURL, adding a couple of new\n> \n> \"it\" in \"enables it\" is a bit unclear...\n\nI was a bit in a rush and I thought I got to get this done before I went\nhome.  This patch dnables various HTTP authentication methods namely\nbasic, digest, GSS and NTLM that are supported by cURL.  cURL tries to\nuse basic authentication if the option is not explicitly provided.\n\n> Linewrapped and whitespace damaged patch that would not apply.\n\nSorry for the crap. I'll try to send the correct one next week.\n\n> I am not a cURL expert, so I'd take your word for these version\n> dependencies.\n> \n> We do not initialize static scope pointers to \"= NULL\" nor variables to 0,\n> instead we let BSS take care of that for us.  ftp_no_epsv we can see in\n> the context is doing unnecessary initialization that should be fixed.\n\nRight.\n\n>> +#if LIBCURL_VERSION_NUM >= 0x070a06\n>> +\tif (!strcmp(\"http.auth\", var)) {\n>> +\t\tif (curl_http_auth == NULL)\n> \n> We tend to say \"if (!pointer)\".\n\nI'll fix this too.\n\n> I see you implemented \"the first one wins\" rule with this test, but I do\n> not think you want that.  We first read $HOME/.gitconfig and then\n> repository specific $GIT_DIR/config, so it is often more useful to use\n> \"the last one wins\" rule.\n\nThe environment variables win over gitconfigs. I thought that's what I\nimplemented and what we want.\n\n> Our isspace() is a sane_isspace(), so you do not have to play casting\n> games between signed vs unsigned char.\n> \n>> +\tfor (;;) {\n>> +\t\tchar *q = buf;\n>> +\t\twhile (*p && isspace(*p))\n>> +\t\t\t++p;\n>> +\n>> +\t\twhile (*p && *p != ',')\n>> +\t\t\t*q++ = tolower(*p++);\n>> +\n>> +\t\twhile (--q >= buf && isspace(*(unsigned char *)q));\n>> +\t\t++q;\n>> +\n>> +\t\t*q = '\\0';\n>> +\n>> +\t\tif (strcmp(buf, \"basic\") == 0)\n> \n> Say !strcmp(buf, \"literal\") like you did in the configuration parsing part\n> earlier.\n\nI tend to like this way, and the reason for the inconsistency between\nthem is that the earlier one is pasted from the nearby code.  I'm\nwilling to fix this as well if I should.\n\n> \n>> +\t\t\tmask |= CURLAUTH_BASIC;\n>> +\t\telse if (strcmp(buf, \"digest\") == 0)\n>> +\t\t\tmask |= CURLAUTH_DIGEST;\n>> +\t\telse if (strcmp(buf, \"gss\") == 0)\n>> +\t\t\tmask |= CURLAUTH_GSSNEGOTIATE;\n>> +\t\telse if (strcmp(buf, \"ntlm\") == 0)\n>> +\t\t\tmask |= CURLAUTH_NTLM;\n>> +\t\telse if (strcmp(buf, \"any\") == 0)\n>> +\t\t\tmask |= CURLAUTH_ANY;\n>> +\t\telse if (strcmp(buf, \"anysafe\") == 0)\n>> +\t\t\tmask |= CURLAUTH_ANYSAFE;\n>> +\n>> +\t\tif (!*p)\n>> +\t\t\tbreak;\n>> +\t\t++p;\n>> +\t}\n> \n> You leak \"buf\" here you forgot to free.  The string you can possibly\n> accept is a known set with some maximum length, so you can use a on-stack\n> buf[] and reject any token longer than that maximum, right?\n\nThat one is really silly and shameful :-( I first thought I could go\nwith the on-stack buffer, but I eventually did this because the input\nmight contain an indefinite set of tokens, and thought safer to alloc it.\n\n>> +\tif (curl_http_proxy) {\n>> +\t\tcurl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);\n>> +\n>> +\t\tif (curl_http_proxy_auth) {\n>> +\t\t\tlong n = get_curl_auth_bitmask(curl_http_proxy_auth);\n>> +\t\t\tcurl_easy_setopt(result, CURLOPT_PROXYAUTH, n);\n>> +\t\t}\n>> +\t}\n>> +\n> \n> This part does not have to be protected with the LIBCURL_VERSION_NUM\n> conditional?  I somehow find it unlikely...\n\nThe block that starts with if (curl_http_proxy_auth) {} should've been\nenclosed by the conditinals. The leading part had been there in the\nfirst place.\n\n> Instead of parsing the string every time a curl handle is asked for, how\n> about parsing them once and store the masks in two file scope static longs\n> in http_init() and use that value to easy_setopt() call here?\n\nThat has to be the way to go, but the question is where I am supposed to\nparse the strings and store them to the globals?\n\n>\n> That way you can free the two strings much early without waiting for\n> http_cleanup(), too, right?\n\nRegards,\nMoriyoshi\n"},{"id":"102449","messageId":"4981B6E6.6020502@mozo.jp","threadId":"17431","inReplyTo":"4981826D.507@viscovery.net","subject":"Re: [PATCH] Support various HTTP authentication methods","fromName":"Moriyoshi Koizumi","fromEmail":"mozo@mozo.jp","sentAt":"2009-01-29T14:02:14Z","receivedAt":"2009-01-29T14:02:14Z","isPatch":true,"sender":{"key":"mozo@mozo.jp","avatar":"https://gravatar.com/avatar/65cac99f5cbc06fe8937f550174c11584ea57e8b831310ca4d8046b3bd0ca752?d=mp&s=160"},"body":"Johannes Sixt wrote:\n> Moriyoshi Koizumi schrieb:\n>> @@ -210,6 +272,20 @@ static CURL* get_curl_handle(void)\n>>  \tif (curl_http_proxy)\n>>  \t\tcurl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);\n> \n> CURLOPT_PROXY is set here...\n\nAs I wrote in the previous post, this part was from the original.\n\n> \n>>  \n>> +\tif (curl_http_auth) {\n>> +\t\tlong n = get_curl_auth_bitmask(curl_http_auth);\n>> +\t\tcurl_easy_setopt(result, CURLOPT_HTTPAUTH, n);\n>> +\t}\n\n> ... and here again. Is that necessary?\n\nWhat part do you mean by that?\n\nRegards,\nMoriyoshi\n"},{"id":"102453","messageId":"4981B872.4040701@viscovery.net","threadId":"17431","inReplyTo":"4981B6E6.6020502@mozo.jp","subject":"Re: [PATCH] Support various HTTP authentication methods","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2009-01-29T14:08:50Z","receivedAt":"2009-01-29T14:08:50Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Moriyoshi Koizumi schrieb:\n> Johannes Sixt wrote:\n>> Moriyoshi Koizumi schrieb:\n>>> @@ -210,6 +272,20 @@ static CURL* get_curl_handle(void)\n>>>  \tif (curl_http_proxy)\n>>>  \t\tcurl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);\n>> CURLOPT_PROXY is set here...\n> \n> As I wrote in the previous post, this part was from the original.\n> \n>>>  \n>>> +\tif (curl_http_auth) {\n>>> +\t\tlong n = get_curl_auth_bitmask(curl_http_auth);\n>>> +\t\tcurl_easy_setopt(result, CURLOPT_HTTPAUTH, n);\n>>> +\t}\n> \n>> ... and here again. Is that necessary?\n> \n> What part do you mean by that?\n\nOops, sorry, I cut too much from your patch:\n\n> +\tif (curl_http_auth) {\n> +\t\tlong n = get_curl_auth_bitmask(curl_http_auth);\n> +\t\tcurl_easy_setopt(result, CURLOPT_HTTPAUTH, n);\n> +\t}\n> +\n> +\tif (curl_http_proxy) {\n> +\t\tcurl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);\n\nHere you set CURLOPT_PROXY again.\n\n-- Hannes\n"},{"id":"102818","messageId":"E1LTqDN-0003MF-DP@lena.gsc.riken.jp","threadId":"17431","inReplyTo":"7v3af2h1b0.fsf@gitster.siamese.dyndns.org","subject":"[PATCH] Support various HTTP authentication methods","fromName":"Moriyoshi Koizumi","fromEmail":"mozo@mozo.jp","sentAt":"2009-02-02T04:09:24Z","receivedAt":"2009-02-02T04:09:24Z","isPatch":true,"sender":{"key":"mozo@mozo.jp","avatar":"https://gravatar.com/avatar/65cac99f5cbc06fe8937f550174c11584ea57e8b831310ca4d8046b3bd0ca752?d=mp&s=160"},"body":"Currently there is no way to specify the preferred authentication\nmethod for the HTTP backend and it always falls back to the CURL's default\nsettings.\n\nThis patch allows users to specify the authentication method if supported\nby CURL, adding a couple of new settings and environment variables\nlisted below (the names within the parentheses indicate the environment\nvariables.)\n\n- http.auth (GIT_HTTP_AUTH)\n  Specifies the preferred authentication method for HTTP.  This can\n  be a method name or the combination of those separated by comma. Valid\n  values are \"basic\", \"digest\", \"gss\" and \"ntlm\". You can also specify\n  \"any\" (all of the above), \"anysafe\" (all of the above except \"basic\").\n\n  Note that the strings are treated case-insensitive.\n\n- http.proxy_auth (GIT_HTTP_PROXY_AUTH)\n  Specifies the preferred authentication method method for HTTP proxy.\n  The same thing as above applies to this setting.\n\nSigned-off-by: Moriyoshi <mozo@mozo.jp>\n---\n http.c |  120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---\n 1 files changed, 114 insertions(+), 6 deletions(-)\n\ndiff --git a/http.c b/http.c\nindex ee58799..41e8e8c 100644\n--- a/http.c\n+++ b/http.c\n@@ -13,18 +13,24 @@ static CURL *curl_default;\n char curl_errorstr[CURL_ERROR_SIZE];\n \n static int curl_ssl_verify = -1;\n-static const char *ssl_cert = NULL;\n+static const char *ssl_cert;\n #if LIBCURL_VERSION_NUM >= 0x070902\n-static const char *ssl_key = NULL;\n+static const char *ssl_key;\n #endif\n #if LIBCURL_VERSION_NUM >= 0x070908\n-static const char *ssl_capath = NULL;\n+static const char *ssl_capath;\n #endif\n-static const char *ssl_cainfo = NULL;\n+static const char *ssl_cainfo;\n static long curl_low_speed_limit = -1;\n static long curl_low_speed_time = -1;\n static int curl_ftp_no_epsv = 0;\n-static const char *curl_http_proxy = NULL;\n+static const char *curl_http_proxy;\n+#if LIBCURL_VERSION_NUM >= 0x070a06\n+static const char *curl_http_auth;\n+#endif\n+#if LIBCURL_VERSION_NUM >= 0x070a07\n+static const char *curl_http_proxy_auth;\n+#endif\n \n static struct curl_slist *pragma_header;\n \n@@ -153,11 +159,69 @@ static int http_options(const char *var, const char *value, void *cb)\n \t\t\treturn git_config_string(&curl_http_proxy, var, value);\n \t\treturn 0;\n \t}\n+#if LIBCURL_VERSION_NUM >= 0x070a06\n+\tif (!strcmp(\"http.auth\", var)) {\n+\t\tif (curl_http_auth == NULL)\n+\t\t\treturn git_config_string(&curl_http_auth, var, value);\n+\t\treturn 0;\n+\t}\n+#endif\n+#if LIBCURL_VERSION_NUM >= 0x070a07\n+\tif (!strcmp(\"http.proxy_auth\", var)) {\n+\t\tif (curl_http_proxy_auth == NULL)\n+\t\t\treturn git_config_string(&curl_http_proxy_auth, var, value);\n+\t\treturn 0;\n+\t}\n+#endif\n \n \t/* Fall back on the default ones */\n \treturn git_default_config(var, value, cb);\n }\n \n+#if LIBCURL_VERSION_NUM >= 0x070a06\n+static long get_curl_auth_bitmask(const char* auth_method)\n+{\n+\tchar buf[4096];\n+\tconst unsigned char *p = (const unsigned char *)auth_method;\n+\tlong mask = CURLAUTH_NONE;\n+\n+    strlcpy(buf, auth_method, sizeof(buf));\n+\n+\tfor (;;) {\n+\t\tchar *q = buf;\n+\t\twhile (*p && isspace(*p))\n+\t\t\t++p;\n+\n+\t\twhile (*p && *p != ',')\n+\t\t\t*q++ = tolower(*p++);\n+\n+\t\twhile (--q >= buf && isspace(*q));\n+\t\t++q;\n+\n+\t\t*q = '\\0';\n+\n+\t\tif (!strcmp(buf, \"basic\"))\n+\t\t\tmask |= CURLAUTH_BASIC;\n+\t\telse if (!strcmp(buf, \"digest\"))\n+\t\t\tmask |= CURLAUTH_DIGEST;\n+\t\telse if (!strcmp(buf, \"gss\"))\n+\t\t\tmask |= CURLAUTH_GSSNEGOTIATE;\n+\t\telse if (!strcmp(buf, \"ntlm\"))\n+\t\t\tmask |= CURLAUTH_NTLM;\n+\t\telse if (!strcmp(buf, \"any\"))\n+\t\t\tmask |= CURLAUTH_ANY;\n+\t\telse if (!strcmp(buf, \"anysafe\"))\n+\t\t\tmask |= CURLAUTH_ANYSAFE;\n+\n+\t\tif (!*p)\n+\t\t\tbreak;\n+\t\t++p;\n+\t}\n+\n+\treturn mask;\n+}\n+#endif\n+\n static CURL* get_curl_handle(void)\n {\n \tCURL* result = curl_easy_init();\n@@ -207,9 +271,24 @@ static CURL* get_curl_handle(void)\n \tif (curl_ftp_no_epsv)\n \t\tcurl_easy_setopt(result, CURLOPT_FTP_USE_EPSV, 0);\n \n-\tif (curl_http_proxy)\n+#if LIBCURL_VERSION_NUM >= 0x070a06\n+\tif (curl_http_auth) {\n+\t\tlong n = get_curl_auth_bitmask(curl_http_auth);\n+\t\tcurl_easy_setopt(result, CURLOPT_HTTPAUTH, n);\n+\t}\n+#endif\n+\n+\tif (curl_http_proxy) {\n \t\tcurl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);\n \n+#if LIBCURL_VERSION_NUM >= 0x070a07\n+\t\tif (curl_http_proxy_auth) {\n+\t\t\tlong n = get_curl_auth_bitmask(curl_http_proxy_auth);\n+\t\t\tcurl_easy_setopt(result, CURLOPT_PROXYAUTH, n);\n+\t\t}\n+#endif\n+\t}\n+\n \treturn result;\n }\n \n@@ -258,6 +337,21 @@ void http_init(struct remote *remote)\n \tif (low_speed_time != NULL)\n \t\tcurl_low_speed_time = strtol(low_speed_time, NULL, 10);\n \n+#if LIBCURL_VERSION_NUM >= 0x070a06\n+\t{\n+\t\tchar *http_auth = getenv(\"GIT_HTTP_AUTH\");\n+\t\tif (http_auth)\n+\t\t\tcurl_http_auth = xstrdup(http_auth);\n+\t}\n+#endif\n+#if LIBCURL_VERSION_NUM >= 0x070a07\n+\t{\n+\t\tchar *http_proxy_auth = getenv(\"GIT_HTTP_PROXY_AUTH\");\n+\t\tif (http_proxy_auth)\n+\t\t\tcurl_http_proxy_auth = xstrdup(http_proxy_auth);\n+\t}\n+#endif\n+\n \tgit_config(http_options, NULL);\n \n \tif (curl_ssl_verify == -1)\n@@ -309,6 +403,20 @@ void http_cleanup(void)\n \t\tfree((void *)curl_http_proxy);\n \t\tcurl_http_proxy = NULL;\n \t}\n+\n+#if LIBCURL_VERSION_NUM >= 0x070a06\n+\tif (curl_http_auth) {\n+\t\tfree((void *)curl_http_auth);\n+\t\tcurl_http_auth = NULL;\n+\t}\n+#endif\n+\n+#if LIBCURL_VERSION_NUM >= 0x070a07\n+\tif (curl_http_proxy_auth) {\n+\t\tfree((void *)curl_http_proxy_auth);\n+\t\tcurl_http_proxy_auth = NULL;\n+\t}\n+#endif\n }\n \n struct active_request_slot *get_active_slot(void)\n-- \n1.5.6.3\n"},{"id":"102824","messageId":"1233556274-1354-1-git-send-email-gitster@pobox.com","threadId":"17431","inReplyTo":"E1LTqDN-0003MF-DP@lena.gsc.riken.jp","subject":"Re: [PATCH] Support various HTTP authentication methods","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-02T06:31:11Z","receivedAt":"2009-02-02T06:31:11Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Moriyoshi Koizumi <mozo@mozo.jp> writes:\n\n> diff --git a/http.c b/http.c\n> index ee58799..41e8e8c 100644\n> --- a/http.c\n> +++ b/http.c\n> @@ -13,18 +13,24 @@ static CURL *curl_default;\n>  char curl_errorstr[CURL_ERROR_SIZE];\n>  \n>  static int curl_ssl_verify = -1;\n> -static const char *ssl_cert = NULL;\n> +static const char *ssl_cert;\n>  #if LIBCURL_VERSION_NUM >= 0x070902\n> -static const char *ssl_key = NULL;\n> +static const char *ssl_key;\n>  #endif\n>  #if LIBCURL_VERSION_NUM >= 0x070908\n> -static const char *ssl_capath = NULL;\n> +static const char *ssl_capath;\n>  #endif\n> -static const char *ssl_cainfo = NULL;\n> +static const char *ssl_cainfo;\n>  static long curl_low_speed_limit = -1;\n>  static long curl_low_speed_time = -1;\n>  static int curl_ftp_no_epsv = 0;\n> -static const char *curl_http_proxy = NULL;\n> +static const char *curl_http_proxy;\n\nApplying style fixes to the existing code is very much appreciated, *but*\nplease make such a clean-up patch a separate one.  A two-patch series\nwhose [1/2] is such a pure clean-up without any feature change, with [2/2]\nthat adds code to the cleaned-up state would be much less distracting for\npeople who nitpick your changes.\n\n> @@ -153,11 +159,69 @@ static int http_options(const char *var, const char *value, void *cb)\n>  \t\t\treturn git_config_string(&curl_http_proxy, var, value);\n>  \t\treturn 0;\n>  \t}\n> +#if LIBCURL_VERSION_NUM >= 0x070a06\n> +\tif (!strcmp(\"http.auth\", var)) {\n> +\t\tif (curl_http_auth == NULL)\n> +\t\t\treturn git_config_string(&curl_http_auth, var, value);\n> +\t\treturn 0;\n> +\t}\n> +#endif\n> +#if LIBCURL_VERSION_NUM >= 0x070a07\n> +\tif (!strcmp(\"http.proxy_auth\", var)) {\n> +\t\tif (curl_http_proxy_auth == NULL)\n> +\t\t\treturn git_config_string(&curl_http_proxy_auth, var, value);\n> +\t\treturn 0;\n> +\t}\n> +#endif\n\nIf you follow config.c::git_config() you will notice that we read from\n/etc/gitconfig, $HOME/.gitconfig and then finally $GIT_DIR/config.  By\nimplementing \"if we already have read curl_http_auth already, we will\nignore the later setting\" like above code does, you break the general\nexpectation that system-wide defaults is overridable by $HOME/.gitconfig\nand that is in turn overridable by per-repository $GIT_DIR/config.\n\nThe preferred order would be:\n\n  - Use the value obtained from command line parameters, if any;\n\n  - Otherwise, if an environment variable is there, use it;\n\n  - Otherwise, the value obtained from git_config(), with \"later one wins\"\n    rule.\n  \nI think you are not adding any command line option, so favoring\nenvironment and then using configuration is fine, but the configuration\nparser must follow the usual \"later one wins\" rule to avoid dissapointing\nthe users.\n\n> +#if LIBCURL_VERSION_NUM >= 0x070a06\n> +static long get_curl_auth_bitmask(const char* auth_method)\n\nIn git codebase, asterisk that means \"a pointer\" sticks to the variable\nname not to type name; \"const char *auth_method\" (I see this file is\nalready infested with such style violations, but if you are doing a\nseparate clean-up patch it would be appreciated to clean them up).\n\n> +{\n> +\tchar buf[4096];\n\nDo you need that much space?\n\n> +\tconst unsigned char *p = (const unsigned char *)auth_method;\n> +\tlong mask = CURLAUTH_NONE;\n> +\n> +    strlcpy(buf, auth_method, sizeof(buf));\n\nA tab is 8-char wide.\n\nWhat happens when auth_method is longer than 4kB?\n\n> +\n> +\tfor (;;) {\n> +\t\tchar *q = buf;\n> +\t\twhile (*p && isspace(*p))\n> +\t\t\t++p;\n\nIf there is no particular reason to choose one over the other, please use\npostincrement, p++, as other existing parts of the codebase.\n\nI'll try to demonstrate what (I think) this patch should look like as a\npair of follow-up messages to this one, but I am not sure about my rewrite\nof get_curl_auth_bitmask().  Please consider it as an easter-egg bughunt\n;-)\n"},{"id":"102826","messageId":"1233556274-1354-2-git-send-email-gitster@pobox.com","threadId":"17431","inReplyTo":"1233556274-1354-1-git-send-email-gitster@pobox.com","subject":"Re: [PATCH] Support various HTTP authentication methods","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-02T06:31:12Z","receivedAt":"2009-02-02T06:31:12Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Moriyoshi Koizumi <mozo@mozo.jp> writes:\n\n> diff --git a/http.c b/http.c\n> index ee58799..41e8e8c 100644\n> --- a/http.c\n> +++ b/http.c\n> @@ -13,18 +13,24 @@ static CURL *curl_default;\n>  char curl_errorstr[CURL_ERROR_SIZE];\n>  \n>  static int curl_ssl_verify = -1;\n> -static const char *ssl_cert = NULL;\n> +static const char *ssl_cert;\n>  #if LIBCURL_VERSION_NUM >= 0x070902\n> -static const char *ssl_key = NULL;\n> +static const char *ssl_key;\n>  #endif\n>  #if LIBCURL_VERSION_NUM >= 0x070908\n> -static const char *ssl_capath = NULL;\n> +static const char *ssl_capath;\n>  #endif\n> -static const char *ssl_cainfo = NULL;\n> +static const char *ssl_cainfo;\n>  static long curl_low_speed_limit = -1;\n>  static long curl_low_speed_time = -1;\n>  static int curl_ftp_no_epsv = 0;\n> -static const char *curl_http_proxy = NULL;\n> +static const char *curl_http_proxy;\n\nApplying style fixes to the existing code is very much appreciated, *but*\nplease make such a clean-up patch a separate one.  A two-patch series\nwhose [1/2] is such a pure clean-up without any feature change, with [2/2]\nthat adds code to the cleaned-up state would be much less distracting for\npeople who nitpick your changes.\n\n> @@ -153,11 +159,69 @@ static int http_options(const char *var, const char *value, void *cb)\n>  \t\t\treturn git_config_string(&curl_http_proxy, var, value);\n>  \t\treturn 0;\n>  \t}\n> +#if LIBCURL_VERSION_NUM >= 0x070a06\n> +\tif (!strcmp(\"http.auth\", var)) {\n> +\t\tif (curl_http_auth == NULL)\n> +\t\t\treturn git_config_string(&curl_http_auth, var, value);\n> +\t\treturn 0;\n> +\t}\n> +#endif\n> +#if LIBCURL_VERSION_NUM >= 0x070a07\n> +\tif (!strcmp(\"http.proxy_auth\", var)) {\n> +\t\tif (curl_http_proxy_auth == NULL)\n> +\t\t\treturn git_config_string(&curl_http_proxy_auth, var, value);\n> +\t\treturn 0;\n> +\t}\n> +#endif\n\nIf you follow config.c::git_config() you will notice that we read from\n/etc/gitconfig, $HOME/.gitconfig and then finally $GIT_DIR/config.  By\nimplementing \"if we already have read curl_http_auth already, we will\nignore the later setting\" like above code does, you break the general\nexpectation that system-wide defaults is overridable by $HOME/.gitconfig\nand that is in turn overridable by per-repository $GIT_DIR/config.\n\nThe preferred order would be:\n\n  - Use the value obtained from command line parameters, if any;\n\n  - Otherwise, if an environment variable is there, use it;\n\n  - Otherwise, the value obtained from git_config(), with \"later one wins\"\n    rule.\n  \nI think you are not adding any command line option, so favoring\nenvironment and then using configuration is fine, but the configuration\nparser must follow the usual \"later one wins\" rule to avoid dissapointing\nthe users.\n\n> +#if LIBCURL_VERSION_NUM >= 0x070a06\n> +static long get_curl_auth_bitmask(const char* auth_method)\n\nIn git codebase, asterisk that means \"a pointer\" sticks to the variable\nname not to type name; \"const char *auth_method\" (I see this file is\nalready infested with such style violations, but if you are doing a\nseparate clean-up patch it would be appreciated to clean them up).\n\n> +{\n> +\tchar buf[4096];\n\nDo you need that much space?\n\n> +\tconst unsigned char *p = (const unsigned char *)auth_method;\n> +\tlong mask = CURLAUTH_NONE;\n> +\n> +    strlcpy(buf, auth_method, sizeof(buf));\n\nA tab is 8-char wide.\n\nWhat happens when auth_method is longer than 4kB?\n\n> +\n> +\tfor (;;) {\n> +\t\tchar *q = buf;\n> +\t\twhile (*p && isspace(*p))\n> +\t\t\t++p;\n\nIf there is no particular reason to choose one over the other, please use\npostincrement, p++, as other existing parts of the codebase.\n\nI'll try to demonstrate what (I think) this patch should look like as a\npair of follow-up messages to this one, but I am not sure about my rewrite\nof get_curl_auth_bitmask().  Please consider it as an easter-egg bughunt\n;-)\n"},{"id":"102827","messageId":"1233556274-1354-3-git-send-email-gitster@pobox.com","threadId":"17431","inReplyTo":"1233556274-1354-2-git-send-email-gitster@pobox.com","subject":"[PATCH 1/2] http.c: fix various style violations","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-02T06:31:13Z","receivedAt":"2009-02-02T06:31:13Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Signed-off-by: Junio C Hamano <gitster@pobox.com>\n---\n http.c |   46 +++++++++++++++++++++-------------------------\n 1 files changed, 21 insertions(+), 25 deletions(-)\n\ndiff --git a/http.c b/http.c\nindex ee58799..86be906 100644\n--- a/http.c\n+++ b/http.c\n@@ -1,7 +1,7 @@\n #include \"http.h\"\n \n int data_received;\n-int active_requests = 0;\n+int active_requests;\n \n #ifdef USE_CURL_MULTI\n static int max_requests = -1;\n@@ -13,22 +13,22 @@ static CURL *curl_default;\n char curl_errorstr[CURL_ERROR_SIZE];\n \n static int curl_ssl_verify = -1;\n-static const char *ssl_cert = NULL;\n+static const char *ssl_cert;\n #if LIBCURL_VERSION_NUM >= 0x070902\n-static const char *ssl_key = NULL;\n+static const char *ssl_key;\n #endif\n #if LIBCURL_VERSION_NUM >= 0x070908\n-static const char *ssl_capath = NULL;\n+static const char *ssl_capath;\n #endif\n-static const char *ssl_cainfo = NULL;\n+static const char *ssl_cainfo;\n static long curl_low_speed_limit = -1;\n static long curl_low_speed_time = -1;\n-static int curl_ftp_no_epsv = 0;\n-static const char *curl_http_proxy = NULL;\n+static int curl_ftp_no_epsv;\n+static const char *curl_http_proxy;\n \n static struct curl_slist *pragma_header;\n \n-static struct active_request_slot *active_queue_head = NULL;\n+static struct active_request_slot *active_queue_head;\n \n size_t fread_buffer(void *ptr, size_t eltsize, size_t nmemb, void *buffer_)\n {\n@@ -94,9 +94,8 @@ static void process_curl_messages(void)\n static int http_options(const char *var, const char *value, void *cb)\n {\n \tif (!strcmp(\"http.sslverify\", var)) {\n-\t\tif (curl_ssl_verify == -1) {\n+\t\tif (curl_ssl_verify == -1)\n \t\t\tcurl_ssl_verify = git_config_bool(var, value);\n-\t\t}\n \t\treturn 0;\n \t}\n \n@@ -158,9 +157,9 @@ static int http_options(const char *var, const char *value, void *cb)\n \treturn git_default_config(var, value, cb);\n }\n \n-static CURL* get_curl_handle(void)\n+static CURL *get_curl_handle(void)\n {\n-\tCURL* result = curl_easy_init();\n+\tCURL *result = curl_easy_init();\n \n \tif (!curl_ssl_verify) {\n \t\tcurl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 0);\n@@ -322,15 +321,13 @@ struct active_request_slot *get_active_slot(void)\n \t/* Wait for a slot to open up if the queue is full */\n \twhile (active_requests >= max_requests) {\n \t\tcurl_multi_perform(curlm, &num_transfers);\n-\t\tif (num_transfers < active_requests) {\n+\t\tif (num_transfers < active_requests)\n \t\t\tprocess_curl_messages();\n-\t\t}\n \t}\n #endif\n \n-\twhile (slot != NULL && slot->in_use) {\n+\twhile (slot != NULL && slot->in_use)\n \t\tslot = slot->next;\n-\t}\n \tif (slot == NULL) {\n \t\tnewslot = xmalloc(sizeof(*newslot));\n \t\tnewslot->curl = NULL;\n@@ -341,9 +338,8 @@ struct active_request_slot *get_active_slot(void)\n \t\tif (slot == NULL) {\n \t\t\tactive_queue_head = newslot;\n \t\t} else {\n-\t\t\twhile (slot->next != NULL) {\n+\t\t\twhile (slot->next != NULL)\n \t\t\t\tslot = slot->next;\n-\t\t\t}\n \t\t\tslot->next = newslot;\n \t\t}\n \t\tslot = newslot;\n@@ -404,7 +400,7 @@ struct fill_chain {\n \tstruct fill_chain *next;\n };\n \n-static struct fill_chain *fill_cfg = NULL;\n+static struct fill_chain *fill_cfg;\n \n void add_fill_function(void *data, int (*fill)(void *))\n {\n@@ -535,9 +531,8 @@ static void finish_active_slot(struct active_request_slot *slot)\n \t}\n \n \t/* Run callback if appropriate */\n-\tif (slot->callback_func != NULL) {\n+\tif (slot->callback_func != NULL)\n \t\tslot->callback_func(slot->callback_data);\n-\t}\n }\n \n void finish_all_active_slots(void)\n@@ -567,8 +562,10 @@ static inline int needs_quote(int ch)\n \n static inline int hex(int v)\n {\n-\tif (v < 10) return '0' + v;\n-\telse return 'A' + v - 10;\n+\tif (v < 10)\n+\t\treturn '0' + v;\n+\telse\n+\t\treturn 'A' + v - 10;\n }\n \n static char *quote_ref_url(const char *base, const char *ref)\n@@ -591,8 +588,7 @@ static char *quote_ref_url(const char *base, const char *ref)\n \t\t\t*dp++ = '%';\n \t\t\t*dp++ = hex((ch >> 4) & 0xF);\n \t\t\t*dp++ = hex(ch & 0xF);\n-\t\t}\n-\t\telse\n+\t\t} else\n \t\t\t*dp++ = ch;\n \t}\n \t*dp = 0;\n-- \n1.6.1.2.333.ged98f\n"},{"id":"102825","messageId":"1233556274-1354-4-git-send-email-gitster@pobox.com","threadId":"17431","inReplyTo":"1233556274-1354-3-git-send-email-gitster@pobox.com","subject":"[PATCH 2/2] Support various HTTP authentication methods","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-02T06:31:14Z","receivedAt":"2009-02-02T06:31:14Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"From: Moriyoshi Koizumi <mozo@mozo.jp>\n\nCurrently there is no way to specify the preferred authentication\nmethod for the HTTP backend and it always falls back to the CURL's default\nsettings.\n\nThis patch allows users to specify the authentication method if supported\nby CURL, adding a couple of new settings and environment variables\nlisted below (the names within the parentheses indicate the environment\nvariables.)\n\n- http.auth (GIT_HTTP_AUTH)\n  Specifies the preferred authentication method for HTTP.  This can\n  be a method name or the combination of those separated by comma. Valid\n  values are \"basic\", \"digest\", \"gss\" and \"ntlm\". You can also specify\n  \"any\" (all of the above), \"anysafe\" (all of the above except \"basic\").\n\n  Note that the strings are treated case-insensitive.\n\n- http.proxy_auth (GIT_HTTP_PROXY_AUTH)\n  Specifies the preferred authentication method method for HTTP proxy.\n  The same thing as above applies to this setting.\n\nSigned-off-by: Moriyoshi Koizumi <mozo@mozo.jp>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n http.c |  128 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-\n 1 files changed, 127 insertions(+), 1 deletions(-)\n\ndiff --git a/http.c b/http.c\nindex 86be906..7eb849b 100644\n--- a/http.c\n+++ b/http.c\n@@ -25,6 +25,14 @@ static long curl_low_speed_limit = -1;\n static long curl_low_speed_time = -1;\n static int curl_ftp_no_epsv;\n static const char *curl_http_proxy;\n+#if LIBCURL_VERSION_NUM >= 0x070a06\n+static const char *curl_http_auth;\n+static long http_auth_bitmask;\n+#endif\n+#if LIBCURL_VERSION_NUM >= 0x070a07\n+static const char *curl_http_proxy_auth;\n+static long http_proxy_auth_bitmask;\n+#endif\n \n static struct curl_slist *pragma_header;\n \n@@ -152,11 +160,78 @@ static int http_options(const char *var, const char *value, void *cb)\n \t\t\treturn git_config_string(&curl_http_proxy, var, value);\n \t\treturn 0;\n \t}\n+#if LIBCURL_VERSION_NUM >= 0x070a06\n+\tif (!strcmp(\"http.auth\", var)) {\n+\t\tif (curl_http_auth == NULL)\n+\t\t\treturn git_config_string(&curl_http_auth, var, value);\n+\t\treturn 0;\n+\t}\n+#endif\n+#if LIBCURL_VERSION_NUM >= 0x070a07\n+\tif (!strcmp(\"http.proxy_auth\", var)) {\n+\t\tif (curl_http_proxy_auth == NULL)\n+\t\t\treturn git_config_string(&curl_http_proxy_auth, var, value);\n+\t\treturn 0;\n+\t}\n+#endif\n \n \t/* Fall back on the default ones */\n \treturn git_default_config(var, value, cb);\n }\n \n+#if LIBCURL_VERSION_NUM >= 0x070a06\n+#define is_delim(x) (isspace(x) || x == ',')\n+\n+static long get_curl_auth_bitmask(const char *auth_method)\n+{\n+\tchar buf[20];\n+\tconst unsigned char *p = (const unsigned char *)auth_method;\n+\tlong mask = CURLAUTH_NONE;\n+\n+\tfor (;;) {\n+\t\tchar *q = buf;\n+\t\tint toolong = 0;\n+\n+\t\twhile (*p && is_delim(*p))\n+\t\t\tp++;\n+\t\tif (!*p)\n+\t\t\tbreak;\n+\n+\t\twhile (*p && !is_delim(*p)) {\n+\t\t\tif (q < buf + sizeof(buf) - 1)\n+\t\t\t\t*q++ = tolower(*p);\n+\t\t\telse\n+\t\t\t\ttoolong = 1;\n+\t\t\tp++;\n+\t\t}\n+\t\tif (toolong)\n+\t\t\tcontinue;\n+\n+\t\twhile (--q >= buf && is_delim(*q))\n+\t\t\t;\n+\t\tq++;\n+\t\t*q = '\\0';\n+\n+\t\tif (!strcmp(buf, \"basic\"))\n+\t\t\tmask |= CURLAUTH_BASIC;\n+\t\telse if (!strcmp(buf, \"digest\"))\n+\t\t\tmask |= CURLAUTH_DIGEST;\n+\t\telse if (!strcmp(buf, \"gss\"))\n+\t\t\tmask |= CURLAUTH_GSSNEGOTIATE;\n+\t\telse if (!strcmp(buf, \"ntlm\"))\n+\t\t\tmask |= CURLAUTH_NTLM;\n+\t\telse if (!strcmp(buf, \"any\"))\n+\t\t\tmask |= CURLAUTH_ANY;\n+\t\telse if (!strcmp(buf, \"anysafe\"))\n+\t\t\tmask |= CURLAUTH_ANYSAFE;\n+\t\tp++;\n+\t}\n+\n+\treturn mask;\n+}\n+#undef is_delim\n+#endif\n+\n static CURL *get_curl_handle(void)\n {\n \tCURL *result = curl_easy_init();\n@@ -206,12 +281,48 @@ static CURL *get_curl_handle(void)\n \tif (curl_ftp_no_epsv)\n \t\tcurl_easy_setopt(result, CURLOPT_FTP_USE_EPSV, 0);\n \n-\tif (curl_http_proxy)\n+#if LIBCURL_VERSION_NUM >= 0x070a06\n+\tif (curl_http_auth)\n+\t\tcurl_easy_setopt(result, CURLOPT_HTTPAUTH,\n+\t\t\t\t http_auth_bitmask);\n+#endif\n+\n+\tif (curl_http_proxy) {\n \t\tcurl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);\n+#if LIBCURL_VERSION_NUM >= 0x070a07\n+\t\tif (curl_http_proxy_auth)\n+\t\t\tcurl_easy_setopt(result, CURLOPT_PROXYAUTH,\n+\t\t\t\t\t http_proxy_auth_bitmask);\n+#endif\n+\t}\n \n \treturn result;\n }\n \n+static void prepare_http_auth_settings(void)\n+{\n+#if LIBCURL_VERSION_NUM >= 0x070a06\n+\tchar *val;\n+\n+\tval = getenv(\"GIT_HTTP_AUTH\");\n+\tif (val)\n+\t\tcurl_http_auth = val;\n+\n+\tif (curl_http_auth) {\n+\t\thttp_auth_bitmask = get_curl_auth_bitmask(curl_http_auth);\n+\t}\n+\n+#if LIBCURL_VERSION_NUM >= 0x070a07\n+\tval = getenv(\"GIT_HTTP_PROXY_AUTH\");\n+\tif (val)\n+\t\tcurl_http_proxy_auth = val;\n+\tif (curl_http_proxy_auth) {\n+\t\thttp_proxy_auth_bitmask = get_curl_auth_bitmask(curl_http_proxy_auth);\n+\t}\n+#endif\n+#endif\n+}\n+\n void http_init(struct remote *remote)\n {\n \tchar *low_speed_limit;\n@@ -258,6 +369,7 @@ void http_init(struct remote *remote)\n \t\tcurl_low_speed_time = strtol(low_speed_time, NULL, 10);\n \n \tgit_config(http_options, NULL);\n+\tprepare_http_auth_settings();\n \n \tif (curl_ssl_verify == -1)\n \t\tcurl_ssl_verify = 1;\n@@ -308,6 +420,20 @@ void http_cleanup(void)\n \t\tfree((void *)curl_http_proxy);\n \t\tcurl_http_proxy = NULL;\n \t}\n+\n+#if LIBCURL_VERSION_NUM >= 0x070a06\n+\tif (curl_http_auth) {\n+\t\tfree((void *)curl_http_auth);\n+\t\tcurl_http_auth = NULL;\n+\t}\n+#endif\n+\n+#if LIBCURL_VERSION_NUM >= 0x070a07\n+\tif (curl_http_proxy_auth) {\n+\t\tfree((void *)curl_http_proxy_auth);\n+\t\tcurl_http_proxy_auth = NULL;\n+\t}\n+#endif\n }\n \n struct active_request_slot *get_active_slot(void)\n-- \n1.6.1.2.333.ged98f\n"},{"id":"102844","messageId":"cd1fb7540902020038p4ea767c0rd01aecf62d20ff07@mail.gmail.com","threadId":"17431","inReplyTo":"1233556274-1354-1-git-send-email-gitster@pobox.com","subject":"Re: [PATCH] Support various HTTP authentication methods","fromName":"Moriyoshi Koizumi","fromEmail":"mozo@mozo.jp","sentAt":"2009-02-02T08:38:17Z","receivedAt":"2009-02-02T08:38:17Z","isPatch":true,"sender":{"key":"mozo@mozo.jp","avatar":"https://gravatar.com/avatar/65cac99f5cbc06fe8937f550174c11584ea57e8b831310ca4d8046b3bd0ca752?d=mp&s=160"},"body":"On Mon, Feb 2, 2009 at 3:31 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Applying style fixes to the existing code is very much appreciated, *but*\n> please make such a clean-up patch a separate one.  A two-patch series\n> whose [1/2] is such a pure clean-up without any feature change, with [2/2]\n> that adds code to the cleaned-up state would be much less distracting for\n> people who nitpick your changes.\n\nOkay, I'll try to do so next time.\n\n>> @@ -153,11 +159,69 @@ static int http_options(const char *var, const char *value, void *cb)\n>>                       return git_config_string(&curl_http_proxy, var, value);\n>>               return 0;\n>>       }\n>> +#if LIBCURL_VERSION_NUM >= 0x070a06\n>> +     if (!strcmp(\"http.auth\", var)) {\n>> +             if (curl_http_auth == NULL)\n>> +                     return git_config_string(&curl_http_auth, var, value);\n>> +             return 0;\n>> +     }\n>> +#endif\n>> +#if LIBCURL_VERSION_NUM >= 0x070a07\n>> +     if (!strcmp(\"http.proxy_auth\", var)) {\n>> +             if (curl_http_proxy_auth == NULL)\n>> +                     return git_config_string(&curl_http_proxy_auth, var, value);\n>> +             return 0;\n>> +     }\n>> +#endif\n>\n> If you follow config.c::git_config() you will notice that we read from\n> /etc/gitconfig, $HOME/.gitconfig and then finally $GIT_DIR/config.  By\n> implementing \"if we already have read curl_http_auth already, we will\n> ignore the later setting\" like above code does, you break the general\n> expectation that system-wide defaults is overridable by $HOME/.gitconfig\n> and that is in turn overridable by per-repository $GIT_DIR/config.\n\nBut aren't the globals supposed to be set just here? I guessed you\nassume that these are set elsewhere and then it prevents the values\nprovided later from being applied.\n\n> The preferred order would be:\n>\n>  - Use the value obtained from command line parameters, if any;\n>\n>  - Otherwise, if an environment variable is there, use it;\n>\n>  - Otherwise, the value obtained from git_config(), with \"later one wins\"\n>    rule.\n>\n> I think you are not adding any command line option, so favoring\n> environment and then using configuration is fine, but the configuration\n> parser must follow the usual \"later one wins\" rule to avoid dissapointing\n> the users.\n\nI just followed the way other options behave. I was just not sure how\nI was supposed to deal with them.\n\n>> +#if LIBCURL_VERSION_NUM >= 0x070a06\n>> +static long get_curl_auth_bitmask(const char* auth_method)\n>\n> In git codebase, asterisk that means \"a pointer\" sticks to the variable\n> name not to type name; \"const char *auth_method\" (I see this file is\n> already infested with such style violations, but if you are doing a\n> separate clean-up patch it would be appreciated to clean them up).\n>\n\nI'm not willing to do it this time ;-)\n\n>> +{\n>> +     char buf[4096];\n>\n> Do you need that much space?\n\nI think as long as we use fixed-size buffers, I should get them enough\nsized. If this is not preferrable, then it'd be better off using\nheap-allocated buffers.\n\n>> +     const unsigned char *p = (const unsigned char *)auth_method;\n>> +     long mask = CURLAUTH_NONE;\n>> +\n>> +    strlcpy(buf, auth_method, sizeof(buf));\n>\n> A tab is 8-char wide.\n\nSorry about this. I actually was careful but I just forgot to turn off\nthe tab expansion for the second time.\n\n> What happens when auth_method is longer than 4kB?\n>\n>> +\n>> +     for (;;) {\n>> +             char *q = buf;\n>> +             while (*p && isspace(*p))\n>> +                     ++p;\n>\n> If there is no particular reason to choose one over the other, please use\n> postincrement, p++, as other existing parts of the codebase.\n>\n> I'll try to demonstrate what (I think) this patch should look like as a\n> pair of follow-up messages to this one, but I am not sure about my rewrite\n> of get_curl_auth_bitmask().  Please consider it as an easter-egg bughunt\n> ;-)\n\nI anyway appreciate this kind of knit-picking as I'd do so to newbies.\nThanks very much for the advice.\n\nRegards,\nMoriyoshi\n"},{"id":"103181","messageId":"20090204185109.GA31250@klangraum.plasmasturm.org","threadId":"17431","inReplyTo":"1233556274-1354-4-git-send-email-gitster@pobox.com","subject":"Re: Support various HTTP authentication methods","fromName":"Aristotle Pagaltzis","fromEmail":"pagaltzis@gmx.de","sentAt":"2009-02-04T18:51:09Z","receivedAt":"2009-02-04T18:51:09Z","isPatch":false,"sender":{"key":"pagaltzis@gmx.de","avatar":"https://gravatar.com/avatar/871c072f71b6f76a364de75e147b5b46319ca6361257be8817c1cee77548ac74?d=mp&s=160"},"body":"* Junio C Hamano <gitster@pobox.com> [2009-02-02 07:35]:\n> This patch allows users to specify the authentication method if\n> supported by CURL, adding a couple of new settings and\n> environment variables listed below (the names within the\n> parentheses indicate the environment variables.)\n\nI tried this patch against my Apache WebDAV server for which I\nuse Digest auth, but it didn’t get very far:\n\n    Initialized empty Git repository in /tmp/xxxxxxx/.git/\n    error: Couldn't get http://xxx:xxx@example.org:8086/xxxxxxx.git/HEAD for HEAD\n    The requested URL returned error: 400\n    Getting alternates list for http://xxx:xxx@example.org:8086/xxxxxxx.git\n    Getting pack list for http://xxx:xxx@example.org:8086/xxxxxxx.git\n    Getting index for pack a9bed5817173acdf0a2dc86ddaf36c4f0c7f9ea3\n    error: Unable to get pack index http://xxx:xxx@example.org:8086/xxxxxxx.git/objects/pack/pack-a9bed5817173acdf0a2dc86ddaf36c4f0c7f9ea3.idx\n    The requested URL returned error: 400\n    error: Unable to find 7ec6910c4d1733d575f955063fd52b2b0ae7ca5b under http://xxx:xxx@example.org:8086/xxxxxxx.git\n    Cannot obtain needed object 7ec6910c4d1733d575f955063fd52b2b0ae7ca5b\n    fatal: Fetch failed.\n\nThe server error log contained the following lines:\n\n    [Wed Feb 04 19:49:14 2009] [error] [client 192.168.1.1] Digest: uri mismatch - </xxxxxxx.git/info/refs> does not match request-uri </xxxxxxx.git/HEAD>\n    [Wed Feb 04 19:49:15 2009] [error] [client 192.168.1.1] Digest: uri mismatch - </xxxxxxx.git/objects/info/packs> does not match request-uri </xxxxxxx.git/objects/pack/pack-a9bed5817173acdf0a2dc86ddaf36c4f0c7f9ea3.idx>\n\nDoes that have to do with something being missing in the Digest\nsupport or is that operator error? If the latter, what might be\nthe culprit – how do I diagnose it?\n\nRegards,\n-- \nAristotle Pagaltzis // <http://plasmasturm.org/>\n"},{"id":"103214","messageId":"alpine.DEB.1.10.0902042307540.3383@yvahk2.pbagnpgbe.fr","threadId":"17431","inReplyTo":"20090204185109.GA31250@klangraum.plasmasturm.org","subject":"Re: Support various HTTP authentication methods","fromName":"Daniel Stenberg","fromEmail":"daniel@haxx.se","sentAt":"2009-02-04T22:09:46Z","receivedAt":"2009-02-04T22:09:46Z","isPatch":false,"sender":{"key":"daniel@haxx.se","avatar":"https://gravatar.com/avatar/69fdca87edd17cee21ca2e79fc2ff671d644603c3dc27167430f3cd3dbab7ba8?d=mp&s=160"},"body":"On Wed, 4 Feb 2009, Aristotle Pagaltzis wrote:\n\n> Does that have to do with something being missing in the Digest support or \n> is that operator error? If the latter, what might be the culprit – how do I \n> diagnose it?\n\nCan you use curl the command line tool with Digest successfully against some \nof those URLs?\n\nWhat libcurl version are you using?\n\n-- \n\n  / daniel.haxx.se"},{"id":"103235","messageId":"20090204232555.GA2358@klangraum.plasmasturm.org","threadId":"17431","inReplyTo":"alpine.DEB.1.10.0902042307540.3383@yvahk2.pbagnpgbe.fr","subject":"Re: Support various HTTP authentication methods","fromName":"Aristotle Pagaltzis","fromEmail":"pagaltzis@gmx.de","sentAt":"2009-02-04T23:25:55Z","receivedAt":"2009-02-04T23:25:55Z","isPatch":false,"sender":{"key":"pagaltzis@gmx.de","avatar":"https://gravatar.com/avatar/871c072f71b6f76a364de75e147b5b46319ca6361257be8817c1cee77548ac74?d=mp&s=160"},"body":"* Daniel Stenberg <daniel@haxx.se> [2009-02-04 23:15]:\n> On Wed, 4 Feb 2009, Aristotle Pagaltzis wrote:\n>> Does that have to do with something being missing in the\n>> Digest support or is that operator error? If the latter, what\n>> might be the culprit – how do I diagnose it?\n>\n> Can you use curl the command line tool with Digest successfully\n> against some of those URLs?\n\nYes, that works.\n\nI have cross-checked the error and access log and here is what\nhappens – I have marked the requests that are sent with correct\ncredentials with a `@` and those which are sent with mismatched\ncredentials with a `#`:\n\nGET   /x.git/info/refs                                         : 401\nGET @ /x.git/info/refs                                         : 200\nGET # /x.git/HEAD                                              : 400\nGET   /x.git/objects/7e/c6910c4d1733d575f955063fd52b2b0ae7ca5b : 401\nGET @ /x.git/objects/7e/c6910c4d1733d575f955063fd52b2b0ae7ca5b : 404\nGET @ /x.git/objects/info/http-alternates                      : 404\nGET @ /x.git/objects/info/alternates                           : 404\nGET   /x.git/objects/info/packs                                : 401\nGET @ /x.git/objects/info/packs                                : 200\nGET # /x.git/objects/pack/pack-a9bed5817173acdf0a2dc86ddaf36c4f0c7f9ea3.idx : 400\n\nRepeating the clone always yiels this exact sequence.\n\nIf I use `curl` manually to fetch those URIs, they work just fine.\n\n> What libcurl version are you using?\n\n    $ curl --version\n    curl 7.16.2 (i686-pc-linux-gnu) libcurl/7.16.2 OpenSSL/0.9.8g\n    zlib/1.2.3 libidn/1.5\n    Protocols: tftp ftp telnet dict ldap http file https ftps\n    Features: IDN IPv6 Largefile NTLM SSL libz\n\nRegards,\n-- \nAristotle Pagaltzis // <http://plasmasturm.org/>\n"},{"id":"103302","messageId":"alpine.DEB.1.10.0902050907190.19922@yvahk2.pbagnpgbe.fr","threadId":"17431","inReplyTo":"20090204232555.GA2358@klangraum.plasmasturm.org","subject":"Re: Support various HTTP authentication methods","fromName":"Daniel Stenberg","fromEmail":"daniel@haxx.se","sentAt":"2009-02-05T08:11:09Z","receivedAt":"2009-02-05T08:11:09Z","isPatch":false,"sender":{"key":"daniel@haxx.se","avatar":"https://gravatar.com/avatar/69fdca87edd17cee21ca2e79fc2ff671d644603c3dc27167430f3cd3dbab7ba8?d=mp&s=160"},"body":"On Thu, 5 Feb 2009, Aristotle Pagaltzis wrote:\n\n> I have cross-checked the error and access log and here is what happens – I \n> have marked the requests that are sent with correct credentials with a `@` \n> and those which are sent with mismatched credentials with a `#`:\n\n[...]\n\n>    curl 7.16.2 (i686-pc-linux-gnu) libcurl/7.16.2 OpenSSL/0.9.8g\n\nAmong the 279 bugfixes done to libcurl since that release there were a few \nones clearly Digest-related, so it's not totally unlikely that this problem \nwill go away if you just update your libcurl.\n\n-- \n\n  / daniel.haxx.se"}]}