* ftpfs.c (ftp_split_url): Don't expect lookup_netrc() to always
return a username. (netrc_has_incorrect_mode): Don't free anything, it can result in freeing some variables twice. (find_machine): New function to find matching "machine" or "default" token. (lookup_netrc): Eliminate external loop - scan for login and password, but don't fallback to another string in case of trouble.
Этот коммит содержится в:
родитель
14bac1dda4
Коммит
e88191dd7c
@ -1,5 +1,15 @@
|
|||||||
2002-07-12 Pavel Roskin <proski@gnu.org>
|
2002-07-12 Pavel Roskin <proski@gnu.org>
|
||||||
|
|
||||||
|
* ftpfs.c (ftp_split_url): Don't expect lookup_netrc() to always
|
||||||
|
return a username.
|
||||||
|
(netrc_has_incorrect_mode): Don't free anything, it can result
|
||||||
|
in freeing some variables twice.
|
||||||
|
(find_machine): New function to find matching "machine" or
|
||||||
|
"default" token.
|
||||||
|
(lookup_netrc): Eliminate external loop - scan for login and
|
||||||
|
password, but don't fallback to another string in case of
|
||||||
|
trouble.
|
||||||
|
|
||||||
* ftpfs.c: Introduce enum keyword_t to improve readability.
|
* ftpfs.c: Introduce enum keyword_t to improve readability.
|
||||||
(netrc_next): Fix return value for unknown keywords.
|
(netrc_next): Fix return value for unknown keywords.
|
||||||
(lookup_netrc): Remove special processing of "*netrc*".
|
(lookup_netrc): Remove special processing of "*netrc*".
|
||||||
|
254
vfs/ftpfs.c
254
vfs/ftpfs.c
@ -228,7 +228,7 @@ ftp_split_url(char *path, char **host, char **user, int *port, char **pass)
|
|||||||
if (!*user) {
|
if (!*user) {
|
||||||
if (use_netrc)
|
if (use_netrc)
|
||||||
lookup_netrc (*host, user, pass);
|
lookup_netrc (*host, user, pass);
|
||||||
else
|
if (!*user)
|
||||||
*user = g_strdup ("anonymous");
|
*user = g_strdup ("anonymous");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1829,23 +1829,23 @@ typedef enum {
|
|||||||
NETRC_PASSWD,
|
NETRC_PASSWD,
|
||||||
NETRC_ACCOUNT,
|
NETRC_ACCOUNT,
|
||||||
NETRC_MACDEF,
|
NETRC_MACDEF,
|
||||||
NETRC_UNKNOWN,
|
NETRC_UNKNOWN
|
||||||
NETRC_BREAK = 20
|
|
||||||
} keyword_t;
|
} keyword_t;
|
||||||
|
|
||||||
static keyword_t netrc_next (void)
|
static keyword_t netrc_next (void)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
keyword_t i;
|
keyword_t i;
|
||||||
static const char * const keywords [] = { "default", "machine",
|
static const char *const keywords[] = { "default", "machine",
|
||||||
"login", "password", "passwd", "account", "macdef", NULL };
|
"login", "password", "passwd", "account", "macdef", NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
netrcp = skip_separators (netrcp);
|
netrcp = skip_separators (netrcp);
|
||||||
if (*netrcp != '\n')
|
if (*netrcp != '\n')
|
||||||
break;
|
break;
|
||||||
netrcp++;
|
netrcp++;
|
||||||
}
|
}
|
||||||
if (!*netrcp)
|
if (!*netrcp)
|
||||||
return NETRC_NONE;
|
return NETRC_NONE;
|
||||||
@ -1857,8 +1857,8 @@ static keyword_t netrc_next (void)
|
|||||||
*p++ = *netrcp;
|
*p++ = *netrcp;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (;*netrcp != '\n' && *netrcp != '\t' && *netrcp != ' ' &&
|
for (; *netrcp != '\n' && *netrcp != '\t' && *netrcp != ' ' &&
|
||||||
*netrcp != ',' && *netrcp; netrcp++) {
|
*netrcp != ',' && *netrcp; netrcp++) {
|
||||||
if (*netrcp == '\\')
|
if (*netrcp == '\\')
|
||||||
netrcp++;
|
netrcp++;
|
||||||
*p++ = *netrcp;
|
*p++ = *netrcp;
|
||||||
@ -1869,35 +1869,89 @@ static keyword_t netrc_next (void)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
i = NETRC_DEFAULT;
|
i = NETRC_DEFAULT;
|
||||||
while (keywords [i - 1]) {
|
while (keywords[i - 1]) {
|
||||||
if (!strcmp (keywords [i - 1], buffer))
|
if (!strcmp (keywords[i - 1], buffer))
|
||||||
return i;
|
return i;
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NETRC_UNKNOWN;
|
return NETRC_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int netrc_has_incorrect_mode (char * netrcname, char * netrc)
|
static int netrc_has_incorrect_mode (char *netrcname, char *netrc)
|
||||||
{
|
{
|
||||||
static int be_angry = 1;
|
static int be_angry = 1;
|
||||||
struct stat mystat;
|
struct stat mystat;
|
||||||
|
|
||||||
if (stat (netrcname, &mystat) >= 0 && (mystat.st_mode & 077)) {
|
if (stat (netrcname, &mystat) >= 0 && (mystat.st_mode & 077)) {
|
||||||
if (be_angry) {
|
if (be_angry) {
|
||||||
message_1s (1, MSG_ERROR, _("~/.netrc file has not correct mode.\n"
|
message_1s (1, MSG_ERROR,
|
||||||
"Remove password or correct mode."));
|
_("~/.netrc file has not correct mode.\n"
|
||||||
|
"Remove password or correct mode."));
|
||||||
be_angry = 0;
|
be_angry = 0;
|
||||||
}
|
}
|
||||||
g_free (netrc);
|
|
||||||
g_free (netrcname);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Extract login and password from .netrc for the host */
|
/* Scan .netrc until we find matching "machine" or "default"
|
||||||
|
* domain is used for additional matching
|
||||||
|
* No search is done after "default" in compliance with "man netrc"
|
||||||
|
* Return 0 if found, -1 otherwise */
|
||||||
|
static int find_machine (const char *host, const char *domain)
|
||||||
|
{
|
||||||
|
keyword_t keyword;
|
||||||
|
|
||||||
|
while ((keyword = netrc_next ()) != NETRC_NONE) {
|
||||||
|
if (keyword == NETRC_DEFAULT)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (keyword == NETRC_MACDEF) {
|
||||||
|
/* Scan for an empty line, which concludes "macdef" */
|
||||||
|
do {
|
||||||
|
while (*netrcp && *netrcp != '\n')
|
||||||
|
netrcp++;
|
||||||
|
if (*netrcp != '\n')
|
||||||
|
break;
|
||||||
|
netrcp++;
|
||||||
|
} while (*netrcp && *netrcp != '\n');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyword != NETRC_MACHINE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Take machine name */
|
||||||
|
if (netrc_next () == NETRC_NONE)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (g_strcasecmp (host, buffer)) {
|
||||||
|
/* Try adding our domain to short names in .netrc */
|
||||||
|
char *host_domain = strchr (host, '.');
|
||||||
|
if (!host_domain)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Compare domain part */
|
||||||
|
if (g_strcasecmp (host_domain, domain))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Compare local part */
|
||||||
|
if (g_strncasecmp (host, buffer, host_domain - host))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* end of .netrc */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Extract login and password from .netrc for the host.
|
||||||
|
* pass may be NULL.
|
||||||
|
* Returns 0 for success, -1 for error */
|
||||||
static int lookup_netrc (const char *host, char **login, char **pass)
|
static int lookup_netrc (const char *host, char **login, char **pass)
|
||||||
{
|
{
|
||||||
char *netrcname;
|
char *netrcname;
|
||||||
@ -1905,102 +1959,106 @@ static int lookup_netrc (const char *host, char **login, char **pass)
|
|||||||
char hostname[MAXHOSTNAMELEN], *domain;
|
char hostname[MAXHOSTNAMELEN], *domain;
|
||||||
keyword_t keyword;
|
keyword_t keyword;
|
||||||
static struct rupcache {
|
static struct rupcache {
|
||||||
struct rupcache *next;
|
struct rupcache *next;
|
||||||
char *host;
|
char *host;
|
||||||
char *login;
|
char *login;
|
||||||
char *pass;
|
char *pass;
|
||||||
} *rup_cache = NULL, *rupp;
|
} *rup_cache = NULL, *rupp;
|
||||||
|
|
||||||
|
/* Initialize *login and *pass */
|
||||||
|
if (!login)
|
||||||
|
return 0;
|
||||||
|
*login = NULL;
|
||||||
|
if (pass)
|
||||||
|
*pass = NULL;
|
||||||
|
|
||||||
/* Look up in the cache first */
|
/* Look up in the cache first */
|
||||||
for (rupp = rup_cache; rupp != NULL; rupp = rupp->next) {
|
for (rupp = rup_cache; rupp != NULL; rupp = rupp->next) {
|
||||||
/* return from cache only if host AND user match! */
|
if (!strcmp (host, rupp->host)) {
|
||||||
if ((!strcmp (host, rupp->host)) &&
|
if (rupp->login)
|
||||||
(rupp->login != NULL) &&
|
*login = g_strdup (rupp->login);
|
||||||
(*login != NULL) &&
|
if (pass && rupp->pass)
|
||||||
(!strcmp(rupp->login, *login))) {
|
*pass = g_strdup (rupp->pass);
|
||||||
*login = g_strdup (rupp->login);
|
return 0;
|
||||||
if (pass && rupp->pass != NULL)
|
|
||||||
*pass = g_strdup (rupp->pass);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Load current .netrc */
|
||||||
netrcname = concat_dir_and_file (home_dir, ".netrc");
|
netrcname = concat_dir_and_file (home_dir, ".netrc");
|
||||||
netrcp = netrc = load_file (netrcname);
|
netrcp = netrc = load_file (netrcname);
|
||||||
if (netrc == NULL) {
|
if (netrc == NULL) {
|
||||||
g_free (netrcname);
|
g_free (netrcname);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Find our own domain name */
|
||||||
if (gethostname (hostname, sizeof (hostname)) < 0)
|
if (gethostname (hostname, sizeof (hostname)) < 0)
|
||||||
*hostname = 0;
|
*hostname = 0;
|
||||||
if (!(domain = strchr (hostname, '.')))
|
if (!(domain = strchr (hostname, '.')))
|
||||||
domain = "";
|
domain = "";
|
||||||
|
|
||||||
while ((keyword = netrc_next ())) {
|
/* Scan for "default" and matching "machine" keywords */
|
||||||
if (keyword == NETRC_MACHINE) {
|
find_machine (host, domain);
|
||||||
char *tmp;
|
|
||||||
|
|
||||||
if (netrc_next () != NETRC_UNKNOWN)
|
/* Scan for keywords following "default" and "machine" */
|
||||||
continue;
|
while (1) {
|
||||||
if (g_strcasecmp (host, buffer) &&
|
int need_break = 0;
|
||||||
((tmp = strchr (host, '.')) == NULL ||
|
keyword = netrc_next ();
|
||||||
g_strcasecmp (tmp, domain) ||
|
|
||||||
g_strncasecmp (host, buffer, tmp - host) ||
|
|
||||||
buffer [tmp - host]))
|
|
||||||
continue;
|
|
||||||
} else if (keyword != NETRC_DEFAULT)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
while ((keyword = netrc_next ()) > NETRC_MACHINE) {
|
switch (keyword) {
|
||||||
switch (keyword) {
|
case NETRC_LOGIN:
|
||||||
case NETRC_LOGIN:
|
if (netrc_next () == NETRC_NONE) {
|
||||||
if (netrc_next ()) {
|
need_break = 1;
|
||||||
if (*login == NULL)
|
break;
|
||||||
*login = g_strdup (buffer);
|
|
||||||
else if (strcmp (*login, buffer))
|
|
||||||
keyword = NETRC_BREAK;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NETRC_PASSWORD:
|
|
||||||
case NETRC_PASSWD:
|
|
||||||
if (strcmp (*login, "anonymous") && strcmp (*login, "ftp") &&
|
|
||||||
netrc_has_incorrect_mode (netrcname, netrc)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (netrc_next () && tmp_pass == NULL)
|
|
||||||
tmp_pass = g_strdup (buffer);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NETRC_ACCOUNT:
|
|
||||||
if (netrc_has_incorrect_mode (netrcname, netrc)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
netrc_next ();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NETRC_MACDEF: /* macdef: skip it */
|
|
||||||
do {
|
|
||||||
while (*netrcp && *netrcp != '\n')
|
|
||||||
netrcp++;
|
|
||||||
if (*netrcp != '\n')
|
|
||||||
break;
|
|
||||||
netrcp++;
|
|
||||||
} while (*netrcp && *netrcp != '\n');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NETRC_NONE:
|
|
||||||
case NETRC_DEFAULT:
|
|
||||||
case NETRC_MACHINE:
|
|
||||||
case NETRC_UNKNOWN:
|
|
||||||
case NETRC_BREAK:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (keyword == NETRC_BREAK)
|
|
||||||
break;
|
/* We have another name already - should not happen */
|
||||||
|
if (*login) {
|
||||||
|
need_break = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We have login name now */
|
||||||
|
*login = g_strdup (buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NETRC_PASSWORD:
|
||||||
|
case NETRC_PASSWD:
|
||||||
|
if (netrc_next () == NETRC_NONE) {
|
||||||
|
need_break = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ignore unsafe passwords */
|
||||||
|
if (strcmp (*login, "anonymous") && strcmp (*login, "ftp")
|
||||||
|
&& netrc_has_incorrect_mode (netrcname, netrc)) {
|
||||||
|
need_break = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remember password. pass may be NULL, so use tmp_pass */
|
||||||
|
if (tmp_pass == NULL)
|
||||||
|
tmp_pass = g_strdup (buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NETRC_ACCOUNT:
|
||||||
|
/* "account" is followed by a token which we ignore */
|
||||||
|
if (netrc_next () == NETRC_NONE) {
|
||||||
|
need_break = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ignore account, but warn user anyways */
|
||||||
|
netrc_has_incorrect_mode (netrcname, netrc);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Unexpected keyword or end of file */
|
||||||
|
need_break = 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (keyword != NETRC_BREAK)
|
|
||||||
|
if (need_break)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2010,12 +2068,12 @@ static int lookup_netrc (const char *host, char **login, char **pass)
|
|||||||
rupp = g_new (struct rupcache, 1);
|
rupp = g_new (struct rupcache, 1);
|
||||||
rupp->host = g_strdup (host);
|
rupp->host = g_strdup (host);
|
||||||
rupp->login = rupp->pass = 0;
|
rupp->login = rupp->pass = 0;
|
||||||
|
|
||||||
if (*login != NULL) {
|
if (*login != NULL) {
|
||||||
rupp->login = g_strdup (*login);
|
rupp->login = g_strdup (*login);
|
||||||
}
|
}
|
||||||
if (tmp_pass != NULL)
|
if (tmp_pass != NULL)
|
||||||
rupp->pass = g_strdup (tmp_pass);
|
rupp->pass = g_strdup (tmp_pass);
|
||||||
rupp->next = rup_cache;
|
rupp->next = rup_cache;
|
||||||
rup_cache = rupp;
|
rup_cache = rupp;
|
||||||
|
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user