"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 }