1223328Sgavin/* $NetBSD: ruserpass.c,v 1.8 2007/08/06 04:33:24 lukem Exp $ */ 2223328Sgavin/* from NetBSD: ruserpass.c,v 1.33 2007/04/17 05:52:04 lukem Exp */ 379971Sobrien 479971Sobrien/* 579971Sobrien * Copyright (c) 1985, 1993, 1994 679971Sobrien * The Regents of the University of California. All rights reserved. 779971Sobrien * 879971Sobrien * Redistribution and use in source and binary forms, with or without 979971Sobrien * modification, are permitted provided that the following conditions 1079971Sobrien * are met: 1179971Sobrien * 1. Redistributions of source code must retain the above copyright 1279971Sobrien * notice, this list of conditions and the following disclaimer. 1379971Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1479971Sobrien * notice, this list of conditions and the following disclaimer in the 1579971Sobrien * documentation and/or other materials provided with the distribution. 16121966Smikeh * 3. Neither the name of the University nor the names of its contributors 1779971Sobrien * may be used to endorse or promote products derived from this software 1879971Sobrien * without specific prior written permission. 1979971Sobrien * 2079971Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2179971Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2279971Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2379971Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2479971Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2579971Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2679971Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2779971Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2879971Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2979971Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3079971Sobrien * SUCH DAMAGE. 3179971Sobrien */ 3279971Sobrien 33223328Sgavin#include "tnftp.h" 34223328Sgavin 35223328Sgavin#if 0 /* tnftp */ 36223328Sgavin 37116424Smikeh#include <sys/cdefs.h> 38116424Smikeh#ifndef lint 39116424Smikeh#if 0 40116424Smikehstatic char sccsid[] = "@(#)ruserpass.c 8.4 (Berkeley) 4/27/95"; 41116424Smikeh#else 42223328Sgavin__RCSID(" NetBSD: ruserpass.c,v 1.33 2007/04/17 05:52:04 lukem Exp "); 43116424Smikeh#endif 44116424Smikeh#endif /* not lint */ 4579971Sobrien 46116424Smikeh#include <sys/types.h> 47116424Smikeh#include <sys/stat.h> 48116424Smikeh 49116424Smikeh#include <ctype.h> 50116424Smikeh#include <err.h> 51116424Smikeh#include <errno.h> 52116424Smikeh#include <netdb.h> 53116424Smikeh#include <stdio.h> 54116424Smikeh#include <stdlib.h> 55116424Smikeh#include <string.h> 56116424Smikeh#include <unistd.h> 57116424Smikeh 58223328Sgavin#endif /* tnftp */ 59223328Sgavin 6079971Sobrien#include "ftp_var.h" 6179971Sobrien 6279971Sobrienstatic int token(void); 6379971Sobrienstatic FILE *cfile; 6479971Sobrien 6579971Sobrien#define DEFAULT 1 6679971Sobrien#define LOGIN 2 6779971Sobrien#define PASSWD 3 6879971Sobrien#define ACCOUNT 4 6979971Sobrien#define MACDEF 5 7079971Sobrien#define ID 10 7179971Sobrien#define MACH 11 7279971Sobrien 7379971Sobrienstatic char tokval[100]; 7479971Sobrien 7579971Sobrienstatic struct toktab { 76223328Sgavin const char *tokstr; 7779971Sobrien int tval; 7879971Sobrien} toktab[] = { 7979971Sobrien { "default", DEFAULT }, 8079971Sobrien { "login", LOGIN }, 8179971Sobrien { "password", PASSWD }, 8279971Sobrien { "passwd", PASSWD }, 8379971Sobrien { "account", ACCOUNT }, 8479971Sobrien { "machine", MACH }, 8579971Sobrien { "macdef", MACDEF }, 8679971Sobrien { NULL, 0 } 8779971Sobrien}; 8879971Sobrien 8979971Sobrienint 90223328Sgavinruserpass(const char *host, char **aname, char **apass, char **aacct) 9179971Sobrien{ 9298247Smikeh char *tmp; 93223328Sgavin const char *mydomain; 94223328Sgavin char myname[MAXHOSTNAMELEN + 1]; 9579971Sobrien int t, i, c, usedefault = 0; 9679971Sobrien struct stat stb; 9779971Sobrien 9898247Smikeh if (netrc[0] == '\0') 9979971Sobrien return (0); 10098247Smikeh cfile = fopen(netrc, "r"); 10179971Sobrien if (cfile == NULL) { 10279971Sobrien if (errno != ENOENT) 103223328Sgavin warn("Can't read `%s'", netrc); 10479971Sobrien return (0); 10579971Sobrien } 10679971Sobrien if (gethostname(myname, sizeof(myname)) < 0) 10779971Sobrien myname[0] = '\0'; 10879971Sobrien myname[sizeof(myname) - 1] = '\0'; 10979971Sobrien if ((mydomain = strchr(myname, '.')) == NULL) 11079971Sobrien mydomain = ""; 11179971Sobrien next: 112223328Sgavin while ((t = token()) > 0) switch(t) { 11379971Sobrien 11479971Sobrien case DEFAULT: 11579971Sobrien usedefault = 1; 11679971Sobrien /* FALL THROUGH */ 11779971Sobrien 11879971Sobrien case MACH: 11979971Sobrien if (!usedefault) { 120223328Sgavin if ((t = token()) == -1) 121223328Sgavin goto bad; 122223328Sgavin if (t != ID) 12379971Sobrien continue; 12479971Sobrien /* 12579971Sobrien * Allow match either for user's input host name 12679971Sobrien * or official hostname. Also allow match of 12779971Sobrien * incompletely-specified host in local domain. 12879971Sobrien */ 12979971Sobrien if (strcasecmp(host, tokval) == 0) 13079971Sobrien goto match; 13179971Sobrien if (strcasecmp(hostname, tokval) == 0) 13279971Sobrien goto match; 13379971Sobrien if ((tmp = strchr(hostname, '.')) != NULL && 13479971Sobrien strcasecmp(tmp, mydomain) == 0 && 13579971Sobrien strncasecmp(hostname, tokval, tmp-hostname) == 0 && 13679971Sobrien tokval[tmp - hostname] == '\0') 13779971Sobrien goto match; 13879971Sobrien if ((tmp = strchr(host, '.')) != NULL && 13979971Sobrien strcasecmp(tmp, mydomain) == 0 && 14079971Sobrien strncasecmp(host, tokval, tmp - host) == 0 && 14179971Sobrien tokval[tmp - host] == '\0') 14279971Sobrien goto match; 14379971Sobrien continue; 14479971Sobrien } 14579971Sobrien match: 146223328Sgavin while ((t = token()) > 0 && 147223328Sgavin t != MACH && t != DEFAULT) switch(t) { 14879971Sobrien 14979971Sobrien case LOGIN: 150223328Sgavin if ((t = token()) == -1) 151223328Sgavin goto bad; 152223328Sgavin if (t) { 15379971Sobrien if (*aname == NULL) 154223328Sgavin *aname = ftp_strdup(tokval); 15579971Sobrien else { 15679971Sobrien if (strcmp(*aname, tokval)) 15779971Sobrien goto next; 15879971Sobrien } 15979971Sobrien } 16079971Sobrien break; 16179971Sobrien case PASSWD: 16279971Sobrien if ((*aname == NULL || strcmp(*aname, "anonymous")) && 16379971Sobrien fstat(fileno(cfile), &stb) >= 0 && 16479971Sobrien (stb.st_mode & 077) != 0) { 165223328Sgavin warnx("Error: .netrc file is readable by others"); 166223328Sgavin warnx("Remove password or make file unreadable by others"); 16779971Sobrien goto bad; 16879971Sobrien } 169223328Sgavin if ((t = token()) == -1) 170223328Sgavin goto bad; 171223328Sgavin if (t && *apass == NULL) 172223328Sgavin *apass = ftp_strdup(tokval); 17379971Sobrien break; 17479971Sobrien case ACCOUNT: 17579971Sobrien if (fstat(fileno(cfile), &stb) >= 0 17679971Sobrien && (stb.st_mode & 077) != 0) { 177223328Sgavin warnx("Error: .netrc file is readable by others"); 178223328Sgavin warnx("Remove account or make file unreadable by others"); 17979971Sobrien goto bad; 18079971Sobrien } 181223328Sgavin if ((t = token()) == -1) 182223328Sgavin goto bad; 183223328Sgavin if (t && *aacct == NULL) 184223328Sgavin *aacct = ftp_strdup(tokval); 18579971Sobrien break; 18679971Sobrien case MACDEF: 18779971Sobrien if (proxy) { 18879971Sobrien (void)fclose(cfile); 18979971Sobrien return (0); 19079971Sobrien } 19179971Sobrien while ((c = getc(cfile)) != EOF) 19279971Sobrien if (c != ' ' && c != '\t') 19379971Sobrien break; 19479971Sobrien if (c == EOF || c == '\n') { 19579971Sobrien fputs("Missing macdef name argument.\n", 19679971Sobrien ttyout); 19779971Sobrien goto bad; 19879971Sobrien } 19979971Sobrien if (macnum == 16) { 20079971Sobrien fputs( 20179971Sobrien "Limit of 16 macros have already been defined.\n", 20279971Sobrien ttyout); 20379971Sobrien goto bad; 20479971Sobrien } 20579971Sobrien tmp = macros[macnum].mac_name; 20679971Sobrien *tmp++ = c; 20779971Sobrien for (i = 0; i < 8 && (c = getc(cfile)) != EOF && 20879971Sobrien !isspace(c); ++i) { 20979971Sobrien *tmp++ = c; 21079971Sobrien } 21179971Sobrien if (c == EOF) { 21279971Sobrien fputs( 21379971Sobrien "Macro definition missing null line terminator.\n", 21479971Sobrien ttyout); 21579971Sobrien goto bad; 21679971Sobrien } 21779971Sobrien *tmp = '\0'; 21879971Sobrien if (c != '\n') { 21979971Sobrien while ((c = getc(cfile)) != EOF && c != '\n'); 22079971Sobrien } 22179971Sobrien if (c == EOF) { 22279971Sobrien fputs( 22379971Sobrien "Macro definition missing null line terminator.\n", 22479971Sobrien ttyout); 22579971Sobrien goto bad; 22679971Sobrien } 22779971Sobrien if (macnum == 0) { 22879971Sobrien macros[macnum].mac_start = macbuf; 22979971Sobrien } 23079971Sobrien else { 23179971Sobrien macros[macnum].mac_start = 23279971Sobrien macros[macnum-1].mac_end + 1; 23379971Sobrien } 23479971Sobrien tmp = macros[macnum].mac_start; 23579971Sobrien while (tmp != macbuf + 4096) { 23679971Sobrien if ((c = getc(cfile)) == EOF) { 23779971Sobrien fputs( 23879971Sobrien "Macro definition missing null line terminator.\n", 23979971Sobrien ttyout); 24079971Sobrien goto bad; 24179971Sobrien } 24279971Sobrien *tmp = c; 24379971Sobrien if (*tmp == '\n') { 244223328Sgavin if (tmp == macros[macnum].mac_start) { 245223328Sgavin macros[macnum++].mac_end = tmp; 246223328Sgavin break; 247223328Sgavin } else if (*(tmp - 1) == '\0') { 248223328Sgavin macros[macnum++].mac_end = 249223328Sgavin tmp - 1; 250223328Sgavin break; 25179971Sobrien } 25279971Sobrien *tmp = '\0'; 25379971Sobrien } 25479971Sobrien tmp++; 25579971Sobrien } 25679971Sobrien if (tmp == macbuf + 4096) { 25779971Sobrien fputs("4K macro buffer exceeded.\n", 25879971Sobrien ttyout); 25979971Sobrien goto bad; 26079971Sobrien } 26179971Sobrien break; 26279971Sobrien default: 263223328Sgavin warnx("Unknown .netrc keyword `%s'", tokval); 26479971Sobrien break; 26579971Sobrien } 26679971Sobrien goto done; 26779971Sobrien } 26879971Sobrien done: 269223328Sgavin if (t == -1) 270223328Sgavin goto bad; 27179971Sobrien (void)fclose(cfile); 27279971Sobrien return (0); 27379971Sobrien bad: 27479971Sobrien (void)fclose(cfile); 27579971Sobrien return (-1); 27679971Sobrien} 27779971Sobrien 27879971Sobrienstatic int 27979971Sobrientoken(void) 28079971Sobrien{ 28179971Sobrien char *cp; 28279971Sobrien int c; 28379971Sobrien struct toktab *t; 28479971Sobrien 28579971Sobrien if (feof(cfile) || ferror(cfile)) 28679971Sobrien return (0); 28779971Sobrien while ((c = getc(cfile)) != EOF && 28879971Sobrien (c == '\n' || c == '\t' || c == ' ' || c == ',')) 28979971Sobrien continue; 29079971Sobrien if (c == EOF) 29179971Sobrien return (0); 29279971Sobrien cp = tokval; 29379971Sobrien if (c == '"') { 29479971Sobrien while ((c = getc(cfile)) != EOF && c != '"') { 29579971Sobrien if (c == '\\') 296223328Sgavin if ((c = getc(cfile)) == EOF) 297223328Sgavin break; 29879971Sobrien *cp++ = c; 299223328Sgavin if (cp == tokval + sizeof(tokval)) { 300223328Sgavin warnx("Token in .netrc too long"); 301223328Sgavin return (-1); 302223328Sgavin } 30379971Sobrien } 30479971Sobrien } else { 30579971Sobrien *cp++ = c; 30679971Sobrien while ((c = getc(cfile)) != EOF 30779971Sobrien && c != '\n' && c != '\t' && c != ' ' && c != ',') { 30879971Sobrien if (c == '\\') 309223328Sgavin if ((c = getc(cfile)) == EOF) 310223328Sgavin break; 31179971Sobrien *cp++ = c; 312223328Sgavin if (cp == tokval + sizeof(tokval)) { 313223328Sgavin warnx("Token in .netrc too long"); 314223328Sgavin return (-1); 315223328Sgavin } 31679971Sobrien } 31779971Sobrien } 31879971Sobrien *cp = 0; 31979971Sobrien if (tokval[0] == 0) 32079971Sobrien return (0); 32179971Sobrien for (t = toktab; t->tokstr; t++) 32279971Sobrien if (!strcmp(t->tokstr, tokval)) 32379971Sobrien return (t->tval); 32479971Sobrien return (ID); 32579971Sobrien} 326