| /* |
| * 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. |
| */ |
| |
| #if defined(LIBC_SCCS) && !defined(lint) |
| static char sccsid[] = "@(#)ruserpass.c 8.3 (Berkeley) 4/2/94"; |
| #endif /* not lint */ |
| |
| #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(host, aname, apass) |
| const char *host, **aname, **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: |
| #if 0 |
| if (fstat64(fileno(cfile), &stb) >= 0 |
| && (stb.st_mode & 077) != 0) { |
| warnx("Error: .netrc file is readable by others."); |
| warnx("Remove account or make file unreadable by others."); |
| goto bad; |
| } |
| if (token() && *aacct == 0) { |
| *aacct = malloc((unsigned) strlen(tokval) + 1); |
| (void) strcpy(*aacct, tokval); |
| } |
| #endif |
| break; |
| case MACDEF: |
| #if 0 |
| if (proxy) { |
| (void) fclose(cfile); |
| return (0); |
| } |
| while ((c=getc_unlocked(cfile)) != EOF && c == ' ' |
| || c == '\t'); |
| if (c == EOF || c == '\n') { |
| printf("Missing macdef name argument.\n"); |
| goto bad; |
| } |
| if (macnum == 16) { |
| printf("Limit of 16 macros have already been defined\n"); |
| goto bad; |
| } |
| tmp = macros[macnum].mac_name; |
| *tmp++ = c; |
| for (i=0; i < 8 && (c=getc_unlocked(cfile)) != EOF && |
| !isspace(c); ++i) { |
| *tmp++ = c; |
| } |
| if (c == EOF) { |
| printf("Macro definition missing null line terminator.\n"); |
| goto bad; |
| } |
| *tmp = '\0'; |
| if (c != '\n') { |
| while ((c=getc_unlocked(cfile)) != EOF |
| && c != '\n'); |
| } |
| if (c == EOF) { |
| printf("Macro definition missing null line terminator.\n"); |
| goto bad; |
| } |
| if (macnum == 0) { |
| macros[macnum].mac_start = macbuf; |
| } |
| else { |
| macros[macnum].mac_start = macros[macnum-1].mac_end + 1; |
| } |
| tmp = macros[macnum].mac_start; |
| while (tmp != macbuf + 4096) { |
| if ((c=getc_unlocked(cfile)) == EOF) { |
| printf("Macro definition missing null line terminator.\n"); |
| goto bad; |
| } |
| *tmp = c; |
| if (*tmp == '\n') { |
| if (*(tmp-1) == '\0') { |
| macros[macnum++].mac_end = tmp - 1; |
| break; |
| } |
| *tmp = '\0'; |
| } |
| tmp++; |
| } |
| if (tmp == macbuf + 4096) { |
| printf("4K macro buffer exceeded\n"); |
| goto bad; |
| } |
| #endif |
| 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); |
| } |