diff options
author | des <des@FreeBSD.org> | 2001-05-26 19:37:15 +0000 |
---|---|---|
committer | des <des@FreeBSD.org> | 2001-05-26 19:37:15 +0000 |
commit | 4f0b3412631a0bb351436f8e864770c93ee8bdaa (patch) | |
tree | 45383a280be7a49c45a9398fdd6c445a08024420 /lib/libfetch | |
parent | 4edf66ad45433dfe5f2ebdca625183c9481390f2 (diff) | |
download | FreeBSD-src-4f0b3412631a0bb351436f8e864770c93ee8bdaa.zip FreeBSD-src-4f0b3412631a0bb351436f8e864770c93ee8bdaa.tar.gz |
Add rudimentary support for an authentication callback function.
Diffstat (limited to 'lib/libfetch')
-rw-r--r-- | lib/libfetch/fetch.c | 2 | ||||
-rw-r--r-- | lib/libfetch/fetch.h | 6 | ||||
-rw-r--r-- | lib/libfetch/ftp.c | 86 | ||||
-rw-r--r-- | lib/libfetch/http.c | 56 |
4 files changed, 91 insertions, 59 deletions
diff --git a/lib/libfetch/fetch.c b/lib/libfetch/fetch.c index de23f00..720c745 100644 --- a/lib/libfetch/fetch.c +++ b/lib/libfetch/fetch.c @@ -39,7 +39,7 @@ #include "fetch.h" #include "common.h" - +auth_t fetchAuthMethod; int fetchLastErrCode; char fetchLastErrString[MAXERRSTRING]; int fetchTimeout; diff --git a/lib/libfetch/fetch.h b/lib/libfetch/fetch.h index dc5fc05..cca0d1f 100644 --- a/lib/libfetch/fetch.h +++ b/lib/libfetch/fetch.h @@ -55,7 +55,7 @@ struct url_stat { }; struct url_ent { - char name[MAXPATHLEN]; + char name[PATH_MAX]; struct url_stat stat; }; @@ -125,6 +125,10 @@ struct url *fetchMakeURL(const char *, const char *, int, struct url *fetchParseURL(const char *); void fetchFreeURL(struct url *); +/* Authentication */ +typedef int (*auth_t)(struct url *); +extern auth_t fetchAuthMethod; + /* Last error code */ extern int fetchLastErrCode; #define MAXERRSTRING 256 diff --git a/lib/libfetch/ftp.c b/lib/libfetch/ftp.c index 0cc9910..ff7bf86 100644 --- a/lib/libfetch/ftp.c +++ b/lib/libfetch/ftp.c @@ -712,6 +712,49 @@ ouch: } /* + * Authenticate + */ +static int +_ftp_authenticate(int cd, struct url *url, struct url *purl) +{ + char *user, *pwd, *logname; + char pbuf[MAXHOSTNAMELEN + MAXLOGNAME + 1]; + int e, len; + + /* XXX FTP_AUTH, and maybe .netrc */ + + /* send user name and password */ + user = url->user; + if (!user || !*user) + user = getenv("FTP_LOGIN"); + if (!user || !*user) + user = FTP_ANONYMOUS_USER; + if (purl && url->port == _fetch_default_port(url->scheme)) + e = _ftp_cmd(cd, "USER %s@%s", user, url->host); + else if (purl) + e = _ftp_cmd(cd, "USER %s@%s@%d", user, url->host, url->port); + else + e = _ftp_cmd(cd, "USER %s", user); + + /* did the server request a password? */ + if (e == FTP_NEED_PASSWORD) { + pwd = url->pwd; + if (!pwd || !*pwd) + pwd = getenv("FTP_PASSWORD"); + if (!pwd || !*pwd) { + if ((logname = getlogin()) == 0) + logname = FTP_ANONYMOUS_USER; + len = snprintf(pbuf, MAXLOGNAME + 1, "%s@", logname); + gethostname(pbuf + len, sizeof pbuf - len); + pwd = pbuf; + } + e = _ftp_cmd(cd, "PASS %s", pwd); + } + + return e; +} + +/* * Log on to FTP server */ static int @@ -723,11 +766,6 @@ _ftp_connect(struct url *url, struct url *purl, const char *flags) #else int af = AF_INET; #endif - const char *logname; - const char *user; - const char *pwd; - char localhost[MAXHOSTNAMELEN]; - char pbuf[MAXHOSTNAMELEN + MAXLOGNAME + 1]; direct = CHECK_FLAG('d'); verbose = CHECK_FLAG('v'); @@ -758,45 +796,11 @@ _ftp_connect(struct url *url, struct url *purl, const char *flags) /* expect welcome message */ if ((e = _ftp_chkerr(cd)) != FTP_SERVICE_READY) goto fouch; - - /* XXX FTP_AUTH, and maybe .netrc */ - /* send user name and password */ - user = url->user; - if (!user || !*user) - user = getenv("FTP_LOGIN"); - if (!user || !*user) - user = FTP_ANONYMOUS_USER; - if (purl && url->port == _fetch_default_port(url->scheme)) - e = _ftp_cmd(cd, "USER %s@%s", user, url->host); - else if (purl) - e = _ftp_cmd(cd, "USER %s@%s@%d", user, url->host, url->port); - else - e = _ftp_cmd(cd, "USER %s", user); - - /* did the server request a password? */ - if (e == FTP_NEED_PASSWORD) { - pwd = url->pwd; - if (!pwd || !*pwd) - pwd = getenv("FTP_PASSWORD"); - if (!pwd || !*pwd) { - if ((logname = getlogin()) == 0) - logname = FTP_ANONYMOUS_USER; - gethostname(localhost, sizeof localhost); - snprintf(pbuf, sizeof pbuf, "%s@%s", logname, localhost); - pwd = pbuf; - } - e = _ftp_cmd(cd, "PASS %s", pwd); - } - - /* did the server request an account? */ - if (e == FTP_NEED_ACCOUNT) + /* authenticate */ + if ((e = _ftp_authenticate(cd, url, purl)) != FTP_LOGGED_IN) goto fouch; - /* we should be done by now */ - if (e != FTP_LOGGED_IN) - goto fouch; - /* might as well select mode and type at once */ #ifdef FTP_FORCE_STREAM_MODE if ((e = _ftp_cmd(cd, "MODE S")) != FTP_OK) /* default is S */ diff --git a/lib/libfetch/http.c b/lib/libfetch/http.c index b1332b3..77c3a2d 100644 --- a/lib/libfetch/http.c +++ b/lib/libfetch/http.c @@ -294,7 +294,8 @@ typedef enum { hdr_content_range, hdr_last_modified, hdr_location, - hdr_transfer_encoding + hdr_transfer_encoding, + hdr_www_authenticate } hdr; /* Names of interesting headers */ @@ -307,6 +308,7 @@ static struct { { hdr_last_modified, "Last-Modified" }, { hdr_location, "Location" }, { hdr_transfer_encoding, "Transfer-Encoding" }, + { hdr_www_authenticate, "WWW-Authenticate" }, { hdr_unknown, NULL }, }; @@ -564,6 +566,8 @@ _http_basic_auth(int fd, const char *hdr, const char *usr, const char *pwd) char *upw, *auth; int r; + DEBUG(fprintf(stderr, "usr: [\033[1m%s\033[m]\n", usr)); + DEBUG(fprintf(stderr, "pwd: [\033[1m%s\033[m]\n", pwd)); if (asprintf(&upw, "%s:%s", usr, pwd) == -1) return -1; auth = _http_base64(upw); @@ -705,16 +709,16 @@ _http_request(struct url *URL, const char *op, struct url_stat *us, n = noredirect ? 1 : MAX_REDIRECT; i = 0; + need_auth = 0; do { new = NULL; chunked = 0; - need_auth = 0; offset = 0; clength = -1; length = -1; size = -1; mtime = 0; - retry: + /* check port */ if (!url->port) url->port = _fetch_default_port(url->scheme); @@ -743,6 +747,12 @@ _http_request(struct url *URL, const char *op, struct url_stat *us, op, url->doc); } + /* virtual host */ + if (url->port == _fetch_default_port(url->scheme)) + _http_cmd(fd, "Host: %s", host); + else + _http_cmd(fd, "Host: %s:%d", host, url->port); + /* proxy authorization */ if (purl) { if (*purl->user || *purl->pwd) @@ -753,22 +763,20 @@ _http_request(struct url *URL, const char *op, struct url_stat *us, } /* server authorization */ - if (need_auth) { + if (need_auth || *url->user || *url->pwd) { if (*url->user || *url->pwd) _http_basic_auth(fd, "Authorization", url->user, url->pwd); else if ((p = getenv("HTTP_AUTH")) != NULL && *p != '\0') _http_authorize(fd, "Authorization", p); - else { + else if (fetchAuthMethod && fetchAuthMethod(url) == 0) { + _http_basic_auth(fd, "Authorization", url->user, url->pwd); + } else { _http_seterr(HTTP_NEED_AUTH); goto ouch; } } /* other headers */ - if (url->port == _fetch_default_port(url->scheme)) - _http_cmd(fd, "Host: %s", host); - else - _http_cmd(fd, "Host: %s:%d", host, url->port); _http_cmd(fd, "User-Agent: %s " _LIBFETCH_VER, __progname); if (url->offset) _http_cmd(fd, "Range: bytes=%lld-", url->offset); @@ -800,9 +808,7 @@ _http_request(struct url *URL, const char *op, struct url_stat *us, /* try again, but send the password this time */ if (verbose) _fetch_info("server requires authorization"); - need_auth = 1; - close(fd); - goto retry; + break; case HTTP_NEED_PROXY_AUTH: /* * If we're talking to a proxy, we already sent our proxy @@ -867,6 +873,11 @@ _http_request(struct url *URL, const char *op, struct url_stat *us, /* XXX weak test*/ chunked = (strcasecmp(p, "chunked") == 0); break; + case hdr_www_authenticate: + if (code != HTTP_NEED_AUTH) + break; + /* if we were smarter, we'd check the method and realm */ + break; case hdr_end: /* fall through */ case hdr_unknown: @@ -875,19 +886,32 @@ _http_request(struct url *URL, const char *op, struct url_stat *us, } } while (h > hdr_end); - /* we either have a hit, or a redirect with no Location: header */ - if (code == HTTP_OK || code == HTTP_PARTIAL || !new) + /* we have a hit */ + if (code == HTTP_OK || code == HTTP_PARTIAL) break; - /* we have a redirect */ + /* we need to provide authentication */ + if (code == HTTP_NEED_AUTH) { + need_auth = 1; + close(fd); + fd = -1; + continue; + } + + /* all other cases: we got a redirect */ + need_auth = 0; close(fd); fd = -1; + if (!new) { + DEBUG(fprintf(stderr, "redirect with no new location\n")); + break; + } if (url != URL) fetchFreeURL(url); url = new; } while (++i < n); - /* no success */ + /* we failed, or ran out of retries */ if (fd == -1) { _http_seterr(code); goto ouch; |