File: | src/usr.sbin/pppd/auth.c |
Warning: | line 769, column 44 Access to field 'pw_uid' results in a dereference of a null pointer (loaded from variable 'pw') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: auth.c,v 1.40 2022/05/06 15:51:09 claudio Exp $ */ | |||
2 | ||||
3 | /* | |||
4 | * auth.c - PPP authentication and phase control. | |||
5 | * | |||
6 | * Copyright (c) 1989-2002 Paul Mackerras. All rights reserved. | |||
7 | * | |||
8 | * Redistribution and use in source and binary forms, with or without | |||
9 | * modification, are permitted provided that the following conditions | |||
10 | * are met: | |||
11 | * | |||
12 | * 1. Redistributions of source code must retain the above copyright | |||
13 | * notice, this list of conditions and the following disclaimer. | |||
14 | * | |||
15 | * 2. Redistributions in binary form must reproduce the above copyright | |||
16 | * notice, this list of conditions and the following disclaimer in | |||
17 | * the documentation and/or other materials provided with the | |||
18 | * distribution. | |||
19 | * | |||
20 | * 3. The name(s) of the authors of this software must not be used to | |||
21 | * endorse or promote products derived from this software without | |||
22 | * prior written permission. | |||
23 | * | |||
24 | * 4. Redistributions of any form whatsoever must retain the following | |||
25 | * acknowledgment: | |||
26 | * "This product includes software developed by Paul Mackerras | |||
27 | * <paulus@samba.org>". | |||
28 | * | |||
29 | * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO | |||
30 | * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | |||
31 | * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY | |||
32 | * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |||
33 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN | |||
34 | * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING | |||
35 | * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
36 | * | |||
37 | * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. | |||
38 | * | |||
39 | * Redistribution and use in source and binary forms, with or without | |||
40 | * modification, are permitted provided that the following conditions | |||
41 | * are met: | |||
42 | * | |||
43 | * 1. Redistributions of source code must retain the above copyright | |||
44 | * notice, this list of conditions and the following disclaimer. | |||
45 | * | |||
46 | * 2. Redistributions in binary form must reproduce the above copyright | |||
47 | * notice, this list of conditions and the following disclaimer in | |||
48 | * the documentation and/or other materials provided with the | |||
49 | * distribution. | |||
50 | * | |||
51 | * 3. The name "Carnegie Mellon University" must not be used to | |||
52 | * endorse or promote products derived from this software without | |||
53 | * prior written permission. For permission or any legal | |||
54 | * details, please contact | |||
55 | * Office of Technology Transfer | |||
56 | * Carnegie Mellon University | |||
57 | * 5000 Forbes Avenue | |||
58 | * Pittsburgh, PA 15213-3890 | |||
59 | * (412) 268-4387, fax: (412) 268-7395 | |||
60 | * tech-transfer@andrew.cmu.edu | |||
61 | * | |||
62 | * 4. Redistributions of any form whatsoever must retain the following | |||
63 | * acknowledgment: | |||
64 | * "This product includes software developed by Computing Services | |||
65 | * at Carnegie Mellon University (http://www.cmu.edu/computing/)." | |||
66 | * | |||
67 | * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO | |||
68 | * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | |||
69 | * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE | |||
70 | * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |||
71 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN | |||
72 | * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING | |||
73 | * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
74 | */ | |||
75 | ||||
76 | #include <stdio.h> | |||
77 | #include <stddef.h> | |||
78 | #include <stdlib.h> | |||
79 | #include <unistd.h> | |||
80 | #include <limits.h> | |||
81 | #include <syslog.h> | |||
82 | #include <pwd.h> | |||
83 | #include <string.h> | |||
84 | #include <sys/types.h> | |||
85 | #include <sys/stat.h> | |||
86 | #include <sys/socket.h> | |||
87 | #include <utmp.h> | |||
88 | #include <fcntl.h> | |||
89 | #if defined(_PATH_LASTLOG"/var/log/lastlog") && defined(_linux_) | |||
90 | #include <lastlog.h> | |||
91 | #endif | |||
92 | ||||
93 | #include <netdb.h> | |||
94 | #include <netinet/in.h> | |||
95 | #include <arpa/inet.h> | |||
96 | ||||
97 | ||||
98 | ||||
99 | #include "pppd.h" | |||
100 | #include "fsm.h" | |||
101 | #include "lcp.h" | |||
102 | #include "ipcp.h" | |||
103 | #include "upap.h" | |||
104 | #include "chap.h" | |||
105 | #ifdef CBCP_SUPPORT | |||
106 | #include "cbcp.h" | |||
107 | #endif | |||
108 | #include "pathnames.h" | |||
109 | ||||
110 | /* Used for storing a sequence of words. Usually malloced. */ | |||
111 | struct wordlist { | |||
112 | struct wordlist *next; | |||
113 | char word[1]; | |||
114 | }; | |||
115 | ||||
116 | /* Bits in scan_authfile return value */ | |||
117 | #define NONWILD_SERVER1 1 | |||
118 | #define NONWILD_CLIENT2 2 | |||
119 | ||||
120 | #define ISWILD(word)(word[0] == '*' && word[1] == 0) (word[0] == '*' && word[1] == 0) | |||
121 | ||||
122 | #define FALSE0 0 | |||
123 | #define TRUE1 1 | |||
124 | ||||
125 | /* The name by which the peer authenticated itself to us. */ | |||
126 | char peer_authname[MAXNAMELEN256]; | |||
127 | ||||
128 | /* Records which authentication operations haven't completed yet. */ | |||
129 | static int auth_pending[NUM_PPP1]; | |||
130 | ||||
131 | /* Set if we have successfully called plogin() */ | |||
132 | static int logged_in; | |||
133 | ||||
134 | /* Set if we have run the /etc/ppp/auth-up script. */ | |||
135 | static int did_authup; | |||
136 | ||||
137 | /* List of addresses which the peer may use. */ | |||
138 | static struct wordlist *addresses[NUM_PPP1]; | |||
139 | ||||
140 | /* Number of network protocols which we have opened. */ | |||
141 | static int num_np_open; | |||
142 | ||||
143 | /* Number of network protocols which have come up. */ | |||
144 | static int num_np_up; | |||
145 | ||||
146 | /* Set if we got the contents of passwd[] from the pap-secrets file. */ | |||
147 | static int passwd_from_file; | |||
148 | ||||
149 | /* Bits in auth_pending[] */ | |||
150 | #define PAP_WITHPEER1 1 | |||
151 | #define PAP_PEER2 2 | |||
152 | #define CHAP_WITHPEER4 4 | |||
153 | #define CHAP_PEER8 8 | |||
154 | ||||
155 | extern char *crypt(const char *, const char *); | |||
156 | ||||
157 | /* Prototypes for procedures local to this file. */ | |||
158 | ||||
159 | static void network_phase(int); | |||
160 | static void check_idle(void *); | |||
161 | static void connect_time_expired(void *); | |||
162 | static int plogin(char *, char *, char **, int *); | |||
163 | static void plogout(void); | |||
164 | static int null_login(int); | |||
165 | static int get_pap_passwd(char *); | |||
166 | static int have_pap_secret(void); | |||
167 | static int have_chap_secret(char *, char *, u_int32_t); | |||
168 | static int ip_addr_check(u_int32_t, struct wordlist *); | |||
169 | static int scan_authfile(FILE *, char *, char *, u_int32_t, char *, | |||
170 | struct wordlist **, char *); | |||
171 | static void free_wordlist(struct wordlist *); | |||
172 | static void auth_script(char *); | |||
173 | static void set_allowed_addrs(int, struct wordlist *); | |||
174 | ||||
175 | /* | |||
176 | * An Open on LCP has requested a change from Dead to Establish phase. | |||
177 | * Do what's necessary to bring the physical layer up. | |||
178 | */ | |||
179 | void | |||
180 | link_required(unit) | |||
181 | int unit; | |||
182 | { | |||
183 | } | |||
184 | ||||
185 | /* | |||
186 | * LCP has terminated the link; go to the Dead phase and take the | |||
187 | * physical layer down. | |||
188 | */ | |||
189 | void | |||
190 | link_terminated(unit) | |||
191 | int unit; | |||
192 | { | |||
193 | if (phase == PHASE_DEAD0) | |||
194 | return; | |||
195 | if (logged_in) | |||
196 | plogout(); | |||
197 | phase = PHASE_DEAD0; | |||
198 | syslog(LOG_NOTICE5, "Connection terminated."); | |||
199 | } | |||
200 | ||||
201 | /* | |||
202 | * LCP has gone down; it will either die or try to re-establish. | |||
203 | */ | |||
204 | void | |||
205 | link_down(unit) | |||
206 | int unit; | |||
207 | { | |||
208 | int i; | |||
209 | struct protent *protp; | |||
210 | ||||
211 | if (did_authup) { | |||
212 | auth_script(_PATH_AUTHDOWN"/etc/ppp/auth-down"); | |||
213 | did_authup = 0; | |||
214 | } | |||
215 | for (i = 0; (protp = protocols[i]) != NULL((void *)0); ++i) { | |||
216 | if (!protp->enabled_flag) | |||
217 | continue; | |||
218 | if (protp->protocol != PPP_LCP0xc021 && protp->lowerdown != NULL((void *)0)) | |||
219 | (*protp->lowerdown)(unit); | |||
220 | if (protp->protocol < 0xC000 && protp->close != NULL((void *)0)) | |||
221 | (*protp->close)(unit, "LCP down"); | |||
222 | } | |||
223 | num_np_open = 0; | |||
224 | num_np_up = 0; | |||
225 | if (phase != PHASE_DEAD0) | |||
226 | phase = PHASE_TERMINATE7; | |||
227 | } | |||
228 | ||||
229 | /* | |||
230 | * The link is established. | |||
231 | * Proceed to the Dead, Authenticate or Network phase as appropriate. | |||
232 | */ | |||
233 | void | |||
234 | link_established(unit) | |||
235 | int unit; | |||
236 | { | |||
237 | int auth; | |||
238 | lcp_options *wo = &lcp_wantoptions[unit]; | |||
239 | lcp_options *go = &lcp_gotoptions[unit]; | |||
240 | lcp_options *ho = &lcp_hisoptions[unit]; | |||
241 | int i; | |||
242 | struct protent *protp; | |||
243 | ||||
244 | /* | |||
245 | * Tell higher-level protocols that LCP is up. | |||
246 | */ | |||
247 | for (i = 0; (protp = protocols[i]) != NULL((void *)0); ++i) | |||
248 | if (protp->protocol != PPP_LCP0xc021 && protp->enabled_flag | |||
249 | && protp->lowerup != NULL((void *)0)) | |||
250 | (*protp->lowerup)(unit); | |||
251 | ||||
252 | if (auth_required && !(go->neg_chap || go->neg_upap)) { | |||
253 | /* | |||
254 | * We wanted the peer to authenticate itself, and it refused: | |||
255 | * treat it as though it authenticated with PAP using a username | |||
256 | * of "" and a password of "". If that's not OK, boot it out. | |||
257 | */ | |||
258 | if (!wo->neg_upap || !null_login(unit)) { | |||
259 | syslog(LOG_WARNING4, "peer refused to authenticate"); | |||
260 | lcp_close(unit, "peer refused to authenticate"); | |||
261 | return; | |||
262 | } | |||
263 | } | |||
264 | ||||
265 | phase = PHASE_AUTHENTICATE4; | |||
266 | auth = 0; | |||
267 | if (go->neg_chap) { | |||
268 | ChapAuthPeer(unit, our_name, go->chap_mdtype); | |||
269 | auth |= CHAP_PEER8; | |||
270 | } else if (go->neg_upap) { | |||
271 | upap_authpeer(unit); | |||
272 | auth |= PAP_PEER2; | |||
273 | } | |||
274 | if (ho->neg_chap) { | |||
275 | ChapAuthWithPeer(unit, user, ho->chap_mdtype); | |||
276 | auth |= CHAP_WITHPEER4; | |||
277 | } else if (ho->neg_upap) { | |||
278 | if (passwd[0] == 0) { | |||
279 | passwd_from_file = 1; | |||
280 | if (!get_pap_passwd(passwd)) | |||
281 | syslog(LOG_ERR3, "No secret found for PAP login"); | |||
282 | } | |||
283 | upap_authwithpeer(unit, user, passwd); | |||
284 | auth |= PAP_WITHPEER1; | |||
285 | } | |||
286 | auth_pending[unit] = auth; | |||
287 | ||||
288 | if (!auth) | |||
289 | network_phase(unit); | |||
290 | } | |||
291 | ||||
292 | /* | |||
293 | * Proceed to the network phase. | |||
294 | */ | |||
295 | static void | |||
296 | network_phase(unit) | |||
297 | int unit; | |||
298 | { | |||
299 | int i; | |||
300 | struct protent *protp; | |||
301 | lcp_options *go = &lcp_gotoptions[unit]; | |||
302 | ||||
303 | /* | |||
304 | * If the peer had to authenticate, run the auth-up script now. | |||
305 | */ | |||
306 | if ((go->neg_chap || go->neg_upap) && !did_authup) { | |||
307 | auth_script(_PATH_AUTHUP"/etc/ppp/auth-up"); | |||
308 | did_authup = 1; | |||
309 | } | |||
310 | ||||
311 | #ifdef CBCP_SUPPORT | |||
312 | /* | |||
313 | * If we negotiated callback, do it now. | |||
314 | */ | |||
315 | if (go->neg_cbcp) { | |||
316 | phase = PHASE_CALLBACK5; | |||
317 | (*cbcp_protent.open)(unit); | |||
318 | return; | |||
319 | } | |||
320 | #endif | |||
321 | ||||
322 | phase = PHASE_NETWORK6; | |||
323 | #if 0 | |||
324 | if (!demand) | |||
325 | set_filters(&pass_filter, &active_filter); | |||
326 | #endif | |||
327 | for (i = 0; (protp = protocols[i]) != NULL((void *)0); ++i) | |||
328 | if (protp->protocol < 0xC000 && protp->enabled_flag | |||
329 | && protp->open != NULL((void *)0)) { | |||
330 | (*protp->open)(unit); | |||
331 | if (protp->protocol != PPP_CCP0x80fd) | |||
332 | ++num_np_open; | |||
333 | } | |||
334 | ||||
335 | if (num_np_open == 0) | |||
336 | /* nothing to do */ | |||
337 | lcp_close(0, "No network protocols running"); | |||
338 | } | |||
339 | ||||
340 | /* | |||
341 | * The peer has failed to authenticate himself using `protocol'. | |||
342 | */ | |||
343 | void | |||
344 | auth_peer_fail(unit, protocol) | |||
345 | int unit, protocol; | |||
346 | { | |||
347 | /* | |||
348 | * Authentication failure: take the link down | |||
349 | */ | |||
350 | lcp_close(unit, "Authentication failed"); | |||
351 | } | |||
352 | ||||
353 | /* | |||
354 | * The peer has been successfully authenticated using `protocol'. | |||
355 | */ | |||
356 | void | |||
357 | auth_peer_success(unit, protocol, name, namelen) | |||
358 | int unit, protocol; | |||
359 | char *name; | |||
360 | int namelen; | |||
361 | { | |||
362 | int bit; | |||
363 | ||||
364 | switch (protocol) { | |||
365 | case PPP_CHAP0xc223: | |||
366 | bit = CHAP_PEER8; | |||
367 | break; | |||
368 | case PPP_PAP0xc023: | |||
369 | bit = PAP_PEER2; | |||
370 | break; | |||
371 | default: | |||
372 | syslog(LOG_WARNING4, "auth_peer_success: unknown protocol %x", | |||
373 | protocol); | |||
374 | return; | |||
375 | } | |||
376 | ||||
377 | /* | |||
378 | * Save the authenticated name of the peer for later. | |||
379 | */ | |||
380 | if (namelen > sizeof(peer_authname) - 1) | |||
381 | namelen = sizeof(peer_authname) - 1; | |||
382 | BCOPY(name, peer_authname, namelen)memcpy(peer_authname, name, namelen); | |||
383 | peer_authname[namelen] = 0; | |||
384 | script_setenv("PEERNAME", peer_authname); | |||
385 | ||||
386 | /* | |||
387 | * If there is no more authentication still to be done, | |||
388 | * proceed to the network (or callback) phase. | |||
389 | */ | |||
390 | if ((auth_pending[unit] &= ~bit) == 0) | |||
391 | network_phase(unit); | |||
392 | } | |||
393 | ||||
394 | /* | |||
395 | * We have failed to authenticate ourselves to the peer using `protocol'. | |||
396 | */ | |||
397 | void | |||
398 | auth_withpeer_fail(unit, protocol) | |||
399 | int unit, protocol; | |||
400 | { | |||
401 | if (passwd_from_file) | |||
402 | EXPLICIT_BZERO(passwd, MAXSECRETLEN)explicit_bzero(passwd, 256); | |||
403 | /* | |||
404 | * We've failed to authenticate ourselves to our peer. | |||
405 | * He'll probably take the link down, and there's not much | |||
406 | * we can do except wait for that. | |||
407 | */ | |||
408 | } | |||
409 | ||||
410 | /* | |||
411 | * We have successfully authenticated ourselves with the peer using `protocol'. | |||
412 | */ | |||
413 | void | |||
414 | auth_withpeer_success(unit, protocol) | |||
415 | int unit, protocol; | |||
416 | { | |||
417 | int bit; | |||
418 | ||||
419 | switch (protocol) { | |||
420 | case PPP_CHAP0xc223: | |||
421 | bit = CHAP_WITHPEER4; | |||
422 | break; | |||
423 | case PPP_PAP0xc023: | |||
424 | if (passwd_from_file) | |||
425 | EXPLICIT_BZERO(passwd, MAXSECRETLEN)explicit_bzero(passwd, 256); | |||
426 | bit = PAP_WITHPEER1; | |||
427 | break; | |||
428 | default: | |||
429 | syslog(LOG_WARNING4, "auth_peer_success: unknown protocol %x", | |||
430 | protocol); | |||
431 | bit = 0; | |||
432 | } | |||
433 | ||||
434 | /* | |||
435 | * If there is no more authentication still being done, | |||
436 | * proceed to the network (or callback) phase. | |||
437 | */ | |||
438 | if ((auth_pending[unit] &= ~bit) == 0) | |||
439 | network_phase(unit); | |||
440 | } | |||
441 | ||||
442 | ||||
443 | /* | |||
444 | * np_up - a network protocol has come up. | |||
445 | */ | |||
446 | void | |||
447 | np_up(unit, proto) | |||
448 | int unit, proto; | |||
449 | { | |||
450 | if (num_np_up == 0) { | |||
451 | /* | |||
452 | * At this point we consider that the link has come up successfully. | |||
453 | */ | |||
454 | need_holdoff = 0; | |||
455 | ||||
456 | if (idle_time_limit > 0) | |||
457 | TIMEOUT(check_idle, NULL, idle_time_limit)timeout((check_idle), (((void *)0)), (idle_time_limit)); | |||
458 | ||||
459 | /* | |||
460 | * Set a timeout to close the connection once the maximum | |||
461 | * connect time has expired. | |||
462 | */ | |||
463 | if (maxconnect > 0) | |||
464 | TIMEOUT(connect_time_expired, 0, maxconnect)timeout((connect_time_expired), (0), (maxconnect)); | |||
465 | ||||
466 | /* | |||
467 | * Detach now, if the updetach option was given. | |||
468 | */ | |||
469 | if (nodetach == -1) | |||
470 | detach(); | |||
471 | } | |||
472 | ++num_np_up; | |||
473 | } | |||
474 | ||||
475 | /* | |||
476 | * np_down - a network protocol has gone down. | |||
477 | */ | |||
478 | void | |||
479 | np_down(unit, proto) | |||
480 | int unit, proto; | |||
481 | { | |||
482 | if (--num_np_up == 0 && idle_time_limit > 0) { | |||
483 | UNTIMEOUT(check_idle, NULL)untimeout((check_idle), (((void *)0))); | |||
484 | } | |||
485 | } | |||
486 | ||||
487 | /* | |||
488 | * np_finished - a network protocol has finished using the link. | |||
489 | */ | |||
490 | void | |||
491 | np_finished(unit, proto) | |||
492 | int unit, proto; | |||
493 | { | |||
494 | if (--num_np_open <= 0) { | |||
495 | /* no further use for the link: shut up shop. */ | |||
496 | lcp_close(0, "No network protocols running"); | |||
497 | } | |||
498 | } | |||
499 | ||||
500 | /* | |||
501 | * check_idle - check whether the link has been idle for long | |||
502 | * enough that we can shut it down. | |||
503 | */ | |||
504 | static void | |||
505 | check_idle(arg) | |||
506 | void *arg; | |||
507 | { | |||
508 | struct ppp_idle idle; | |||
509 | time_t itime; | |||
510 | ||||
511 | if (!get_idle_time(0, &idle)) | |||
512 | return; | |||
513 | itime = MIN(idle.xmit_idle, idle.recv_idle)((idle.xmit_idle) < (idle.recv_idle)? (idle.xmit_idle): (idle .recv_idle)); | |||
514 | if (itime >= idle_time_limit) { | |||
515 | /* link is idle: shut it down. */ | |||
516 | syslog(LOG_INFO6, "Terminating connection due to lack of activity."); | |||
517 | lcp_close(0, "Link inactive"); | |||
518 | } else { | |||
519 | TIMEOUT(check_idle, NULL, idle_time_limit - itime)timeout((check_idle), (((void *)0)), (idle_time_limit - itime )); | |||
520 | } | |||
521 | } | |||
522 | ||||
523 | /* | |||
524 | * connect_time_expired - log a message and close the connection. | |||
525 | */ | |||
526 | static void | |||
527 | connect_time_expired(arg) | |||
528 | void *arg; | |||
529 | { | |||
530 | syslog(LOG_INFO6, "Connect time expired"); | |||
531 | lcp_close(0, "Connect time expired"); /* Close connection */ | |||
532 | } | |||
533 | ||||
534 | /* | |||
535 | * auth_check_options - called to check authentication options. | |||
536 | */ | |||
537 | void | |||
538 | auth_check_options() | |||
539 | { | |||
540 | lcp_options *wo = &lcp_wantoptions[0]; | |||
541 | int can_auth; | |||
542 | ipcp_options *ipwo = &ipcp_wantoptions[0]; | |||
543 | u_int32_t remote; | |||
544 | ||||
545 | /* Default our_name to hostname, and user to our_name */ | |||
546 | if (our_name[0] == 0 || usehostname) | |||
547 | strlcpy(our_name, hostname, HOST_NAME_MAX255+1); | |||
548 | if (user[0] == 0) | |||
549 | strlcpy(user, our_name, MAXNAMELEN256); | |||
550 | ||||
551 | /* If authentication is required, ask peer for CHAP or PAP. */ | |||
552 | if (auth_required && !wo->neg_chap && !wo->neg_upap) { | |||
553 | wo->neg_chap = 1; | |||
554 | wo->neg_upap = 1; | |||
555 | } | |||
556 | ||||
557 | /* | |||
558 | * Check whether we have appropriate secrets to use | |||
559 | * to authenticate the peer. | |||
560 | */ | |||
561 | can_auth = wo->neg_upap && (uselogin || have_pap_secret()); | |||
562 | if (!can_auth && wo->neg_chap) { | |||
563 | remote = ipwo->accept_remote? 0: ipwo->hisaddr; | |||
564 | can_auth = have_chap_secret(remote_name, our_name, remote); | |||
565 | } | |||
566 | ||||
567 | if (auth_required && !can_auth) { | |||
568 | option_error("peer authentication required but no suitable secret(s) found\n"); | |||
569 | if (remote_name[0] == 0) | |||
570 | option_error("for authenticating any peer to us (%s)\n", our_name); | |||
571 | else | |||
572 | option_error("for authenticating peer %s to us (%s)\n", | |||
573 | remote_name, our_name); | |||
574 | exit(1); | |||
575 | } | |||
576 | ||||
577 | /* | |||
578 | * Check whether the user tried to override certain values | |||
579 | * set by root. | |||
580 | */ | |||
581 | if (!auth_required && auth_req_info.priv > 0) { | |||
582 | if (!default_device && devnam_info.priv == 0) { | |||
583 | option_error("can't override device name when noauth option used"); | |||
584 | exit(1); | |||
585 | } | |||
586 | if ((connector != NULL((void *)0) && connector_info.priv == 0) | |||
587 | || (disconnector != NULL((void *)0) && disconnector_info.priv == 0) | |||
588 | || (welcomer != NULL((void *)0) && welcomer_info.priv == 0)) { | |||
589 | option_error("can't override connect, disconnect or welcome"); | |||
590 | option_error("option values when noauth option used"); | |||
591 | exit(1); | |||
592 | } | |||
593 | } | |||
594 | } | |||
595 | ||||
596 | /* | |||
597 | * auth_reset - called when LCP is starting negotiations to recheck | |||
598 | * authentication options, i.e. whether we have appropriate secrets | |||
599 | * to use for authenticating ourselves and/or the peer. | |||
600 | */ | |||
601 | void | |||
602 | auth_reset(unit) | |||
603 | int unit; | |||
604 | { | |||
605 | lcp_options *go = &lcp_gotoptions[unit]; | |||
606 | lcp_options *ao = &lcp_allowoptions[0]; | |||
607 | ipcp_options *ipwo = &ipcp_wantoptions[0]; | |||
608 | u_int32_t remote; | |||
609 | ||||
610 | ao->neg_upap = !refuse_pap && (passwd[0] != 0 || get_pap_passwd(NULL((void *)0))); | |||
611 | ao->neg_chap = !refuse_chap | |||
612 | && have_chap_secret(user, remote_name, (u_int32_t)0); | |||
613 | ||||
614 | if (go->neg_upap && !uselogin && !have_pap_secret()) | |||
615 | go->neg_upap = 0; | |||
616 | if (go->neg_chap) { | |||
617 | remote = ipwo->accept_remote? 0: ipwo->hisaddr; | |||
618 | if (!have_chap_secret(remote_name, our_name, remote)) | |||
619 | go->neg_chap = 0; | |||
620 | } | |||
621 | } | |||
622 | ||||
623 | ||||
624 | /* | |||
625 | * check_passwd - Check the user name and passwd against the PAP secrets | |||
626 | * file. If requested, also check against the system password database, | |||
627 | * and login the user if OK. | |||
628 | * | |||
629 | * returns: | |||
630 | * UPAP_AUTHNAK: Authentication failed. | |||
631 | * UPAP_AUTHACK: Authentication succeeded. | |||
632 | * In either case, msg points to an appropriate message. | |||
633 | */ | |||
634 | int | |||
635 | check_passwd(unit, auser, userlen, apasswd, passwdlen, msg, msglen) | |||
636 | int unit; | |||
637 | char *auser; | |||
638 | int userlen; | |||
639 | char *apasswd; | |||
640 | int passwdlen; | |||
641 | char **msg; | |||
642 | int *msglen; | |||
643 | { | |||
644 | int ret; | |||
645 | char *filename; | |||
646 | FILE *f; | |||
647 | struct wordlist *addrs; | |||
648 | u_int32_t remote; | |||
649 | ipcp_options *ipwo = &ipcp_wantoptions[unit]; | |||
650 | char passwd[256], user[256]; | |||
651 | char secret[MAXWORDLEN1024]; | |||
652 | static int attempts = 0; | |||
653 | ||||
654 | /* | |||
655 | * Make copies of apasswd and auser, then null-terminate them. | |||
656 | */ | |||
657 | BCOPY(apasswd, passwd, passwdlen)memcpy(passwd, apasswd, passwdlen); | |||
658 | passwd[passwdlen] = '\0'; | |||
659 | BCOPY(auser, user, userlen)memcpy(user, auser, userlen); | |||
660 | user[userlen] = '\0'; | |||
661 | *msg = (char *) 0; | |||
662 | ||||
663 | /* | |||
664 | * Open the file of pap secrets and scan for a suitable secret | |||
665 | * for authenticating this user. | |||
666 | */ | |||
667 | filename = _PATH_UPAPFILE"/etc/ppp/pap-secrets"; | |||
668 | addrs = NULL((void *)0); | |||
669 | ret = UPAP_AUTHACK2; | |||
670 | f = fopen(filename, "r"); | |||
671 | if (f == NULL((void *)0)) { | |||
| ||||
672 | syslog(LOG_ERR3, "Can't open PAP password file %s: %m", filename); | |||
673 | ret = UPAP_AUTHNAK3; | |||
674 | } else { | |||
675 | check_access(f, filename); | |||
676 | remote = ipwo->accept_remote? 0: ipwo->hisaddr; | |||
677 | if (scan_authfile(f, user, our_name, remote, | |||
678 | secret, &addrs, filename) < 0 | |||
679 | || (secret[0] != 0 && (cryptpap || strcmp(passwd, secret) != 0) | |||
680 | && strcmp(crypt(passwd, secret), secret) != 0)) { | |||
681 | syslog(LOG_WARNING4, "PAP authentication failure for %s", user); | |||
682 | ret = UPAP_AUTHNAK3; | |||
683 | } | |||
684 | fclose(f); | |||
685 | } | |||
686 | ||||
687 | if (uselogin && ret
| |||
688 | ret = plogin(user, passwd, msg, msglen); | |||
689 | if (ret == UPAP_AUTHNAK3) { | |||
690 | syslog(LOG_WARNING4, "PAP login failure for %s", user); | |||
691 | } | |||
692 | } | |||
693 | ||||
694 | if (ret == UPAP_AUTHNAK3) { | |||
695 | if (*msg == (char *) 0) | |||
696 | *msg = "Login incorrect"; | |||
697 | *msglen = strlen(*msg); | |||
698 | /* | |||
699 | * Frustrate passwd stealer programs. | |||
700 | * Allow 10 tries, but start backing off after 3 (stolen from login). | |||
701 | * On 10'th, drop the connection. | |||
702 | */ | |||
703 | if (attempts++ >= 10) { | |||
704 | syslog(LOG_WARNING4, "%d LOGIN FAILURES ON %s, %s", | |||
705 | attempts, devnam, user); | |||
706 | quit(); | |||
707 | } | |||
708 | if (attempts > 3) | |||
709 | sleep((u_int) (attempts - 3) * 5); | |||
710 | if (addrs != NULL((void *)0)) | |||
711 | free_wordlist(addrs); | |||
712 | ||||
713 | } else { | |||
714 | attempts = 0; /* Reset count */ | |||
715 | if (*msg == (char *) 0) | |||
716 | *msg = "Login ok"; | |||
717 | *msglen = strlen(*msg); | |||
718 | set_allowed_addrs(unit, addrs); | |||
719 | } | |||
720 | ||||
721 | EXPLICIT_BZERO(passwd, sizeof(passwd))explicit_bzero(passwd, sizeof(passwd)); | |||
722 | EXPLICIT_BZERO(secret, sizeof(secret))explicit_bzero(secret, sizeof(secret)); | |||
723 | ||||
724 | return ret; | |||
725 | } | |||
726 | ||||
727 | /* | |||
728 | * plogin - Check the user name and password against the system | |||
729 | * password database, and login the user if OK. | |||
730 | * | |||
731 | * returns: | |||
732 | * UPAP_AUTHNAK: Login failed. | |||
733 | * UPAP_AUTHACK: Login succeeded. | |||
734 | * In either case, msg points to an appropriate message. | |||
735 | */ | |||
736 | ||||
737 | static int | |||
738 | plogin(user, passwd, msg, msglen) | |||
739 | char *user; | |||
740 | char *passwd; | |||
741 | char **msg; | |||
742 | int *msglen; | |||
743 | { | |||
744 | struct passwd *pw; | |||
745 | char *tty; | |||
746 | ||||
747 | pw = getpwnam_shadow(user); | |||
748 | if (crypt_checkpass(passwd, pw ? pw->pw_passwd : NULL((void *)0))) | |||
749 | return UPAP_AUTHNAK3; | |||
750 | ||||
751 | /* | |||
752 | * Write a wtmp entry for this user. | |||
753 | */ | |||
754 | ||||
755 | tty = devnam; | |||
756 | if (strncmp(tty, "/dev/", 5) == 0) | |||
757 | tty += 5; | |||
758 | logwtmp(tty, user, remote_name); /* Add wtmp login entry */ | |||
759 | ||||
760 | #if defined(_PATH_LASTLOG"/var/log/lastlog") | |||
761 | { | |||
762 | struct lastlog ll; | |||
763 | int fd; | |||
764 | ||||
765 | if ((fd = open(_PATH_LASTLOG"/var/log/lastlog", O_RDWR0x0002)) >= 0) { | |||
766 | memset(&ll, 0, sizeof(ll)); | |||
767 | (void)time(&ll.ll_time); | |||
768 | (void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line)); | |||
769 | (void)pwrite(fd, &ll, sizeof(ll), (off_t)pw->pw_uid * | |||
| ||||
770 | sizeof(ll)); | |||
771 | (void)close(fd); | |||
772 | } | |||
773 | } | |||
774 | #endif | |||
775 | ||||
776 | ||||
777 | syslog(LOG_INFO6, "user %s logged in", user); | |||
778 | logged_in = TRUE1; | |||
779 | ||||
780 | return (UPAP_AUTHACK2); | |||
781 | } | |||
782 | ||||
783 | /* | |||
784 | * plogout - Logout the user. | |||
785 | */ | |||
786 | static void | |||
787 | plogout() | |||
788 | { | |||
789 | char *tty; | |||
790 | ||||
791 | tty = devnam; | |||
792 | if (strncmp(tty, "/dev/", 5) == 0) | |||
793 | tty += 5; | |||
794 | logwtmp(tty, "", ""); /* Wipe out utmp logout entry */ | |||
795 | ||||
796 | logged_in = FALSE0; | |||
797 | } | |||
798 | ||||
799 | ||||
800 | /* | |||
801 | * null_login - Check if a username of "" and a password of "" are | |||
802 | * acceptable, and iff so, set the list of acceptable IP addresses | |||
803 | * and return 1. | |||
804 | */ | |||
805 | static int | |||
806 | null_login(unit) | |||
807 | int unit; | |||
808 | { | |||
809 | char *filename; | |||
810 | FILE *f; | |||
811 | int i, ret; | |||
812 | struct wordlist *addrs; | |||
813 | char secret[MAXWORDLEN1024]; | |||
814 | ||||
815 | /* | |||
816 | * Open the file of pap secrets and scan for a suitable secret. | |||
817 | * We don't accept a wildcard client. | |||
818 | */ | |||
819 | filename = _PATH_UPAPFILE"/etc/ppp/pap-secrets"; | |||
820 | addrs = NULL((void *)0); | |||
821 | f = fopen(filename, "r"); | |||
822 | if (f == NULL((void *)0)) | |||
823 | return 0; | |||
824 | check_access(f, filename); | |||
825 | ||||
826 | i = scan_authfile(f, "", our_name, (u_int32_t)0, secret, &addrs, filename); | |||
827 | ret = i >= 0 && (i & NONWILD_CLIENT2) != 0 && secret[0] == 0; | |||
828 | EXPLICIT_BZERO(secret, sizeof(secret))explicit_bzero(secret, sizeof(secret)); | |||
829 | ||||
830 | if (ret) | |||
831 | set_allowed_addrs(unit, addrs); | |||
832 | else | |||
833 | free_wordlist(addrs); | |||
834 | ||||
835 | fclose(f); | |||
836 | return ret; | |||
837 | } | |||
838 | ||||
839 | ||||
840 | /* | |||
841 | * get_pap_passwd - get a password for authenticating ourselves with | |||
842 | * our peer using PAP. Returns 1 on success, 0 if no suitable password | |||
843 | * could be found. | |||
844 | */ | |||
845 | static int | |||
846 | get_pap_passwd(passwd) | |||
847 | char *passwd; | |||
848 | { | |||
849 | char *filename; | |||
850 | FILE *f; | |||
851 | int ret; | |||
852 | char secret[MAXWORDLEN1024]; | |||
853 | ||||
854 | filename = _PATH_UPAPFILE"/etc/ppp/pap-secrets"; | |||
855 | f = fopen(filename, "r"); | |||
856 | if (f == NULL((void *)0)) | |||
857 | return 0; | |||
858 | check_access(f, filename); | |||
859 | ret = scan_authfile(f, user, | |||
860 | remote_name[0]? remote_name: NULL((void *)0), | |||
861 | (u_int32_t)0, secret, NULL((void *)0), filename); | |||
862 | fclose(f); | |||
863 | if (ret < 0) | |||
864 | return 0; | |||
865 | if (passwd != NULL((void *)0)) | |||
866 | strlcpy(passwd, secret, MAXSECRETLEN256); | |||
867 | EXPLICIT_BZERO(secret, sizeof(secret))explicit_bzero(secret, sizeof(secret)); | |||
868 | return 1; | |||
869 | } | |||
870 | ||||
871 | ||||
872 | /* | |||
873 | * have_pap_secret - check whether we have a PAP file with any | |||
874 | * secrets that we could possibly use for authenticating the peer. | |||
875 | */ | |||
876 | static int | |||
877 | have_pap_secret() | |||
878 | { | |||
879 | FILE *f; | |||
880 | int ret; | |||
881 | char *filename; | |||
882 | ipcp_options *ipwo = &ipcp_wantoptions[0]; | |||
883 | u_int32_t remote; | |||
884 | ||||
885 | filename = _PATH_UPAPFILE"/etc/ppp/pap-secrets"; | |||
886 | f = fopen(filename, "r"); | |||
887 | if (f == NULL((void *)0)) | |||
888 | return 0; | |||
889 | ||||
890 | remote = ipwo->accept_remote? 0: ipwo->hisaddr; | |||
891 | ret = scan_authfile(f, NULL((void *)0), our_name, remote, NULL((void *)0), NULL((void *)0), filename); | |||
892 | fclose(f); | |||
893 | if (ret < 0) | |||
894 | return 0; | |||
895 | ||||
896 | return 1; | |||
897 | } | |||
898 | ||||
899 | ||||
900 | /* | |||
901 | * have_chap_secret - check whether we have a CHAP file with a | |||
902 | * secret that we could possibly use for authenticating `client' | |||
903 | * on `server'. Either can be the null string, meaning we don't | |||
904 | * know the identity yet. | |||
905 | */ | |||
906 | static int | |||
907 | have_chap_secret(client, server, remote) | |||
908 | char *client; | |||
909 | char *server; | |||
910 | u_int32_t remote; | |||
911 | { | |||
912 | FILE *f; | |||
913 | int ret; | |||
914 | char *filename; | |||
915 | ||||
916 | filename = _PATH_CHAPFILE"/etc/ppp/chap-secrets"; | |||
917 | f = fopen(filename, "r"); | |||
918 | if (f == NULL((void *)0)) | |||
919 | return 0; | |||
920 | ||||
921 | if (client[0] == 0) | |||
922 | client = NULL((void *)0); | |||
923 | else if (server[0] == 0) | |||
924 | server = NULL((void *)0); | |||
925 | ||||
926 | ret = scan_authfile(f, client, server, remote, NULL((void *)0), NULL((void *)0), filename); | |||
927 | fclose(f); | |||
928 | if (ret < 0) | |||
929 | return 0; | |||
930 | ||||
931 | return 1; | |||
932 | } | |||
933 | ||||
934 | ||||
935 | /* | |||
936 | * get_secret - open the CHAP secret file and return the secret | |||
937 | * for authenticating the given client on the given server. | |||
938 | * (We could be either client or server). | |||
939 | */ | |||
940 | int | |||
941 | get_secret(unit, client, server, secret, secret_len, save_addrs) | |||
942 | int unit; | |||
943 | char *client; | |||
944 | char *server; | |||
945 | char *secret; | |||
946 | int *secret_len; | |||
947 | int save_addrs; | |||
948 | { | |||
949 | FILE *f; | |||
950 | int ret, len; | |||
951 | char *filename; | |||
952 | struct wordlist *addrs; | |||
953 | char secbuf[MAXWORDLEN1024]; | |||
954 | ||||
955 | filename = _PATH_CHAPFILE"/etc/ppp/chap-secrets"; | |||
956 | addrs = NULL((void *)0); | |||
957 | secbuf[0] = 0; | |||
958 | ||||
959 | f = fopen(filename, "r"); | |||
960 | if (f == NULL((void *)0)) { | |||
961 | syslog(LOG_ERR3, "Can't open chap secret file %s: %m", filename); | |||
962 | return 0; | |||
963 | } | |||
964 | check_access(f, filename); | |||
965 | ||||
966 | ret = scan_authfile(f, client, server, (u_int32_t)0, | |||
967 | secbuf, &addrs, filename); | |||
968 | fclose(f); | |||
969 | if (ret < 0) | |||
970 | return 0; | |||
971 | ||||
972 | if (save_addrs) | |||
973 | set_allowed_addrs(unit, addrs); | |||
974 | ||||
975 | len = strlen(secbuf); | |||
976 | if (len > MAXSECRETLEN256) { | |||
977 | syslog(LOG_ERR3, "Secret for %s on %s is too long", client, server); | |||
978 | len = MAXSECRETLEN256; | |||
979 | } | |||
980 | BCOPY(secbuf, secret, len)memcpy(secret, secbuf, len); | |||
981 | EXPLICIT_BZERO(secbuf, sizeof(secbuf))explicit_bzero(secbuf, sizeof(secbuf)); | |||
982 | *secret_len = len; | |||
983 | ||||
984 | return 1; | |||
985 | } | |||
986 | ||||
987 | /* | |||
988 | * set_allowed_addrs() - set the list of allowed addresses. | |||
989 | */ | |||
990 | static void | |||
991 | set_allowed_addrs(unit, addrs) | |||
992 | int unit; | |||
993 | struct wordlist *addrs; | |||
994 | { | |||
995 | if (addresses[unit] != NULL((void *)0)) | |||
996 | free_wordlist(addresses[unit]); | |||
997 | addresses[unit] = addrs; | |||
998 | ||||
999 | /* | |||
1000 | * If there's only one authorized address we might as well | |||
1001 | * ask our peer for that one right away | |||
1002 | */ | |||
1003 | if (addrs != NULL((void *)0) && addrs->next == NULL((void *)0)) { | |||
1004 | char *p = addrs->word; | |||
1005 | struct ipcp_options *wo = &ipcp_wantoptions[unit]; | |||
1006 | struct in_addr ina; | |||
1007 | struct hostent *hp; | |||
1008 | ||||
1009 | if (*p != '!' && *p != '-' && !ISWILD(p)(p[0] == '*' && p[1] == 0) && strchr(p, '/') == NULL((void *)0)) { | |||
1010 | hp = gethostbyname(p); | |||
1011 | if (hp != NULL((void *)0) && hp->h_addrtype == AF_INET2) | |||
1012 | wo->hisaddr = *(u_int32_t *)hp->h_addrh_addr_list[0]; | |||
1013 | else if (inet_aton(p, &ina) == 1) | |||
1014 | wo->hisaddr = ina.s_addr; | |||
1015 | } | |||
1016 | } | |||
1017 | } | |||
1018 | ||||
1019 | /* | |||
1020 | * auth_ip_addr - check whether the peer is authorized to use | |||
1021 | * a given IP address. Returns 1 if authorized, 0 otherwise. | |||
1022 | */ | |||
1023 | int | |||
1024 | auth_ip_addr(unit, addr) | |||
1025 | int unit; | |||
1026 | u_int32_t addr; | |||
1027 | { | |||
1028 | return ip_addr_check(addr, addresses[unit]); | |||
1029 | } | |||
1030 | ||||
1031 | static int | |||
1032 | ip_addr_check(addr, addrs) | |||
1033 | u_int32_t addr; | |||
1034 | struct wordlist *addrs; | |||
1035 | { | |||
1036 | u_int32_t mask, ah; | |||
1037 | struct in_addr ina; | |||
1038 | int accept, r = 1; | |||
1039 | char *ptr_word, *ptr_mask; | |||
1040 | struct hostent *hp; | |||
1041 | ||||
1042 | /* don't allow loopback or multicast address */ | |||
1043 | if (bad_ip_adrs(addr)) | |||
1044 | return 0; | |||
1045 | ||||
1046 | if (addrs == NULL((void *)0)) | |||
1047 | return !auth_required; /* no addresses authorized */ | |||
1048 | ||||
1049 | for (; addrs != NULL((void *)0); addrs = addrs->next) { | |||
1050 | /* "-" means no addresses authorized, "*" means any address allowed */ | |||
1051 | ptr_word = addrs->word; | |||
1052 | if (strcmp(ptr_word, "-") == 0) | |||
1053 | break; | |||
1054 | if (strcmp(ptr_word, "*") == 0) | |||
1055 | return 1; | |||
1056 | ||||
1057 | accept = 1; | |||
1058 | if (*ptr_word == '!') { | |||
1059 | accept = 0; | |||
1060 | ++ptr_word; | |||
1061 | } | |||
1062 | ||||
1063 | mask = ~ (u_int32_t) 0; | |||
1064 | ptr_mask = strchr (ptr_word, '/'); | |||
1065 | if (ptr_mask != NULL((void *)0)) { | |||
1066 | int bit_count; | |||
1067 | ||||
1068 | bit_count = (int) strtol (ptr_mask+1, (char **) 0, 10); | |||
1069 | if (bit_count <= 0 || bit_count > 32) { | |||
1070 | syslog (LOG_WARNING4, | |||
1071 | "invalid address length %s in auth. address list", | |||
1072 | ptr_mask); | |||
1073 | continue; | |||
1074 | } | |||
1075 | *ptr_mask = '\0'; | |||
1076 | mask <<= 32 - bit_count; | |||
1077 | } | |||
1078 | ||||
1079 | hp = gethostbyname(ptr_word); | |||
1080 | if (hp != NULL((void *)0) && hp->h_addrtype == AF_INET2) { | |||
1081 | ina.s_addr = *(u_int32_t *)hp->h_addrh_addr_list[0]; | |||
1082 | } else { | |||
1083 | r = inet_aton (ptr_word, &ina); | |||
1084 | if (ptr_mask == NULL((void *)0)) { | |||
1085 | /* calculate appropriate mask for net */ | |||
1086 | ah = ntohl(ina.s_addr)(__uint32_t)(__builtin_constant_p(ina.s_addr) ? (__uint32_t)( ((__uint32_t)(ina.s_addr) & 0xff) << 24 | ((__uint32_t )(ina.s_addr) & 0xff00) << 8 | ((__uint32_t)(ina.s_addr ) & 0xff0000) >> 8 | ((__uint32_t)(ina.s_addr) & 0xff000000) >> 24) : __swap32md(ina.s_addr)); | |||
1087 | if (IN_CLASSA(ah)(((u_int32_t)(ah) & ((u_int32_t)(0x80000000))) == ((u_int32_t )(0x00000000)))) | |||
1088 | mask = IN_CLASSA_NET((u_int32_t)(0xff000000)); | |||
1089 | else if (IN_CLASSB(ah)(((u_int32_t)(ah) & ((u_int32_t)(0xc0000000))) == ((u_int32_t )(0x80000000)))) | |||
1090 | mask = IN_CLASSB_NET((u_int32_t)(0xffff0000)); | |||
1091 | else if (IN_CLASSC(ah)(((u_int32_t)(ah) & ((u_int32_t)(0xe0000000))) == ((u_int32_t )(0xc0000000)))) | |||
1092 | mask = IN_CLASSC_NET((u_int32_t)(0xffffff00)); | |||
1093 | } | |||
1094 | } | |||
1095 | ||||
1096 | if (ptr_mask != NULL((void *)0)) | |||
1097 | *ptr_mask = '/'; | |||
1098 | ||||
1099 | if (r == 0) | |||
1100 | syslog (LOG_WARNING4, | |||
1101 | "unknown host %s in auth. address list", | |||
1102 | addrs->word); | |||
1103 | else | |||
1104 | /* Here ina.s_addr and addr are in network byte order, | |||
1105 | and mask is in host order. */ | |||
1106 | if (((addr ^ ina.s_addr) & htonl(mask)(__uint32_t)(__builtin_constant_p(mask) ? (__uint32_t)(((__uint32_t )(mask) & 0xff) << 24 | ((__uint32_t)(mask) & 0xff00 ) << 8 | ((__uint32_t)(mask) & 0xff0000) >> 8 | ((__uint32_t)(mask) & 0xff000000) >> 24) : __swap32md (mask))) == 0) | |||
1107 | return accept; | |||
1108 | } | |||
1109 | return 0; /* not in list => can't have it */ | |||
1110 | } | |||
1111 | ||||
1112 | /* | |||
1113 | * bad_ip_adrs - return 1 if the IP address is one we don't want | |||
1114 | * to use, such as an address in the loopback net or a multicast address. | |||
1115 | * addr is in network byte order. | |||
1116 | */ | |||
1117 | int | |||
1118 | bad_ip_adrs(addr) | |||
1119 | u_int32_t addr; | |||
1120 | { | |||
1121 | addr = ntohl(addr)(__uint32_t)(__builtin_constant_p(addr) ? (__uint32_t)(((__uint32_t )(addr) & 0xff) << 24 | ((__uint32_t)(addr) & 0xff00 ) << 8 | ((__uint32_t)(addr) & 0xff0000) >> 8 | ((__uint32_t)(addr) & 0xff000000) >> 24) : __swap32md (addr)); | |||
1122 | return (addr >> IN_CLASSA_NSHIFT24) == IN_LOOPBACKNET127 | |||
1123 | || IN_MULTICAST(addr)(((u_int32_t)(addr) & ((u_int32_t)(0xf0000000))) == ((u_int32_t )(0xe0000000))); | |||
1124 | } | |||
1125 | ||||
1126 | /* | |||
1127 | * check_access - complain if a secret file has too-liberal permissions. | |||
1128 | */ | |||
1129 | void | |||
1130 | check_access(f, filename) | |||
1131 | FILE *f; | |||
1132 | char *filename; | |||
1133 | { | |||
1134 | struct stat sbuf; | |||
1135 | ||||
1136 | if (fstat(fileno(f)(!__isthreaded ? ((f)->_file) : (fileno)(f)), &sbuf) < 0) { | |||
1137 | syslog(LOG_WARNING4, "cannot stat secret file %s: %m", filename); | |||
1138 | } else if ((sbuf.st_mode & (S_IRWXG0000070 | S_IRWXO0000007)) != 0) { | |||
1139 | syslog(LOG_WARNING4, "Warning - secret file %s has world and/or group access", filename); | |||
1140 | } | |||
1141 | } | |||
1142 | ||||
1143 | ||||
1144 | /* | |||
1145 | * scan_authfile - Scan an authorization file for a secret suitable | |||
1146 | * for authenticating `client' on `server'. The return value is -1 | |||
1147 | * if no secret is found, otherwise >= 0. The return value has | |||
1148 | * NONWILD_CLIENT set if the secret didn't have "*" for the client, and | |||
1149 | * NONWILD_SERVER set if the secret didn't have "*" for the server. | |||
1150 | * Any following words on the line (i.e. address authorization | |||
1151 | * info) are placed in a wordlist and returned in *addrs. | |||
1152 | */ | |||
1153 | static int | |||
1154 | scan_authfile(f, client, server, ipaddr, secret, addrs, filename) | |||
1155 | FILE *f; | |||
1156 | char *client; | |||
1157 | char *server; | |||
1158 | u_int32_t ipaddr; | |||
1159 | char *secret; | |||
1160 | struct wordlist **addrs; | |||
1161 | char *filename; | |||
1162 | { | |||
1163 | int newline, xxx; | |||
1164 | int got_flag, best_flag; | |||
1165 | FILE *sf; | |||
1166 | struct wordlist *ap, *addr_list, *alist, *alast; | |||
1167 | char word[MAXWORDLEN1024]; | |||
1168 | char atfile[MAXWORDLEN1024]; | |||
1169 | char lsecret[MAXWORDLEN1024]; | |||
1170 | ||||
1171 | if (addrs != NULL((void *)0)) | |||
1172 | *addrs = NULL((void *)0); | |||
1173 | addr_list = NULL((void *)0); | |||
1174 | if (!getword(f, word, &newline, filename)) | |||
1175 | return -1; /* file is empty??? */ | |||
1176 | newline = 1; | |||
1177 | best_flag = -1; | |||
1178 | for (;;) { | |||
1179 | /* | |||
1180 | * Skip until we find a word at the start of a line. | |||
1181 | */ | |||
1182 | while (!newline && getword(f, word, &newline, filename)) | |||
1183 | ; | |||
1184 | if (!newline) | |||
1185 | break; /* got to end of file */ | |||
1186 | ||||
1187 | /* | |||
1188 | * Got a client - check if it's a match or a wildcard. | |||
1189 | */ | |||
1190 | got_flag = 0; | |||
1191 | if (client != NULL((void *)0) && strcmp(word, client) != 0 && !ISWILD(word)(word[0] == '*' && word[1] == 0)) { | |||
1192 | newline = 0; | |||
1193 | continue; | |||
1194 | } | |||
1195 | if (!ISWILD(word)(word[0] == '*' && word[1] == 0)) | |||
1196 | got_flag = NONWILD_CLIENT2; | |||
1197 | ||||
1198 | /* | |||
1199 | * Now get a server and check if it matches. | |||
1200 | */ | |||
1201 | if (!getword(f, word, &newline, filename)) | |||
1202 | break; | |||
1203 | if (newline) | |||
1204 | continue; | |||
1205 | if (server != NULL((void *)0) && strcmp(word, server) != 0 && !ISWILD(word)(word[0] == '*' && word[1] == 0)) | |||
1206 | continue; | |||
1207 | if (!ISWILD(word)(word[0] == '*' && word[1] == 0)) | |||
1208 | got_flag |= NONWILD_SERVER1; | |||
1209 | ||||
1210 | /* | |||
1211 | * Got some sort of a match - see if it's better than what | |||
1212 | * we have already. | |||
1213 | */ | |||
1214 | if (got_flag <= best_flag) | |||
1215 | continue; | |||
1216 | ||||
1217 | /* | |||
1218 | * Get the secret. | |||
1219 | */ | |||
1220 | if (!getword(f, word, &newline, filename)) | |||
1221 | break; | |||
1222 | if (newline) | |||
1223 | continue; | |||
1224 | ||||
1225 | /* | |||
1226 | * Special syntax: @filename means read secret from file. | |||
1227 | */ | |||
1228 | if (word[0] == '@') { | |||
1229 | strlcpy(atfile, word+1, sizeof atfile); | |||
1230 | if ((sf = fopen(atfile, "r")) == NULL((void *)0)) { | |||
1231 | syslog(LOG_WARNING4, "can't open indirect secret file %s", | |||
1232 | atfile); | |||
1233 | continue; | |||
1234 | } | |||
1235 | check_access(sf, atfile); | |||
1236 | if (!getword(sf, word, &xxx, atfile)) { | |||
1237 | syslog(LOG_WARNING4, "no secret in indirect secret file %s", | |||
1238 | atfile); | |||
1239 | fclose(sf); | |||
1240 | continue; | |||
1241 | } | |||
1242 | fclose(sf); | |||
1243 | } | |||
1244 | if (secret != NULL((void *)0)) | |||
1245 | strlcpy(lsecret, word, sizeof lsecret); | |||
1246 | ||||
1247 | /* | |||
1248 | * Now read address authorization info and make a wordlist. | |||
1249 | */ | |||
1250 | alist = alast = NULL((void *)0); | |||
1251 | for (;;) { | |||
1252 | size_t wordlen; | |||
1253 | ||||
1254 | if (!getword(f, word, &newline, filename) || newline) | |||
1255 | break; | |||
1256 | wordlen = strlen(word); /* NUL in struct wordlist */ | |||
1257 | ap = (struct wordlist *) malloc(sizeof(struct wordlist) + | |||
1258 | wordlen); | |||
1259 | ||||
1260 | if (ap == NULL((void *)0)) | |||
1261 | novm("authorized addresses"); | |||
1262 | ap->next = NULL((void *)0); | |||
1263 | strlcpy(ap->word, word, wordlen + 1); | |||
1264 | if (alist == NULL((void *)0)) | |||
1265 | alist = ap; | |||
1266 | else | |||
1267 | alast->next = ap; | |||
1268 | alast = ap; | |||
1269 | } | |||
1270 | ||||
1271 | /* | |||
1272 | * Check if the given IP address is allowed by the wordlist. | |||
1273 | */ | |||
1274 | if (ipaddr != 0 && !ip_addr_check(ipaddr, alist)) { | |||
1275 | free_wordlist(alist); | |||
1276 | continue; | |||
1277 | } | |||
1278 | ||||
1279 | /* | |||
1280 | * This is the best so far; remember it. | |||
1281 | */ | |||
1282 | best_flag = got_flag; | |||
1283 | if (addr_list) | |||
1284 | free_wordlist(addr_list); | |||
1285 | addr_list = alist; | |||
1286 | if (secret != NULL((void *)0)) | |||
1287 | strlcpy(secret, lsecret, MAXWORDLEN1024); | |||
1288 | ||||
1289 | if (!newline) | |||
1290 | break; | |||
1291 | } | |||
1292 | ||||
1293 | if (addrs != NULL((void *)0)) | |||
1294 | *addrs = addr_list; | |||
1295 | else if (addr_list != NULL((void *)0)) | |||
1296 | free_wordlist(addr_list); | |||
1297 | ||||
1298 | return best_flag; | |||
1299 | } | |||
1300 | ||||
1301 | /* | |||
1302 | * free_wordlist - release memory allocated for a wordlist. | |||
1303 | */ | |||
1304 | static void | |||
1305 | free_wordlist(wp) | |||
1306 | struct wordlist *wp; | |||
1307 | { | |||
1308 | struct wordlist *next; | |||
1309 | ||||
1310 | while (wp != NULL((void *)0)) { | |||
1311 | next = wp->next; | |||
1312 | free(wp); | |||
1313 | wp = next; | |||
1314 | } | |||
1315 | } | |||
1316 | ||||
1317 | /* | |||
1318 | * auth_script - execute a script with arguments | |||
1319 | * interface-name peer-name real-user tty speed | |||
1320 | */ | |||
1321 | static void | |||
1322 | auth_script(script) | |||
1323 | char *script; | |||
1324 | { | |||
1325 | char strspeed[32]; | |||
1326 | struct passwd *pw; | |||
1327 | char struid[32]; | |||
1328 | char *user_name; | |||
1329 | char *argv[8]; | |||
1330 | ||||
1331 | if ((pw = getpwuid(getuid())) != NULL((void *)0) && pw->pw_name != NULL((void *)0)) | |||
1332 | user_name = pw->pw_name; | |||
1333 | else { | |||
1334 | snprintf(struid, sizeof struid, "%u", getuid()); | |||
1335 | user_name = struid; | |||
1336 | } | |||
1337 | snprintf(strspeed, sizeof strspeed, "%d", baud_rate); | |||
1338 | ||||
1339 | argv[0] = script; | |||
1340 | argv[1] = ifname; | |||
1341 | argv[2] = peer_authname; | |||
1342 | argv[3] = user_name; | |||
1343 | argv[4] = devnam; | |||
1344 | argv[5] = strspeed; | |||
1345 | argv[6] = NULL((void *)0); | |||
1346 | ||||
1347 | run_program(script, argv, 0); | |||
1348 | } |