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