Darran Shepherd
/
AutoIpNetStack
Net stack with AutoIP enabled
Embed:
(wiki syntax)
Show/hide line numbers
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 * XXX Warning: the unit number indicates the interface which is 00639 * not necessarily the PPP connection. It works here as long 00640 * as we are only supporting PPP interfaces. 00641 */ 00642 /* @todo: Remove pppIOCtl, it is not used anywhere else. 00643 Instead, directly set errCode. */ 00644 pppIOCtl(unit, PPPCTLS_ERRCODE, &errCode); 00645 00646 /* 00647 * We've failed to authenticate ourselves to our peer. 00648 * He'll probably take the link down, and there's not much 00649 * we can do except wait for that. 00650 */ 00651 } 00652 00653 /* 00654 * We have successfully authenticated ourselves with the peer using `protocol'. 00655 */ 00656 void 00657 auth_withpeer_success(int unit, u16_t protocol) 00658 { 00659 int pbit; 00660 00661 AUTHDEBUG(LOG_INFO, ("auth_withpeer_success: %d proto=%X\n", unit, protocol)); 00662 switch (protocol) { 00663 case PPP_CHAP: 00664 pbit = CHAP_WITHPEER; 00665 break; 00666 case PPP_PAP: 00667 if (passwd_from_file) { 00668 BZERO(ppp_settings.passwd, MAXSECRETLEN); 00669 } 00670 pbit = PAP_WITHPEER; 00671 break; 00672 default: 00673 AUTHDEBUG(LOG_WARNING, ("auth_peer_success: unknown protocol %x\n", protocol)); 00674 pbit = 0; 00675 } 00676 00677 /* 00678 * If there is no more authentication still being done, 00679 * proceed to the network (or callback) phase. 00680 */ 00681 if ((auth_pending[unit] &= ~pbit) == 0) { 00682 network_phase(unit); 00683 } 00684 } 00685 #endif /* PAP_SUPPORT || CHAP_SUPPORT */ 00686 00687 00688 /* 00689 * np_up - a network protocol has come up. 00690 */ 00691 void 00692 np_up(int unit, u16_t proto) 00693 { 00694 LWIP_UNUSED_ARG(unit); 00695 LWIP_UNUSED_ARG(proto); 00696 00697 AUTHDEBUG(LOG_INFO, ("np_up: %d proto=%X\n", unit, proto)); 00698 if (num_np_up == 0) { 00699 AUTHDEBUG(LOG_INFO, ("np_up: maxconnect=%d idle_time_limit=%d\n",ppp_settings.maxconnect,ppp_settings.idle_time_limit)); 00700 /* 00701 * At this point we consider that the link has come up successfully. 00702 */ 00703 if (ppp_settings.idle_time_limit > 0) { 00704 TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit); 00705 } 00706 00707 /* 00708 * Set a timeout to close the connection once the maximum 00709 * connect time has expired. 00710 */ 00711 if (ppp_settings.maxconnect > 0) { 00712 TIMEOUT(connect_time_expired, 0, ppp_settings.maxconnect); 00713 } 00714 } 00715 ++num_np_up; 00716 } 00717 00718 /* 00719 * np_down - a network protocol has gone down. 00720 */ 00721 void 00722 np_down(int unit, u16_t proto) 00723 { 00724 LWIP_UNUSED_ARG(unit); 00725 LWIP_UNUSED_ARG(proto); 00726 00727 AUTHDEBUG(LOG_INFO, ("np_down: %d proto=%X\n", unit, proto)); 00728 if (--num_np_up == 0 && ppp_settings.idle_time_limit > 0) { 00729 UNTIMEOUT(check_idle, NULL); 00730 } 00731 } 00732 00733 /* 00734 * np_finished - a network protocol has finished using the link. 00735 */ 00736 void 00737 np_finished(int unit, u16_t proto) 00738 { 00739 LWIP_UNUSED_ARG(unit); 00740 LWIP_UNUSED_ARG(proto); 00741 00742 AUTHDEBUG(LOG_INFO, ("np_finished: %d proto=%X\n", unit, proto)); 00743 if (--num_np_open <= 0) { 00744 /* no further use for the link: shut up shop. */ 00745 lcp_close(0, "No network protocols running"); 00746 } 00747 } 00748 00749 /* 00750 * check_idle - check whether the link has been idle for long 00751 * enough that we can shut it down. 00752 */ 00753 static void 00754 check_idle(void *arg) 00755 { 00756 struct ppp_idle idle; 00757 u_short itime; 00758 00759 LWIP_UNUSED_ARG(arg); 00760 if (!get_idle_time(0, &idle)) { 00761 return; 00762 } 00763 itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle); 00764 if (itime >= ppp_settings.idle_time_limit) { 00765 /* link is idle: shut it down. */ 00766 AUTHDEBUG(LOG_INFO, ("Terminating connection due to lack of activity.\n")); 00767 lcp_close(0, "Link inactive"); 00768 } else { 00769 TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit - itime); 00770 } 00771 } 00772 00773 /* 00774 * connect_time_expired - log a message and close the connection. 00775 */ 00776 static void 00777 connect_time_expired(void *arg) 00778 { 00779 LWIP_UNUSED_ARG(arg); 00780 00781 AUTHDEBUG(LOG_INFO, ("Connect time expired\n")); 00782 lcp_close(0, "Connect time expired"); /* Close connection */ 00783 } 00784 00785 #if 0 /* UNUSED */ 00786 /* 00787 * auth_check_options - called to check authentication options. 00788 */ 00789 void 00790 auth_check_options(void) 00791 { 00792 lcp_options *wo = &lcp_wantoptions[0]; 00793 int can_auth; 00794 ipcp_options *ipwo = &ipcp_wantoptions[0]; 00795 u32_t remote; 00796 00797 /* Default our_name to hostname, and user to our_name */ 00798 if (ppp_settings.our_name[0] == 0 || ppp_settings.usehostname) { 00799 strcpy(ppp_settings.our_name, ppp_settings.hostname); 00800 } 00801 00802 if (ppp_settings.user[0] == 0) { 00803 strcpy(ppp_settings.user, ppp_settings.our_name); 00804 } 00805 00806 /* If authentication is required, ask peer for CHAP or PAP. */ 00807 if (ppp_settings.auth_required && !wo->neg_chap && !wo->neg_upap) { 00808 wo->neg_chap = 1; 00809 wo->neg_upap = 1; 00810 } 00811 00812 /* 00813 * Check whether we have appropriate secrets to use 00814 * to authenticate the peer. 00815 */ 00816 can_auth = wo->neg_upap && have_pap_secret(); 00817 if (!can_auth && wo->neg_chap) { 00818 remote = ipwo->accept_remote? 0: ipwo->hisaddr; 00819 can_auth = have_chap_secret(ppp_settings.remote_name, ppp_settings.our_name, remote); 00820 } 00821 00822 if (ppp_settings.auth_required && !can_auth) { 00823 ppp_panic("No auth secret"); 00824 } 00825 } 00826 #endif /* UNUSED */ 00827 00828 /* 00829 * auth_reset - called when LCP is starting negotiations to recheck 00830 * authentication options, i.e. whether we have appropriate secrets 00831 * to use for authenticating ourselves and/or the peer. 00832 */ 00833 void 00834 auth_reset(int unit) 00835 { 00836 lcp_options *go = &lcp_gotoptions[unit]; 00837 lcp_options *ao = &lcp_allowoptions[0]; 00838 ipcp_options *ipwo = &ipcp_wantoptions[0]; 00839 u32_t remote; 00840 00841 AUTHDEBUG(LOG_INFO, ("auth_reset: %d\n", unit)); 00842 ao->neg_upap = !ppp_settings.refuse_pap && (ppp_settings.passwd[0] != 0 || get_pap_passwd(unit, NULL, NULL)); 00843 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)*/; 00844 00845 if (go->neg_upap && !have_pap_secret()) { 00846 go->neg_upap = 0; 00847 } 00848 if (go->neg_chap) { 00849 remote = ipwo->accept_remote? 0: ipwo->hisaddr; 00850 if (!have_chap_secret(ppp_settings.remote_name, ppp_settings.our_name, remote)) { 00851 go->neg_chap = 0; 00852 } 00853 } 00854 } 00855 00856 #if PAP_SUPPORT 00857 /* 00858 * check_passwd - Check the user name and passwd against the PAP secrets 00859 * file. If requested, also check against the system password database, 00860 * and login the user if OK. 00861 * 00862 * returns: 00863 * UPAP_AUTHNAK: Authentication failed. 00864 * UPAP_AUTHACK: Authentication succeeded. 00865 * In either case, msg points to an appropriate message. 00866 */ 00867 u_char 00868 check_passwd( int unit, char *auser, int userlen, char *apasswd, int passwdlen, char **msg, int *msglen) 00869 { 00870 #if 1 /* XXX Assume all entries OK. */ 00871 LWIP_UNUSED_ARG(unit); 00872 LWIP_UNUSED_ARG(auser); 00873 LWIP_UNUSED_ARG(userlen); 00874 LWIP_UNUSED_ARG(apasswd); 00875 LWIP_UNUSED_ARG(passwdlen); 00876 LWIP_UNUSED_ARG(msglen); 00877 *msg = (char *) 0; 00878 return UPAP_AUTHACK; /* XXX Assume all entries OK. */ 00879 #else 00880 u_char ret = 0; 00881 struct wordlist *addrs = NULL; 00882 char passwd[256], user[256]; 00883 char secret[MAXWORDLEN]; 00884 static u_short attempts = 0; 00885 00886 /* 00887 * Make copies of apasswd and auser, then null-terminate them. 00888 */ 00889 BCOPY(apasswd, passwd, passwdlen); 00890 passwd[passwdlen] = '\0'; 00891 BCOPY(auser, user, userlen); 00892 user[userlen] = '\0'; 00893 *msg = (char *) 0; 00894 00895 /* XXX Validate user name and password. */ 00896 ret = UPAP_AUTHACK; /* XXX Assume all entries OK. */ 00897 00898 if (ret == UPAP_AUTHNAK) { 00899 if (*msg == (char *) 0) { 00900 *msg = "Login incorrect"; 00901 } 00902 *msglen = strlen(*msg); 00903 /* 00904 * Frustrate passwd stealer programs. 00905 * Allow 10 tries, but start backing off after 3 (stolen from login). 00906 * On 10'th, drop the connection. 00907 */ 00908 if (attempts++ >= 10) { 00909 AUTHDEBUG(LOG_WARNING, ("%d LOGIN FAILURES BY %s\n", attempts, user)); 00910 /*ppp_panic("Excess Bad Logins");*/ 00911 } 00912 if (attempts > 3) { 00913 /* @todo: this was sleep(), i.e. seconds, not milliseconds 00914 * I don't think we really need this in lwIP - we would block tcpip_thread! 00915 */ 00916 /*sys_msleep((attempts - 3) * 5);*/ 00917 } 00918 if (addrs != NULL) { 00919 free_wordlist(addrs); 00920 } 00921 } else { 00922 attempts = 0; /* Reset count */ 00923 if (*msg == (char *) 0) { 00924 *msg = "Login ok"; 00925 } 00926 *msglen = strlen(*msg); 00927 set_allowed_addrs(unit, addrs); 00928 } 00929 00930 BZERO(passwd, sizeof(passwd)); 00931 BZERO(secret, sizeof(secret)); 00932 00933 return ret; 00934 #endif 00935 } 00936 #endif /* PAP_SUPPORT */ 00937 00938 #if 0 /* UNUSED */ 00939 /* 00940 * This function is needed for PAM. 00941 */ 00942 00943 #ifdef USE_PAM 00944 00945 /* lwip does not support PAM*/ 00946 00947 #endif /* USE_PAM */ 00948 00949 #endif /* UNUSED */ 00950 00951 00952 #if 0 /* UNUSED */ 00953 /* 00954 * plogin - Check the user name and password against the system 00955 * password database, and login the user if OK. 00956 * 00957 * returns: 00958 * UPAP_AUTHNAK: Login failed. 00959 * UPAP_AUTHACK: Login succeeded. 00960 * In either case, msg points to an appropriate message. 00961 */ 00962 static int 00963 plogin(char *user, char *passwd, char **msg, int *msglen) 00964 { 00965 00966 LWIP_UNUSED_ARG(user); 00967 LWIP_UNUSED_ARG(passwd); 00968 LWIP_UNUSED_ARG(msg); 00969 LWIP_UNUSED_ARG(msglen); 00970 00971 00972 /* The new lines are here align the file when 00973 * compared against the pppd 2.3.11 code */ 00974 00975 00976 00977 00978 00979 00980 00981 00982 00983 00984 00985 00986 00987 00988 00989 00990 /* XXX Fail until we decide that we want to support logins. */ 00991 return (UPAP_AUTHNAK); 00992 } 00993 #endif 00994 00995 00996 00997 /* 00998 * plogout - Logout the user. 00999 */ 01000 static void 01001 plogout(void) 01002 { 01003 logged_in = 0; 01004 } 01005 01006 /* 01007 * null_login - Check if a username of "" and a password of "" are 01008 * acceptable, and iff so, set the list of acceptable IP addresses 01009 * and return 1. 01010 */ 01011 static int 01012 null_login(int unit) 01013 { 01014 LWIP_UNUSED_ARG(unit); 01015 /* XXX Fail until we decide that we want to support logins. */ 01016 return 0; 01017 } 01018 01019 01020 /* 01021 * get_pap_passwd - get a password for authenticating ourselves with 01022 * our peer using PAP. Returns 1 on success, 0 if no suitable password 01023 * could be found. 01024 */ 01025 static int 01026 get_pap_passwd(int unit, char *user, char *passwd) 01027 { 01028 LWIP_UNUSED_ARG(unit); 01029 /* normally we would reject PAP if no password is provided, 01030 but this causes problems with some providers (like CHT in Taiwan) 01031 who incorrectly request PAP and expect a bogus/empty password, so 01032 always provide a default user/passwd of "none"/"none" 01033 01034 @todo: This should be configured by the user, instead of being hardcoded here! 01035 */ 01036 if(user) { 01037 strcpy(user, "none"); 01038 } 01039 if(passwd) { 01040 strcpy(passwd, "none"); 01041 } 01042 return 1; 01043 } 01044 01045 /* 01046 * have_pap_secret - check whether we have a PAP file with any 01047 * secrets that we could possibly use for authenticating the peer. 01048 */ 01049 static int 01050 have_pap_secret(void) 01051 { 01052 /* XXX Fail until we set up our passwords. */ 01053 return 0; 01054 } 01055 01056 /* 01057 * have_chap_secret - check whether we have a CHAP file with a 01058 * secret that we could possibly use for authenticating `client' 01059 * on `server'. Either can be the null string, meaning we don't 01060 * know the identity yet. 01061 */ 01062 static int 01063 have_chap_secret(char *client, char *server, u32_t remote) 01064 { 01065 LWIP_UNUSED_ARG(client); 01066 LWIP_UNUSED_ARG(server); 01067 LWIP_UNUSED_ARG(remote); 01068 01069 /* XXX Fail until we set up our passwords. */ 01070 return 0; 01071 } 01072 #if CHAP_SUPPORT 01073 01074 /* 01075 * get_secret - open the CHAP secret file and return the secret 01076 * for authenticating the given client on the given server. 01077 * (We could be either client or server). 01078 */ 01079 int 01080 get_secret(int unit, char *client, char *server, char *secret, int *secret_len, int save_addrs) 01081 { 01082 #if 1 01083 int len; 01084 struct wordlist *addrs; 01085 01086 LWIP_UNUSED_ARG(unit); 01087 LWIP_UNUSED_ARG(server); 01088 LWIP_UNUSED_ARG(save_addrs); 01089 01090 addrs = NULL; 01091 01092 if(!client || !client[0] || strcmp(client, ppp_settings.user)) { 01093 return 0; 01094 } 01095 01096 len = (int)strlen(ppp_settings.passwd); 01097 if (len > MAXSECRETLEN) { 01098 AUTHDEBUG(LOG_ERR, ("Secret for %s on %s is too long\n", client, server)); 01099 len = MAXSECRETLEN; 01100 } 01101 01102 BCOPY(ppp_settings.passwd, secret, len); 01103 *secret_len = len; 01104 01105 return 1; 01106 #else 01107 int ret = 0, len; 01108 struct wordlist *addrs; 01109 char secbuf[MAXWORDLEN]; 01110 01111 addrs = NULL; 01112 secbuf[0] = 0; 01113 01114 /* XXX Find secret. */ 01115 if (ret < 0) { 01116 return 0; 01117 } 01118 01119 if (save_addrs) { 01120 set_allowed_addrs(unit, addrs); 01121 } 01122 01123 len = strlen(secbuf); 01124 if (len > MAXSECRETLEN) { 01125 AUTHDEBUG(LOG_ERR, ("Secret for %s on %s is too long\n", client, server)); 01126 len = MAXSECRETLEN; 01127 } 01128 01129 BCOPY(secbuf, secret, len); 01130 BZERO(secbuf, sizeof(secbuf)); 01131 *secret_len = len; 01132 01133 return 1; 01134 #endif 01135 } 01136 #endif /* CHAP_SUPPORT */ 01137 01138 01139 #if 0 /* PAP_SUPPORT || CHAP_SUPPORT */ 01140 /* 01141 * set_allowed_addrs() - set the list of allowed addresses. 01142 */ 01143 static void 01144 set_allowed_addrs(int unit, struct wordlist *addrs) 01145 { 01146 if (addresses[unit] != NULL) { 01147 free_wordlist(addresses[unit]); 01148 } 01149 addresses[unit] = addrs; 01150 01151 #if 0 01152 /* 01153 * If there's only one authorized address we might as well 01154 * ask our peer for that one right away 01155 */ 01156 if (addrs != NULL && addrs->next == NULL) { 01157 char *p = addrs->word; 01158 struct ipcp_options *wo = &ipcp_wantoptions[unit]; 01159 u32_t a; 01160 struct hostent *hp; 01161 01162 if (wo->hisaddr == 0 && *p != '!' && *p != '-' && strchr(p, '/') == NULL) { 01163 hp = gethostbyname(p); 01164 if (hp != NULL && hp->h_addrtype == AF_INET) { 01165 a = *(u32_t *)hp->h_addr; 01166 } else { 01167 a = inet_addr(p); 01168 } 01169 if (a != (u32_t) -1) { 01170 wo->hisaddr = a; 01171 } 01172 } 01173 } 01174 #endif 01175 } 01176 #endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */ 01177 01178 /* 01179 * auth_ip_addr - check whether the peer is authorized to use 01180 * a given IP address. Returns 1 if authorized, 0 otherwise. 01181 */ 01182 int 01183 auth_ip_addr(int unit, u32_t addr) 01184 { 01185 return ip_addr_check(addr, addresses[unit]); 01186 } 01187 01188 static int /* @todo: integrate this funtion into auth_ip_addr()*/ 01189 ip_addr_check(u32_t addr, struct wordlist *addrs) 01190 { 01191 /* don't allow loopback or multicast address */ 01192 if (bad_ip_adrs(addr)) { 01193 return 0; 01194 } 01195 01196 if (addrs == NULL) { 01197 return !ppp_settings.auth_required; /* no addresses authorized */ 01198 } 01199 01200 /* XXX All other addresses allowed. */ 01201 return 1; 01202 } 01203 01204 /* 01205 * bad_ip_adrs - return 1 if the IP address is one we don't want 01206 * to use, such as an address in the loopback net or a multicast address. 01207 * addr is in network byte order. 01208 */ 01209 int 01210 bad_ip_adrs(u32_t addr) 01211 { 01212 addr = ntohl(addr); 01213 return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET 01214 || IN_MULTICAST(addr) || IN_BADCLASS(addr); 01215 } 01216 01217 #if 0 /* UNUSED */ /* PAP_SUPPORT || CHAP_SUPPORT */ 01218 /* 01219 * some_ip_ok - check a wordlist to see if it authorizes any 01220 * IP address(es). 01221 */ 01222 static int 01223 some_ip_ok(struct wordlist *addrs) 01224 { 01225 for (; addrs != 0; addrs = addrs->next) { 01226 if (addrs->word[0] == '-') 01227 break; 01228 if (addrs->word[0] != '!') 01229 return 1; /* some IP address is allowed */ 01230 } 01231 return 0; 01232 } 01233 01234 /* 01235 * check_access - complain if a secret file has too-liberal permissions. 01236 */ 01237 static void 01238 check_access(FILE *f, char *filename) 01239 { 01240 struct stat sbuf; 01241 01242 if (fstat(fileno(f), &sbuf) < 0) { 01243 warn("cannot stat secret file %s: %m", filename); 01244 } else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) { 01245 warn("Warning - secret file %s has world and/or group access", 01246 filename); 01247 } 01248 } 01249 01250 01251 /* 01252 * scan_authfile - Scan an authorization file for a secret suitable 01253 * for authenticating `client' on `server'. The return value is -1 01254 * if no secret is found, otherwise >= 0. The return value has 01255 * NONWILD_CLIENT set if the secret didn't have "*" for the client, and 01256 * NONWILD_SERVER set if the secret didn't have "*" for the server. 01257 * Any following words on the line up to a "--" (i.e. address authorization 01258 * info) are placed in a wordlist and returned in *addrs. Any 01259 * following words (extra options) are placed in a wordlist and 01260 * returned in *opts. 01261 * We assume secret is NULL or points to MAXWORDLEN bytes of space. 01262 */ 01263 static int 01264 scan_authfile(FILE *f, char *client, char *server, char *secret, struct wordlist **addrs, struct wordlist **opts, char *filename) 01265 { 01266 /* We do not (currently) need this in lwip */ 01267 return 0; /* dummy */ 01268 } 01269 /* 01270 * free_wordlist - release memory allocated for a wordlist. 01271 */ 01272 static void 01273 free_wordlist(struct wordlist *wp) 01274 { 01275 struct wordlist *next; 01276 01277 while (wp != NULL) { 01278 next = wp->next; 01279 free(wp); 01280 wp = next; 01281 } 01282 } 01283 01284 /* 01285 * auth_script_done - called when the auth-up or auth-down script 01286 * has finished. 01287 */ 01288 static void 01289 auth_script_done(void *arg) 01290 { 01291 auth_script_pid = 0; 01292 switch (auth_script_state) { 01293 case s_up: 01294 if (auth_state == s_down) { 01295 auth_script_state = s_down; 01296 auth_script(_PATH_AUTHDOWN); 01297 } 01298 break; 01299 case s_down: 01300 if (auth_state == s_up) { 01301 auth_script_state = s_up; 01302 auth_script(_PATH_AUTHUP); 01303 } 01304 break; 01305 } 01306 } 01307 01308 /* 01309 * auth_script - execute a script with arguments 01310 * interface-name peer-name real-user tty speed 01311 */ 01312 static void 01313 auth_script(char *script) 01314 { 01315 char strspeed[32]; 01316 struct passwd *pw; 01317 char struid[32]; 01318 char *user_name; 01319 char *argv[8]; 01320 01321 if ((pw = getpwuid(getuid())) != NULL && pw->pw_name != NULL) 01322 user_name = pw->pw_name; 01323 else { 01324 slprintf(struid, sizeof(struid), "%d", getuid()); 01325 user_name = struid; 01326 } 01327 slprintf(strspeed, sizeof(strspeed), "%d", baud_rate); 01328 01329 argv[0] = script; 01330 argv[1] = ifname; 01331 argv[2] = peer_authname; 01332 argv[3] = user_name; 01333 argv[4] = devnam; 01334 argv[5] = strspeed; 01335 argv[6] = NULL; 01336 01337 auth_script_pid = run_program(script, argv, 0, auth_script_done, NULL); 01338 } 01339 #endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */ 01340 #endif /* PPP_SUPPORT */
Generated on Tue Jul 12 2022 15:37:03 by 1.7.2