|
1586
|
1 //========================================================================== |
|
|
2 // |
|
|
3 // src/auth.c |
|
|
4 // |
|
|
5 //========================================================================== |
|
|
6 //####ECOSGPLCOPYRIGHTBEGIN#### |
|
|
7 // ------------------------------------------- |
|
|
8 // This file is part of eCos, the Embedded Configurable Operating System. |
|
|
9 // Portions created by Nick Garnett are |
|
|
10 // Copyright (C) 2003 eCosCentric Ltd. |
|
|
11 // |
|
|
12 // eCos is free software; you can redistribute it and/or modify it under |
|
|
13 // the terms of the GNU General Public License as published by the Free |
|
|
14 // Software Foundation; either version 2 or (at your option) any later version. |
|
|
15 // |
|
|
16 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY |
|
|
17 // WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
|
18 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
|
19 // for more details. |
|
|
20 // |
|
|
21 // You should have received a copy of the GNU General Public License along |
|
|
22 // with eCos; if not, write to the Free Software Foundation, Inc., |
|
|
23 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
|
|
24 // |
|
|
25 // As a special exception, if other files instantiate templates or use macros |
|
|
26 // or inline functions from this file, or you compile this file and link it |
|
|
27 // with other works to produce a work based on this file, this file does not |
|
|
28 // by itself cause the resulting work to be covered by the GNU General Public |
|
|
29 // License. However the source code for this file must still be made available |
|
|
30 // in accordance with section (3) of the GNU General Public License. |
|
|
31 // |
|
|
32 // This exception does not invalidate any other reasons why a work based on |
|
|
33 // this file might be covered by the GNU General Public License. |
|
|
34 // |
|
|
35 // ------------------------------------------- |
|
|
36 //####ECOSGPLCOPYRIGHTEND#### |
|
|
37 //####BSDCOPYRIGHTBEGIN#### |
|
|
38 // |
|
|
39 // ------------------------------------------- |
|
|
40 // |
|
|
41 // Portions of this software may have been derived from OpenBSD, |
|
|
42 // FreeBSD or other sources, and are covered by the appropriate |
|
|
43 // copyright disclaimers included herein. |
|
|
44 // |
|
|
45 // ------------------------------------------- |
|
|
46 // |
|
|
47 //####BSDCOPYRIGHTEND#### |
|
|
48 //========================================================================== |
|
|
49 |
|
|
50 /* |
|
|
51 * auth.c - PPP authentication and phase control. |
|
|
52 * |
|
|
53 * Copyright (c) 1993 The Australian National University. |
|
|
54 * All rights reserved. |
|
|
55 * |
|
|
56 * Redistribution and use in source and binary forms are permitted |
|
|
57 * provided that the above copyright notice and this paragraph are |
|
|
58 * duplicated in all such forms and that any documentation, |
|
|
59 * advertising materials, and other materials related to such |
|
|
60 * distribution and use acknowledge that the software was developed |
|
|
61 * by the Australian National University. The name of the University |
|
|
62 * may not be used to endorse or promote products derived from this |
|
|
63 * software without specific prior written permission. |
|
|
64 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
|
|
65 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
|
|
66 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
|
|
67 * |
|
|
68 * Copyright (c) 1989 Carnegie Mellon University. |
|
|
69 * All rights reserved. |
|
|
70 * |
|
|
71 * Redistribution and use in source and binary forms are permitted |
|
|
72 * provided that the above copyright notice and this paragraph are |
|
|
73 * duplicated in all such forms and that any documentation, |
|
|
74 * advertising materials, and other materials related to such |
|
|
75 * distribution and use acknowledge that the software was developed |
|
|
76 * by Carnegie Mellon University. The name of the |
|
|
77 * University may not be used to endorse or promote products derived |
|
|
78 * from this software without specific prior written permission. |
|
|
79 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
|
|
80 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
|
|
81 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
|
|
82 */ |
|
|
83 |
|
|
84 #ifndef lint |
|
|
85 //static char rcsid[] = "$FreeBSD: src/usr.sbin/pppd/auth.c,v 1.24.2.1 2000/12/11 01:03:37 obrien Exp $"; |
|
|
86 #endif |
|
|
87 |
|
|
88 #include <stdio.h> |
|
|
89 #include <stddef.h> |
|
|
90 #include <stdlib.h> |
|
|
91 #include <unistd.h> |
|
|
92 #include <cyg/ppp/syslog.h> |
|
1628
|
93 #ifndef __ECOS |
|
1586
|
94 #include <paths.h> |
|
1628
|
95 #endif |
|
1586
|
96 //#include <pwd.h> |
|
|
97 #include <string.h> |
|
|
98 #include <sys/types.h> |
|
|
99 #include <sys/stat.h> |
|
|
100 #include <sys/socket.h> |
|
|
101 //#include <utmp.h> |
|
|
102 #include <fcntl.h> |
|
|
103 #if defined(_PATH_LASTLOG) && defined(_linux_) |
|
|
104 #include <lastlog.h> |
|
|
105 #endif |
|
|
106 |
|
|
107 #include <netdb.h> |
|
|
108 #include <netinet/in.h> |
|
|
109 #include <arpa/inet.h> |
|
|
110 #include <sys/time.h> |
|
|
111 //#include <utmp.h> |
|
|
112 |
|
|
113 #ifdef USE_PAM |
|
|
114 #include <security/pam_appl.h> |
|
|
115 #endif |
|
|
116 |
|
|
117 #ifdef HAS_SHADOW |
|
|
118 #include <shadow.h> |
|
|
119 #ifndef PW_PPP |
|
|
120 #define PW_PPP PW_LOGIN |
|
|
121 #endif |
|
|
122 #endif |
|
|
123 |
|
|
124 #include "cyg/ppp/pppd.h" |
|
|
125 #include "cyg/ppp/fsm.h" |
|
|
126 #include "cyg/ppp/lcp.h" |
|
|
127 #include "cyg/ppp/ipcp.h" |
|
|
128 #include "cyg/ppp/upap.h" |
|
|
129 #include "cyg/ppp/chap.h" |
|
|
130 #ifdef CBCP_SUPPORT |
|
|
131 #include "cyg/ppp/cbcp.h" |
|
|
132 #endif |
|
|
133 //#include "cyg/ppp/pathnames.h" |
|
|
134 |
|
|
135 /* Used for storing a sequence of words. Usually malloced. */ |
|
|
136 struct wordlist { |
|
|
137 struct wordlist *next; |
|
|
138 char word[1]; |
|
|
139 }; |
|
|
140 |
|
|
141 /* Bits in scan_authfile return value */ |
|
|
142 #define NONWILD_SERVER 1 |
|
|
143 #define NONWILD_CLIENT 2 |
|
|
144 |
|
|
145 #define ISWILD(word) (word[0] == '*' && word[1] == 0) |
|
|
146 |
|
|
147 #define FALSE 0 |
|
|
148 #define TRUE 1 |
|
|
149 |
|
|
150 /* The name by which the peer authenticated itself to us. */ |
|
|
151 char peer_authname[MAXNAMELEN]; |
|
|
152 |
|
|
153 /* Records which authentication operations haven't completed yet. */ |
|
|
154 static int auth_pending[NUM_PPP]; |
|
|
155 |
|
|
156 /* Set if we have successfully called plogin() */ |
|
|
157 //static int logged_in; |
|
|
158 |
|
|
159 /* Set if not wild or blank */ |
|
|
160 //static int non_wildclient; |
|
|
161 |
|
|
162 /* Set if we have run the /etc/ppp/auth-up script. */ |
|
|
163 //static int did_authup; |
|
|
164 |
|
|
165 /* List of addresses which the peer may use. */ |
|
|
166 static struct wordlist *addresses[NUM_PPP]; |
|
|
167 |
|
|
168 /* Number of network protocols which we have opened. */ |
|
|
169 static int num_np_open; |
|
|
170 |
|
|
171 /* Number of network protocols which have come up. */ |
|
|
172 static int num_np_up; |
|
|
173 |
|
|
174 /* Set if we got the contents of passwd[] from the pap-secrets file. */ |
|
|
175 static int passwd_from_file; |
|
|
176 |
|
|
177 /* Bits in auth_pending[] */ |
|
|
178 #define PAP_WITHPEER 1 |
|
|
179 #define PAP_PEER 2 |
|
|
180 #define CHAP_WITHPEER 4 |
|
|
181 #define CHAP_PEER 8 |
|
|
182 |
|
|
183 extern char *crypt __P((const char *, const char *)); |
|
|
184 |
|
|
185 /* Prototypes for procedures local to this file. */ |
|
|
186 |
|
|
187 static void network_phase __P((int)); |
|
|
188 static void check_idle __P((void *)); |
|
|
189 static void connect_time_expired __P((void *)); |
|
|
190 static int null_login __P((int)); |
|
|
191 static int get_pap_passwd __P((char *)); |
|
|
192 static int have_pap_secret __P((void)); |
|
|
193 static int have_chap_secret __P((char *, char *, u_int32_t)); |
|
|
194 static int ip_addr_check __P((u_int32_t, struct wordlist *)); |
|
|
195 |
|
|
196 static void auth_set_ip_addr __P((int)); |
|
|
197 |
|
|
198 /* |
|
|
199 * An Open on LCP has requested a change from Dead to Establish phase. |
|
|
200 * Do what's necessary to bring the physical layer up. |
|
|
201 */ |
|
|
202 void |
|
|
203 link_required(unit) |
|
|
204 int unit; |
|
|
205 { |
|
|
206 } |
|
|
207 |
|
|
208 /* |
|
|
209 * LCP has terminated the link; go to the Dead phase and take the |
|
|
210 * physical layer down. |
|
|
211 */ |
|
|
212 void |
|
|
213 link_terminated(unit) |
|
|
214 int unit; |
|
|
215 { |
|
|
216 extern time_t etime, stime; |
|
|
217 extern int minutes; |
|
|
218 |
|
|
219 db_printf("%s()\n",__PRETTY_FUNCTION__); |
|
|
220 if (phase == PHASE_DEAD) |
|
|
221 return; |
|
|
222 phase = PHASE_DEAD; |
|
|
223 etime = time((time_t *) NULL); |
|
|
224 minutes = (etime-stime)/60; |
|
|
225 syslog(LOG_NOTICE, "Connection terminated, connected for %d minutes\n", |
|
|
226 minutes > 1 ? minutes : 1); |
|
|
227 } |
|
|
228 |
|
|
229 /* |
|
|
230 * LCP has gone down; it will either die or try to re-establish. |
|
|
231 */ |
|
|
232 void |
|
|
233 link_down(unit) |
|
|
234 int unit; |
|
|
235 { |
|
|
236 int i; |
|
|
237 struct protent *protp; |
|
|
238 |
|
|
239 db_printf("%s()\n",__PRETTY_FUNCTION__); |
|
|
240 for (i = 0; (protp = protocols[i]) != NULL; ++i) { |
|
|
241 if (!protp->enabled_flag) |
|
|
242 continue; |
|
|
243 if (protp->protocol != PPP_LCP && protp->lowerdown != NULL) |
|
|
244 (*protp->lowerdown)(unit); |
|
|
245 if (protp->protocol < 0xC000 && protp->close != NULL) |
|
|
246 (*protp->close)(unit, "LCP down"); |
|
|
247 } |
|
|
248 num_np_open = 0; |
|
|
249 num_np_up = 0; |
|
|
250 if (phase != PHASE_DEAD) |
|
|
251 phase = PHASE_TERMINATE; |
|
|
252 } |
|
|
253 |
|
|
254 /* |
|
|
255 * The link is established. |
|
|
256 * Proceed to the Dead, Authenticate or Network phase as appropriate. |
|
|
257 */ |
|
|
258 void |
|
|
259 link_established(unit) |
|
|
260 int unit; |
|
|
261 { |
|
|
262 int auth; |
|
|
263 lcp_options *wo = &lcp_wantoptions[unit]; |
|
|
264 lcp_options *go = &lcp_gotoptions[unit]; |
|
|
265 lcp_options *ho = &lcp_hisoptions[unit]; |
|
|
266 int i; |
|
|
267 struct protent *protp; |
|
|
268 |
|
|
269 /* |
|
|
270 * Tell higher-level protocols that LCP is up. |
|
|
271 */ |
|
|
272 for (i = 0; (protp = protocols[i]) != NULL; ++i) |
|
|
273 if (protp->protocol != PPP_LCP && protp->enabled_flag |
|
|
274 && protp->lowerup != NULL) |
|
|
275 (*protp->lowerup)(unit); |
|
|
276 |
|
|
277 if (auth_required && !(go->neg_chap || go->neg_upap)) { |
|
|
278 /* |
|
|
279 * We wanted the peer to authenticate itself, and it refused: |
|
|
280 * treat it as though it authenticated with PAP using a username |
|
|
281 * of "" and a password of "". If that's not OK, boot it out. |
|
|
282 */ |
|
|
283 if (!wo->neg_upap || !null_login(unit)) { |
|
|
284 syslog(LOG_WARNING, "peer refused to authenticate"); |
|
|
285 lcp_close(unit, "peer refused to authenticate"); |
|
|
286 return; |
|
|
287 } |
|
|
288 } |
|
|
289 |
|
|
290 phase = PHASE_AUTHENTICATE; |
|
|
291 auth = 0; |
|
|
292 if (go->neg_chap) { |
|
|
293 ChapAuthPeer(unit, our_name, go->chap_mdtype); |
|
|
294 auth |= CHAP_PEER; |
|
|
295 } else if (go->neg_upap) { |
|
|
296 upap_authpeer(unit); |
|
|
297 auth |= PAP_PEER; |
|
|
298 } |
|
|
299 if (ho->neg_chap) { |
|
|
300 ChapAuthWithPeer(unit, user, ho->chap_mdtype); |
|
|
301 auth |= CHAP_WITHPEER; |
|
|
302 } else if (ho->neg_upap) { |
|
|
303 if (passwd[0] == 0) { |
|
|
304 passwd_from_file = 1; |
|
|
305 if (!get_pap_passwd(passwd)) |
|
|
306 syslog(LOG_ERR, "No secret found for PAP login"); |
|
|
307 } |
|
|
308 upap_authwithpeer(unit, user, passwd); |
|
|
309 auth |= PAP_WITHPEER; |
|
|
310 } |
|
|
311 auth_pending[unit] = auth; |
|
|
312 |
|
|
313 if (!auth) |
|
|
314 network_phase(unit); |
|
|
315 } |
|
|
316 |
|
|
317 /* |
|
|
318 * Proceed to the network phase. |
|
|
319 */ |
|
|
320 static void |
|
|
321 network_phase(unit) |
|
|
322 int unit; |
|
|
323 { |
|
|
324 int i; |
|
|
325 struct protent *protp; |
|
|
326 |
|
|
327 #ifdef CBCP_SUPPORT |
|
|
328 /* |
|
|
329 * If we negotiated callback, do it now. |
|
|
330 */ |
|
|
331 if (go->neg_cbcp) { |
|
|
332 phase = PHASE_CALLBACK; |
|
|
333 (*cbcp_protent.open)(unit); |
|
|
334 return; |
|
|
335 } |
|
|
336 #endif |
|
|
337 |
|
|
338 phase = PHASE_NETWORK; |
|
|
339 for (i = 0; (protp = protocols[i]) != NULL; ++i) |
|
|
340 if (protp->protocol < 0xC000 && protp->enabled_flag |
|
|
341 && protp->open != NULL) { |
|
|
342 (*protp->open)(unit); |
|
|
343 if (protp->protocol != PPP_CCP) |
|
|
344 ++num_np_open; |
|
|
345 } |
|
|
346 |
|
|
347 if (num_np_open == 0) |
|
|
348 /* nothing to do */ |
|
|
349 lcp_close(0, "No network protocols running"); |
|
|
350 } |
|
|
351 |
|
|
352 /* |
|
|
353 * The peer has failed to authenticate himself using `protocol'. |
|
|
354 */ |
|
|
355 void |
|
|
356 auth_peer_fail(unit, protocol) |
|
|
357 int unit, protocol; |
|
|
358 { |
|
|
359 /* |
|
|
360 * Authentication failure: take the link down |
|
|
361 */ |
|
|
362 lcp_close(unit, "Authentication failed"); |
|
|
363 } |
|
|
364 |
|
|
365 /* |
|
|
366 * The peer has been successfully authenticated using `protocol'. |
|
|
367 */ |
|
|
368 void |
|
|
369 auth_peer_success(unit, protocol, name, namelen) |
|
|
370 int unit, protocol; |
|
|
371 char *name; |
|
|
372 int namelen; |
|
|
373 { |
|
|
374 int bit; |
|
|
375 |
|
|
376 switch (protocol) { |
|
|
377 case PPP_CHAP: |
|
|
378 bit = CHAP_PEER; |
|
|
379 break; |
|
|
380 case PPP_PAP: |
|
|
381 bit = PAP_PEER; |
|
|
382 break; |
|
|
383 default: |
|
|
384 syslog(LOG_WARNING, "auth_peer_success: unknown protocol %x", |
|
|
385 protocol); |
|
|
386 return; |
|
|
387 } |
|
|
388 |
|
|
389 /* |
|
|
390 * Save the authenticated name of the peer for later. |
|
|
391 */ |
|
|
392 if (namelen > sizeof(peer_authname) - 1) |
|
|
393 namelen = sizeof(peer_authname) - 1; |
|
|
394 BCOPY(name, peer_authname, namelen); |
|
|
395 peer_authname[namelen] = 0; |
|
|
396 |
|
|
397 /* |
|
|
398 * If we have overridden addresses based on auth info |
|
|
399 * then set that information now before continuing. |
|
|
400 */ |
|
|
401 auth_set_ip_addr(unit); |
|
|
402 |
|
|
403 /* |
|
|
404 * If there is no more authentication still to be done, |
|
|
405 * proceed to the network (or callback) phase. |
|
|
406 */ |
|
|
407 if ((auth_pending[unit] &= ~bit) == 0) |
|
|
408 network_phase(unit); |
|
|
409 } |
|
|
410 |
|
|
411 /* |
|
|
412 * We have failed to authenticate ourselves to the peer using `protocol'. |
|
|
413 */ |
|
|
414 void |
|
|
415 auth_withpeer_fail(unit, protocol) |
|
|
416 int unit, protocol; |
|
|
417 { |
|
|
418 if (passwd_from_file) |
|
|
419 BZERO(passwd, MAXSECRETLEN); |
|
|
420 /* |
|
|
421 * We've failed to authenticate ourselves to our peer. |
|
|
422 * He'll probably take the link down, and there's not much |
|
|
423 * we can do except wait for that. |
|
|
424 */ |
|
|
425 } |
|
|
426 |
|
|
427 /* |
|
|
428 * We have successfully authenticated ourselves with the peer using `protocol'. |
|
|
429 */ |
|
|
430 void |
|
|
431 auth_withpeer_success(unit, protocol) |
|
|
432 int unit, protocol; |
|
|
433 { |
|
|
434 int bit; |
|
|
435 |
|
|
436 switch (protocol) { |
|
|
437 case PPP_CHAP: |
|
|
438 bit = CHAP_WITHPEER; |
|
|
439 break; |
|
|
440 case PPP_PAP: |
|
|
441 if (passwd_from_file) |
|
|
442 BZERO(passwd, MAXSECRETLEN); |
|
|
443 bit = PAP_WITHPEER; |
|
|
444 break; |
|
|
445 default: |
|
|
446 syslog(LOG_WARNING, "auth_peer_success: unknown protocol %x", |
|
|
447 protocol); |
|
|
448 bit = 0; |
|
|
449 } |
|
|
450 |
|
|
451 /* |
|
|
452 * If we have overridden addresses based on auth info |
|
|
453 * then set that information now before continuing. |
|
|
454 */ |
|
|
455 auth_set_ip_addr(unit); |
|
|
456 |
|
|
457 /* |
|
|
458 * If there is no more authentication still being done, |
|
|
459 * proceed to the network (or callback) phase. |
|
|
460 */ |
|
|
461 if ((auth_pending[unit] &= ~bit) == 0) |
|
|
462 network_phase(unit); |
|
|
463 } |
|
|
464 |
|
|
465 |
|
|
466 /* |
|
|
467 * np_up - a network protocol has come up. |
|
|
468 */ |
|
|
469 void |
|
|
470 np_up(unit, proto) |
|
|
471 int unit, proto; |
|
|
472 { |
|
|
473 if (num_np_up == 0) { |
|
|
474 /* |
|
|
475 * At this point we consider that the link has come up successfully. |
|
|
476 */ |
|
|
477 need_holdoff = 0; |
|
|
478 |
|
|
479 if (idle_time_limit > 0) |
|
|
480 TIMEOUT(check_idle, NULL, idle_time_limit); |
|
|
481 |
|
|
482 /* |
|
|
483 * Set a timeout to close the connection once the maximum |
|
|
484 * connect time has expired. |
|
|
485 */ |
|
|
486 if (maxconnect > 0) |
|
|
487 TIMEOUT(connect_time_expired, 0, maxconnect); |
|
|
488 |
|
|
489 } |
|
|
490 ++num_np_up; |
|
|
491 } |
|
|
492 |
|
|
493 /* |
|
|
494 * np_down - a network protocol has gone down. |
|
|
495 */ |
|
|
496 void |
|
|
497 np_down(unit, proto) |
|
|
498 int unit, proto; |
|
|
499 { |
|
|
500 if (--num_np_up == 0 && idle_time_limit > 0) { |
|
|
501 UNTIMEOUT(check_idle, NULL); |
|
|
502 } |
|
|
503 } |
|
|
504 |
|
|
505 /* |
|
|
506 * np_finished - a network protocol has finished using the link. |
|
|
507 */ |
|
|
508 void |
|
|
509 np_finished(unit, proto) |
|
|
510 int unit, proto; |
|
|
511 { |
|
|
512 if (--num_np_open <= 0) { |
|
|
513 /* no further use for the link: shut up shop. */ |
|
|
514 lcp_close(0, "No network protocols running"); |
|
|
515 } |
|
|
516 } |
|
|
517 |
|
|
518 /* |
|
|
519 * check_idle - check whether the link has been idle for long |
|
|
520 * enough that we can shut it down. |
|
|
521 */ |
|
|
522 static void |
|
|
523 check_idle(arg) |
|
|
524 void *arg; |
|
|
525 { |
|
|
526 struct ppp_idle idle; |
|
|
527 time_t itime; |
|
|
528 |
|
|
529 if (!get_idle_time(0, &idle)) |
|
|
530 return; |
|
|
531 itime = MIN(idle.xmit_idle, idle.recv_idle); |
|
|
532 if (itime >= idle_time_limit) { |
|
|
533 /* link is idle: shut it down. */ |
|
|
534 syslog(LOG_INFO, "Terminating connection due to lack of activity."); |
|
|
535 lcp_close(0, "Link inactive"); |
|
|
536 } else { |
|
|
537 TIMEOUT(check_idle, NULL, idle_time_limit - itime); |
|
|
538 } |
|
|
539 } |
|
|
540 |
|
|
541 /* |
|
|
542 * connect_time_expired - log a message and close the connection. |
|
|
543 */ |
|
|
544 static void |
|
|
545 connect_time_expired(arg) |
|
|
546 void *arg; |
|
|
547 { |
|
|
548 syslog(LOG_INFO, "Connect time expired"); |
|
|
549 lcp_close(0, "Connect time expired"); /* Close connection */ |
|
|
550 } |
|
|
551 |
|
|
552 /* |
|
|
553 * auth_check_options - called to check authentication options. |
|
|
554 */ |
|
|
555 void |
|
|
556 auth_check_options() |
|
|
557 { |
|
|
558 lcp_options *wo = &lcp_wantoptions[0]; |
|
|
559 int can_auth; |
|
|
560 ipcp_options *ipwo = &ipcp_wantoptions[0]; |
|
|
561 u_int32_t remote; |
|
|
562 |
|
|
563 /* Default our_name to hostname, and user to our_name */ |
|
|
564 if (our_name[0] == 0 || usehostname) |
|
|
565 strcpy(our_name, cyg_ppp_hostname); |
|
|
566 if (user[0] == 0) |
|
|
567 strcpy(user, our_name); |
|
|
568 |
|
|
569 /* If authentication is required, ask peer for CHAP or PAP. */ |
|
|
570 if (auth_required && !wo->neg_chap && !wo->neg_upap) { |
|
|
571 wo->neg_chap = 1; |
|
|
572 wo->neg_upap = 1; |
|
|
573 } |
|
|
574 |
|
|
575 /* |
|
|
576 * Check whether we have appropriate secrets to use |
|
|
577 * to authenticate the peer. |
|
|
578 */ |
|
|
579 can_auth = wo->neg_upap && (uselogin || have_pap_secret()); |
|
|
580 if (!can_auth && wo->neg_chap) { |
|
|
581 remote = ipwo->accept_remote? 0: ipwo->hisaddr; |
|
|
582 can_auth = have_chap_secret(remote_name, our_name, remote); |
|
|
583 } |
|
|
584 |
|
|
585 if (auth_required && !can_auth) { |
|
|
586 option_error("peer authentication required but no suitable secret(s) found\n"); |
|
|
587 if (remote_name[0] == 0) |
|
|
588 option_error("for authenticating any peer to us (%s)\n", our_name); |
|
|
589 else |
|
|
590 option_error("for authenticating peer %s to us (%s)\n", |
|
|
591 remote_name, our_name); |
|
|
592 exit(1); |
|
|
593 } |
|
|
594 |
|
|
595 /* |
|
|
596 * Check whether the user tried to override certain values |
|
|
597 * set by root. |
|
|
598 */ |
|
|
599 if (!auth_required && auth_req_info.priv > 0) { |
|
|
600 if (!default_device && devnam_info.priv == 0) { |
|
|
601 option_error("can't override device name when noauth option used"); |
|
|
602 exit(1); |
|
|
603 } |
|
|
604 if ((connector != NULL && connector_info.priv == 0) |
|
|
605 || (disconnector != NULL && disconnector_info.priv == 0) |
|
|
606 || (welcomer != NULL && welcomer_info.priv == 0)) { |
|
|
607 option_error("can't override connect, disconnect or welcome"); |
|
|
608 option_error("option values when noauth option used"); |
|
|
609 exit(1); |
|
|
610 } |
|
|
611 } |
|
|
612 } |
|
|
613 |
|
|
614 /* |
|
|
615 * auth_reset - called when LCP is starting negotiations to recheck |
|
|
616 * authentication options, i.e. whether we have appropriate secrets |
|
|
617 * to use for authenticating ourselves and/or the peer. |
|
|
618 */ |
|
|
619 void |
|
|
620 auth_reset(unit) |
|
|
621 int unit; |
|
|
622 { |
|
|
623 lcp_options *go = &lcp_gotoptions[unit]; |
|
|
624 lcp_options *ao = &lcp_allowoptions[0]; |
|
|
625 ipcp_options *ipwo = &ipcp_wantoptions[0]; |
|
|
626 u_int32_t remote; |
|
|
627 ao->neg_upap = !refuse_pap && (passwd[0] != 0 || get_pap_passwd(NULL)); |
|
|
628 ao->neg_chap = !refuse_chap |
|
|
629 && have_chap_secret(user, remote_name, (u_int32_t)0); |
|
|
630 if (go->neg_upap && !uselogin && !have_pap_secret()) |
|
|
631 go->neg_upap = 0; |
|
|
632 if (go->neg_chap) { |
|
|
633 remote = ipwo->accept_remote? 0: ipwo->hisaddr; |
|
|
634 if (!have_chap_secret(remote_name, our_name, remote)) |
|
|
635 go->neg_chap = 0; |
|
|
636 } |
|
|
637 } |
|
|
638 |
|
|
639 |
|
|
640 /* |
|
|
641 * check_passwd - Check the user name and passwd against the PAP secrets |
|
|
642 * file. If requested, also check against the system password database, |
|
|
643 * and login the user if OK. |
|
|
644 * |
|
|
645 * returns: |
|
|
646 * UPAP_AUTHNAK: Authentication failed. |
|
|
647 * UPAP_AUTHACK: Authentication succeeded. |
|
|
648 * In either case, msg points to an appropriate message. |
|
|
649 */ |
|
|
650 int |
|
|
651 check_passwd(unit, auser, userlen, apasswd, passwdlen, msg, msglen) |
|
|
652 int unit; |
|
|
653 char *auser; |
|
|
654 int userlen; |
|
|
655 char *apasswd; |
|
|
656 int passwdlen; |
|
|
657 char **msg; |
|
|
658 int *msglen; |
|
|
659 { |
|
|
660 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
661 return 0; |
|
|
662 } |
|
|
663 |
|
|
664 /* |
|
|
665 * null_login - Check if a username of "" and a password of "" are |
|
|
666 * acceptable, and iff so, set the list of acceptable IP addresses |
|
|
667 * and return 1. |
|
|
668 */ |
|
|
669 static int |
|
|
670 null_login(unit) |
|
|
671 int unit; |
|
|
672 { |
|
|
673 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
674 return 0; |
|
|
675 } |
|
|
676 |
|
|
677 |
|
|
678 /* |
|
|
679 * get_pap_passwd - get a password for authenticating ourselves with |
|
|
680 * our peer using PAP. Returns 1 on success, 0 if no suitable password |
|
|
681 * could be found. |
|
|
682 */ |
|
|
683 static int |
|
|
684 get_pap_passwd(passwd) |
|
|
685 char *passwd; |
|
|
686 { |
|
|
687 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
688 return 0; |
|
|
689 } |
|
|
690 |
|
|
691 |
|
|
692 /* |
|
|
693 * have_pap_secret - check whether we have a PAP file with any |
|
|
694 * secrets that we could possibly use for authenticating the peer. |
|
|
695 */ |
|
|
696 static int |
|
|
697 have_pap_secret() |
|
|
698 { |
|
|
699 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
700 return 0; |
|
|
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, remote) |
|
|
712 char *client; |
|
|
713 char *server; |
|
|
714 u_int32_t remote; |
|
|
715 { |
|
|
716 // db_printf("%s(%s,%s,%d) called\n", __PRETTY_FUNCTION__,client,server,remote); |
|
|
717 return 1; |
|
|
718 } |
|
|
719 |
|
|
720 |
|
|
721 /* |
|
|
722 * get_secret - open the CHAP secret file and return the secret |
|
|
723 * for authenticating the given client on the given server. |
|
|
724 * (We could be either client or server). |
|
|
725 */ |
|
|
726 int |
|
|
727 get_secret(unit, client, server, secret, secret_len, save_addrs) |
|
|
728 int unit; |
|
|
729 char *client; |
|
|
730 char *server; |
|
|
731 char *secret; |
|
|
732 int *secret_len; |
|
|
733 int save_addrs; |
|
|
734 { |
|
|
735 db_printf("%s(%d,%s,%s,%08x,%d,%d) called\n", __PRETTY_FUNCTION__, |
|
|
736 unit, client, server, secret, secret_len, save_addrs); |
|
|
737 // We use the PAP password as the CHAP secret also. |
|
|
738 strncpy( secret, passwd, MAXNAMELEN ); |
|
|
739 *secret_len = strlen(secret); |
|
|
740 return 1; |
|
|
741 } |
|
|
742 |
|
|
743 static void |
|
|
744 auth_set_ip_addr(unit) |
|
|
745 int unit; |
|
|
746 { |
|
|
747 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
748 } |
|
|
749 |
|
|
750 /* |
|
|
751 * auth_ip_addr - check whether the peer is authorized to use |
|
|
752 * a given IP address. Returns 1 if authorized, 0 otherwise. |
|
|
753 */ |
|
|
754 int |
|
|
755 auth_ip_addr(unit, addr) |
|
|
756 int unit; |
|
|
757 u_int32_t addr; |
|
|
758 { |
|
|
759 return ip_addr_check(addr, addresses[unit]); |
|
|
760 } |
|
|
761 |
|
|
762 static int |
|
|
763 ip_addr_check(addr, addrs) |
|
|
764 u_int32_t addr; |
|
|
765 struct wordlist *addrs; |
|
|
766 { |
|
|
767 int x, y; |
|
|
768 // u_int32_t a, mask, ah; |
|
|
769 u_int32_t a = -1, mask; |
|
|
770 int accept; |
|
|
771 char *ptr_word, *ptr_mask; |
|
|
772 // struct hostent *hp; |
|
|
773 // struct netent *np; |
|
|
774 |
|
|
775 /* don't allow loopback or multicast address */ |
|
|
776 if (bad_ip_adrs(addr)) |
|
|
777 return 0; |
|
|
778 |
|
|
779 if (addrs == NULL) |
|
|
780 return !auth_required; /* no addresses authorized */ |
|
|
781 |
|
|
782 x = y = 0; |
|
|
783 for (; addrs != NULL; addrs = addrs->next) { |
|
|
784 y++; |
|
|
785 /* "-" means no addresses authorized, "*" means any address allowed */ |
|
|
786 ptr_word = addrs->word; |
|
|
787 if (strcmp(ptr_word, "-") == 0) |
|
|
788 break; |
|
|
789 if (strcmp(ptr_word, "*") == 0) |
|
|
790 return 1; |
|
|
791 |
|
|
792 /* |
|
|
793 * A colon in the string means that we wish to force a specific |
|
|
794 * local:remote address, but we ignore these for now. |
|
|
795 */ |
|
|
796 if (strchr(addrs->word, ':') != NULL) |
|
|
797 x++; |
|
|
798 else { |
|
|
799 |
|
|
800 accept = 1; |
|
|
801 if (*ptr_word == '!') { |
|
|
802 accept = 0; |
|
|
803 ++ptr_word; |
|
|
804 } |
|
|
805 |
|
|
806 mask = ~ (u_int32_t) 0; |
|
|
807 ptr_mask = strchr (ptr_word, '/'); |
|
|
808 if (ptr_mask != NULL) { |
|
|
809 int bit_count; |
|
|
810 |
|
|
811 bit_count = (int) strtol (ptr_mask+1, (char **) 0, 10); |
|
|
812 if (bit_count <= 0 || bit_count > 32) { |
|
|
813 syslog (LOG_WARNING, |
|
|
814 "invalid address length %s in auth. address list", |
|
|
815 ptr_mask); |
|
|
816 continue; |
|
|
817 } |
|
|
818 *ptr_mask = '\0'; |
|
|
819 mask <<= 32 - bit_count; |
|
|
820 } |
|
|
821 |
|
|
822 #ifndef __ECOS |
|
|
823 hp = gethostbyname(ptr_word); |
|
|
824 if (hp != NULL && hp->h_addrtype == AF_INET) { |
|
|
825 a = *(u_int32_t *)hp->h_addr; |
|
|
826 } else { |
|
|
827 np = getnetbyname (ptr_word); |
|
|
828 if (np != NULL && np->n_addrtype == AF_INET) { |
|
|
829 a = htonl (*(u_int32_t *)np->n_net); |
|
|
830 if (ptr_mask == NULL) { |
|
|
831 /* calculate appropriate mask for net */ |
|
|
832 ah = ntohl(a); |
|
|
833 if (IN_CLASSA(ah)) |
|
|
834 mask = IN_CLASSA_NET; |
|
|
835 else if (IN_CLASSB(ah)) |
|
|
836 mask = IN_CLASSB_NET; |
|
|
837 else if (IN_CLASSC(ah)) |
|
|
838 mask = IN_CLASSC_NET; |
|
|
839 } |
|
|
840 } else { |
|
|
841 a = inet_addr (ptr_word); |
|
|
842 } |
|
|
843 } |
|
|
844 #endif |
|
|
845 |
|
|
846 if (ptr_mask != NULL) |
|
|
847 *ptr_mask = '/'; |
|
|
848 |
|
|
849 if (a == (u_int32_t)-1L) |
|
|
850 syslog (LOG_WARNING, |
|
|
851 "unknown host %s in auth. address list", |
|
|
852 addrs->word); |
|
|
853 else |
|
|
854 /* Here a and addr are in network byte order, |
|
|
855 and mask is in host order. */ |
|
|
856 if (((addr ^ a) & htonl(mask)) == 0) |
|
|
857 return accept; |
|
|
858 } /* else */ |
|
|
859 } |
|
|
860 return x == y; /* not in list => can't have it */ |
|
|
861 } |
|
|
862 |
|
|
863 /* |
|
|
864 * bad_ip_adrs - return 1 if the IP address is one we don't want |
|
|
865 * to use, such as an address in the loopback net or a multicast address. |
|
|
866 * addr is in network byte order. |
|
|
867 */ |
|
|
868 int |
|
|
869 bad_ip_adrs(addr) |
|
|
870 u_int32_t addr; |
|
|
871 { |
|
|
872 addr = ntohl(addr); |
|
|
873 return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET |
|
|
874 || IN_MULTICAST(addr) || IN_BADCLASS(addr); |
|
|
875 } |
|
|
876 |
|
|
877 /* |
|
|
878 * check_access - complain if a secret file has too-liberal permissions. |
|
|
879 */ |
|
|
880 void |
|
|
881 check_access(f, filename) |
|
|
882 FILE *f; |
|
|
883 char *filename; |
|
|
884 { |
|
|
885 struct stat sbuf; |
|
|
886 |
|
|
887 if (fstat(fileno(f), &sbuf) < 0) { |
|
|
888 syslog(LOG_WARNING, "cannot stat secret file %s: %m", filename); |
|
|
889 } else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) { |
|
|
890 syslog(LOG_WARNING, "Warning - secret file %s has world and/or group access", filename); |
|
|
891 } |
|
|
892 } |