]> git.sur5r.net Git - freertos/blob - Demo/Common/ethernet/lwIP/netif/ppp/auth.c
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@82 1d2547de-c912-0410-9cb9...
[freertos] / Demo / Common / ethernet / lwIP / netif / ppp / auth.c
1 /*****************************************************************************\r
2 * auth.c - Network Authentication and Phase Control program file.\r
3 *\r
4 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.\r
5 * Copyright (c) 1997 by Global Election Systems Inc.  All rights reserved.\r
6 *\r
7 * The authors hereby grant permission to use, copy, modify, distribute,\r
8 * and license this software and its documentation for any purpose, provided\r
9 * that existing copyright notices are retained in all copies and that this\r
10 * notice and the following disclaimer are included verbatim in any \r
11 * distributions. No written agreement, license, or royalty fee is required\r
12 * for any of the authorized uses.\r
13 *\r
14 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR\r
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\r
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. \r
17 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
24 *\r
25 ******************************************************************************\r
26 * REVISION HISTORY\r
27 *\r
28 * 03-01-01 Marc Boucher <marc@mbsi.ca>\r
29 *   Ported to lwIP.\r
30 * 97-12-08 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.\r
31 *   Ported from public pppd code.\r
32 *****************************************************************************/\r
33 /*\r
34  * auth.c - PPP authentication and phase control.\r
35  *\r
36  * Copyright (c) 1993 The Australian National University.\r
37  * All rights reserved.\r
38  *\r
39  * Redistribution and use in source and binary forms are permitted\r
40  * provided that the above copyright notice and this paragraph are\r
41  * duplicated in all such forms and that any documentation,\r
42  * advertising materials, and other materials related to such\r
43  * distribution and use acknowledge that the software was developed\r
44  * by the Australian National University.  The name of the University\r
45  * may not be used to endorse or promote products derived from this\r
46  * software without specific prior written permission.\r
47  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR\r
48  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED\r
49  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.\r
50  *\r
51  * Copyright (c) 1989 Carnegie Mellon University.\r
52  * All rights reserved.\r
53  *\r
54  * Redistribution and use in source and binary forms are permitted\r
55  * provided that the above copyright notice and this paragraph are\r
56  * duplicated in all such forms and that any documentation,\r
57  * advertising materials, and other materials related to such\r
58  * distribution and use acknowledge that the software was developed\r
59  * by Carnegie Mellon University.  The name of the\r
60  * University may not be used to endorse or promote products derived\r
61  * from this software without specific prior written permission.\r
62  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR\r
63  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED\r
64  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.\r
65  */\r
66 \r
67 #include "ppp.h"\r
68 #if PPP_SUPPORT > 0\r
69 #include "fsm.h"\r
70 #include "lcp.h"\r
71 #include "pap.h"\r
72 #include "chap.h"\r
73 #include "auth.h"\r
74 #include "ipcp.h"\r
75 \r
76 #if CBCP_SUPPORT > 0\r
77 #include "cbcp.h"\r
78 #endif\r
79 \r
80 #include "pppdebug.h"\r
81 \r
82 \r
83 /*************************/\r
84 /*** LOCAL DEFINITIONS ***/\r
85 /*************************/\r
86 \r
87 /* Bits in auth_pending[] */\r
88 #define PAP_WITHPEER    1\r
89 #define PAP_PEER    2\r
90 #define CHAP_WITHPEER   4\r
91 #define CHAP_PEER   8\r
92 \r
93 \r
94                                                                     \r
95 /************************/\r
96 /*** LOCAL DATA TYPES ***/\r
97 /************************/\r
98 /* Used for storing a sequence of words.  Usually malloced. */\r
99 struct wordlist {\r
100     struct wordlist *next;\r
101     char        word[1];\r
102 };\r
103 \r
104 \r
105 \r
106 /***********************************/\r
107 /*** LOCAL FUNCTION DECLARATIONS ***/\r
108 /***********************************/\r
109 extern char *crypt (const char *, const char *);\r
110 \r
111 /* Prototypes for procedures local to this file. */\r
112 \r
113 static void network_phase (int);\r
114 static void check_idle (void *);\r
115 static void connect_time_expired (void *);\r
116 #if 0\r
117 static int  login (char *, char *, char **, int *);\r
118 #endif\r
119 static void logout (void);\r
120 static int  null_login (int);\r
121 static int  get_pap_passwd (int, char *, char *);\r
122 static int  have_pap_secret (void);\r
123 static int  have_chap_secret (char *, char *, u32_t);\r
124 static int  ip_addr_check (u32_t, struct wordlist *);\r
125 #if 0 /* PAP_SUPPORT > 0 || CHAP_SUPPORT > 0 */\r
126 static void set_allowed_addrs(int unit, struct wordlist *addrs);\r
127 static void free_wordlist (struct wordlist *);\r
128 #endif\r
129 #if CBCP_SUPPORT > 0\r
130 static void callback_phase (int);\r
131 #endif\r
132 \r
133 \r
134 /******************************/\r
135 /*** PUBLIC DATA STRUCTURES ***/\r
136 /******************************/\r
137 \r
138 \r
139 /*****************************/\r
140 /*** LOCAL DATA STRUCTURES ***/\r
141 /*****************************/\r
142 #if PAP_SUPPORT > 0 || CHAP_SUPPORT > 0\r
143 /* The name by which the peer authenticated itself to us. */\r
144 static char peer_authname[MAXNAMELEN];\r
145 #endif\r
146 \r
147 /* Records which authentication operations haven't completed yet. */\r
148 static int auth_pending[NUM_PPP];\r
149 \r
150 /* Set if we have successfully called login() */\r
151 static int logged_in;\r
152 \r
153 /* Set if we have run the /etc/ppp/auth-up script. */\r
154 static int did_authup;\r
155 \r
156 /* List of addresses which the peer may use. */\r
157 static struct wordlist *addresses[NUM_PPP];\r
158 \r
159 /* Number of network protocols which we have opened. */\r
160 static int num_np_open;\r
161 \r
162 /* Number of network protocols which have come up. */\r
163 static int num_np_up;\r
164 \r
165 #if PAP_SUPPORT > 0 || CHAP_SUPPORT > 0\r
166 /* Set if we got the contents of passwd[] from the pap-secrets file. */\r
167 static int passwd_from_file;\r
168 #endif\r
169 \r
170 \r
171 \r
172 /***********************************/\r
173 /*** PUBLIC FUNCTION DEFINITIONS ***/\r
174 /***********************************/\r
175 /*\r
176  * An Open on LCP has requested a change from Dead to Establish phase.\r
177  * Do what's necessary to bring the physical layer up.\r
178  */\r
179 void link_required(int unit)\r
180 {\r
181     AUTHDEBUG((LOG_INFO, "link_required: %d\n", unit));\r
182 }\r
183 \r
184 /*\r
185  * LCP has terminated the link; go to the Dead phase and take the\r
186  * physical layer down.\r
187  */\r
188 void link_terminated(int unit)\r
189 {\r
190     AUTHDEBUG((LOG_INFO, "link_terminated: %d\n", unit));\r
191     \r
192     if (lcp_phase[unit] == PHASE_DEAD)\r
193         return;\r
194     if (logged_in)\r
195         logout();\r
196     lcp_phase[unit] = PHASE_DEAD;\r
197     AUTHDEBUG((LOG_NOTICE, "Connection terminated.\n"));\r
198         pppMainWakeup(unit);\r
199 }\r
200 \r
201 /*\r
202  * LCP has gone down; it will either die or try to re-establish.\r
203  */\r
204 void link_down(int unit)\r
205 {\r
206     int i;\r
207     struct protent *protp;\r
208     \r
209     AUTHDEBUG((LOG_INFO, "link_down: %d\n", unit));\r
210     if (did_authup) {\r
211         /* XXX Do link down processing. */\r
212         did_authup = 0;\r
213     }\r
214     for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) {\r
215         if (!protp->enabled_flag)\r
216             continue;\r
217         if (protp->protocol != PPP_LCP && protp->lowerdown != NULL)\r
218             (*protp->lowerdown)(unit);\r
219         if (protp->protocol < 0xC000 && protp->close != NULL)\r
220             (*protp->close)(unit, "LCP down");\r
221     }\r
222     num_np_open = 0;\r
223     num_np_up = 0;\r
224     if (lcp_phase[unit] != PHASE_DEAD)\r
225         lcp_phase[unit] = PHASE_TERMINATE;\r
226         pppMainWakeup(unit);\r
227 }\r
228 \r
229 /*\r
230  * The link is established.\r
231  * Proceed to the Dead, Authenticate or Network phase as appropriate.\r
232  */\r
233 void link_established(int unit)\r
234 {\r
235     int auth;\r
236     int i;\r
237     struct protent *protp;\r
238     lcp_options *wo = &lcp_wantoptions[unit];\r
239     lcp_options *go = &lcp_gotoptions[unit];\r
240 #if PAP_SUPPORT > 0 || CHAP_SUPPORT > 0\r
241     lcp_options *ho = &lcp_hisoptions[unit];\r
242 #endif\r
243     \r
244     AUTHDEBUG((LOG_INFO, "link_established: %d\n", unit));\r
245     /*\r
246      * Tell higher-level protocols that LCP is up.\r
247      */\r
248     for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i)\r
249         if (protp->protocol != PPP_LCP && protp->enabled_flag\r
250                 && protp->lowerup != NULL)\r
251             (*protp->lowerup)(unit);\r
252     \r
253     if (ppp_settings.auth_required && !(go->neg_chap || go->neg_upap)) {\r
254         /*\r
255          * We wanted the peer to authenticate itself, and it refused:\r
256          * treat it as though it authenticated with PAP using a username\r
257          * of "" and a password of "".  If that's not OK, boot it out.\r
258          */\r
259         if (!wo->neg_upap || !null_login(unit)) {\r
260             AUTHDEBUG((LOG_WARNING, "peer refused to authenticate\n"));\r
261             lcp_close(unit, "peer refused to authenticate");\r
262             return;\r
263         }\r
264     }\r
265     \r
266     lcp_phase[unit] = PHASE_AUTHENTICATE;\r
267     auth = 0;\r
268 #if CHAP_SUPPORT > 0\r
269     if (go->neg_chap) {\r
270         ChapAuthPeer(unit, ppp_settings.our_name, go->chap_mdtype);\r
271         auth |= CHAP_PEER;\r
272     } \r
273 #endif\r
274 #if PAP_SUPPORT > 0 && CHAP_SUPPORT > 0\r
275     else\r
276 #endif\r
277 #if PAP_SUPPORT > 0\r
278     if (go->neg_upap) {\r
279         upap_authpeer(unit);\r
280         auth |= PAP_PEER;\r
281     }\r
282 #endif\r
283 #if CHAP_SUPPORT > 0\r
284     if (ho->neg_chap) {\r
285         ChapAuthWithPeer(unit, ppp_settings.user, ho->chap_mdtype);\r
286         auth |= CHAP_WITHPEER;\r
287     }\r
288 #endif\r
289 #if PAP_SUPPORT > 0 && CHAP_SUPPORT > 0\r
290     else\r
291 #endif\r
292 #if PAP_SUPPORT > 0\r
293     if (ho->neg_upap) {\r
294         if (ppp_settings.passwd[0] == 0) {\r
295             passwd_from_file = 1;\r
296             if (!get_pap_passwd(unit, ppp_settings.user, ppp_settings.passwd))\r
297                 AUTHDEBUG((LOG_ERR, "No secret found for PAP login\n"));\r
298         }\r
299         upap_authwithpeer(unit, ppp_settings.user, ppp_settings.passwd);\r
300         auth |= PAP_WITHPEER;\r
301     }\r
302 #endif\r
303     auth_pending[unit] = auth;\r
304     \r
305     if (!auth)\r
306         network_phase(unit);\r
307 }\r
308 \r
309 \r
310 /*\r
311  * The peer has failed to authenticate himself using `protocol'.\r
312  */\r
313 void auth_peer_fail(int unit, u16_t protocol)\r
314 {\r
315     AUTHDEBUG((LOG_INFO, "auth_peer_fail: %d proto=%X\n", unit, protocol));\r
316     /*\r
317      * Authentication failure: take the link down\r
318      */\r
319     lcp_close(unit, "Authentication failed");\r
320 }\r
321 \r
322 \r
323 #if PAP_SUPPORT > 0 || CHAP_SUPPORT > 0\r
324 /*\r
325  * The peer has been successfully authenticated using `protocol'.\r
326  */\r
327 void auth_peer_success(int unit, u16_t protocol, char *name, int namelen)\r
328 {\r
329     int pbit;\r
330     \r
331     AUTHDEBUG((LOG_INFO, "auth_peer_success: %d proto=%X\n", unit, protocol));\r
332     switch (protocol) {\r
333     case PPP_CHAP:\r
334         pbit = CHAP_PEER;\r
335         break;\r
336     case PPP_PAP:\r
337         pbit = PAP_PEER;\r
338         break;\r
339     default:\r
340         AUTHDEBUG((LOG_WARNING, "auth_peer_success: unknown protocol %x\n",\r
341                protocol));\r
342         return;\r
343     }\r
344     \r
345     /*\r
346      * Save the authenticated name of the peer for later.\r
347      */\r
348     if (namelen > sizeof(peer_authname) - 1)\r
349         namelen = sizeof(peer_authname) - 1;\r
350     BCOPY(name, peer_authname, namelen);\r
351     peer_authname[namelen] = 0;\r
352     \r
353     /*\r
354      * If there is no more authentication still to be done,\r
355      * proceed to the network (or callback) phase.\r
356      */\r
357     if ((auth_pending[unit] &= ~pbit) == 0)\r
358         network_phase(unit);\r
359 }\r
360 \r
361 /*\r
362  * We have failed to authenticate ourselves to the peer using `protocol'.\r
363  */\r
364 void auth_withpeer_fail(int unit, u16_t protocol)\r
365 {\r
366     int errCode = PPPERR_AUTHFAIL;\r
367     \r
368     AUTHDEBUG((LOG_INFO, "auth_withpeer_fail: %d proto=%X\n", unit, protocol));\r
369     if (passwd_from_file)\r
370         BZERO(ppp_settings.passwd, MAXSECRETLEN);\r
371     /* \r
372      * XXX Warning: the unit number indicates the interface which is\r
373      * not necessarily the PPP connection.  It works here as long\r
374      * as we are only supporting PPP interfaces.\r
375      */\r
376     pppIOCtl(unit, PPPCTLS_ERRCODE, &errCode);\r
377 \r
378     /*\r
379      * We've failed to authenticate ourselves to our peer.\r
380      * He'll probably take the link down, and there's not much\r
381      * we can do except wait for that.\r
382      */\r
383 }\r
384 \r
385 /*\r
386  * We have successfully authenticated ourselves with the peer using `protocol'.\r
387  */\r
388 void auth_withpeer_success(int unit, u16_t protocol)\r
389 {\r
390     int pbit;\r
391     \r
392     AUTHDEBUG((LOG_INFO, "auth_withpeer_success: %d proto=%X\n", unit, protocol));\r
393     switch (protocol) {\r
394     case PPP_CHAP:\r
395         pbit = CHAP_WITHPEER;\r
396         break;\r
397     case PPP_PAP:\r
398         if (passwd_from_file)\r
399             BZERO(ppp_settings.passwd, MAXSECRETLEN);\r
400         pbit = PAP_WITHPEER;\r
401         break;\r
402     default:\r
403         AUTHDEBUG((LOG_WARNING, "auth_peer_success: unknown protocol %x\n",\r
404                protocol));\r
405         pbit = 0;\r
406     }\r
407     \r
408     /*\r
409      * If there is no more authentication still being done,\r
410      * proceed to the network (or callback) phase.\r
411      */\r
412     if ((auth_pending[unit] &= ~pbit) == 0)\r
413         network_phase(unit);\r
414 }\r
415 #endif\r
416 \r
417 \r
418 /*\r
419  * np_up - a network protocol has come up.\r
420  */\r
421 void np_up(int unit, u16_t proto)\r
422 {\r
423     AUTHDEBUG((LOG_INFO, "np_up: %d proto=%X\n", unit, proto));\r
424     if (num_np_up == 0) {\r
425         AUTHDEBUG((LOG_INFO, "np_up: maxconnect=%d idle_time_limit=%d\n",ppp_settings.maxconnect,ppp_settings.idle_time_limit));\r
426         /*\r
427          * At this point we consider that the link has come up successfully.\r
428          */\r
429         if (ppp_settings.idle_time_limit > 0)\r
430             TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit);\r
431         \r
432         /*\r
433          * Set a timeout to close the connection once the maximum\r
434          * connect time has expired.\r
435          */\r
436         if (ppp_settings.maxconnect > 0)\r
437             TIMEOUT(connect_time_expired, 0, ppp_settings.maxconnect);\r
438     }\r
439     ++num_np_up;\r
440 }\r
441 \r
442 /*\r
443  * np_down - a network protocol has gone down.\r
444  */\r
445 void np_down(int unit, u16_t proto)\r
446 {\r
447     AUTHDEBUG((LOG_INFO, "np_down: %d proto=%X\n", unit, proto));\r
448     if (--num_np_up == 0 && ppp_settings.idle_time_limit > 0) {\r
449         UNTIMEOUT(check_idle, NULL);\r
450     }\r
451 }\r
452 \r
453 /*\r
454  * np_finished - a network protocol has finished using the link.\r
455  */\r
456 void np_finished(int unit, u16_t proto)\r
457 {\r
458     AUTHDEBUG((LOG_INFO, "np_finished: %d proto=%X\n", unit, proto));\r
459     if (--num_np_open <= 0) {\r
460         /* no further use for the link: shut up shop. */\r
461         lcp_close(0, "No network protocols running");\r
462     }\r
463 }\r
464 \r
465 /*\r
466  * auth_reset - called when LCP is starting negotiations to recheck\r
467  * authentication options, i.e. whether we have appropriate secrets\r
468  * to use for authenticating ourselves and/or the peer.\r
469  */\r
470 void auth_reset(int unit)\r
471 {\r
472     lcp_options *go = &lcp_gotoptions[unit];\r
473     lcp_options *ao = &lcp_allowoptions[0];\r
474     ipcp_options *ipwo = &ipcp_wantoptions[0];\r
475     u32_t remote;\r
476     \r
477     AUTHDEBUG((LOG_INFO, "auth_reset: %d\n", unit));\r
478     ao->neg_upap = !ppp_settings.refuse_pap && (ppp_settings.passwd[0] != 0 || get_pap_passwd(unit, NULL, NULL));\r
479     ao->neg_chap = !ppp_settings.refuse_chap && ppp_settings.passwd[0] != 0 /*have_chap_secret(ppp_settings.user, ppp_settings.remote_name, (u32_t)0)*/;\r
480     \r
481     if (go->neg_upap && !have_pap_secret())\r
482         go->neg_upap = 0;\r
483     if (go->neg_chap) {\r
484         remote = ipwo->accept_remote? 0: ipwo->hisaddr;\r
485         if (!have_chap_secret(ppp_settings.remote_name, ppp_settings.our_name, remote))\r
486             go->neg_chap = 0;\r
487     }\r
488 }\r
489 \r
490 \r
491 #if PAP_SUPPORT > 0\r
492 /*\r
493  * check_passwd - Check the user name and passwd against the PAP secrets\r
494  * file.  If requested, also check against the system password database,\r
495  * and login the user if OK.\r
496  *\r
497  * returns:\r
498  *  UPAP_AUTHNAK: Authentication failed.\r
499  *  UPAP_AUTHACK: Authentication succeeded.\r
500  * In either case, msg points to an appropriate message.\r
501  */\r
502 int check_passwd(\r
503         int unit,\r
504         char *auser,\r
505         int userlen,\r
506         char *apasswd,\r
507         int passwdlen,\r
508         char **msg,\r
509         int *msglen\r
510 )\r
511 {\r
512 #if 1\r
513         *msg = (char *) 0;\r
514         return UPAP_AUTHACK;     /* XXX Assume all entries OK. */\r
515 #else\r
516     int ret = 0;\r
517     struct wordlist *addrs = NULL;\r
518     char passwd[256], user[256];\r
519     char secret[MAXWORDLEN];\r
520     static u_short attempts = 0;\r
521     \r
522     /*\r
523      * Make copies of apasswd and auser, then null-terminate them.\r
524      */\r
525     BCOPY(apasswd, passwd, passwdlen);\r
526     passwd[passwdlen] = '\0';\r
527     BCOPY(auser, user, userlen);\r
528     user[userlen] = '\0';\r
529     *msg = (char *) 0;\r
530 \r
531     /* XXX Validate user name and password. */\r
532     ret = UPAP_AUTHACK;     /* XXX Assume all entries OK. */\r
533         \r
534     if (ret == UPAP_AUTHNAK) {\r
535         if (*msg == (char *) 0)\r
536             *msg = "Login incorrect";\r
537         *msglen = strlen(*msg);\r
538         /*\r
539          * Frustrate passwd stealer programs.\r
540          * Allow 10 tries, but start backing off after 3 (stolen from login).\r
541          * On 10'th, drop the connection.\r
542          */\r
543         if (attempts++ >= 10) {\r
544             AUTHDEBUG((LOG_WARNING, "%d LOGIN FAILURES BY %s\n", attempts, user));\r
545             /*ppp_panic("Excess Bad Logins");*/\r
546         }\r
547         if (attempts > 3) {\r
548             sys_msleep((attempts - 3) * 5);\r
549         }\r
550         if (addrs != NULL) {\r
551             free_wordlist(addrs);\r
552         }\r
553     } else {\r
554         attempts = 0;           /* Reset count */\r
555         if (*msg == (char *) 0)\r
556             *msg = "Login ok";\r
557         *msglen = strlen(*msg);\r
558         set_allowed_addrs(unit, addrs);\r
559     }\r
560     \r
561     BZERO(passwd, sizeof(passwd));\r
562     BZERO(secret, sizeof(secret));\r
563     \r
564     return ret;\r
565 #endif\r
566 }\r
567 #endif\r
568 \r
569 \r
570 /*\r
571  * auth_ip_addr - check whether the peer is authorized to use\r
572  * a given IP address.  Returns 1 if authorized, 0 otherwise.\r
573  */\r
574 int auth_ip_addr(int unit, u32_t addr)\r
575 {\r
576     return ip_addr_check(addr, addresses[unit]);\r
577 }\r
578 \r
579 /*\r
580  * bad_ip_adrs - return 1 if the IP address is one we don't want\r
581  * to use, such as an address in the loopback net or a multicast address.\r
582  * addr is in network byte order.\r
583  */\r
584 int bad_ip_adrs(u32_t addr)\r
585 {\r
586     addr = ntohl(addr);\r
587     return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET\r
588         || IN_MULTICAST(addr) || IN_BADCLASS(addr);\r
589 }\r
590 \r
591 \r
592 #if CHAP_SUPPORT > 0\r
593 /*\r
594  * get_secret - open the CHAP secret file and return the secret\r
595  * for authenticating the given client on the given server.\r
596  * (We could be either client or server).\r
597  */\r
598 int get_secret(\r
599     int unit,\r
600     char *client,\r
601     char *server,\r
602     char *secret,\r
603     int *secret_len,\r
604     int save_addrs\r
605 )\r
606 {\r
607 #if 1\r
608     int len;\r
609     struct wordlist *addrs;\r
610     \r
611     addrs = NULL;\r
612 \r
613     if(!client || !client[0] || strcmp(client, ppp_settings.user)) {\r
614         return 0;\r
615     }\r
616 \r
617     len = strlen(ppp_settings.passwd);\r
618     if (len > MAXSECRETLEN) {\r
619         AUTHDEBUG((LOG_ERR, "Secret for %s on %s is too long\n", client, server));\r
620         len = MAXSECRETLEN;\r
621     }\r
622     BCOPY(ppp_settings.passwd, secret, len);\r
623     *secret_len = len;\r
624     \r
625     return 1;\r
626 #else\r
627     int ret = 0, len;\r
628     struct wordlist *addrs;\r
629     char secbuf[MAXWORDLEN];\r
630     \r
631     addrs = NULL;\r
632     secbuf[0] = 0;\r
633 \r
634     /* XXX Find secret. */  \r
635     if (ret < 0)\r
636         return 0;\r
637     \r
638     if (save_addrs)\r
639         set_allowed_addrs(unit, addrs);\r
640     \r
641     len = strlen(secbuf);\r
642     if (len > MAXSECRETLEN) {\r
643         AUTHDEBUG((LOG_ERR, "Secret for %s on %s is too long\n", client, server));\r
644         len = MAXSECRETLEN;\r
645     }\r
646     BCOPY(secbuf, secret, len);\r
647     BZERO(secbuf, sizeof(secbuf));\r
648     *secret_len = len;\r
649     \r
650     return 1;\r
651 #endif\r
652 }\r
653 #endif\r
654 \r
655 \r
656 #if 0 /* UNUSED */\r
657 /*\r
658  * auth_check_options - called to check authentication options.\r
659  */\r
660 void auth_check_options(void)\r
661 {\r
662     lcp_options *wo = &lcp_wantoptions[0];\r
663     int can_auth;\r
664     ipcp_options *ipwo = &ipcp_wantoptions[0];\r
665     u32_t remote;\r
666     \r
667     /* Default our_name to hostname, and user to our_name */\r
668     if (ppp_settings.our_name[0] == 0 || ppp_settings.usehostname)\r
669         strcpy(ppp_settings.our_name, ppp_settings.hostname);\r
670     if (ppp_settings.user[0] == 0)\r
671         strcpy(ppp_settings.user, ppp_settings.our_name);\r
672     \r
673     /* If authentication is required, ask peer for CHAP or PAP. */\r
674     if (ppp_settings.auth_required && !wo->neg_chap && !wo->neg_upap) {\r
675         wo->neg_chap = 1;\r
676         wo->neg_upap = 1;\r
677     }\r
678     \r
679     /*\r
680      * Check whether we have appropriate secrets to use\r
681      * to authenticate the peer.\r
682      */\r
683     can_auth = wo->neg_upap && have_pap_secret();\r
684     if (!can_auth && wo->neg_chap) {\r
685         remote = ipwo->accept_remote? 0: ipwo->hisaddr;\r
686         can_auth = have_chap_secret(ppp_settings.remote_name, ppp_settings.our_name, remote);\r
687     }\r
688     \r
689     if (ppp_settings.auth_required && !can_auth) {\r
690         ppp_panic("No auth secret");\r
691     }\r
692 }\r
693 #endif\r
694 \r
695 \r
696 /**********************************/\r
697 /*** LOCAL FUNCTION DEFINITIONS ***/\r
698 /**********************************/\r
699 /*\r
700  * Proceed to the network phase.\r
701  */\r
702 static void network_phase(int unit)\r
703 {\r
704     int i;\r
705     struct protent *protp;\r
706     lcp_options *go = &lcp_gotoptions[unit];\r
707     \r
708     /*\r
709      * If the peer had to authenticate, run the auth-up script now.\r
710      */\r
711     if ((go->neg_chap || go->neg_upap) && !did_authup) {\r
712         /* XXX Do setup for peer authentication. */\r
713         did_authup = 1;\r
714     }\r
715     \r
716 #if CBCP_SUPPORT > 0\r
717     /*\r
718      * If we negotiated callback, do it now.\r
719      */\r
720     if (go->neg_cbcp) {\r
721         lcp_phase[unit] = PHASE_CALLBACK;\r
722         (*cbcp_protent.open)(unit);\r
723         return;\r
724     }\r
725 #endif\r
726     \r
727     lcp_phase[unit] = PHASE_NETWORK;\r
728     for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i)\r
729         if (protp->protocol < 0xC000 && protp->enabled_flag\r
730                 && protp->open != NULL) {\r
731             (*protp->open)(unit);\r
732             if (protp->protocol != PPP_CCP)\r
733                 ++num_np_open;\r
734         }\r
735     \r
736     if (num_np_open == 0)\r
737         /* nothing to do */\r
738         lcp_close(0, "No network protocols running");\r
739 }\r
740 \r
741 /*\r
742  * check_idle - check whether the link has been idle for long\r
743  * enough that we can shut it down.\r
744  */\r
745 static void check_idle(void *arg)\r
746 {\r
747     struct ppp_idle idle;\r
748     u_short itime;\r
749     \r
750         (void)arg;\r
751     if (!get_idle_time(0, &idle))\r
752         return;\r
753     itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle);\r
754     if (itime >= ppp_settings.idle_time_limit) {\r
755         /* link is idle: shut it down. */\r
756         AUTHDEBUG((LOG_INFO, "Terminating connection due to lack of activity.\n"));\r
757         lcp_close(0, "Link inactive");\r
758     } else {\r
759         TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit - itime);\r
760     }\r
761 }\r
762 \r
763 /*\r
764  * connect_time_expired - log a message and close the connection.\r
765  */\r
766 static void connect_time_expired(void *arg)\r
767 {\r
768         (void)arg;\r
769 \r
770     AUTHDEBUG((LOG_INFO, "Connect time expired\n"));\r
771     lcp_close(0, "Connect time expired");   /* Close connection */\r
772 }\r
773 \r
774 #if 0\r
775 /*\r
776  * login - Check the user name and password against the system\r
777  * password database, and login the user if OK.\r
778  *\r
779  * returns:\r
780  *  UPAP_AUTHNAK: Login failed.\r
781  *  UPAP_AUTHACK: Login succeeded.\r
782  * In either case, msg points to an appropriate message.\r
783  */\r
784 static int login(char *user, char *passwd, char **msg, int *msglen)\r
785 {\r
786     /* XXX Fail until we decide that we want to support logins. */\r
787     return (UPAP_AUTHNAK);\r
788 }\r
789 #endif\r
790 \r
791 /*\r
792  * logout - Logout the user.\r
793  */\r
794 static void logout(void)\r
795 {\r
796     logged_in = 0;\r
797 }\r
798 \r
799 \r
800 /*\r
801  * null_login - Check if a username of "" and a password of "" are\r
802  * acceptable, and iff so, set the list of acceptable IP addresses\r
803  * and return 1.\r
804  */\r
805 static int null_login(int unit)\r
806 {\r
807         (void)unit;\r
808     /* XXX Fail until we decide that we want to support logins. */\r
809     return 0;\r
810 }\r
811 \r
812 \r
813 /*\r
814  * get_pap_passwd - get a password for authenticating ourselves with\r
815  * our peer using PAP.  Returns 1 on success, 0 if no suitable password\r
816  * could be found.\r
817  */\r
818 static int get_pap_passwd(int unit, char *user, char *passwd)\r
819 {\r
820 /* normally we would reject PAP if no password is provided,\r
821    but this causes problems with some providers (like CHT in Taiwan)\r
822    who incorrectly request PAP and expect a bogus/empty password, so\r
823    always provide a default user/passwd of "none"/"none"\r
824 */\r
825     if(user)\r
826         strcpy(user,   "none");\r
827     if(passwd)\r
828         strcpy(passwd, "none");\r
829 \r
830     return 1;\r
831 }\r
832 \r
833 \r
834 /*\r
835  * have_pap_secret - check whether we have a PAP file with any\r
836  * secrets that we could possibly use for authenticating the peer.\r
837  */\r
838 static int have_pap_secret(void)\r
839 {\r
840     /* XXX Fail until we set up our passwords. */\r
841     return 0;\r
842 }\r
843 \r
844 \r
845 /*\r
846  * have_chap_secret - check whether we have a CHAP file with a\r
847  * secret that we could possibly use for authenticating `client'\r
848  * on `server'.  Either can be the null string, meaning we don't\r
849  * know the identity yet.\r
850  */\r
851 static int have_chap_secret(char *client, char *server, u32_t remote)\r
852 {\r
853         (void)client;\r
854         (void)server;\r
855         (void)remote;\r
856     /* XXX Fail until we set up our passwords. */\r
857     return 0;\r
858 }\r
859 \r
860 \r
861 #if 0 /* PAP_SUPPORT > 0 || CHAP_SUPPORT > 0 */\r
862 /*\r
863  * set_allowed_addrs() - set the list of allowed addresses.\r
864  */\r
865 static void set_allowed_addrs(int unit, struct wordlist *addrs)\r
866 {\r
867     if (addresses[unit] != NULL)\r
868         free_wordlist(addresses[unit]);\r
869     addresses[unit] = addrs;\r
870 \r
871 #if 0\r
872     /*\r
873      * If there's only one authorized address we might as well\r
874      * ask our peer for that one right away\r
875      */\r
876     if (addrs != NULL && addrs->next == NULL) {\r
877         char *p = addrs->word;\r
878         struct ipcp_options *wo = &ipcp_wantoptions[unit];\r
879         u32_t a;\r
880         struct hostent *hp;\r
881         \r
882         if (wo->hisaddr == 0 && *p != '!' && *p != '-'\r
883                 && strchr(p, '/') == NULL) {\r
884             hp = gethostbyname(p);\r
885             if (hp != NULL && hp->h_addrtype == AF_INET)\r
886                 a = *(u32_t *)hp->h_addr;\r
887             else\r
888                 a = inet_addr(p);\r
889             if (a != (u32_t) -1)\r
890                 wo->hisaddr = a;\r
891         }\r
892     }\r
893 #endif\r
894 }\r
895 #endif\r
896 \r
897 static int ip_addr_check(u32_t addr, struct wordlist *addrs)\r
898 {\r
899     \r
900     /* don't allow loopback or multicast address */\r
901     if (bad_ip_adrs(addr))\r
902         return 0;\r
903     \r
904     if (addrs == NULL)\r
905         return !ppp_settings.auth_required;      /* no addresses authorized */\r
906     \r
907     /* XXX All other addresses allowed. */\r
908     return 1;\r
909 }\r
910 \r
911 #if 0 /* PAP_SUPPORT > 0 || CHAP_SUPPORT */\r
912 /*\r
913  * free_wordlist - release memory allocated for a wordlist.\r
914  */\r
915 static void free_wordlist(struct wordlist *wp)\r
916 {\r
917     struct wordlist *next;\r
918     \r
919     while (wp != NULL) {\r
920         next = wp->next;\r
921         free(wp);\r
922         wp = next;\r
923     }\r
924 }\r
925 #endif\r
926 \r
927 #endif /* PPP_SUPPORT */\r