diff options
Diffstat (limited to 'lib/libfetch')
-rw-r--r-- | lib/libfetch/http.c | 161 |
1 files changed, 83 insertions, 78 deletions
diff --git a/lib/libfetch/http.c b/lib/libfetch/http.c index 6d8d66d..d8ae744 100644 --- a/lib/libfetch/http.c +++ b/lib/libfetch/http.c @@ -109,11 +109,9 @@ _http_cmd(FILE *f, char *fmt, ...) va_start(ap, fmt); vfprintf(f, fmt, ap); -#ifndef NDEBUG - fprintf(stderr, "\033[1m>>> "); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\033[m"); -#endif + DEBUG(fprintf(stderr, "\033[1m>>> ")); + DEBUG(vfprintf(stderr, fmt, ap)); + DEBUG(fprintf(stderr, "\033[m")); va_end(ap); return 0; /* XXX */ @@ -224,14 +222,22 @@ fetchContentType(FILE *f) /* * Base64 encoding */ -int -_http_base64(char *dst, char *src, int l) +static char * +_http_base64(char *src) { static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; - int t, r = 0; + char *str, *dst; + size_t l; + int t, r; + + l = strlen(src); + if ((str = malloc(((l + 2) / 3) * 4)) == NULL) + return NULL; + dst = str; + r = 0; while (l >= 3) { t = (src[0] << 16) | (src[1] << 8) | src[2]; @@ -266,39 +272,62 @@ _http_base64(char *dst, char *src, int l) } *dst = 0; - return r; + return str; } /* * Encode username and password */ -char * -_http_auth(char *usr, char *pwd) +static int +_http_basic_auth(FILE *f, char *hdr, char *usr, char *pwd) { - int len, lup; - char *uandp, *str = NULL; - - lup = strlen(usr) + 1 + strlen(pwd);/* length of "usr:pwd" */ - uandp = (char*)malloc(lup + 1); - if (uandp) { - len = ((lup + 2) / 3) * 4; /* length of base64 encoded "usr:pwd" incl. padding */ - str = (char*)malloc(len + 1); - if (str) { - strcpy(uandp, usr); - strcat(uandp, ":"); - strcat(uandp, pwd); - _http_base64(str, uandp, lup); - } - free(uandp); + char *upw, *auth; + int r; + + if (asprintf(&upw, "%s:%s", usr, pwd) == -1) + return -1; + auth = _http_base64(upw); + free(upw); + if (auth == NULL) + return -1; + r = _http_cmd(f, "%s: Basic %s" ENDL, hdr, auth); + free(auth); + return r; +} + +/* + * Send an authorization header + */ +static int +_http_authorize(FILE *f, char *hdr, char *p) +{ + /* basic authorization */ + if (strncasecmp(p, "basic:", 6) == 0) { + char *user, *pwd, *str; + int r; + + /* skip realm */ + for (p += 6; *p && *p != ':'; ++p) + /* nothing */ ; + if (!*p || strchr(++p, ':') == NULL) + return -1; + if ((str = strdup(p)) == NULL) + return -1; /* XXX */ + user = str; + pwd = strchr(str, ':'); + *pwd++ = '\0'; + r = _http_basic_auth(f, hdr, user, pwd); + free(str); + return r; } - return str; + return -1; } /* * Connect to server or proxy */ -FILE * -_http_connect(struct url *URL, char *flags) +static FILE * +_http_connect(struct url *URL, char *flags, int *proxy) { int direct, sd = -1, verbose; #ifdef INET6 @@ -389,7 +418,8 @@ _http_connect(struct url *URL, char *flags) } /* if no proxy is configured or could be contacted, try direct */ - if (sd == -1) { + *proxy = (sd != -1); + if (!*proxy) { if (strcasecmp(URL->scheme, "ftp") == 0) goto ouch; if ((sd = _fetch_connect(URL->host, URL->port, af, verbose)) == -1) @@ -412,7 +442,7 @@ ouch: /* * Check a header line */ -char * +static char * _http_match(char *str, char *hdr) { while (*str && *hdr && tolower(*str++) == tolower(*hdr++)) @@ -427,8 +457,8 @@ _http_match(char *str, char *hdr) /* * Send a HEAD or GET request */ -int -_http_request(FILE *f, char *op, struct url *URL, char *flags) +static int +_http_request(FILE *f, char *op, struct url *URL, char *flags, int proxy) { int e, verbose; char *ln, *p; @@ -448,50 +478,25 @@ _http_request(FILE *f, char *op, struct url *URL, char *flags) } #endif - /* send request (proxies require absolute form, so use that) */ + /* send request (proxies require absolute form) */ if (verbose) _fetch_info("requesting %s://%s:%d%s", URL->scheme, host, URL->port, URL->doc); - _http_cmd(f, "%s %s://%s:%d%s HTTP/1.1" ENDL, - op, URL->scheme, host, URL->port, URL->doc); + if (proxy) + _http_cmd(f, "%s %s://%s:%d%s HTTP/1.1" ENDL, + op, URL->scheme, host, URL->port, URL->doc); + else + _http_cmd(f, "%s %s HTTP/1.1" ENDL, op, URL->doc); /* start sending headers away */ - if (URL->user[0] || URL->pwd[0]) { - char *auth_str = _http_auth(URL->user, URL->pwd); - if (!auth_str) - return 999; /* XXX wrong */ - _http_cmd(f, "Authorization: Basic %s" ENDL, auth_str); - free(auth_str); - } - if (p = getenv("HTTP_PROXY_AUTH")) { - char *auth; - - /* skip leading "basic:*:", if present */ - if (strncmp(p, "basic:*:", 6 + 2) == 0) - p += 6 + 2; - auth = strchr(p, ':'); - if (auth != NULL) { - int len = auth - p; - char *user; - char *auth_str; - - if ((user = (char*)malloc(len + 1)) == NULL) { - free(auth); - return 999; /* XXX wrong */ - } - strncpy(user, p, len); - user[len] = 0; - auth++; - auth_str = _http_auth(user, auth); - free(user); - if (auth_str == NULL) - return 999; /* XXX wrong */ - _http_cmd(f, "Proxy-Authorization: Basic %s" ENDL, auth_str); - free(auth_str); - } else { - return 999; /* XXX wrong */ - } - } + if (URL->user[0] || URL->pwd[0]) + _http_basic_auth(f, "Authorization", + URL->user ? URL->user : "", + URL->pwd ? URL->pwd : ""); + else if ((p = getenv("HTTP_AUTH")) != NULL) + _http_authorize(f, "Authorization", p); + if (proxy && (p = getenv("HTTP_PROXY_AUTH")) != NULL) + _http_authorize(f, "Proxy-Authorization", p); _http_cmd(f, "Host: %s:%d" ENDL, host, URL->port); _http_cmd(f, "User-Agent: %s " _LIBFETCH_VER ENDL, __progname); if (URL->offset) @@ -524,7 +529,7 @@ _http_request(FILE *f, char *op, struct url *URL, char *flags) FILE * fetchGetHTTP(struct url *URL, char *flags) { - int e, enc = ENC_NONE, i, noredirect; + int e, enc = ENC_NONE, i, noredirect, proxy; struct cookie *c; char *ln, *p, *q; FILE *f, *cf; @@ -538,13 +543,13 @@ fetchGetHTTP(struct url *URL, char *flags) return NULL; /* connect */ - if ((f = _http_connect(URL, flags)) == NULL) { + if ((f = _http_connect(URL, flags, &proxy)) == NULL) { free(c); return NULL; } c->real_f = f; - e = _http_request(f, "GET", URL, flags); + e = _http_request(f, "GET", URL, flags, proxy); if (e != (URL->offset ? HTTP_PARTIAL : HTTP_OK) && (e != HTTP_MOVED || noredirect)) { _http_seterr(e); @@ -644,7 +649,7 @@ fetchPutHTTP(struct url *URL, char *flags) int fetchStatHTTP(struct url *URL, struct url_stat *us, char *flags) { - int e, noredirect; + int e, noredirect, proxy; size_t len; char *ln, *p, *q; FILE *f; @@ -655,10 +660,10 @@ fetchStatHTTP(struct url *URL, struct url_stat *us, char *flags) us->atime = us->mtime = 0; /* connect */ - if ((f = _http_connect(URL, flags)) == NULL) + if ((f = _http_connect(URL, flags, &proxy)) == NULL) return -1; - e = _http_request(f, "HEAD", URL, flags); + e = _http_request(f, "HEAD", URL, flags, proxy); if (e != HTTP_OK && (e != HTTP_MOVED || noredirect)) { _http_seterr(e); fclose(f); |