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