Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of lwip by
auth.c
00001 /***************************************************************************** 00002 * auth.c - Network Authentication and Phase Control program file. 00003 * 00004 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. 00005 * Copyright (c) 1997 by Global Election Systems Inc. All rights reserved. 00006 * 00007 * The authors hereby grant permission to use, copy, modify, distribute, 00008 * and license this software and its documentation for any purpose, provided 00009 * that existing copyright notices are retained in all copies and that this 00010 * notice and the following disclaimer are included verbatim in any 00011 * distributions. No written agreement, license, or royalty fee is required 00012 * for any of the authorized uses. 00013 * 00014 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR 00015 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00016 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00017 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00018 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00019 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00020 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00021 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00022 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00023 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00024 * 00025 ****************************************************************************** 00026 * REVISION HISTORY 00027 * 00028 * 03-01-01 Marc Boucher <marc@mbsi.ca> 00029 * Ported to lwIP. 00030 * 97-12-08 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc. 00031 * Ported from public pppd code. 00032 *****************************************************************************/ 00033 /* 00034 * auth.c - PPP authentication and phase control. 00035 * 00036 * Copyright (c) 1993 The Australian National University. 00037 * All rights reserved. 00038 * 00039 * Redistribution and use in source and binary forms are permitted 00040 * provided that the above copyright notice and this paragraph are 00041 * duplicated in all such forms and that any documentation, 00042 * advertising materials, and other materials related to such 00043 * distribution and use acknowledge that the software was developed 00044 * by the Australian National University. The name of the University 00045 * may not be used to endorse or promote products derived from this 00046 * software without specific prior written permission. 00047 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 00048 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 00049 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00050 * 00051 * Copyright (c) 1989 Carnegie Mellon University. 00052 * All rights reserved. 00053 * 00054 * Redistribution and use in source and binary forms are permitted 00055 * provided that the above copyright notice and this paragraph are 00056 * duplicated in all such forms and that any documentation, 00057 * advertising materials, and other materials related to such 00058 * distribution and use acknowledge that the software was developed 00059 * by Carnegie Mellon University. The name of the 00060 * University may not be used to endorse or promote products derived 00061 * from this software without specific prior written permission. 00062 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 00063 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 00064 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00065 */ 00066 00067 #include "lwip/opt.h" 00068 00069 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ 00070 00071 #include "ppp.h" 00072 #include "pppdebug.h" 00073 00074 #include "fsm.h" 00075 #include "lcp.h" 00076 #include "pap.h" 00077 #include "chap.h" 00078 #include "auth.h" 00079 #include "ipcp.h" 00080 00081 #if CBCP_SUPPORT 00082 #include "cbcp.h" 00083 #endif /* CBCP_SUPPORT */ 00084 00085 #include "lwip/inet.h" 00086 00087 #include <string.h> 00088 00089 #if 0 /* UNUSED */ 00090 /* Bits in scan_authfile return value */ 00091 #define NONWILD_SERVER 1 00092 #define NONWILD_CLIENT 2 00093 00094 #define ISWILD(word) (word[0] == '*' && word[1] == 0) 00095 #endif /* UNUSED */ 00096 00097 #if PAP_SUPPORT || CHAP_SUPPORT 00098 /* The name by which the peer authenticated itself to us. */ 00099 static char peer_authname[MAXNAMELEN]; 00100 #endif /* PAP_SUPPORT || CHAP_SUPPORT */ 00101 00102 /* Records which authentication operations haven't completed yet. */ 00103 static int auth_pending[NUM_PPP]; 00104 00105 /* Set if we have successfully called plogin() */ 00106 static int logged_in; 00107 00108 /* Set if we have run the /etc/ppp/auth-up script. */ 00109 static int did_authup; /* @todo, we don't need this in lwip*/ 00110 00111 /* List of addresses which the peer may use. */ 00112 static struct wordlist *addresses[NUM_PPP]; 00113 00114 #if 0 /* UNUSED */ 00115 /* Wordlist giving addresses which the peer may use 00116 without authenticating itself. */ 00117 static struct wordlist *noauth_addrs; 00118 00119 /* Extra options to apply, from the secrets file entry for the peer. */ 00120 static struct wordlist *extra_options; 00121 #endif /* UNUSED */ 00122 00123 /* Number of network protocols which we have opened. */ 00124 static int num_np_open; 00125 00126 /* Number of network protocols which have come up. */ 00127 static int num_np_up; 00128 00129 #if PAP_SUPPORT || CHAP_SUPPORT 00130 /* Set if we got the contents of passwd[] from the pap-secrets file. */ 00131 static int passwd_from_file; 00132 #endif /* PAP_SUPPORT || CHAP_SUPPORT */ 00133 00134 #if 0 /* UNUSED */ 00135 /* Set if we require authentication only because we have a default route. */ 00136 static bool default_auth; 00137 00138 /* Hook to enable a plugin to control the idle time limit */ 00139 int (*idle_time_hook) __P((struct ppp_idle *)) = NULL; 00140 00141 /* Hook for a plugin to say whether we can possibly authenticate any peer */ 00142 int (*pap_check_hook) __P((void)) = NULL; 00143 00144 /* Hook for a plugin to check the PAP user and password */ 00145 int (*pap_auth_hook) __P((char *user, char *passwd, char **msgp, 00146 struct wordlist **paddrs, 00147 struct wordlist **popts)) = NULL; 00148 00149 /* Hook for a plugin to know about the PAP user logout */ 00150 void (*pap_logout_hook) __P((void)) = NULL; 00151 00152 /* Hook for a plugin to get the PAP password for authenticating us */ 00153 int (*pap_passwd_hook) __P((char *user, char *passwd)) = NULL; 00154 00155 /* 00156 * This is used to ensure that we don't start an auth-up/down 00157 * script while one is already running. 00158 */ 00159 enum script_state { 00160 s_down, 00161 s_up 00162 }; 00163 00164 static enum script_state auth_state = s_down; 00165 static enum script_state auth_script_state = s_down; 00166 static pid_t auth_script_pid = 0; 00167 00168 /* 00169 * Option variables. 00170 * lwip: some of these are present in the ppp_settings structure 00171 */ 00172 bool uselogin = 0; /* Use /etc/passwd for checking PAP */ 00173 bool cryptpap = 0; /* Passwords in pap-secrets are encrypted */ 00174 bool refuse_pap = 0; /* Don't wanna auth. ourselves with PAP */ 00175 bool refuse_chap = 0; /* Don't wanna auth. ourselves with CHAP */ 00176 bool usehostname = 0; /* Use hostname for our_name */ 00177 bool auth_required = 0; /* Always require authentication from peer */ 00178 bool allow_any_ip = 0; /* Allow peer to use any IP address */ 00179 bool explicit_remote = 0; /* User specified explicit remote name */ 00180 char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ 00181 00182 #endif /* UNUSED */ 00183 00184 /* Bits in auth_pending[] */ 00185 #define PAP_WITHPEER 1 00186 #define PAP_PEER 2 00187 #define CHAP_WITHPEER 4 00188 #define CHAP_PEER 8 00189 00190 /* @todo, move this somewhere */ 00191 /* Used for storing a sequence of words. Usually malloced. */ 00192 struct wordlist { 00193 struct wordlist *next; 00194 char word[1]; 00195 }; 00196 00197 00198 extern char *crypt (const char *, const char *); 00199 00200 /* Prototypes for procedures local to this file. */ 00201 00202 static void network_phase (int); 00203 static void check_idle (void *); 00204 static void connect_time_expired (void *); 00205 #if 0 00206 static int plogin (char *, char *, char **, int *); 00207 #endif 00208 static void plogout (void); 00209 static int null_login (int); 00210 static int get_pap_passwd (int, char *, char *); 00211 static int have_pap_secret (void); 00212 static int have_chap_secret (char *, char *, u32_t); 00213 static int ip_addr_check (u32_t, struct wordlist *); 00214 00215 #if 0 /* PAP_SUPPORT || CHAP_SUPPORT */ 00216 static int scan_authfile (FILE *, char *, char *, char *, 00217 struct wordlist **, struct wordlist **, 00218 char *); 00219 static void free_wordlist (struct wordlist *); 00220 static void auth_script (char *); 00221 static void auth_script_done (void *); 00222 static void set_allowed_addrs (int unit, struct wordlist *addrs); 00223 static int some_ip_ok (struct wordlist *); 00224 static int setupapfile (char **); 00225 static int privgroup (char **); 00226 static int set_noauth_addr (char **); 00227 static void check_access (FILE *, char *); 00228 #endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */ 00229 00230 #if 0 /* UNUSED */ 00231 /* 00232 * Authentication-related options. 00233 */ 00234 option_t auth_options[] = { 00235 { "require-pap", o_bool, &lcp_wantoptions[0].neg_upap, 00236 "Require PAP authentication from peer", 1, &auth_required }, 00237 { "+pap", o_bool, &lcp_wantoptions[0].neg_upap, 00238 "Require PAP authentication from peer", 1, &auth_required }, 00239 { "refuse-pap", o_bool, &refuse_pap, 00240 "Don't agree to auth to peer with PAP", 1 }, 00241 { "-pap", o_bool, &refuse_pap, 00242 "Don't allow PAP authentication with peer", 1 }, 00243 { "require-chap", o_bool, &lcp_wantoptions[0].neg_chap, 00244 "Require CHAP authentication from peer", 1, &auth_required }, 00245 { "+chap", o_bool, &lcp_wantoptions[0].neg_chap, 00246 "Require CHAP authentication from peer", 1, &auth_required }, 00247 { "refuse-chap", o_bool, &refuse_chap, 00248 "Don't agree to auth to peer with CHAP", 1 }, 00249 { "-chap", o_bool, &refuse_chap, 00250 "Don't allow CHAP authentication with peer", 1 }, 00251 { "name", o_string, our_name, 00252 "Set local name for authentication", 00253 OPT_PRIV|OPT_STATIC, NULL, MAXNAMELEN }, 00254 { "user", o_string, user, 00255 "Set name for auth with peer", OPT_STATIC, NULL, MAXNAMELEN }, 00256 { "usehostname", o_bool, &usehostname, 00257 "Must use hostname for authentication", 1 }, 00258 { "remotename", o_string, remote_name, 00259 "Set remote name for authentication", OPT_STATIC, 00260 &explicit_remote, MAXNAMELEN }, 00261 { "auth", o_bool, &auth_required, 00262 "Require authentication from peer", 1 }, 00263 { "noauth", o_bool, &auth_required, 00264 "Don't require peer to authenticate", OPT_PRIV, &allow_any_ip }, 00265 { "login", o_bool, &uselogin, 00266 "Use system password database for PAP", 1 }, 00267 { "papcrypt", o_bool, &cryptpap, 00268 "PAP passwords are encrypted", 1 }, 00269 { "+ua", o_special, (void *)setupapfile, 00270 "Get PAP user and password from file" }, 00271 { "password", o_string, passwd, 00272 "Password for authenticating us to the peer", OPT_STATIC, 00273 NULL, MAXSECRETLEN }, 00274 { "privgroup", o_special, (void *)privgroup, 00275 "Allow group members to use privileged options", OPT_PRIV }, 00276 { "allow-ip", o_special, (void *)set_noauth_addr, 00277 "Set IP address(es) which can be used without authentication", 00278 OPT_PRIV }, 00279 { NULL } 00280 }; 00281 #endif /* UNUSED */ 00282 #if 0 /* UNUSED */ 00283 /* 00284 * setupapfile - specifies UPAP info for authenticating with peer. 00285 */ 00286 static int 00287 setupapfile(char **argv) 00288 { 00289 FILE * ufile; 00290 int l; 00291 00292 lcp_allowoptions[0].neg_upap = 1; 00293 00294 /* open user info file */ 00295 seteuid(getuid()); 00296 ufile = fopen(*argv, "r"); 00297 seteuid(0); 00298 if (ufile == NULL) { 00299 option_error("unable to open user login data file %s", *argv); 00300 return 0; 00301 } 00302 check_access(ufile, *argv); 00303 00304 /* get username */ 00305 if (fgets(user, MAXNAMELEN - 1, ufile) == NULL 00306 || fgets(passwd, MAXSECRETLEN - 1, ufile) == NULL){ 00307 option_error("unable to read user login data file %s", *argv); 00308 return 0; 00309 } 00310 fclose(ufile); 00311 00312 /* get rid of newlines */ 00313 l = strlen(user); 00314 if (l > 0 && user[l-1] == '\n') 00315 user[l-1] = 0; 00316 l = strlen(passwd); 00317 if (l > 0 && passwd[l-1] == '\n') 00318 passwd[l-1] = 0; 00319 00320 return (1); 00321 } 00322 #endif /* UNUSED */ 00323 00324 #if 0 /* UNUSED */ 00325 /* 00326 * privgroup - allow members of the group to have privileged access. 00327 */ 00328 static int 00329 privgroup(char **argv) 00330 { 00331 struct group *g; 00332 int i; 00333 00334 g = getgrnam(*argv); 00335 if (g == 0) { 00336 option_error("group %s is unknown", *argv); 00337 return 0; 00338 } 00339 for (i = 0; i < ngroups; ++i) { 00340 if (groups[i] == g->gr_gid) { 00341 privileged = 1; 00342 break; 00343 } 00344 } 00345 return 1; 00346 } 00347 #endif 00348 00349 #if 0 /* UNUSED */ 00350 /* 00351 * set_noauth_addr - set address(es) that can be used without authentication. 00352 * Equivalent to specifying an entry like `"" * "" addr' in pap-secrets. 00353 */ 00354 static int 00355 set_noauth_addr(char **argv) 00356 { 00357 char *addr = *argv; 00358 int l = strlen(addr); 00359 struct wordlist *wp; 00360 00361 wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l + 1); 00362 if (wp == NULL) 00363 novm("allow-ip argument"); 00364 wp->word = (char *) (wp + 1); 00365 wp->next = noauth_addrs; 00366 BCOPY(addr, wp->word, l); 00367 noauth_addrs = wp; 00368 return 1; 00369 } 00370 #endif /* UNUSED */ 00371 00372 /* 00373 * An Open on LCP has requested a change from Dead to Establish phase. 00374 * Do what's necessary to bring the physical layer up. 00375 */ 00376 void 00377 link_required(int unit) 00378 { 00379 LWIP_UNUSED_ARG(unit); 00380 00381 AUTHDEBUG(LOG_INFO, ("link_required: %d\n", unit)); 00382 } 00383 00384 /* 00385 * LCP has terminated the link; go to the Dead phase and take the 00386 * physical layer down. 00387 */ 00388 void 00389 link_terminated(int unit) 00390 { 00391 AUTHDEBUG(LOG_INFO, ("link_terminated: %d\n", unit)); 00392 if (lcp_phase[unit] == PHASE_DEAD) { 00393 return; 00394 } 00395 if (logged_in) { 00396 plogout(); 00397 } 00398 lcp_phase[unit] = PHASE_DEAD; 00399 AUTHDEBUG(LOG_NOTICE, ("Connection terminated.\n")); 00400 pppLinkTerminated(unit); 00401 } 00402 00403 /* 00404 * LCP has gone down; it will either die or try to re-establish. 00405 */ 00406 void 00407 link_down(int unit) 00408 { 00409 int i; 00410 struct protent *protp; 00411 00412 AUTHDEBUG(LOG_INFO, ("link_down: %d\n", unit)); 00413 00414 if (did_authup) { 00415 /* XXX Do link down processing. */ 00416 did_authup = 0; 00417 } 00418 for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { 00419 if (!protp->enabled_flag) { 00420 continue; 00421 } 00422 if (protp->protocol != PPP_LCP && protp->lowerdown != NULL) { 00423 (*protp->lowerdown)(unit); 00424 } 00425 if (protp->protocol < 0xC000 && protp->close != NULL) { 00426 (*protp->close)(unit, "LCP down"); 00427 } 00428 } 00429 num_np_open = 0; /* number of network protocols we have opened */ 00430 num_np_up = 0; /* Number of network protocols which have come up */ 00431 00432 if (lcp_phase[unit] != PHASE_DEAD) { 00433 lcp_phase[unit] = PHASE_TERMINATE; 00434 } 00435 pppLinkDown(unit); 00436 } 00437 00438 /* 00439 * The link is established. 00440 * Proceed to the Dead, Authenticate or Network phase as appropriate. 00441 */ 00442 void 00443 link_established(int unit) 00444 { 00445 int auth; 00446 int i; 00447 struct protent *protp; 00448 lcp_options *wo = &lcp_wantoptions[unit]; 00449 lcp_options *go = &lcp_gotoptions[unit]; 00450 #if PAP_SUPPORT || CHAP_SUPPORT 00451 lcp_options *ho = &lcp_hisoptions[unit]; 00452 #endif /* PAP_SUPPORT || CHAP_SUPPORT */ 00453 00454 AUTHDEBUG(LOG_INFO, ("link_established: unit %d; Lowering up all protocols...\n", unit)); 00455 /* 00456 * Tell higher-level protocols that LCP is up. 00457 */ 00458 for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { 00459 if (protp->protocol != PPP_LCP && protp->enabled_flag && protp->lowerup != NULL) { 00460 (*protp->lowerup)(unit); 00461 } 00462 } 00463 if (ppp_settings.auth_required && !(go->neg_chap || go->neg_upap)) { 00464 /* 00465 * We wanted the peer to authenticate itself, and it refused: 00466 * treat it as though it authenticated with PAP using a username 00467 * of "" and a password of "". If that's not OK, boot it out. 00468 */ 00469 if (!wo->neg_upap || !null_login(unit)) { 00470 AUTHDEBUG(LOG_WARNING, ("peer refused to authenticate\n")); 00471 lcp_close(unit, "peer refused to authenticate"); 00472 return; 00473 } 00474 } 00475 00476 lcp_phase[unit] = PHASE_AUTHENTICATE; 00477 auth = 0; 00478 #if CHAP_SUPPORT 00479 if (go->neg_chap) { 00480 ChapAuthPeer(unit, ppp_settings.our_name, go->chap_mdtype); 00481 auth |= CHAP_PEER; 00482 } 00483 #endif /* CHAP_SUPPORT */ 00484 #if PAP_SUPPORT && CHAP_SUPPORT 00485 else 00486 #endif /* PAP_SUPPORT && CHAP_SUPPORT */ 00487 #if PAP_SUPPORT 00488 if (go->neg_upap) { 00489 upap_authpeer(unit); 00490 auth |= PAP_PEER; 00491 } 00492 #endif /* PAP_SUPPORT */ 00493 #if CHAP_SUPPORT 00494 if (ho->neg_chap) { 00495 ChapAuthWithPeer(unit, ppp_settings.user, ho->chap_mdtype); 00496 auth |= CHAP_WITHPEER; 00497 } 00498 #endif /* CHAP_SUPPORT */ 00499 #if PAP_SUPPORT && CHAP_SUPPORT 00500 else 00501 #endif /* PAP_SUPPORT && CHAP_SUPPORT */ 00502 #if PAP_SUPPORT 00503 if (ho->neg_upap) { 00504 if (ppp_settings.passwd[0] == 0) { 00505 passwd_from_file = 1; 00506 if (!get_pap_passwd(unit, ppp_settings.user, ppp_settings.passwd)) { 00507 AUTHDEBUG(LOG_ERR, ("No secret found for PAP login\n")); 00508 } 00509 } 00510 upap_authwithpeer(unit, ppp_settings.user, ppp_settings.passwd); 00511 auth |= PAP_WITHPEER; 00512 } 00513 #endif /* PAP_SUPPORT */ 00514 auth_pending[unit] = auth; 00515 00516 if (!auth) { 00517 network_phase(unit); 00518 } 00519 } 00520 00521 /* 00522 * Proceed to the network phase. 00523 */ 00524 static void 00525 network_phase(int unit) 00526 { 00527 int i; 00528 struct protent *protp; 00529 lcp_options *go = &lcp_gotoptions[unit]; 00530 00531 /* 00532 * If the peer had to authenticate, run the auth-up script now. 00533 */ 00534 if ((go->neg_chap || go->neg_upap) && !did_authup) { 00535 /* XXX Do setup for peer authentication. */ 00536 did_authup = 1; 00537 } 00538 00539 #if CBCP_SUPPORT 00540 /* 00541 * If we negotiated callback, do it now. 00542 */ 00543 if (go->neg_cbcp) { 00544 lcp_phase[unit] = PHASE_CALLBACK; 00545 (*cbcp_protent.open)(unit); 00546 return; 00547 } 00548 #endif /* CBCP_SUPPORT */ 00549 00550 lcp_phase[unit] = PHASE_NETWORK; 00551 for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { 00552 if (protp->protocol < 0xC000 && protp->enabled_flag && protp->open != NULL) { 00553 (*protp->open)(unit); 00554 if (protp->protocol != PPP_CCP) { 00555 ++num_np_open; 00556 } 00557 } 00558 } 00559 00560 if (num_np_open == 0) { 00561 /* nothing to do */ 00562 lcp_close(0, "No network protocols running"); 00563 } 00564 } 00565 /* @todo: add void start_networks(void) here (pppd 2.3.11) */ 00566 00567 /* 00568 * The peer has failed to authenticate himself using `protocol'. 00569 */ 00570 void 00571 auth_peer_fail(int unit, u16_t protocol) 00572 { 00573 LWIP_UNUSED_ARG(protocol); 00574 00575 AUTHDEBUG(LOG_INFO, ("auth_peer_fail: %d proto=%X\n", unit, protocol)); 00576 /* 00577 * Authentication failure: take the link down 00578 */ 00579 lcp_close(unit, "Authentication failed"); 00580 } 00581 00582 00583 #if PAP_SUPPORT || CHAP_SUPPORT 00584 /* 00585 * The peer has been successfully authenticated using `protocol'. 00586 */ 00587 void 00588 auth_peer_success(int unit, u16_t protocol, char *name, int namelen) 00589 { 00590 int pbit; 00591 00592 AUTHDEBUG(LOG_INFO, ("auth_peer_success: %d proto=%X\n", unit, protocol)); 00593 switch (protocol) { 00594 case PPP_CHAP: 00595 pbit = CHAP_PEER; 00596 break; 00597 case PPP_PAP: 00598 pbit = PAP_PEER; 00599 break; 00600 default: 00601 AUTHDEBUG(LOG_WARNING, ("auth_peer_success: unknown protocol %x\n", protocol)); 00602 return; 00603 } 00604 00605 /* 00606 * Save the authenticated name of the peer for later. 00607 */ 00608 if (namelen > (int)sizeof(peer_authname) - 1) { 00609 namelen = sizeof(peer_authname) - 1; 00610 } 00611 BCOPY(name, peer_authname, namelen); 00612 peer_authname[namelen] = 0; 00613 00614 /* 00615 * If there is no more authentication still to be done, 00616 * proceed to the network (or callback) phase. 00617 */ 00618 if ((auth_pending[unit] &= ~pbit) == 0) { 00619 network_phase(unit); 00620 } 00621 } 00622 00623 /* 00624 * We have failed to authenticate ourselves to the peer using `protocol'. 00625 */ 00626 void 00627 auth_withpeer_fail(int unit, u16_t protocol) 00628 { 00629 int errCode = PPPERR_AUTHFAIL; 00630 00631 LWIP_UNUSED_ARG(protocol); 00632 00633 AUTHDEBUG(LOG_INFO, ("auth_withpeer_fail: %d proto=%X\n", unit, protocol)); 00634 if (passwd_from_file) { 00635 BZERO(ppp_settings.passwd, MAXSECRETLEN); 00636 } 00637 00638 /* 00639 * We've failed to authenticate ourselves to our peer. 00640 * He'll probably take the link down, and there's not much 00641 * we can do except wait for that. 00642 */ 00643 pppIOCtl(unit, PPPCTLS_ERRCODE, &errCode); 00644 lcp_close(unit, "Failed to authenticate ourselves to peer"); 00645 } 00646 00647 /* 00648 * We have successfully authenticated ourselves with the peer using `protocol'. 00649 */ 00650 void 00651 auth_withpeer_success(int unit, u16_t protocol) 00652 { 00653 int pbit; 00654 00655 AUTHDEBUG(LOG_INFO, ("auth_withpeer_success: %d proto=%X\n", unit, protocol)); 00656 switch (protocol) { 00657 case PPP_CHAP: 00658 pbit = CHAP_WITHPEER; 00659 break; 00660 case PPP_PAP: 00661 if (passwd_from_file) { 00662 BZERO(ppp_settings.passwd, MAXSECRETLEN); 00663 } 00664 pbit = PAP_WITHPEER; 00665 break; 00666 default: 00667 AUTHDEBUG(LOG_WARNING, ("auth_peer_success: unknown protocol %x\n", protocol)); 00668 pbit = 0; 00669 } 00670 00671 /* 00672 * If there is no more authentication still being done, 00673 * proceed to the network (or callback) phase. 00674 */ 00675 if ((auth_pending[unit] &= ~pbit) == 0) { 00676 network_phase(unit); 00677 } 00678 } 00679 #endif /* PAP_SUPPORT || CHAP_SUPPORT */ 00680 00681 00682 /* 00683 * np_up - a network protocol has come up. 00684 */ 00685 void 00686 np_up(int unit, u16_t proto) 00687 { 00688 LWIP_UNUSED_ARG(unit); 00689 LWIP_UNUSED_ARG(proto); 00690 00691 AUTHDEBUG(LOG_INFO, ("np_up: %d proto=%X\n", unit, proto)); 00692 if (num_np_up == 0) { 00693 AUTHDEBUG(LOG_INFO, ("np_up: maxconnect=%d idle_time_limit=%d\n",ppp_settings.maxconnect,ppp_settings.idle_time_limit)); 00694 /* 00695 * At this point we consider that the link has come up successfully. 00696 */ 00697 if (ppp_settings.idle_time_limit > 0) { 00698 TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit); 00699 } 00700 00701 /* 00702 * Set a timeout to close the connection once the maximum 00703 * connect time has expired. 00704 */ 00705 if (ppp_settings.maxconnect > 0) { 00706 TIMEOUT(connect_time_expired, 0, ppp_settings.maxconnect); 00707 } 00708 } 00709 ++num_np_up; 00710 } 00711 00712 /* 00713 * np_down - a network protocol has gone down. 00714 */ 00715 void 00716 np_down(int unit, u16_t proto) 00717 { 00718 LWIP_UNUSED_ARG(unit); 00719 LWIP_UNUSED_ARG(proto); 00720 00721 AUTHDEBUG(LOG_INFO, ("np_down: %d proto=%X\n", unit, proto)); 00722 if (--num_np_up == 0 && ppp_settings.idle_time_limit > 0) { 00723 UNTIMEOUT(check_idle, NULL); 00724 } 00725 } 00726 00727 /* 00728 * np_finished - a network protocol has finished using the link. 00729 */ 00730 void 00731 np_finished(int unit, u16_t proto) 00732 { 00733 LWIP_UNUSED_ARG(unit); 00734 LWIP_UNUSED_ARG(proto); 00735 00736 AUTHDEBUG(LOG_INFO, ("np_finished: %d proto=%X\n", unit, proto)); 00737 if (--num_np_open <= 0) { 00738 /* no further use for the link: shut up shop. */ 00739 lcp_close(0, "No network protocols running"); 00740 } 00741 } 00742 00743 /* 00744 * check_idle - check whether the link has been idle for long 00745 * enough that we can shut it down. 00746 */ 00747 static void 00748 check_idle(void *arg) 00749 { 00750 struct ppp_idle idle; 00751 u_short itime; 00752 00753 LWIP_UNUSED_ARG(arg); 00754 if (!get_idle_time(0, &idle)) { 00755 return; 00756 } 00757 itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle); 00758 if (itime >= ppp_settings.idle_time_limit) { 00759 /* link is idle: shut it down. */ 00760 AUTHDEBUG(LOG_INFO, ("Terminating connection due to lack of activity.\n")); 00761 lcp_close(0, "Link inactive"); 00762 } else { 00763 TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit - itime); 00764 } 00765 } 00766 00767 /* 00768 * connect_time_expired - log a message and close the connection. 00769 */ 00770 static void 00771 connect_time_expired(void *arg) 00772 { 00773 LWIP_UNUSED_ARG(arg); 00774 00775 AUTHDEBUG(LOG_INFO, ("Connect time expired\n")); 00776 lcp_close(0, "Connect time expired"); /* Close connection */ 00777 } 00778 00779 #if 0 /* UNUSED */ 00780 /* 00781 * auth_check_options - called to check authentication options. 00782 */ 00783 void 00784 auth_check_options(void) 00785 { 00786 lcp_options *wo = &lcp_wantoptions[0]; 00787 int can_auth; 00788 ipcp_options *ipwo = &ipcp_wantoptions[0]; 00789 u32_t remote; 00790 00791 /* Default our_name to hostname, and user to our_name */ 00792 if (ppp_settings.our_name[0] == 0 || ppp_settings.usehostname) { 00793 strcpy(ppp_settings.our_name, ppp_settings.hostname); 00794 } 00795 00796 if (ppp_settings.user[0] == 0) { 00797 strcpy(ppp_settings.user, ppp_settings.our_name); 00798 } 00799 00800 /* If authentication is required, ask peer for CHAP or PAP. */ 00801 if (ppp_settings.auth_required && !wo->neg_chap && !wo->neg_upap) { 00802 wo->neg_chap = 1; 00803 wo->neg_upap = 1; 00804 } 00805 00806 /* 00807 * Check whether we have appropriate secrets to use 00808 * to authenticate the peer. 00809 */ 00810 can_auth = wo->neg_upap && have_pap_secret(); 00811 if (!can_auth && wo->neg_chap) { 00812 remote = ipwo->accept_remote? 0: ipwo->hisaddr; 00813 can_auth = have_chap_secret(ppp_settings.remote_name, ppp_settings.our_name, remote); 00814 } 00815 00816 if (ppp_settings.auth_required && !can_auth) { 00817 ppp_panic("No auth secret"); 00818 } 00819 } 00820 #endif /* UNUSED */ 00821 00822 /* 00823 * auth_reset - called when LCP is starting negotiations to recheck 00824 * authentication options, i.e. whether we have appropriate secrets 00825 * to use for authenticating ourselves and/or the peer. 00826 */ 00827 void 00828 auth_reset(int unit) 00829 { 00830 lcp_options *go = &lcp_gotoptions[unit]; 00831 lcp_options *ao = &lcp_allowoptions[0]; 00832 ipcp_options *ipwo = &ipcp_wantoptions[0]; 00833 u32_t remote; 00834 00835 AUTHDEBUG(LOG_INFO, ("auth_reset: %d\n", unit)); 00836 ao->neg_upap = !ppp_settings.refuse_pap && (ppp_settings.passwd[0] != 0 || get_pap_passwd(unit, NULL, NULL)); 00837 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)*/; 00838 00839 if (go->neg_upap && !have_pap_secret()) { 00840 go->neg_upap = 0; 00841 } 00842 if (go->neg_chap) { 00843 remote = ipwo->accept_remote? 0: ipwo->hisaddr; 00844 if (!have_chap_secret(ppp_settings.remote_name, ppp_settings.our_name, remote)) { 00845 go->neg_chap = 0; 00846 } 00847 } 00848 } 00849 00850 #if PAP_SUPPORT 00851 /* 00852 * check_passwd - Check the user name and passwd against the PAP secrets 00853 * file. If requested, also check against the system password database, 00854 * and login the user if OK. 00855 * 00856 * returns: 00857 * UPAP_AUTHNAK: Authentication failed. 00858 * UPAP_AUTHACK: Authentication succeeded. 00859 * In either case, msg points to an appropriate message. 00860 */ 00861 u_char 00862 check_passwd( int unit, char *auser, int userlen, char *apasswd, int passwdlen, char **msg, int *msglen) 00863 { 00864 #if 1 /* XXX Assume all entries OK. */ 00865 LWIP_UNUSED_ARG(unit); 00866 LWIP_UNUSED_ARG(auser); 00867 LWIP_UNUSED_ARG(userlen); 00868 LWIP_UNUSED_ARG(apasswd); 00869 LWIP_UNUSED_ARG(passwdlen); 00870 LWIP_UNUSED_ARG(msglen); 00871 *msg = (char *) 0; 00872 return UPAP_AUTHACK; /* XXX Assume all entries OK. */ 00873 #else 00874 u_char ret = 0; 00875 struct wordlist *addrs = NULL; 00876 char passwd[256], user[256]; 00877 char secret[MAXWORDLEN]; 00878 static u_short attempts = 0; 00879 00880 /* 00881 * Make copies of apasswd and auser, then null-terminate them. 00882 */ 00883 BCOPY(apasswd, passwd, passwdlen); 00884 passwd[passwdlen] = '\0'; 00885 BCOPY(auser, user, userlen); 00886 user[userlen] = '\0'; 00887 *msg = (char *) 0; 00888 00889 /* XXX Validate user name and password. */ 00890 ret = UPAP_AUTHACK; /* XXX Assume all entries OK. */ 00891 00892 if (ret == UPAP_AUTHNAK) { 00893 if (*msg == (char *) 0) { 00894 *msg = "Login incorrect"; 00895 } 00896 *msglen = strlen(*msg); 00897 /* 00898 * Frustrate passwd stealer programs. 00899 * Allow 10 tries, but start backing off after 3 (stolen from login). 00900 * On 10'th, drop the connection. 00901 */ 00902 if (attempts++ >= 10) { 00903 AUTHDEBUG(LOG_WARNING, ("%d LOGIN FAILURES BY %s\n", attempts, user)); 00904 /*ppp_panic("Excess Bad Logins");*/ 00905 } 00906 if (attempts > 3) { 00907 /* @todo: this was sleep(), i.e. seconds, not milliseconds 00908 * I don't think we really need this in lwIP - we would block tcpip_thread! 00909 */ 00910 /*sys_msleep((attempts - 3) * 5);*/ 00911 } 00912 if (addrs != NULL) { 00913 free_wordlist(addrs); 00914 } 00915 } else { 00916 attempts = 0; /* Reset count */ 00917 if (*msg == (char *) 0) { 00918 *msg = "Login ok"; 00919 } 00920 *msglen = strlen(*msg); 00921 set_allowed_addrs(unit, addrs); 00922 } 00923 00924 BZERO(passwd, sizeof(passwd)); 00925 BZERO(secret, sizeof(secret)); 00926 00927 return ret; 00928 #endif 00929 } 00930 #endif /* PAP_SUPPORT */ 00931 00932 #if 0 /* UNUSED */ 00933 /* 00934 * This function is needed for PAM. 00935 */ 00936 00937 #ifdef USE_PAM 00938 00939 /* lwip does not support PAM*/ 00940 00941 #endif /* USE_PAM */ 00942 00943 #endif /* UNUSED */ 00944 00945 00946 #if 0 /* UNUSED */ 00947 /* 00948 * plogin - Check the user name and password against the system 00949 * password database, and login the user if OK. 00950 * 00951 * returns: 00952 * UPAP_AUTHNAK: Login failed. 00953 * UPAP_AUTHACK: Login succeeded. 00954 * In either case, msg points to an appropriate message. 00955 */ 00956 static int 00957 plogin(char *user, char *passwd, char **msg, int *msglen) 00958 { 00959 00960 LWIP_UNUSED_ARG(user); 00961 LWIP_UNUSED_ARG(passwd); 00962 LWIP_UNUSED_ARG(msg); 00963 LWIP_UNUSED_ARG(msglen); 00964 00965 00966 /* The new lines are here align the file when 00967 * compared against the pppd 2.3.11 code */ 00968 00969 00970 00971 00972 00973 00974 00975 00976 00977 00978 00979 00980 00981 00982 00983 00984 /* XXX Fail until we decide that we want to support logins. */ 00985 return (UPAP_AUTHNAK); 00986 } 00987 #endif 00988 00989 00990 00991 /* 00992 * plogout - Logout the user. 00993 */ 00994 static void 00995 plogout(void) 00996 { 00997 logged_in = 0; 00998 } 00999 01000 /* 01001 * null_login - Check if a username of "" and a password of "" are 01002 * acceptable, and iff so, set the list of acceptable IP addresses 01003 * and return 1. 01004 */ 01005 static int 01006 null_login(int unit) 01007 { 01008 LWIP_UNUSED_ARG(unit); 01009 /* XXX Fail until we decide that we want to support logins. */ 01010 return 0; 01011 } 01012 01013 01014 /* 01015 * get_pap_passwd - get a password for authenticating ourselves with 01016 * our peer using PAP. Returns 1 on success, 0 if no suitable password 01017 * could be found. 01018 */ 01019 static int 01020 get_pap_passwd(int unit, char *user, char *passwd) 01021 { 01022 LWIP_UNUSED_ARG(unit); 01023 /* normally we would reject PAP if no password is provided, 01024 but this causes problems with some providers (like CHT in Taiwan) 01025 who incorrectly request PAP and expect a bogus/empty password, so 01026 always provide a default user/passwd of "none"/"none" 01027 01028 @todo: This should be configured by the user, instead of being hardcoded here! 01029 */ 01030 if(user) { 01031 strcpy(user, "none"); 01032 } 01033 if(passwd) { 01034 strcpy(passwd, "none"); 01035 } 01036 return 1; 01037 } 01038 01039 /* 01040 * have_pap_secret - check whether we have a PAP file with any 01041 * secrets that we could possibly use for authenticating the peer. 01042 */ 01043 static int 01044 have_pap_secret(void) 01045 { 01046 /* XXX Fail until we set up our passwords. */ 01047 return 0; 01048 } 01049 01050 /* 01051 * have_chap_secret - check whether we have a CHAP file with a 01052 * secret that we could possibly use for authenticating `client' 01053 * on `server'. Either can be the null string, meaning we don't 01054 * know the identity yet. 01055 */ 01056 static int 01057 have_chap_secret(char *client, char *server, u32_t remote) 01058 { 01059 LWIP_UNUSED_ARG(client); 01060 LWIP_UNUSED_ARG(server); 01061 LWIP_UNUSED_ARG(remote); 01062 01063 /* XXX Fail until we set up our passwords. */ 01064 return 0; 01065 } 01066 #if CHAP_SUPPORT 01067 01068 /* 01069 * get_secret - open the CHAP secret file and return the secret 01070 * for authenticating the given client on the given server. 01071 * (We could be either client or server). 01072 */ 01073 int 01074 get_secret(int unit, char *client, char *server, char *secret, int *secret_len, int save_addrs) 01075 { 01076 #if 1 01077 int len; 01078 struct wordlist *addrs; 01079 01080 LWIP_UNUSED_ARG(unit); 01081 LWIP_UNUSED_ARG(server); 01082 LWIP_UNUSED_ARG(save_addrs); 01083 01084 addrs = NULL; 01085 01086 if(!client || !client[0] || strcmp(client, ppp_settings.user)) { 01087 return 0; 01088 } 01089 01090 len = (int)strlen(ppp_settings.passwd); 01091 if (len > MAXSECRETLEN) { 01092 AUTHDEBUG(LOG_ERR, ("Secret for %s on %s is too long\n", client, server)); 01093 len = MAXSECRETLEN; 01094 } 01095 01096 BCOPY(ppp_settings.passwd, secret, len); 01097 *secret_len = len; 01098 01099 return 1; 01100 #else 01101 int ret = 0, len; 01102 struct wordlist *addrs; 01103 char secbuf[MAXWORDLEN]; 01104 01105 addrs = NULL; 01106 secbuf[0] = 0; 01107 01108 /* XXX Find secret. */ 01109 if (ret < 0) { 01110 return 0; 01111 } 01112 01113 if (save_addrs) { 01114 set_allowed_addrs(unit, addrs); 01115 } 01116 01117 len = strlen(secbuf); 01118 if (len > MAXSECRETLEN) { 01119 AUTHDEBUG(LOG_ERR, ("Secret for %s on %s is too long\n", client, server)); 01120 len = MAXSECRETLEN; 01121 } 01122 01123 BCOPY(secbuf, secret, len); 01124 BZERO(secbuf, sizeof(secbuf)); 01125 *secret_len = len; 01126 01127 return 1; 01128 #endif 01129 } 01130 #endif /* CHAP_SUPPORT */ 01131 01132 01133 #if 0 /* PAP_SUPPORT || CHAP_SUPPORT */ 01134 /* 01135 * set_allowed_addrs() - set the list of allowed addresses. 01136 */ 01137 static void 01138 set_allowed_addrs(int unit, struct wordlist *addrs) 01139 { 01140 if (addresses[unit] != NULL) { 01141 free_wordlist(addresses[unit]); 01142 } 01143 addresses[unit] = addrs; 01144 01145 #if 0 01146 /* 01147 * If there's only one authorized address we might as well 01148 * ask our peer for that one right away 01149 */ 01150 if (addrs != NULL && addrs->next == NULL) { 01151 char *p = addrs->word; 01152 struct ipcp_options *wo = &ipcp_wantoptions[unit]; 01153 u32_t a; 01154 struct hostent *hp; 01155 01156 if (wo->hisaddr == 0 && *p != '!' && *p != '-' && strchr(p, '/') == NULL) { 01157 hp = gethostbyname(p); 01158 if (hp != NULL && hp->h_addrtype == AF_INET) { 01159 a = *(u32_t *)hp->h_addr; 01160 } else { 01161 a = inet_addr(p); 01162 } 01163 if (a != (u32_t) -1) { 01164 wo->hisaddr = a; 01165 } 01166 } 01167 } 01168 #endif 01169 } 01170 #endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */ 01171 01172 /* 01173 * auth_ip_addr - check whether the peer is authorized to use 01174 * a given IP address. Returns 1 if authorized, 0 otherwise. 01175 */ 01176 int 01177 auth_ip_addr(int unit, u32_t addr) 01178 { 01179 return ip_addr_check(addr, addresses[unit]); 01180 } 01181 01182 static int /* @todo: integrate this funtion into auth_ip_addr()*/ 01183 ip_addr_check(u32_t addr, struct wordlist *addrs) 01184 { 01185 /* don't allow loopback or multicast address */ 01186 if (bad_ip_adrs(addr)) { 01187 return 0; 01188 } 01189 01190 if (addrs == NULL) { 01191 return !ppp_settings.auth_required; /* no addresses authorized */ 01192 } 01193 01194 /* XXX All other addresses allowed. */ 01195 return 1; 01196 } 01197 01198 /* 01199 * bad_ip_adrs - return 1 if the IP address is one we don't want 01200 * to use, such as an address in the loopback net or a multicast address. 01201 * addr is in network byte order. 01202 */ 01203 int 01204 bad_ip_adrs(u32_t addr) 01205 { 01206 addr = ntohl(addr); 01207 return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET 01208 || IN_MULTICAST(addr) || IN_BADCLASS(addr); 01209 } 01210 01211 #if 0 /* UNUSED */ /* PAP_SUPPORT || CHAP_SUPPORT */ 01212 /* 01213 * some_ip_ok - check a wordlist to see if it authorizes any 01214 * IP address(es). 01215 */ 01216 static int 01217 some_ip_ok(struct wordlist *addrs) 01218 { 01219 for (; addrs != 0; addrs = addrs->next) { 01220 if (addrs->word[0] == '-') 01221 break; 01222 if (addrs->word[0] != '!') 01223 return 1; /* some IP address is allowed */ 01224 } 01225 return 0; 01226 } 01227 01228 /* 01229 * check_access - complain if a secret file has too-liberal permissions. 01230 */ 01231 static void 01232 check_access(FILE *f, char *filename) 01233 { 01234 struct stat sbuf; 01235 01236 if (fstat(fileno(f), &sbuf) < 0) { 01237 warn("cannot stat secret file %s: %m", filename); 01238 } else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) { 01239 warn("Warning - secret file %s has world and/or group access", 01240 filename); 01241 } 01242 } 01243 01244 01245 /* 01246 * scan_authfile - Scan an authorization file for a secret suitable 01247 * for authenticating `client' on `server'. The return value is -1 01248 * if no secret is found, otherwise >= 0. The return value has 01249 * NONWILD_CLIENT set if the secret didn't have "*" for the client, and 01250 * NONWILD_SERVER set if the secret didn't have "*" for the server. 01251 * Any following words on the line up to a "--" (i.e. address authorization 01252 * info) are placed in a wordlist and returned in *addrs. Any 01253 * following words (extra options) are placed in a wordlist and 01254 * returned in *opts. 01255 * We assume secret is NULL or points to MAXWORDLEN bytes of space. 01256 */ 01257 static int 01258 scan_authfile(FILE *f, char *client, char *server, char *secret, struct wordlist **addrs, struct wordlist **opts, char *filename) 01259 { 01260 /* We do not (currently) need this in lwip */ 01261 return 0; /* dummy */ 01262 } 01263 /* 01264 * free_wordlist - release memory allocated for a wordlist. 01265 */ 01266 static void 01267 free_wordlist(struct wordlist *wp) 01268 { 01269 struct wordlist *next; 01270 01271 while (wp != NULL) { 01272 next = wp->next; 01273 free(wp); 01274 wp = next; 01275 } 01276 } 01277 01278 /* 01279 * auth_script_done - called when the auth-up or auth-down script 01280 * has finished. 01281 */ 01282 static void 01283 auth_script_done(void *arg) 01284 { 01285 auth_script_pid = 0; 01286 switch (auth_script_state) { 01287 case s_up: 01288 if (auth_state == s_down) { 01289 auth_script_state = s_down; 01290 auth_script(_PATH_AUTHDOWN); 01291 } 01292 break; 01293 case s_down: 01294 if (auth_state == s_up) { 01295 auth_script_state = s_up; 01296 auth_script(_PATH_AUTHUP); 01297 } 01298 break; 01299 } 01300 } 01301 01302 /* 01303 * auth_script - execute a script with arguments 01304 * interface-name peer-name real-user tty speed 01305 */ 01306 static void 01307 auth_script(char *script) 01308 { 01309 char strspeed[32]; 01310 struct passwd *pw; 01311 char struid[32]; 01312 char *user_name; 01313 char *argv[8]; 01314 01315 if ((pw = getpwuid(getuid())) != NULL && pw->pw_name != NULL) 01316 user_name = pw->pw_name; 01317 else { 01318 slprintf(struid, sizeof(struid), "%d", getuid()); 01319 user_name = struid; 01320 } 01321 slprintf(strspeed, sizeof(strspeed), "%d", baud_rate); 01322 01323 argv[0] = script; 01324 argv[1] = ifname; 01325 argv[2] = peer_authname; 01326 argv[3] = user_name; 01327 argv[4] = devnam; 01328 argv[5] = strspeed; 01329 argv[6] = NULL; 01330 01331 auth_script_pid = run_program(script, argv, 0, auth_script_done, NULL); 01332 } 01333 #endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */ 01334 #endif /* PPP_SUPPORT */
Generated on Tue Jul 12 2022 11:29:36 by
