/* * Copyright (c) 1985, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include <sys/types.h> #include <sys/stat.h> #include <ctype.h> #include <err.h> #include <errno.h> #include <netdb.h> #include <stdio.h> #include <stdio_ext.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <libintl.h> /* #include "ftp_var.h" */ static int token (void); static FILE *cfile; #define DEFAULT 1 #define LOGIN 2 #define PASSWD 3 #define ACCOUNT 4 #define MACDEF 5 #define ID 10 #define MACHINE 11 static char tokval[100]; static const char tokstr[] = { #define TOK_DEFAULT_IDX 0 "default\0" #define TOK_LOGIN_IDX (TOK_DEFAULT_IDX + sizeof "default") "login\0" #define TOK_PASSWORD_IDX (TOK_LOGIN_IDX + sizeof "login") "password\0" #define TOK_PASSWD_IDX (TOK_PASSWORD_IDX + sizeof "password") "passwd\0" #define TOK_ACCOUNT_IDX (TOK_PASSWD_IDX + sizeof "passwd") "account\0" #define TOK_MACHINE_IDX (TOK_ACCOUNT_IDX + sizeof "account") "machine\0" #define TOK_MACDEF_IDX (TOK_MACHINE_IDX + sizeof "machine") "macdef" }; static const struct toktab { int tokstr_off; int tval; } toktab[]= { { TOK_DEFAULT_IDX, DEFAULT }, { TOK_LOGIN_IDX, LOGIN }, { TOK_PASSWORD_IDX, PASSWD }, { TOK_PASSWD_IDX, PASSWD }, { TOK_ACCOUNT_IDX, ACCOUNT }, { TOK_MACHINE_IDX, MACHINE }, { TOK_MACDEF_IDX, MACDEF } }; int ruserpass (const char *host, const char **aname, const char **apass) { char *hdir, *buf, *tmp; char myname[1024], *mydomain; int t, usedefault = 0; struct stat64 stb; hdir = __libc_secure_getenv("HOME"); if (hdir == NULL) { /* If we can't get HOME, fail instead of trying ".", which is no improvement. This really should call getpwuid(getuid()). */ /*hdir = ".";*/ return -1; } buf = alloca (strlen (hdir) + 8); __stpcpy (__stpcpy (buf, hdir), "/.netrc"); cfile = fopen(buf, "rce"); if (cfile == NULL) { if (errno != ENOENT) warn("%s", buf); return (0); } /* No threads use this stream. */ __fsetlocking (cfile, FSETLOCKING_BYCALLER); if (__gethostname(myname, sizeof(myname)) < 0) myname[0] = '\0'; mydomain = __strchrnul(myname, '.'); next: while ((t = token())) switch(t) { case DEFAULT: usedefault = 1; /* FALL THROUGH */ case MACHINE: if (!usedefault) { if (token() != ID) continue; /* * Allow match either for user's input host name * or official hostname. Also allow match of * incompletely-specified host in local domain. */ if (__strcasecmp(host, tokval) == 0) goto match; /* if (__strcasecmp(hostname, tokval) == 0) goto match; if ((tmp = strchr(hostname, '.')) != NULL && __strcasecmp(tmp, mydomain) == 0 && __strncasecmp(hostname, tokval, tmp-hostname) == 0 && tokval[tmp - hostname] == '\0') goto match; */ if ((tmp = strchr(host, '.')) != NULL && __strcasecmp(tmp, mydomain) == 0 && __strncasecmp(host, tokval, tmp - host) == 0 && tokval[tmp - host] == '\0') goto match; continue; } match: while ((t = token()) && t != MACHINE && t != DEFAULT) switch(t) { case LOGIN: if (token()) { if (*aname == 0) { char *newp; newp = malloc((unsigned) strlen(tokval) + 1); if (newp == NULL) { warnx(_("out of memory")); goto bad; } *aname = strcpy(newp, tokval); } else { if (strcmp(*aname, tokval)) goto next; } } break; case PASSWD: if (strcmp(*aname, "anonymous") && fstat64(fileno(cfile), &stb) >= 0 && (stb.st_mode & 077) != 0) { warnx(_("Error: .netrc file is readable by others.")); warnx(_("Remove password or make file unreadable by others.")); goto bad; } if (token() && *apass == 0) { char *newp; newp = malloc((unsigned) strlen(tokval) + 1); if (newp == NULL) { warnx(_("out of memory")); goto bad; } *apass = strcpy(newp, tokval); } break; case ACCOUNT: break; case MACDEF: break; default: warnx(_("Unknown .netrc keyword %s"), tokval); break; } goto done; } done: (void) fclose(cfile); return (0); bad: (void) fclose(cfile); return (-1); } libc_hidden_def (ruserpass) static int token (void) { char *cp; int c; int i; if (feof_unlocked(cfile) || ferror_unlocked(cfile)) return (0); while ((c = getc_unlocked(cfile)) != EOF && (c == '\n' || c == '\t' || c == ' ' || c == ',')) continue; if (c == EOF) return (0); cp = tokval; if (c == '"') { while ((c = getc_unlocked(cfile)) != EOF && c != '"') { if (c == '\\') c = getc_unlocked(cfile); *cp++ = c; } } else { *cp++ = c; while ((c = getc_unlocked(cfile)) != EOF && c != '\n' && c != '\t' && c != ' ' && c != ',') { if (c == '\\') c = getc_unlocked(cfile); *cp++ = c; } } *cp = 0; if (tokval[0] == 0) return (0); for (i = 0; i < (int) (sizeof (toktab) / sizeof (toktab[0])); ++i) if (!strcmp(&tokstr[toktab[i].tokstr_off], tokval)) return toktab[i].tval; return (ID); }