1 /* $NetBSD: ruserpass.c,v 1.8 2007/08/06 04:33:24 lukem Exp $ */ 2 /* from NetBSD: ruserpass.c,v 1.33 2007/04/17 05:52:04 lukem Exp */ 3 4 /* 5 * Copyright (c) 1985, 1993, 1994 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include "tnftp.h" 34 35 #if 0 /* tnftp */ 36 37 #include <sys/cdefs.h> 38 #ifndef lint 39 #if 0 40 static char sccsid[] = "@(#)ruserpass.c 8.4 (Berkeley) 4/27/95"; 41 #else 42 __RCSID(" NetBSD: ruserpass.c,v 1.33 2007/04/17 05:52:04 lukem Exp "); 43 #endif 44 #endif /* not lint */ 45 46 #include <sys/types.h> 47 #include <sys/stat.h> 48 49 #include <ctype.h> 50 #include <err.h> 51 #include <errno.h> 52 #include <netdb.h> 53 #include <stdio.h> 54 #include <stdlib.h> 55 #include <string.h> 56 #include <unistd.h> 57 58 #endif /* tnftp */ 59 60 #include "ftp_var.h" 61 62 static int token(void); 63 static FILE *cfile; 64 65 #define DEFAULT 1 66 #define LOGIN 2 67 #define PASSWD 3 68 #define ACCOUNT 4 69 #define MACDEF 5 70 #define ID 10 71 #define MACH 11 72 73 static char tokval[100]; 74 75 static struct toktab { 76 const char *tokstr; 77 int tval; 78 } toktab[] = { 79 { "default", DEFAULT }, 80 { "login", LOGIN }, 81 { "password", PASSWD }, 82 { "passwd", PASSWD }, 83 { "account", ACCOUNT }, 84 { "machine", MACH }, 85 { "macdef", MACDEF }, 86 { NULL, 0 } 87 }; 88 89 int 90 ruserpass(const char *host, char **aname, char **apass, char **aacct) 91 { 92 char *tmp; 93 const char *mydomain; 94 char myname[MAXHOSTNAMELEN + 1]; 95 int t, i, c, usedefault = 0; 96 struct stat stb; 97 98 if (netrc[0] == '\0') 99 return (0); 100 cfile = fopen(netrc, "r"); 101 if (cfile == NULL) { 102 if (errno != ENOENT) 103 warn("Can't read `%s'", netrc); 104 return (0); 105 } 106 if (gethostname(myname, sizeof(myname)) < 0) 107 myname[0] = '\0'; 108 myname[sizeof(myname) - 1] = '\0'; 109 if ((mydomain = strchr(myname, '.')) == NULL) 110 mydomain = ""; 111 next: 112 while ((t = token()) > 0) switch(t) { 113 114 case DEFAULT: 115 usedefault = 1; 116 /* FALL THROUGH */ 117 118 case MACH: 119 if (!usedefault) { 120 if ((t = token()) == -1) 121 goto bad; 122 if (t != ID) 123 continue; 124 /* 125 * Allow match either for user's input host name 126 * or official hostname. Also allow match of 127 * incompletely-specified host in local domain. 128 */ 129 if (strcasecmp(host, tokval) == 0) 130 goto match; 131 if (strcasecmp(hostname, tokval) == 0) 132 goto match; 133 if ((tmp = strchr(hostname, '.')) != NULL && 134 strcasecmp(tmp, mydomain) == 0 && 135 strncasecmp(hostname, tokval, tmp-hostname) == 0 && 136 tokval[tmp - hostname] == '\0') 137 goto match; 138 if ((tmp = strchr(host, '.')) != NULL && 139 strcasecmp(tmp, mydomain) == 0 && 140 strncasecmp(host, tokval, tmp - host) == 0 && 141 tokval[tmp - host] == '\0') 142 goto match; 143 continue; 144 } 145 match: 146 while ((t = token()) > 0 && 147 t != MACH && t != DEFAULT) switch(t) { 148 149 case LOGIN: 150 if ((t = token()) == -1) 151 goto bad; 152 if (t) { 153 if (*aname == NULL) 154 *aname = ftp_strdup(tokval); 155 else { 156 if (strcmp(*aname, tokval)) 157 goto next; 158 } 159 } 160 break; 161 case PASSWD: 162 if ((*aname == NULL || strcmp(*aname, "anonymous")) && 163 fstat(fileno(cfile), &stb) >= 0 && 164 (stb.st_mode & 077) != 0) { 165 warnx("Error: .netrc file is readable by others"); 166 warnx("Remove password or make file unreadable by others"); 167 goto bad; 168 } 169 if ((t = token()) == -1) 170 goto bad; 171 if (t && *apass == NULL) 172 *apass = ftp_strdup(tokval); 173 break; 174 case ACCOUNT: 175 if (fstat(fileno(cfile), &stb) >= 0 176 && (stb.st_mode & 077) != 0) { 177 warnx("Error: .netrc file is readable by others"); 178 warnx("Remove account or make file unreadable by others"); 179 goto bad; 180 } 181 if ((t = token()) == -1) 182 goto bad; 183 if (t && *aacct == NULL) 184 *aacct = ftp_strdup(tokval); 185 break; 186 case MACDEF: 187 if (proxy) { 188 (void)fclose(cfile); 189 return (0); 190 } 191 while ((c = getc(cfile)) != EOF) 192 if (c != ' ' && c != '\t') 193 break; 194 if (c == EOF || c == '\n') { 195 fputs("Missing macdef name argument.\n", 196 ttyout); 197 goto bad; 198 } 199 if (macnum == 16) { 200 fputs( 201 "Limit of 16 macros have already been defined.\n", 202 ttyout); 203 goto bad; 204 } 205 tmp = macros[macnum].mac_name; 206 *tmp++ = c; 207 for (i = 0; i < 8 && (c = getc(cfile)) != EOF && 208 !isspace(c); ++i) { 209 *tmp++ = c; 210 } 211 if (c == EOF) { 212 fputs( 213 "Macro definition missing null line terminator.\n", 214 ttyout); 215 goto bad; 216 } 217 *tmp = '\0'; 218 if (c != '\n') { 219 while ((c = getc(cfile)) != EOF && c != '\n'); 220 } 221 if (c == EOF) { 222 fputs( 223 "Macro definition missing null line terminator.\n", 224 ttyout); 225 goto bad; 226 } 227 if (macnum == 0) { 228 macros[macnum].mac_start = macbuf; 229 } 230 else { 231 macros[macnum].mac_start = 232 macros[macnum-1].mac_end + 1; 233 } 234 tmp = macros[macnum].mac_start; 235 while (tmp != macbuf + 4096) { 236 if ((c = getc(cfile)) == EOF) { 237 fputs( 238 "Macro definition missing null line terminator.\n", 239 ttyout); 240 goto bad; 241 } 242 *tmp = c; 243 if (*tmp == '\n') { 244 if (tmp == macros[macnum].mac_start) { 245 macros[macnum++].mac_end = tmp; 246 break; 247 } else if (*(tmp - 1) == '\0') { 248 macros[macnum++].mac_end = 249 tmp - 1; 250 break; 251 } 252 *tmp = '\0'; 253 } 254 tmp++; 255 } 256 if (tmp == macbuf + 4096) { 257 fputs("4K macro buffer exceeded.\n", 258 ttyout); 259 goto bad; 260 } 261 break; 262 default: 263 warnx("Unknown .netrc keyword `%s'", tokval); 264 break; 265 } 266 goto done; 267 } 268 done: 269 if (t == -1) 270 goto bad; 271 (void)fclose(cfile); 272 return (0); 273 bad: 274 (void)fclose(cfile); 275 return (-1); 276 } 277 278 static int 279 token(void) 280 { 281 char *cp; 282 int c; 283 struct toktab *t; 284 285 if (feof(cfile) || ferror(cfile)) 286 return (0); 287 while ((c = getc(cfile)) != EOF && 288 (c == '\n' || c == '\t' || c == ' ' || c == ',')) 289 continue; 290 if (c == EOF) 291 return (0); 292 cp = tokval; 293 if (c == '"') { 294 while ((c = getc(cfile)) != EOF && c != '"') { 295 if (c == '\\') 296 if ((c = getc(cfile)) == EOF) 297 break; 298 *cp++ = c; 299 if (cp == tokval + sizeof(tokval)) { 300 warnx("Token in .netrc too long"); 301 return (-1); 302 } 303 } 304 } else { 305 *cp++ = c; 306 while ((c = getc(cfile)) != EOF 307 && c != '\n' && c != '\t' && c != ' ' && c != ',') { 308 if (c == '\\') 309 if ((c = getc(cfile)) == EOF) 310 break; 311 *cp++ = c; 312 if (cp == tokval + sizeof(tokval)) { 313 warnx("Token in .netrc too long"); 314 return (-1); 315 } 316 } 317 } 318 *cp = 0; 319 if (tokval[0] == 0) 320 return (0); 321 for (t = toktab; t->tokstr; t++) 322 if (!strcmp(t->tokstr, tokval)) 323 return (t->tval); 324 return (ID); 325 } 326