126053Sminshall /*
266673Spendry * Copyright (c) 1985, 1993, 1994
362012Sbostic * The Regents of the University of California. All rights reserved.
433737Sbostic *
542666Sbostic * %sccs.include.redist.c%
626053Sminshall */
726053Sminshall
826053Sminshall #ifndef lint
9*68958Sbostic static char sccsid[] = "@(#)ruserpass.c 8.4 (Berkeley) 04/27/95";
1033737Sbostic #endif /* not lint */
1126053Sminshall
1235631Sbostic #include <sys/types.h>
1366670Spendry #include <sys/stat.h>
1466670Spendry
1526053Sminshall #include <ctype.h>
1666670Spendry #include <err.h>
1726053Sminshall #include <errno.h>
1866670Spendry #include <stdio.h>
1966670Spendry #include <stdlib.h>
2066670Spendry #include <string.h>
2166670Spendry #include <unistd.h>
2266670Spendry
2336940Skarels #include "ftp_var.h"
2426053Sminshall
2566670Spendry static int token __P((void));
2626053Sminshall static FILE *cfile;
2726053Sminshall
2826053Sminshall #define DEFAULT 1
2926053Sminshall #define LOGIN 2
3026053Sminshall #define PASSWD 3
3126053Sminshall #define ACCOUNT 4
3226053Sminshall #define MACDEF 5
3326053Sminshall #define ID 10
3436940Skarels #define MACH 11
3526053Sminshall
3626053Sminshall static char tokval[100];
3726053Sminshall
3826053Sminshall static struct toktab {
3926053Sminshall char *tokstr;
4026053Sminshall int tval;
4126053Sminshall } toktab[]= {
4266670Spendry { "default", DEFAULT },
4366670Spendry { "login", LOGIN },
4466670Spendry { "password", PASSWD },
4566670Spendry { "passwd", PASSWD },
4666670Spendry { "account", ACCOUNT },
4766670Spendry { "machine", MACH },
4866670Spendry { "macdef", MACDEF },
4966670Spendry { NULL, 0 }
5026053Sminshall };
5126053Sminshall
5266670Spendry int
ruserpass(host,aname,apass,aacct)5336940Skarels ruserpass(host, aname, apass, aacct)
5426053Sminshall char *host, **aname, **apass, **aacct;
5526053Sminshall {
5626498Sminshall char *hdir, buf[BUFSIZ], *tmp;
5736940Skarels char myname[MAXHOSTNAMELEN], *mydomain;
5836935Skarels int t, i, c, usedefault = 0;
5926053Sminshall struct stat stb;
6026053Sminshall
6126053Sminshall hdir = getenv("HOME");
6226053Sminshall if (hdir == NULL)
6326053Sminshall hdir = ".";
6426498Sminshall (void) sprintf(buf, "%s/.netrc", hdir);
6526053Sminshall cfile = fopen(buf, "r");
6626053Sminshall if (cfile == NULL) {
6726053Sminshall if (errno != ENOENT)
6866670Spendry warn("%s", buf);
6966670Spendry return (0);
7026053Sminshall }
7136940Skarels if (gethostname(myname, sizeof(myname)) < 0)
7236940Skarels myname[0] = '\0';
7366670Spendry if ((mydomain = strchr(myname, '.')) == NULL)
7436940Skarels mydomain = "";
7526053Sminshall next:
7626053Sminshall while ((t = token())) switch(t) {
7726053Sminshall
7826053Sminshall case DEFAULT:
7936935Skarels usedefault = 1;
8036935Skarels /* FALL THROUGH */
8126053Sminshall
8236940Skarels case MACH:
8336940Skarels if (!usedefault) {
8436940Skarels if (token() != ID)
8536940Skarels continue;
8636940Skarels /*
8736940Skarels * Allow match either for user's input host name
8836940Skarels * or official hostname. Also allow match of
8936940Skarels * incompletely-specified host in local domain.
9036940Skarels */
9136940Skarels if (strcasecmp(host, tokval) == 0)
9236940Skarels goto match;
9336940Skarels if (strcasecmp(hostname, tokval) == 0)
9436940Skarels goto match;
9566670Spendry if ((tmp = strchr(hostname, '.')) != NULL &&
9636940Skarels strcasecmp(tmp, mydomain) == 0 &&
9736940Skarels strncasecmp(hostname, tokval, tmp-hostname) == 0 &&
9836940Skarels tokval[tmp - hostname] == '\0')
9936940Skarels goto match;
10066670Spendry if ((tmp = strchr(host, '.')) != NULL &&
10136940Skarels strcasecmp(tmp, mydomain) == 0 &&
10236940Skarels strncasecmp(host, tokval, tmp - host) == 0 &&
10336940Skarels tokval[tmp - host] == '\0')
10436940Skarels goto match;
10526053Sminshall continue;
10636940Skarels }
10736940Skarels match:
10836940Skarels while ((t = token()) && t != MACH && t != DEFAULT) switch(t) {
10926053Sminshall
11026053Sminshall case LOGIN:
11126053Sminshall if (token())
11226053Sminshall if (*aname == 0) {
11326498Sminshall *aname = malloc((unsigned) strlen(tokval) + 1);
11426498Sminshall (void) strcpy(*aname, tokval);
11526053Sminshall } else {
11626053Sminshall if (strcmp(*aname, tokval))
11726053Sminshall goto next;
11826053Sminshall }
11926053Sminshall break;
12026053Sminshall case PASSWD:
121*68958Sbostic if ((*aname == NULL || strcmp(*aname, "anonymous")) &&
12236940Skarels fstat(fileno(cfile), &stb) >= 0 &&
12336940Skarels (stb.st_mode & 077) != 0) {
12466670Spendry warnx("Error: .netrc file is readable by others.");
12566670Spendry warnx("Remove password or make file unreadable by others.");
12636940Skarels goto bad;
12726053Sminshall }
12826053Sminshall if (token() && *apass == 0) {
12926498Sminshall *apass = malloc((unsigned) strlen(tokval) + 1);
13026498Sminshall (void) strcpy(*apass, tokval);
13126053Sminshall }
13226053Sminshall break;
13326053Sminshall case ACCOUNT:
13426053Sminshall if (fstat(fileno(cfile), &stb) >= 0
13526053Sminshall && (stb.st_mode & 077) != 0) {
13666670Spendry warnx("Error: .netrc file is readable by others.");
13766670Spendry warnx("Remove account or make file unreadable by others.");
13836940Skarels goto bad;
13926053Sminshall }
14026053Sminshall if (token() && *aacct == 0) {
14126498Sminshall *aacct = malloc((unsigned) strlen(tokval) + 1);
14226498Sminshall (void) strcpy(*aacct, tokval);
14326053Sminshall }
14426053Sminshall break;
14526053Sminshall case MACDEF:
14626053Sminshall if (proxy) {
14736940Skarels (void) fclose(cfile);
14866670Spendry return (0);
14926053Sminshall }
15026053Sminshall while ((c=getc(cfile)) != EOF && c == ' ' || c == '\t');
15126053Sminshall if (c == EOF || c == '\n') {
15226053Sminshall printf("Missing macdef name argument.\n");
15336940Skarels goto bad;
15426053Sminshall }
15526053Sminshall if (macnum == 16) {
15626053Sminshall printf("Limit of 16 macros have already been defined\n");
15736940Skarels goto bad;
15826053Sminshall }
15926053Sminshall tmp = macros[macnum].mac_name;
16026053Sminshall *tmp++ = c;
16126053Sminshall for (i=0; i < 8 && (c=getc(cfile)) != EOF &&
16226053Sminshall !isspace(c); ++i) {
16326053Sminshall *tmp++ = c;
16426053Sminshall }
16526053Sminshall if (c == EOF) {
16626053Sminshall printf("Macro definition missing null line terminator.\n");
16736940Skarels goto bad;
16826053Sminshall }
16926053Sminshall *tmp = '\0';
17026053Sminshall if (c != '\n') {
17126053Sminshall while ((c=getc(cfile)) != EOF && c != '\n');
17226053Sminshall }
17326053Sminshall if (c == EOF) {
17426053Sminshall printf("Macro definition missing null line terminator.\n");
17536940Skarels goto bad;
17626053Sminshall }
17726053Sminshall if (macnum == 0) {
17826053Sminshall macros[macnum].mac_start = macbuf;
17926053Sminshall }
18026053Sminshall else {
18126053Sminshall macros[macnum].mac_start = macros[macnum-1].mac_end + 1;
18226053Sminshall }
18326053Sminshall tmp = macros[macnum].mac_start;
18426053Sminshall while (tmp != macbuf + 4096) {
18526053Sminshall if ((c=getc(cfile)) == EOF) {
18626053Sminshall printf("Macro definition missing null line terminator.\n");
18736940Skarels goto bad;
18826053Sminshall }
18926053Sminshall *tmp = c;
19026053Sminshall if (*tmp == '\n') {
19126053Sminshall if (*(tmp-1) == '\0') {
19226053Sminshall macros[macnum++].mac_end = tmp - 1;
19326053Sminshall break;
19426053Sminshall }
19526053Sminshall *tmp = '\0';
19626053Sminshall }
19726053Sminshall tmp++;
19826053Sminshall }
19926053Sminshall if (tmp == macbuf + 4096) {
20026053Sminshall printf("4K macro buffer exceeded\n");
20136940Skarels goto bad;
20226053Sminshall }
20326053Sminshall break;
20426053Sminshall default:
20566670Spendry warnx("Unknown .netrc keyword %s", tokval);
20626053Sminshall break;
20726053Sminshall }
20826053Sminshall goto done;
20926053Sminshall }
21026053Sminshall done:
21126498Sminshall (void) fclose(cfile);
21266670Spendry return (0);
21336940Skarels bad:
21436940Skarels (void) fclose(cfile);
21566670Spendry return (-1);
21626053Sminshall }
21726053Sminshall
21866670Spendry static int
token()21926053Sminshall token()
22026053Sminshall {
22126053Sminshall char *cp;
22226053Sminshall int c;
22326053Sminshall struct toktab *t;
22426053Sminshall
22554057Sandrew if (feof(cfile) || ferror(cfile))
22626053Sminshall return (0);
22726053Sminshall while ((c = getc(cfile)) != EOF &&
22826053Sminshall (c == '\n' || c == '\t' || c == ' ' || c == ','))
22926053Sminshall continue;
23026053Sminshall if (c == EOF)
23126053Sminshall return (0);
23226053Sminshall cp = tokval;
23326053Sminshall if (c == '"') {
23426053Sminshall while ((c = getc(cfile)) != EOF && c != '"') {
23526053Sminshall if (c == '\\')
23626053Sminshall c = getc(cfile);
23726053Sminshall *cp++ = c;
23826053Sminshall }
23926053Sminshall } else {
24026053Sminshall *cp++ = c;
24126053Sminshall while ((c = getc(cfile)) != EOF
24226053Sminshall && c != '\n' && c != '\t' && c != ' ' && c != ',') {
24326053Sminshall if (c == '\\')
24426053Sminshall c = getc(cfile);
24526053Sminshall *cp++ = c;
24626053Sminshall }
24726053Sminshall }
24826053Sminshall *cp = 0;
24926053Sminshall if (tokval[0] == 0)
25026053Sminshall return (0);
25126053Sminshall for (t = toktab; t->tokstr; t++)
25226053Sminshall if (!strcmp(t->tokstr, tokval))
25326053Sminshall return (t->tval);
25426053Sminshall return (ID);
25526053Sminshall }
256