"SfR Fresh" - the SfR Freeware/Shareware Archive

Member "slirp-1.0.16/src/ppp/auth.c" of archive slirp-1.0.16.tar.gz:


As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
    1 /*
    2  * auth.c - PPP authentication and phase control.
    3  *
    4  * Copyright (c) 1993 The Australian National University.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms are permitted
    8  * provided that the above copyright notice and this paragraph are
    9  * duplicated in all such forms and that any documentation,
   10  * advertising materials, and other materials related to such
   11  * distribution and use acknowledge that the software was developed
   12  * by the Australian National University.  The name of the University
   13  * may not be used to endorse or promote products derived from this
   14  * software without specific prior written permission.
   15  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
   17  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
   18  *
   19  * Copyright (c) 1989 Carnegie Mellon University.
   20  * All rights reserved.
   21  *
   22  * Redistribution and use in source and binary forms are permitted
   23  * provided that the above copyright notice and this paragraph are
   24  * duplicated in all such forms and that any documentation,
   25  * advertising materials, and other materials related to such
   26  * distribution and use acknowledge that the software was developed
   27  * by Carnegie Mellon University.  The name of the
   28  * University may not be used to endorse or promote products derived
   29  * from this software without specific prior written permission.
   30  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
   31  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
   32  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
   33  */
   34 
   35 #ifndef lint
   36 static char rcsid[] = "$Id: auth.c,v 1.15 1995/05/19 03:16:12 paulus Exp $";
   37 #endif
   38 
   39 #include <stdio.h>
   40 #include <stddef.h>
   41 /* #include <stdlib.h> */
   42 #include <syslog.h>
   43 #include <pwd.h>
   44 #include <string.h>
   45 #include <sys/types.h>
   46 #include <sys/stat.h>
   47 
   48 #ifdef HAS_SHADOW
   49 #include <shadow.h>
   50 #include <shadow/pwauth.h>
   51 #ifndef PW_PPP
   52 #define PW_PPP PW_LOGIN
   53 #endif
   54 #endif
   55 
   56 #include "pppd.h"
   57 #include "fsm.h"
   58 #include "lcp.h"
   59 #include "upap.h"
   60 #include "chap.h"
   61 #include "ipcp.h"
   62 #include "ccp.h"
   63 #include "pathnames.h"
   64 
   65 #if defined(sun) && defined(sparc)
   66 #include <alloca.h>
   67 #endif /*sparc*/
   68 
   69 extern char *crypt _P((const char *, const char *));
   70 
   71 /* Used for storing a sequence of words.  Usually malloced. */
   72 struct wordlist {
   73     struct wordlist	*next;
   74     char		word[1];
   75 };
   76 
   77 /* Bits in scan_authfile return value */
   78 #define NONWILD_SERVER	1
   79 #define NONWILD_CLIENT	2
   80 
   81 #define ISWILD(word)	(word[0] == '*' && word[1] == 0)
   82 
   83 #undef FALSE
   84 #define FALSE	0
   85 #undef TRUE
   86 #define TRUE	1
   87 
   88 #ifndef IN_LOOPBACKNET
   89 #define IN_LOOPBACKNET 127
   90 #endif
   91 
   92 #ifndef IN_MULTICAST
   93 #define IN_MULTICAST(i) (((long)(i) & 0xf0000000) == 0xe0000000)
   94 #endif
   95 
   96 #ifndef IN_BADCLASS
   97 #define IN_BADCLASS(i) (((long)(i) & 0xf0000000) == 0xf0000000)
   98 #endif
   99 
  100 /* Records which authentication operations haven't completed yet. */
  101 static int auth_pending[NUM_PPP];
  102 static int logged_in;
  103 static struct wordlist *addresses[NUM_PPP];
  104 
  105 /* Bits in auth_pending[] */
  106 #define UPAP_WITHPEER	1
  107 #define UPAP_PEER	2
  108 #define CHAP_WITHPEER	4
  109 #define CHAP_PEER	8
  110 
  111 /* Prototypes */
  112 void check_access __P((FILE *, char *));
  113 
  114 static void network_phase __P((int));
  115 static int  login __P((char *, char *, char **, int *));
  116 static void logout __P((void));
  117 static int  null_login __P((int));
  118 static int  get_upap_passwd __P((void));
  119 static int  have_upap_secret __P((void));
  120 static int  have_chap_secret __P((char *, char *));
  121 static int  scan_authfile __P((FILE *, char *, char *, char *, int,
  122 				  struct wordlist **, char *));
  123 static void free_wordlist __P((struct wordlist *));
  124 
  125 /*
  126  * An Open on LCP has requested a change from Dead to Establish phase.
  127  * Do what's necessary to bring the physical layer up.
  128  */
  129 void
  130 link_required(unit)
  131     int unit;
  132 {
  133 }
  134 
  135 /*
  136  * LCP has terminated the link; go to the Dead phase and take the
  137  * physical layer down.
  138  */
  139 void
  140 link_terminated(unit)
  141     int unit;
  142 {
  143     if (phase == PHASE_DEAD)
  144 	return;
  145     if (logged_in)
  146 	logout();
  147     phase = PHASE_DEAD;
  148     do_syslog(LOG_NOTICE, "Connection terminated.");
  149     if (ppp_exit)
  150 	slirp_exit(0);
  151 }
  152 
  153 /*
  154  * LCP has gone down; it will either die or try to re-establish.
  155  */
  156 void
  157 link_down(unit)
  158     int unit;
  159 {
  160     ipcp_close(0);
  161     ccp_close(0);
  162     phase = PHASE_TERMINATE;
  163 }
  164 
  165 /*
  166  * The link is established.
  167  * Proceed to the Dead, Authenticate or Network phase as appropriate.
  168  */
  169 void
  170 link_established(unit)
  171     int unit;
  172 {
  173     int auth;
  174     lcp_options *wo = &lcp_wantoptions[unit];
  175     lcp_options *go = &lcp_gotoptions[unit];
  176     lcp_options *ho = &lcp_hisoptions[unit];
  177 
  178     if (auth_required && !(go->neg_chap || go->neg_upap)) {
  179 	/*
  180 	 * We wanted the peer to authenticate itself, and it refused:
  181 	 * treat it as though it authenticated with PAP using a username
  182 	 * of "" and a password of "".  If that's not OK, boot it out.
  183 	 */
  184 	if (!wo->neg_upap || !null_login(unit)) {
  185 	    do_syslog(LOG_WARNING, "peer refused to authenticate");
  186 	    lcp_close(unit);
  187 	    phase = PHASE_TERMINATE;
  188 	    return;
  189 	}
  190     }
  191 
  192     phase = PHASE_AUTHENTICATE;
  193     auth = 0;
  194     if (go->neg_chap) {
  195 	ChapAuthPeer(unit, our_name, go->chap_mdtype);
  196 	auth |= CHAP_PEER;
  197     } else if (go->neg_upap) {
  198 	upap_authpeer(unit);
  199 	auth |= UPAP_PEER;
  200     }
  201     if (ho->neg_chap) {
  202 	ChapAuthWithPeer(unit, our_name, ho->chap_mdtype);
  203 	auth |= CHAP_WITHPEER;
  204     } else if (ho->neg_upap) {
  205 	upap_authwithpeer(unit, user, passwd);
  206 	auth |= UPAP_WITHPEER;
  207     }
  208     auth_pending[unit] = auth;
  209 
  210     if (!auth)
  211 	network_phase(unit);
  212 }
  213 
  214 /*
  215  * Proceed to the network phase.
  216  */
  217 static void
  218 network_phase(unit)
  219     int unit;
  220 {
  221     phase = PHASE_NETWORK;
  222     ipcp_open(unit);
  223     ccp_open(unit);
  224 }
  225 
  226 /*
  227  * The peer has failed to authenticate himself using `protocol'.
  228  */
  229 void
  230 auth_peer_fail(unit, protocol)
  231     int unit, protocol;
  232 {
  233     /*
  234      * Authentication failure: take the link down
  235      */
  236     lcp_close(unit);
  237     phase = PHASE_TERMINATE;
  238 }
  239 
  240 /*
  241  * The peer has been successfully authenticated using `protocol'.
  242  */
  243 void
  244 auth_peer_success(unit, protocol)
  245     int unit, protocol;
  246 {
  247     int bit;
  248 
  249     switch (protocol) {
  250     case PPP_CHAP:
  251 	bit = CHAP_PEER;
  252 	break;
  253     case PPP_PAP:
  254 	bit = UPAP_PEER;
  255 	break;
  256     default:
  257 	do_syslog(LOG_WARNING, "auth_peer_success: unknown protocol %x",
  258 	       protocol);
  259 	return;
  260     }
  261 
  262     /*
  263      * If there is no more authentication still to be done,
  264      * proceed to the network phase.
  265      */
  266     if ((auth_pending[unit] &= ~bit) == 0) {
  267 	phase = PHASE_NETWORK;
  268 	ipcp_open(unit);
  269 	ccp_open(unit);
  270     }
  271 }
  272 
  273 /*
  274  * We have failed to authenticate ourselves to the peer using `protocol'.
  275  */
  276 void
  277 auth_withpeer_fail(unit, protocol)
  278     int unit, protocol;
  279 {
  280     /*
  281      * We've failed to authenticate ourselves to our peer.
  282      * He'll probably take the link down, and there's not much
  283      * we can do except wait for that.
  284      */
  285 }
  286 
  287 /*
  288  * We have successfully authenticated ourselves with the peer using `protocol'.
  289  */
  290 void
  291 auth_withpeer_success(unit, protocol)
  292     int unit, protocol;
  293 {
  294     int bit;
  295 
  296     switch (protocol) {
  297     case PPP_CHAP:
  298 	bit = CHAP_WITHPEER;
  299 	break;
  300     case PPP_PAP:
  301 	bit = UPAP_WITHPEER;
  302 	break;
  303     default:
  304 	do_syslog(LOG_WARNING, "auth_peer_success: unknown protocol %x",
  305 	       protocol);
  306 	bit = 0;
  307     }
  308 
  309     /*
  310      * If there is no more authentication still being done,
  311      * proceed to the network phase.
  312      */
  313     if ((auth_pending[unit] &= ~bit) == 0)
  314 	network_phase(unit);
  315 }
  316 
  317 
  318 /*
  319  * check_auth_options - called to check authentication options.
  320  */
  321 void
  322 check_auth_options()
  323 {
  324     lcp_options *wo = &lcp_wantoptions[0];
  325     lcp_options *ao = &lcp_allowoptions[0];
  326 
  327     /* Default our_name to hostname, and user to our_name */
  328     if (our_name[0] == 0 || usehostname)
  329 	strncpy2(our_name, hostname, sizeof(our_name));
  330     if (user[0] == 0)
  331 	strncpy2(user, our_name, sizeof(user));
  332 
  333     /* If authentication is required, ask peer for CHAP or PAP. */
  334     if (auth_required && !wo->neg_chap && !wo->neg_upap) {
  335 	wo->neg_chap = 1;
  336 	wo->neg_upap = 1;
  337     }
  338 
  339     /*
  340      * Check whether we have appropriate secrets to use
  341      * to authenticate ourselves and/or the peer.
  342      */
  343     if (ao->neg_upap && passwd[0] == 0 && !get_upap_passwd())
  344 	ao->neg_upap = 0;
  345     if (wo->neg_upap && !uselogin && !have_upap_secret())
  346 	wo->neg_upap = 0;
  347     if (ao->neg_chap && !have_chap_secret(our_name, remote_name))
  348 	ao->neg_chap = 0;
  349     if (wo->neg_chap && !have_chap_secret(remote_name, our_name))
  350 	wo->neg_chap = 0;
  351 
  352     if (auth_required && !wo->neg_chap && !wo->neg_upap) {
  353 	fprintf(stderr, "\
  354 pppd: peer authentication required but no authentication files accessible\n");
  355 	exit(1);
  356     }
  357 
  358 }
  359 
  360 
  361 /*
  362  * check_passwd - Check the user name and passwd against the PAP secrets
  363  * file.  If requested, also check against the system password database,
  364  * and login the user if OK.
  365  *
  366  * returns:
  367  *	UPAP_AUTHNAK: Authentication failed.
  368  *	UPAP_AUTHACK: Authentication succeeded.
  369  * In either case, msg points to an appropriate message.
  370  */
  371 int
  372 check_passwd(unit, auser, userlen, apasswd, passwdlen, msg, msglen)
  373     int unit;
  374     char *auser;
  375     int userlen;
  376     char *apasswd;
  377     int passwdlen;
  378     char **msg;
  379     int *msglen;
  380 {
  381     int ret;
  382     char *filename;
  383     FILE *f;
  384     struct wordlist *addrs;
  385     char passwd[256], user[256];
  386     char secret[MAXWORDLEN];
  387     static int attempts = 0;
  388 
  389     /*
  390      * Make copies of apasswd and auser, then null-terminate them.
  391      */
  392     BCOPY(apasswd, passwd, passwdlen);
  393     passwd[passwdlen] = '\0';
  394     BCOPY(auser, user, userlen);
  395     user[userlen] = '\0';
  396 
  397     /*
  398      * Open the file of upap secrets and scan for a suitable secret
  399      * for authenticating this user.
  400      */
  401     filename = _PATH_UPAPFILE;
  402     addrs = NULL;
  403     ret = UPAP_AUTHACK;
  404     f = fopen(filename, "r");
  405     if (f == NULL) {
  406 	if (!uselogin) {
  407 	    do_syslog(LOG_ERR, "Can't open upap password file %s: %m", filename);
  408 	    ret = UPAP_AUTHNAK;
  409 	}
  410 
  411     } else {
  412 	check_access(f, filename);
  413 	if (scan_authfile(f, user, our_name, secret, sizeof(secret), &addrs, filename) < 0
  414 	    || (secret[0] != 0 && (cryptpap || strcmp(passwd, secret) != 0)
  415 		&& strcmp(crypt(passwd, secret), secret) != 0)) {
  416 	    do_syslog(LOG_WARNING, "upap authentication failure for %s", user);
  417 	    ret = UPAP_AUTHNAK;
  418 	}
  419 	fclose(f);
  420     }
  421 
  422     if (uselogin && ret == UPAP_AUTHACK) {
  423 	ret = login(user, passwd, msg, msglen);
  424 	if (ret == UPAP_AUTHNAK) {
  425 	    do_syslog(LOG_WARNING, "upap login failure for %s", user);
  426 	}
  427     }
  428 
  429     if (ret == UPAP_AUTHNAK) {
  430 	*msg = "Login incorrect";
  431 	*msglen = strlen(*msg);
  432 	/*
  433 	 * Frustrate passwd stealer programs.
  434 	 * Allow 10 tries, but start backing off after 3 (stolen from login).
  435 	 * On 10'th, drop the connection.
  436 	 */
  437 	if (attempts++ >= 10) {
  438 	    do_syslog(LOG_WARNING, "%d LOGIN FAILURES ON %s, %s",
  439 		   attempts, devnam, user);
  440 	    quit();
  441 	}
  442 	if (attempts > 3)
  443 	    sleep((u_int) (attempts - 3) * 5);
  444 	if (addrs != NULL)
  445 	    free_wordlist(addrs);
  446 
  447     } else {
  448 	attempts = 0;			/* Reset count */
  449 	*msg = "Login ok";
  450 	*msglen = strlen(*msg);
  451 	if (addresses[unit] != NULL)
  452 	    free_wordlist(addresses[unit]);
  453 	addresses[unit] = addrs;
  454     }
  455 
  456     return ret;
  457 }
  458 
  459 
  460 /*
  461  * login - Check the user name and password against the system
  462  * password database, and login the user if OK.
  463  *
  464  * returns:
  465  *	UPAP_AUTHNAK: Login failed.
  466  *	UPAP_AUTHACK: Login succeeded.
  467  * In either case, msg points to an appropriate message.
  468  */
  469 static int
  470 login(user, passwd, msg, msglen)
  471     char *user;
  472     char *passwd;
  473     char **msg;
  474     int *msglen;
  475 {
  476     struct passwd *pw;
  477     char *epasswd;
  478     char *tty;
  479 
  480 #ifdef HAS_SHADOW
  481     struct spwd *spwd;
  482     struct spwd *getspnam();
  483 #endif
  484 
  485     if ((pw = getpwnam(user)) == NULL) {
  486 	return (UPAP_AUTHNAK);
  487     }
  488 
  489 #ifdef HAS_SHADOW
  490     if ((spwd = getspnam(user)) == NULL) {
  491         pw->pw_passwd = "";
  492     } else {
  493 	pw->pw_passwd = spwd->sp_pwdp;
  494     }
  495 #endif
  496 
  497     /*
  498      * XXX If no passwd, let them login without one.
  499      */
  500     if (pw->pw_passwd == '\0') {
  501 	return (UPAP_AUTHACK);
  502     }
  503 
  504 #ifdef HAS_SHADOW
  505     if ((pw->pw_passwd && pw->pw_passwd[0] == '@'
  506 	 && pw_auth (pw->pw_passwd+1, pw->pw_name, PW_PPP, NULL))
  507 	|| !valid (passwd, pw)) {
  508 	return (UPAP_AUTHNAK);
  509     }
  510 #else
  511     epasswd = crypt(passwd, pw->pw_passwd);
  512     if (strcmp(epasswd, pw->pw_passwd)) {
  513 	return (UPAP_AUTHNAK);
  514     }
  515 #endif
  516 
  517     do_syslog(LOG_INFO, "user %s logged in", user);
  518 
  519     /*
  520      * Write a wtmp entry for this user.
  521      */
  522     tty = strrchr(devnam, '/');
  523     if (tty == NULL)
  524 	tty = devnam;
  525     else
  526 	tty++;
  527 #ifdef LOGWTMP_WORKED
  528     logwtmp(tty, user, "");   /* Add wtmp login entry -- which just returned 1 */
  529 #endif
  530     logged_in = TRUE;
  531 
  532     return (UPAP_AUTHACK);
  533 }
  534 
  535 /*
  536  * logout - Logout the user.
  537  */
  538 static void
  539 logout()
  540 {
  541     char *tty;
  542 
  543     tty = strrchr(devnam, '/');
  544     if (tty == NULL)
  545 	tty = devnam;
  546     else
  547 	tty++;
  548 #ifdef LOGWTMP_WORKED
  549     logwtmp(tty, "", "");	/*	Wipe out wtmp logout entry  */
  550 #endif
  551     logged_in = FALSE;
  552 }
  553 
  554 
  555 /*
  556  * null_login - Check if a username of "" and a password of "" are
  557  * acceptable, and iff so, set the list of acceptable IP addresses
  558  * and return 1.
  559  */
  560 static int
  561 null_login(unit)
  562     int unit;
  563 {
  564     char *filename;
  565     FILE *f;
  566     int i, ret;
  567     struct wordlist *addrs;
  568     char secret[MAXWORDLEN];
  569 
  570     /*
  571      * Open the file of upap secrets and scan for a suitable secret.
  572      * We don't accept a wildcard client.
  573      */
  574     filename = _PATH_UPAPFILE;
  575     addrs = NULL;
  576     f = fopen(filename, "r");
  577     if (f == NULL)
  578 	return 0;
  579     check_access(f, filename);
  580 
  581     i = scan_authfile(f, "", our_name, secret, sizeof(secret), &addrs, filename);
  582     ret = i >= 0 && (i & NONWILD_CLIENT) != 0 && secret[0] == 0;
  583 
  584     if (ret) {
  585 	if (addresses[unit] != NULL)
  586 	    free_wordlist(addresses[unit]);
  587 	addresses[unit] = addrs;
  588     }
  589 
  590     fclose(f);
  591     return ret;
  592 }
  593 
  594 
  595 /*
  596  * get_upap_passwd - get a password for authenticating ourselves with
  597  * our peer using PAP.  Returns 1 on success, 0 if no suitable password
  598  * could be found.
  599  */
  600 static int
  601 get_upap_passwd()
  602 {
  603     char *filename;
  604     FILE *f;
  605     struct wordlist *addrs;
  606     char secret[MAXWORDLEN];
  607 
  608     filename = _PATH_UPAPFILE;
  609     addrs = NULL;
  610     f = fopen(filename, "r");
  611     if (f == NULL)
  612 	return 0;
  613     check_access(f, filename);
  614     if (scan_authfile(f, user, remote_name, secret, sizeof(secret), NULL, filename) < 0)
  615 	return 0;
  616     strncpy(passwd, secret, MAXSECRETLEN);
  617     passwd[MAXSECRETLEN-1] = 0;
  618     return 1;
  619 }
  620 
  621 
  622 /*
  623  * have_upap_secret - check whether we have a PAP file with any
  624  * secrets that we could possibly use for authenticating the peer.
  625  */
  626 static int
  627 have_upap_secret()
  628 {
  629     FILE *f;
  630     int ret;
  631     char *filename;
  632 
  633     filename = _PATH_UPAPFILE;
  634     f = fopen(filename, "r");
  635     if (f == NULL)
  636 	return 0;
  637 
  638     ret = scan_authfile(f, NULL, our_name, NULL, 0, NULL, filename);
  639     fclose(f);
  640     if (ret < 0)
  641 	return 0;
  642 
  643     return 1;
  644 }
  645 
  646 
  647 /*
  648  * have_chap_secret - check whether we have a CHAP file with a
  649  * secret that we could possibly use for authenticating `client'
  650  * on `server'.  Either can be the null string, meaning we don't
  651  * know the identity yet.
  652  */
  653 static int
  654 have_chap_secret(client, server)
  655     char *client;
  656     char *server;
  657 {
  658     FILE *f;
  659     int ret;
  660     char *filename;
  661 
  662     filename = _PATH_CHAPFILE;
  663     f = fopen(filename, "r");
  664     if (f == NULL)
  665 	return 0;
  666 
  667     if (client[0] == 0)
  668 	client = NULL;
  669     else if (server[0] == 0)
  670 	server = NULL;
  671 
  672     ret = scan_authfile(f, client, server, NULL, 0, NULL, filename);
  673     fclose(f);
  674     if (ret < 0)
  675 	return 0;
  676 
  677     return 1;
  678 }
  679 
  680 
  681 /*
  682  * get_secret - open the CHAP secret file and return the secret
  683  * for authenticating the given client on the given server.
  684  * (We could be either client or server).
  685  */
  686 int
  687 get_secret(unit, client, server, secret, secret_len, save_addrs)
  688     int unit;
  689     char *client;
  690     char *server;
  691     char *secret;
  692     int *secret_len;
  693     int save_addrs;
  694 {
  695     FILE *f;
  696     int ret, len;
  697     char *filename;
  698     struct wordlist *addrs;
  699     char secbuf[MAXWORDLEN];
  700 
  701     filename = _PATH_CHAPFILE;
  702     addrs = NULL;
  703     secbuf[0] = 0;
  704 
  705     f = fopen(filename, "r");
  706     if (f == NULL) {
  707 	do_syslog(LOG_ERR, "Can't open chap secret file %s: %m", filename);
  708 	return 0;
  709     }
  710     check_access(f, filename);
  711 
  712     ret = scan_authfile(f, client, server, secbuf, sizeof(secbuf), &addrs, filename);
  713     fclose(f);
  714     if (ret < 0)
  715 	return 0;
  716 
  717     if (save_addrs) {
  718 	if (addresses[unit] != NULL)
  719 	    free_wordlist(addresses[unit]);
  720 	addresses[unit] = addrs;
  721     }
  722 
  723     len = strlen(secbuf);
  724     if (len > MAXSECRETLEN) {
  725 	do_syslog(LOG_ERR, "Secret for %s on %s is too long", client, server);
  726 	len = MAXSECRETLEN;
  727     }
  728     BCOPY(secbuf, secret, len);
  729     *secret_len = len;
  730 
  731     return 1;
  732 }
  733 
  734 /*
  735  * auth_ip_addr - check whether the peer is authorized to use
  736  * a given IP address.  Returns 1 if authorized, 0 otherwise.
  737  */
  738 int
  739 auth_ip_addr(unit, addr)
  740     int unit;
  741     u_int32_t addr;
  742 {
  743     u_int32_t a;
  744     struct hostent *hp;
  745     struct wordlist *addrs;
  746 
  747     /* don't allow loopback or multicast address */
  748     if (bad_ip_adrs(addr))
  749 	return 0;
  750 
  751     if ((addrs = addresses[unit]) == NULL)
  752 	return 1;		/* no restriction */
  753 
  754     for (; addrs != NULL; addrs = addrs->next) {
  755 	/* "-" means no addresses authorized */
  756 	if (strcmp(addrs->word, "-") == 0)
  757 	    break;
  758 	if ((a = inet_addr(addrs->word)) == -1) {
  759 	    if ((hp = gethostbyname(addrs->word)) == NULL) {
  760 		do_syslog(LOG_WARNING, "unknown host %s in auth. address list",
  761 		       addrs->word);
  762 		continue;
  763 	    } else
  764 		a = *(u_int32_t *)hp->h_addr;
  765 	}
  766 	if (addr == a)
  767 	    return 1;
  768     }
  769     return 0;			/* not in list => can't have it */
  770 }
  771 
  772 /*
  773  * bad_ip_adrs - return 1 if the IP address is one we don't want
  774  * to use, such as an address in the loopback net or a multicast address.
  775  * addr is in network byte order.
  776  */
  777 int
  778 bad_ip_adrs(addr)
  779     u_int32_t addr;
  780 {
  781     addr = ntohl(addr);
  782     return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET
  783 	|| IN_MULTICAST(addr) || IN_BADCLASS(addr);
  784 }
  785 
  786 /*
  787  * check_access - complain if a secret file has too-liberal permissions.
  788  */
  789 void
  790 check_access(f, filename)
  791     FILE *f;
  792     char *filename;
  793 {
  794     struct stat sbuf;
  795 
  796     if (fstat(fileno(f), &sbuf) < 0) {
  797 	do_syslog(LOG_WARNING, "cannot stat secret file %s: %m", filename);
  798     } else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) {
  799 	do_syslog(LOG_WARNING, "Warning - secret file %s has world and/or group access", filename);
  800     }
  801 }
  802 
  803 
  804 /*
  805  * scan_authfile - Scan an authorization file for a secret suitable
  806  * for authenticating `client' on `server'.  The return value is -1
  807  * if no secret is found, otherwise >= 0.  The return value has
  808  * NONWILD_CLIENT set if the secret didn't have "*" for the client, and
  809  * NONWILD_SERVER set if the secret didn't have "*" for the server.
  810  * Any following words on the line (i.e. address authorization
  811  * info) are placed in a wordlist and returned in *addrs.
  812  */
  813 static int
  814 scan_authfile(f, client, server, secret, max_secret, addrs, filename)
  815     FILE *f;
  816     char *client;
  817     char *server;
  818     char *secret;
  819     int max_secret;
  820     struct wordlist **addrs;
  821     char *filename;
  822 {
  823     int newline, xxx;
  824     int got_flag, best_flag;
  825     FILE *sf;
  826     struct wordlist *ap, *addr_list, *addr_last;
  827     char word[MAXWORDLEN];
  828     char atfile[MAXWORDLEN];
  829 
  830     if (addrs != NULL)
  831 	*addrs = NULL;
  832     addr_list = NULL;
  833     if (!getword(f, word, &newline, filename))
  834 	return -1;		/* file is empty??? */
  835     newline = 1;
  836     best_flag = -1;
  837     for (;;) {
  838 	/*
  839 	 * Skip until we find a word at the start of a line.
  840 	 */
  841 	while (!newline && getword(f, word, &newline, filename))
  842 	    ;
  843 	if (!newline)
  844 	    break;		/* got to end of file */
  845 
  846 	/*
  847 	 * Got a client - check if it's a match or a wildcard.
  848 	 */
  849 	got_flag = 0;
  850 	if (client != NULL && strcmp(word, client) != 0 && !ISWILD(word)) {
  851 	    newline = 0;
  852 	    continue;
  853 	}
  854 	if (!ISWILD(word))
  855 	    got_flag = NONWILD_CLIENT;
  856 
  857 	/*
  858 	 * Now get a server and check if it matches.
  859 	 */
  860 	if (!getword(f, word, &newline, filename))
  861 	    break;
  862 	if (newline)
  863 	    continue;
  864 	if (server != NULL && strcmp(word, server) != 0 && !ISWILD(word))
  865 	    continue;
  866 	if (!ISWILD(word))
  867 	    got_flag |= NONWILD_SERVER;
  868 
  869 	/*
  870 	 * Got some sort of a match - see if it's better than what
  871 	 * we have already.
  872 	 */
  873 	if (got_flag <= best_flag)
  874 	    continue;
  875 
  876 	/*
  877 	 * Get the secret.
  878 	 */
  879 	if (!getword(f, word, &newline, filename))
  880 	    break;
  881 	if (newline)
  882 	    continue;
  883 
  884 	/*
  885 	 * Special syntax: @filename means read secret from file.
  886 	 */
  887 	if (word[0] == '@') {
  888 	    strncpy2(atfile, word+1, sizeof(atfile));
  889 	    if ((sf = fopen(atfile, "r")) == NULL) {
  890 		do_syslog(LOG_WARNING, "can't open indirect secret file %s",
  891 		       atfile);
  892 		continue;
  893 	    }
  894 	    check_access(sf, atfile);
  895 	    if (!getword(sf, word, &xxx, atfile)) {
  896 		do_syslog(LOG_WARNING, "no secret in indirect secret file %s",
  897 		       atfile);
  898 		fclose(sf);
  899 		continue;
  900 	    }
  901 	    fclose(sf);
  902 	}
  903 
  904 	if (secret != NULL)
  905 	    strncpy2(secret, word, max_secret);
  906 
  907 	best_flag = got_flag;
  908 
  909 	/*
  910 	 * Now read address authorization info and make a wordlist.
  911 	 */
  912 	if (addr_list)
  913 	    free_wordlist(addr_list);
  914 	addr_list = addr_last = NULL;
  915 	for (;;) {
  916 	    if (!getword(f, word, &newline, filename) || newline)
  917 		break;
  918 	    ap = (struct wordlist *) malloc(sizeof(struct wordlist)
  919 					    + strlen(word));
  920 	    if (ap == NULL)
  921 		novm("authorized addresses");
  922 	    ap->next = NULL;
  923             /* TODO: check lengths should be ok, alloced correctly above.*/
  924 	    strcpy(ap->word, word);
  925 	    if (addr_list == NULL)
  926 		addr_list = ap;
  927 	    else
  928 		addr_last->next = ap;
  929 	    addr_last = ap;
  930 	}
  931 	if (!newline)
  932 	    break;
  933     }
  934 
  935     if (addrs != NULL)
  936 	*addrs = addr_list;
  937     else if (addr_list != NULL)
  938 	free_wordlist(addr_list);
  939 
  940     return best_flag;
  941 }
  942 
  943 /*
  944  * free_wordlist - release memory allocated for a wordlist.
  945  */
  946 static void
  947 free_wordlist(wp)
  948     struct wordlist *wp;
  949 {
  950     struct wordlist *next;
  951 
  952     while (wp != NULL) {
  953 	next = wp->next;
  954 	free(wp);
  955 	wp = next;
  956     }
  957 }