diff --git a/lib/libfetch/common.c b/lib/libfetch/common.c index 43f0a5fdd7b0..a7f55697a60d 100644 --- a/lib/libfetch/common.c +++ b/lib/libfetch/common.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -611,3 +612,93 @@ _fetch_add_entry(struct url_ent **p, int *size, int *len, return (0); } + + +/*** Authentication-related utility functions ********************************/ + +static const char * +_fetch_read_word(FILE *f) +{ + static char word[1024]; + + if (fscanf(f, " %1024s ", word) != 1) + return (NULL); + return (word); +} + +/* + * Get authentication data for a URL from .netrc + */ +int +_fetch_netrc_auth(struct url *url) +{ + char fn[PATH_MAX]; + const char *word; + char *p; + FILE *f; + + if ((p = getenv("NETRC")) != NULL) { + if (snprintf(fn, sizeof fn, "%s", p) >= sizeof fn) { + _fetch_info("$NETRC specifies a file name " + "longer than PATH_MAX"); + return (-1); + } + } else { + if ((p = getenv("HOME")) != NULL) { + struct passwd *pwd; + + if ((pwd = getpwuid(getuid())) == NULL || + (p = pwd->pw_dir) == NULL) + return (-1); + } + if (snprintf(fn, sizeof fn, "%s/.netrc", p) >= sizeof fn) + return (-1); + } + + if ((f = fopen(fn, "r")) == NULL) + return (-1); + while ((word = _fetch_read_word(f)) != NULL) { + if (strcmp(word, "default") == 0) { + DEBUG(_fetch_info("Using default .netrc settings")); + break; + } + if (strcmp(word, "machine") == 0 && + (word = _fetch_read_word(f)) != NULL && + strcasecmp(word, url->host) == 0) { + DEBUG(_fetch_info("Using .netrc settings for %s", word)); + break; + } + } + if (word == NULL) + goto ferr; + while ((word = _fetch_read_word(f)) != NULL) { + if (strcmp(word, "login") == 0) { + if ((word = _fetch_read_word(f)) == NULL) + goto ferr; + if (snprintf(url->user, sizeof url->user, + "%s", word) > sizeof url->user) { + _fetch_info("login name in .netrc is too long"); + url->user[0] = '\0'; + } + } else if (strcmp(word, "password") == 0) { + if ((word = _fetch_read_word(f)) == NULL) + goto ferr; + if (snprintf(url->pwd, sizeof url->pwd, + "%s", word) > sizeof url->pwd) { + _fetch_info("password in .netrc is too long"); + url->pwd[0] = '\0'; + } + } else if (strcmp(word, "account") == 0) { + if ((word = _fetch_read_word(f)) == NULL) + goto ferr; + /* XXX not supported! */ + } else { + break; + } + } + fclose(f); + return (0); + ferr: + fclose(f); + return (-1); +} diff --git a/lib/libfetch/common.h b/lib/libfetch/common.h index 4b42bf2324f8..adc0f38a1325 100644 --- a/lib/libfetch/common.h +++ b/lib/libfetch/common.h @@ -88,6 +88,7 @@ int _fetch_putln(conn_t *, const char *, size_t); int _fetch_close(conn_t *); int _fetch_add_entry(struct url_ent **, int *, int *, const char *, struct url_stat *); +int _fetch_netrc_auth(struct url *url); #define _ftp_seterr(n) _fetch_seterr(_ftp_errlist, n) #define _http_seterr(n) _fetch_seterr(_http_errlist, n)