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