Home | History | Annotate | Download | only in inet
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     28 /*	  All Rights Reserved  	*/
     29 
     30 /*
     31  * University Copyright- Copyright (c) 1982, 1986, 1988
     32  * The Regents of the University of California
     33  * All Rights Reserved
     34  *
     35  * University Acknowledgment- Portions of this document are derived from
     36  * software developed by the University of California, Berkeley, and its
     37  * contributors.
     38  */
     39 
     40 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     41 
     42 #include <stdio.h>
     43 #include <ctype.h>
     44 #include <sys/types.h>
     45 #include <sys/stat.h>
     46 #include <errno.h>
     47 #include <unistd.h>
     48 #include <strings.h>
     49 #include <stdlib.h>
     50 #include <libintl.h>
     51 
     52 #ifdef SYSV
     53 #define	index	strchr
     54 #endif /* SYSV */
     55 
     56 static void rnetrc(const char *host, char **aname, char **apass);
     57 static int token();
     58 
     59 #define	DEFAULT	1
     60 #define	LOGIN	2
     61 #define	PASSWD	3
     62 #define	NOTIFY	4
     63 #define	WRITE	5
     64 #define	YES	6
     65 #define	NO	7
     66 #define	COMMAND	8
     67 #define	FORCE	9
     68 #define	ID	10
     69 #define	MACHINE	11
     70 
     71 #define	MAXTOKEN  11
     72 #define	NTOKENS	(MAXTOKEN - 1 + 2 + 1)	/* two duplicates and null, minus id */
     73 
     74 static struct ruserdata {
     75 	char tokval[100];
     76 	struct toktab {
     77 		char *tokstr;
     78 		int tval;
     79 	} toktab[NTOKENS];
     80 	FILE *cfile;
     81 } *ruserdata, *_ruserdata();
     82 
     83 
     84 static struct ruserdata *
     85 _ruserdata()
     86 {
     87 	struct ruserdata *d = ruserdata;
     88 	struct toktab *t;
     89 
     90 	if (d == 0) {
     91 		if ((d = (struct ruserdata *)
     92 			calloc(1, sizeof (struct ruserdata))) == NULL) {
     93 				return (NULL);
     94 		}
     95 		ruserdata = d;
     96 		t = d->toktab;
     97 		t->tokstr = "default";  t++->tval = DEFAULT;
     98 		t->tokstr = "login";    t++->tval = LOGIN;
     99 		t->tokstr = "password"; t++->tval = PASSWD;
    100 		t->tokstr = "notify";   t++->tval = NOTIFY;
    101 		t->tokstr = "write";    t++->tval = WRITE;
    102 		t->tokstr = "yes";	t++->tval = YES;
    103 		t->tokstr = "y";	t++->tval = YES;
    104 		t->tokstr = "no";	t++->tval = NO;
    105 		t->tokstr = "n";	t++->tval = NO;
    106 		t->tokstr = "command";  t++->tval = COMMAND;
    107 		t->tokstr = "force";    t++->tval = FORCE;
    108 		t->tokstr = "machine";  t++->tval = MACHINE;
    109 		t->tokstr = 0;		t->tval = 0;
    110 	}
    111 	return (d);
    112 }
    113 
    114 
    115 #define	MAXANAME	16
    116 
    117 void
    118 _ruserpass(const char *host, char **aname, char **apass)
    119 {
    120 
    121 	if (*aname == 0 || *apass == 0)
    122 		rnetrc(host, aname, apass);
    123 	if (*aname == 0) {
    124 		char myname[L_cuserid];
    125 
    126 		*aname = malloc(MAXANAME + 1);
    127 		(void) cuserid(myname);
    128 		(void) printf(dgettext(TEXT_DOMAIN, "Name (%s:%s): "),
    129 		    host, myname);
    130 		(void) fflush(stdout);
    131 		if (read(2, *aname, MAXANAME) <= 0)
    132 			exit(1);
    133 		aname[0][MAXANAME] = '\0';
    134 		if ((*aname)[0] == '\n')
    135 			(void) strcpy(*aname, myname);
    136 		else
    137 			if (index(*aname, '\n'))
    138 				*index(*aname, '\n') = 0;
    139 	}
    140 	if (*aname && *apass == 0) {
    141 		(void) printf(dgettext(TEXT_DOMAIN, "Password (%s:%s): "),
    142 		    host, *aname);
    143 		(void) fflush(stdout);
    144 		*apass = getpass("");
    145 	}
    146 }
    147 
    148 
    149 static void
    150 rnetrc(const char *host, char **aname, char **apass)
    151 {
    152 	struct ruserdata *d = _ruserdata();
    153 	char *hdir, buf[BUFSIZ];
    154 	int t;
    155 	struct stat64 stb;
    156 
    157 	if (d == 0)
    158 		return;
    159 
    160 	hdir = getenv("HOME");
    161 	if (hdir == NULL)
    162 		hdir = ".";
    163 	(void) sprintf(buf, "%s/.netrc", hdir);
    164 	d->cfile = fopen(buf, "rF");
    165 	if (d->cfile == NULL) {
    166 		if (errno != ENOENT)
    167 			perror(buf);
    168 		return;
    169 	}
    170 next:
    171 	while ((t = token()))
    172 	switch (t) {
    173 
    174 	case DEFAULT:
    175 		(void) token();
    176 		continue;
    177 
    178 	case MACHINE:
    179 		if (token() != ID || strcmp(host, d->tokval))
    180 			continue;
    181 		while ((t = token()) != 0 && t != MACHINE)
    182 		switch (t) {
    183 
    184 		case LOGIN:
    185 			if (token())
    186 				if (*aname == 0) {
    187 					*aname = malloc(strlen(d->tokval) + 1);
    188 					(void) strcpy(*aname, d->tokval);
    189 				} else {
    190 					if (strcmp(*aname, d->tokval))
    191 						goto next;
    192 				}
    193 			break;
    194 		case PASSWD:
    195 			if (fstat64(fileno(d->cfile), &stb) >= 0 &&
    196 			    (stb.st_mode & 077) != 0) {
    197 				(void) fprintf(stderr,
    198 				    dgettext(TEXT_DOMAIN,
    199 				    "Error - .netrc file not correct mode.\n"));
    200 				(void) fprintf(stderr,
    201 				    dgettext(TEXT_DOMAIN,
    202 				    "Remove password or correct mode.\n"));
    203 				exit(1);
    204 			}
    205 			if (token() && *apass == 0) {
    206 				*apass = malloc(strlen(d->tokval) + 1);
    207 				(void) strcpy(*apass, d->tokval);
    208 			}
    209 			break;
    210 		case COMMAND:
    211 		case NOTIFY:
    212 		case WRITE:
    213 		case FORCE:
    214 			(void) token();
    215 			break;
    216 		default:
    217 			(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
    218 			    "Unknown .netrc option %s\n"), d->tokval);
    219 			break;
    220 		}
    221 		goto done;
    222 	}
    223 done:
    224 	(void) fclose(d->cfile);
    225 }
    226 
    227 static int
    228 token()
    229 {
    230 	struct ruserdata *d = _ruserdata();
    231 	char *cp;
    232 	int c;
    233 	struct toktab *t;
    234 
    235 	if (d == 0)
    236 		return (0);
    237 
    238 	if (feof(d->cfile))
    239 		return (0);
    240 	while ((c = getc(d->cfile)) != EOF &&
    241 	    (c == '\n' || c == '\t' || c == ' ' || c == ','))
    242 		continue;
    243 	if (c == EOF)
    244 		return (0);
    245 	cp = d->tokval;
    246 	if (c == '"') {
    247 		while ((c = getc(d->cfile)) != EOF && c != '"') {
    248 			if (c == '\\')
    249 				c = getc(d->cfile);
    250 			*cp++ = (char)c;
    251 		}
    252 	} else {
    253 		*cp++ = (char)c;
    254 		while ((c = getc(d->cfile)) != EOF &&
    255 		    c != '\n' && c != '\t' && c != ' ' && c != ',') {
    256 			if (c == '\\')
    257 				c = getc(d->cfile);
    258 			*cp++ = (char)c;
    259 		}
    260 	}
    261 	*cp = 0;
    262 	if (d->tokval[0] == 0)
    263 		return (0);
    264 	for (t = d->toktab; t->tokstr; t++)
    265 		if ((strcmp(t->tokstr, d->tokval) == 0))
    266 			return (t->tval);
    267 	return (ID);
    268 }
    269