17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * auth.c - PPP authentication and phase control. 37c478bd9Sstevel@tonic-gate * 42a9459bdSsangeeta * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 57c478bd9Sstevel@tonic-gate * Use is subject to license terms. 67c478bd9Sstevel@tonic-gate * 77c478bd9Sstevel@tonic-gate * Copyright (c) 1993 The Australian National University. 87c478bd9Sstevel@tonic-gate * All rights reserved. 97c478bd9Sstevel@tonic-gate * 107c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms are permitted 117c478bd9Sstevel@tonic-gate * provided that the above copyright notice and this paragraph are 127c478bd9Sstevel@tonic-gate * duplicated in all such forms and that any documentation, 137c478bd9Sstevel@tonic-gate * advertising materials, and other materials related to such 147c478bd9Sstevel@tonic-gate * distribution and use acknowledge that the software was developed 157c478bd9Sstevel@tonic-gate * by the Australian National University. The name of the University 167c478bd9Sstevel@tonic-gate * may not be used to endorse or promote products derived from this 177c478bd9Sstevel@tonic-gate * software without specific prior written permission. 187c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 197c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 207c478bd9Sstevel@tonic-gate * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 217c478bd9Sstevel@tonic-gate * 227c478bd9Sstevel@tonic-gate * Copyright (c) 1989 Carnegie Mellon University. 237c478bd9Sstevel@tonic-gate * All rights reserved. 247c478bd9Sstevel@tonic-gate * 257c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms are permitted 267c478bd9Sstevel@tonic-gate * provided that the above copyright notice and this paragraph are 277c478bd9Sstevel@tonic-gate * duplicated in all such forms and that any documentation, 287c478bd9Sstevel@tonic-gate * advertising materials, and other materials related to such 297c478bd9Sstevel@tonic-gate * distribution and use acknowledge that the software was developed 307c478bd9Sstevel@tonic-gate * by Carnegie Mellon University. The name of the 317c478bd9Sstevel@tonic-gate * University may not be used to endorse or promote products derived 327c478bd9Sstevel@tonic-gate * from this software without specific prior written permission. 337c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 347c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 357c478bd9Sstevel@tonic-gate * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 367c478bd9Sstevel@tonic-gate */ 377c478bd9Sstevel@tonic-gate 38*2de0a7d6SDan McDonald #pragma ident "%Z%%M% %I% %E% SMI" 397c478bd9Sstevel@tonic-gate #define RCSID "$Id: auth.c,v 1.65 2000/04/15 01:27:10 masputra Exp $" 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate /* Pull in crypt() definition. */ 427c478bd9Sstevel@tonic-gate #define __EXTENSIONS__ 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate #include <stdio.h> 457c478bd9Sstevel@tonic-gate #include <stddef.h> 467c478bd9Sstevel@tonic-gate #include <stdlib.h> 477c478bd9Sstevel@tonic-gate #include <unistd.h> 487c478bd9Sstevel@tonic-gate #include <pwd.h> 497c478bd9Sstevel@tonic-gate #include <grp.h> 507c478bd9Sstevel@tonic-gate #include <string.h> 517c478bd9Sstevel@tonic-gate #include <sys/types.h> 527c478bd9Sstevel@tonic-gate #include <sys/stat.h> 537c478bd9Sstevel@tonic-gate #include <sys/socket.h> 547c478bd9Sstevel@tonic-gate #include <utmp.h> 557c478bd9Sstevel@tonic-gate #include <fcntl.h> 567c478bd9Sstevel@tonic-gate #if defined(_PATH_LASTLOG) && (defined(_linux_) || defined(__linux__)) 577c478bd9Sstevel@tonic-gate #include <lastlog.h> 587c478bd9Sstevel@tonic-gate #endif 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate #if defined(_linux_) || defined(__linux__) 617c478bd9Sstevel@tonic-gate #include <crypt.h> 627c478bd9Sstevel@tonic-gate #endif 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate #include <netdb.h> 657c478bd9Sstevel@tonic-gate #include <netinet/in.h> 667c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate /* Backward compatibility with old Makefiles */ 697c478bd9Sstevel@tonic-gate #if defined(USE_PAM) && !defined(ALLOW_PAM) 707c478bd9Sstevel@tonic-gate #define ALLOW_PAM 717c478bd9Sstevel@tonic-gate #endif 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate #ifdef ALLOW_PAM 747c478bd9Sstevel@tonic-gate #include <security/pam_appl.h> 757c478bd9Sstevel@tonic-gate #endif 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate #ifdef HAS_SHADOW 787c478bd9Sstevel@tonic-gate #include <shadow.h> 797c478bd9Sstevel@tonic-gate #ifndef PW_PPP 807c478bd9Sstevel@tonic-gate #define PW_PPP PW_LOGIN 817c478bd9Sstevel@tonic-gate #endif 827c478bd9Sstevel@tonic-gate #endif 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate #include "pppd.h" 857c478bd9Sstevel@tonic-gate #include "fsm.h" 867c478bd9Sstevel@tonic-gate #include "lcp.h" 877c478bd9Sstevel@tonic-gate #include "ipcp.h" 887c478bd9Sstevel@tonic-gate #include "upap.h" 897c478bd9Sstevel@tonic-gate #include "chap.h" 907c478bd9Sstevel@tonic-gate #ifdef CBCP_SUPPORT 917c478bd9Sstevel@tonic-gate #include "cbcp.h" 927c478bd9Sstevel@tonic-gate #endif 937c478bd9Sstevel@tonic-gate #include "pathnames.h" 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate #if !defined(lint) && !defined(_lint) 967c478bd9Sstevel@tonic-gate static const char rcsid[] = RCSID; 977c478bd9Sstevel@tonic-gate #endif 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate /* Bits in scan_authfile return value */ 1007c478bd9Sstevel@tonic-gate #define NONWILD_SERVER 1 1017c478bd9Sstevel@tonic-gate #define NONWILD_CLIENT 2 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate #define ISWILD(word) (word[0] == '*' && word[1] == '\0') 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate /* The name by which the peer authenticated itself to us. */ 1067c478bd9Sstevel@tonic-gate char peer_authname[MAXNAMELEN]; 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate /* Records which authentication operations haven't completed yet. */ 1097c478bd9Sstevel@tonic-gate static int auth_pending[NUM_PPP]; 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate /* Set if we have successfully called plogin() */ 1127c478bd9Sstevel@tonic-gate static int logged_in; 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate /* List of addresses which the peer may use. */ 1157c478bd9Sstevel@tonic-gate static struct permitted_ip *addresses[NUM_PPP]; 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate /* Wordlist giving addresses which the peer may use 1187c478bd9Sstevel@tonic-gate without authenticating itself. */ 1197c478bd9Sstevel@tonic-gate static struct wordlist *noauth_addrs; 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate /* Extra options to apply, from the secrets file entry for the peer. */ 1227c478bd9Sstevel@tonic-gate static struct wordlist *extra_options; 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate /* Source of those extra options. */ 1257c478bd9Sstevel@tonic-gate static const char *extra_opt_filename; 1267c478bd9Sstevel@tonic-gate static int extra_opt_line; 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate /* Number of network protocols which we have opened. */ 1297c478bd9Sstevel@tonic-gate static int num_np_open; 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate /* Number of network protocols which have come up. */ 1327c478bd9Sstevel@tonic-gate static int num_np_up; 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate /* Set if we got the contents of passwd[] from the pap-secrets file. */ 1357c478bd9Sstevel@tonic-gate static int passwd_from_file; 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate /* Set if we require authentication only because we have a default route. */ 1387c478bd9Sstevel@tonic-gate static bool default_auth; 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate /* Hook to enable a plugin to control the idle time limit */ 1417c478bd9Sstevel@tonic-gate int (*idle_time_hook) __P((struct ppp_idle *)) = NULL; 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate /* Hook for a plugin to say whether we can possibly authenticate any peer */ 1447c478bd9Sstevel@tonic-gate int (*pap_check_hook) __P((void)) = NULL; 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate /* Hook for a plugin to check the PAP user and password */ 1477c478bd9Sstevel@tonic-gate int (*pap_auth_hook) __P((char *user, char *passwd, char **msgp, 1487c478bd9Sstevel@tonic-gate struct wordlist **paddrs, 1497c478bd9Sstevel@tonic-gate struct wordlist **popts)) = NULL; 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate /* Hook for a plugin to know about the PAP user logout */ 1527c478bd9Sstevel@tonic-gate void (*pap_logout_hook) __P((void)) = NULL; 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate /* Hook for a plugin to get the PAP password for authenticating us */ 1557c478bd9Sstevel@tonic-gate int (*pap_passwd_hook) __P((char *user, char *passwd)) = NULL; 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate /* 1587c478bd9Sstevel@tonic-gate * This is used to ensure that we don't start an auth-up/down 1597c478bd9Sstevel@tonic-gate * script while one is already running. 1607c478bd9Sstevel@tonic-gate */ 1617c478bd9Sstevel@tonic-gate enum script_state { 1627c478bd9Sstevel@tonic-gate s_down, 1637c478bd9Sstevel@tonic-gate s_up 1647c478bd9Sstevel@tonic-gate }; 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate static enum script_state auth_state = s_down; 1677c478bd9Sstevel@tonic-gate static enum script_state auth_script_state = s_down; 1687c478bd9Sstevel@tonic-gate static pid_t auth_script_pid = 0; 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate /* 1717c478bd9Sstevel@tonic-gate * This is set by scan_authfile if a client matches, but server doesn't 1727c478bd9Sstevel@tonic-gate * (possible configuration error). 1737c478bd9Sstevel@tonic-gate */ 1747c478bd9Sstevel@tonic-gate static char scan_server_match_failed[MAXWORDLEN]; 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate /* 1777c478bd9Sstevel@tonic-gate * Option variables. 1787c478bd9Sstevel@tonic-gate */ 1797c478bd9Sstevel@tonic-gate bool uselogin = 0; /* Use /etc/passwd for checking PAP */ 1807c478bd9Sstevel@tonic-gate bool cryptpap = 0; /* Passwords in pap-secrets are encrypted */ 1817c478bd9Sstevel@tonic-gate bool refuse_pap = 0; /* Don't wanna auth. ourselves with PAP */ 1827c478bd9Sstevel@tonic-gate bool refuse_chap = 0; /* Don't wanna auth. ourselves with CHAP */ 1837c478bd9Sstevel@tonic-gate bool usehostname = 0; /* Use hostname for our_name */ 1847c478bd9Sstevel@tonic-gate bool auth_required = 0; /* Always require authentication from peer */ 1857c478bd9Sstevel@tonic-gate bool allow_any_ip = 0; /* Allow peer to use any IP address */ 1867c478bd9Sstevel@tonic-gate bool explicit_remote = 0; /* User specified explicit remote name */ 1877c478bd9Sstevel@tonic-gate char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate #ifdef CHAPMS 1907c478bd9Sstevel@tonic-gate bool refuse_mschap = 0; /* Don't wanna auth. ourself with MS-CHAPv1 */ 1917c478bd9Sstevel@tonic-gate #else 1927c478bd9Sstevel@tonic-gate bool refuse_mschap = 1; /* Never auth. ourself with MS-CHAPv1 */ 1937c478bd9Sstevel@tonic-gate #endif 1947c478bd9Sstevel@tonic-gate #ifdef CHAPMSV2 1957c478bd9Sstevel@tonic-gate bool refuse_mschapv2 = 0; /* Don't wanna auth. ourself with MS-CHAPv2 */ 1967c478bd9Sstevel@tonic-gate #else 1977c478bd9Sstevel@tonic-gate bool refuse_mschapv2 = 1; /* Never auth. ourself with MS-CHAPv2 */ 1987c478bd9Sstevel@tonic-gate #endif 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate #ifdef USE_PAM 2017c478bd9Sstevel@tonic-gate bool use_pam = 1; /* Enable use of PAM by default */ 2027c478bd9Sstevel@tonic-gate #else 2037c478bd9Sstevel@tonic-gate bool use_pam = 0; /* Disable use of PAM by default */ 2047c478bd9Sstevel@tonic-gate #endif 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate /* Bits in auth_pending[] */ 2077c478bd9Sstevel@tonic-gate #define PAP_WITHPEER 1 2087c478bd9Sstevel@tonic-gate #define PAP_PEER 2 2097c478bd9Sstevel@tonic-gate #define CHAP_WITHPEER 4 2107c478bd9Sstevel@tonic-gate #define CHAP_PEER 8 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate /* Prototypes for procedures local to this file. */ 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate static void network_phase __P((int)); 2157c478bd9Sstevel@tonic-gate static void check_idle __P((void *)); 2167c478bd9Sstevel@tonic-gate static void connect_time_expired __P((void *)); 2177c478bd9Sstevel@tonic-gate static int plogin __P((char *, char *, char **)); 2187c478bd9Sstevel@tonic-gate static void plogout __P((void)); 2197c478bd9Sstevel@tonic-gate static int null_login __P((int)); 2207c478bd9Sstevel@tonic-gate static int get_pap_passwd __P((char *)); 2217c478bd9Sstevel@tonic-gate static int have_pap_secret __P((int *)); 2227c478bd9Sstevel@tonic-gate static int have_chap_secret __P((char *, char *, int, int *)); 2237c478bd9Sstevel@tonic-gate static int ip_addr_check __P((u_int32_t, struct permitted_ip *)); 2247c478bd9Sstevel@tonic-gate static int scan_authfile __P((FILE *, char *, char *, char *, 2257c478bd9Sstevel@tonic-gate struct wordlist **, struct wordlist **, 2267c478bd9Sstevel@tonic-gate char *)); 2277c478bd9Sstevel@tonic-gate static void free_wordlist __P((struct wordlist *)); 2287c478bd9Sstevel@tonic-gate static void auth_script __P((char *)); 2297c478bd9Sstevel@tonic-gate static void auth_script_done __P((void *, int)); 2307c478bd9Sstevel@tonic-gate static void set_allowed_addrs __P((int, struct wordlist *, struct wordlist *)); 2317c478bd9Sstevel@tonic-gate static int some_ip_ok __P((struct wordlist *)); 2327c478bd9Sstevel@tonic-gate static int setupapfile __P((char **, option_t *)); 2337c478bd9Sstevel@tonic-gate static int privgroup __P((char **, option_t *)); 2347c478bd9Sstevel@tonic-gate static int set_noauth_addr __P((char **, option_t *)); 2357c478bd9Sstevel@tonic-gate static void check_access __P((FILE *, char *)); 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate /* 2387c478bd9Sstevel@tonic-gate * Authentication-related options. 2397c478bd9Sstevel@tonic-gate */ 2407c478bd9Sstevel@tonic-gate option_t auth_options[] = { 2417c478bd9Sstevel@tonic-gate { "require-pap", o_bool, &lcp_wantoptions[0].neg_upap, 2427c478bd9Sstevel@tonic-gate "Require PAP authentication from peer", 1, &auth_required }, 2437c478bd9Sstevel@tonic-gate { "+pap", o_bool, &lcp_wantoptions[0].neg_upap, 2447c478bd9Sstevel@tonic-gate "Require PAP authentication from peer", 1, &auth_required }, 2457c478bd9Sstevel@tonic-gate { "refuse-pap", o_bool, &refuse_pap, 2467c478bd9Sstevel@tonic-gate "Don't agree to auth to peer with PAP", 1 }, 2477c478bd9Sstevel@tonic-gate { "-pap", o_bool, &refuse_pap, 2487c478bd9Sstevel@tonic-gate "Don't allow PAP authentication with peer", 1 }, 2497c478bd9Sstevel@tonic-gate { "require-chap", o_bool, &lcp_wantoptions[0].neg_chap, 2507c478bd9Sstevel@tonic-gate "Require CHAP authentication from peer", 1, &auth_required }, 2517c478bd9Sstevel@tonic-gate { "+chap", o_bool, &lcp_wantoptions[0].neg_chap, 2527c478bd9Sstevel@tonic-gate "Require CHAP authentication from peer", 1, &auth_required }, 2537c478bd9Sstevel@tonic-gate { "refuse-chap", o_bool, &refuse_chap, 2547c478bd9Sstevel@tonic-gate "Don't agree to auth to peer with CHAP", 1 }, 2557c478bd9Sstevel@tonic-gate { "-chap", o_bool, &refuse_chap, 2567c478bd9Sstevel@tonic-gate "Don't allow CHAP authentication with peer", 1 }, 2577c478bd9Sstevel@tonic-gate { "name", o_string, our_name, 2587c478bd9Sstevel@tonic-gate "Set local name for authentication", 2597c478bd9Sstevel@tonic-gate OPT_PRIV|OPT_STATIC, NULL, MAXNAMELEN }, 2607c478bd9Sstevel@tonic-gate { "user", o_string, user, 2617c478bd9Sstevel@tonic-gate "Set name for auth with peer", OPT_STATIC, NULL, MAXNAMELEN }, 2627c478bd9Sstevel@tonic-gate { "usehostname", o_bool, &usehostname, 2637c478bd9Sstevel@tonic-gate "Must use hostname for authentication", 1 }, 2647c478bd9Sstevel@tonic-gate { "remotename", o_string, remote_name, 2657c478bd9Sstevel@tonic-gate "Set remote name for authentication", OPT_STATIC, 2667c478bd9Sstevel@tonic-gate &explicit_remote, MAXNAMELEN }, 2677c478bd9Sstevel@tonic-gate { "auth", o_bool, &auth_required, 2687c478bd9Sstevel@tonic-gate "Require authentication from peer", 1 }, 2697c478bd9Sstevel@tonic-gate { "noauth", o_bool, &auth_required, 2707c478bd9Sstevel@tonic-gate "Don't require peer to authenticate", OPT_PRIV, &allow_any_ip }, 2717c478bd9Sstevel@tonic-gate { "login", o_bool, &uselogin, 2727c478bd9Sstevel@tonic-gate "Use system password database for PAP", 1 }, 2737c478bd9Sstevel@tonic-gate { "papcrypt", o_bool, &cryptpap, 2747c478bd9Sstevel@tonic-gate "PAP passwords are encrypted", 1 }, 2757c478bd9Sstevel@tonic-gate { "+ua", o_special, (void *)setupapfile, 2767c478bd9Sstevel@tonic-gate "Get PAP user and password from file" }, 2777c478bd9Sstevel@tonic-gate { "password", o_string, passwd, 2787c478bd9Sstevel@tonic-gate "Password for authenticating us to the peer", OPT_STATIC, 2797c478bd9Sstevel@tonic-gate NULL, MAXSECRETLEN }, 2807c478bd9Sstevel@tonic-gate { "privgroup", o_special, (void *)privgroup, 2817c478bd9Sstevel@tonic-gate "Allow group members to use privileged options", OPT_PRIV }, 2827c478bd9Sstevel@tonic-gate { "allow-ip", o_special, (void *)set_noauth_addr, 2837c478bd9Sstevel@tonic-gate "Set peer IP address(es) usable without authentication", 2847c478bd9Sstevel@tonic-gate OPT_PRIV }, 2857c478bd9Sstevel@tonic-gate #ifdef CHAPMS 2867c478bd9Sstevel@tonic-gate { "require-mschap", o_bool, &lcp_wantoptions[0].neg_mschap, 2877c478bd9Sstevel@tonic-gate "Require MS-CHAPv1 authentication from peer", 1, &auth_required }, 2887c478bd9Sstevel@tonic-gate { "refuse-mschap", o_bool, &refuse_mschap, 2897c478bd9Sstevel@tonic-gate "Don't agree to authenticate to peer with MS-CHAPv1", 1 }, 2907c478bd9Sstevel@tonic-gate #endif 2917c478bd9Sstevel@tonic-gate #ifdef CHAPMSV2 2927c478bd9Sstevel@tonic-gate { "require-mschapv2", o_bool, &lcp_wantoptions[0].neg_mschapv2, 2937c478bd9Sstevel@tonic-gate "Require MS-CHAPv2 authentication from peer", 1, &auth_required }, 2947c478bd9Sstevel@tonic-gate { "refuse-mschapv2", o_bool, &refuse_mschapv2, 2957c478bd9Sstevel@tonic-gate "Don't agree to authenticate to peer with MS-CHAPv2", 1 }, 2967c478bd9Sstevel@tonic-gate #endif 2977c478bd9Sstevel@tonic-gate #ifdef ALLOW_PAM 2987c478bd9Sstevel@tonic-gate { "pam", o_bool, &use_pam, 2997c478bd9Sstevel@tonic-gate "Enable use of Pluggable Authentication Modules", OPT_PRIV|1 }, 3007c478bd9Sstevel@tonic-gate { "nopam", o_bool, &use_pam, 3017c478bd9Sstevel@tonic-gate "Disable use of Pluggable Authentication Modules", OPT_PRIV|0 }, 3027c478bd9Sstevel@tonic-gate #endif 3037c478bd9Sstevel@tonic-gate { NULL } 3047c478bd9Sstevel@tonic-gate }; 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate /* 3077c478bd9Sstevel@tonic-gate * setupapfile - specifies UPAP info for authenticating with peer. 3087c478bd9Sstevel@tonic-gate */ 3097c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3107c478bd9Sstevel@tonic-gate static int 3117c478bd9Sstevel@tonic-gate setupapfile(argv, opt) 3127c478bd9Sstevel@tonic-gate char **argv; 3137c478bd9Sstevel@tonic-gate option_t *opt; 3147c478bd9Sstevel@tonic-gate { 3157c478bd9Sstevel@tonic-gate FILE * ufile; 3167c478bd9Sstevel@tonic-gate int l; 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate lcp_allowoptions[0].neg_upap = 1; 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate /* open user info file */ 3217c478bd9Sstevel@tonic-gate (void) seteuid(getuid()); 3227c478bd9Sstevel@tonic-gate ufile = fopen(*argv, "r"); 3237c478bd9Sstevel@tonic-gate (void) seteuid(0); 3247c478bd9Sstevel@tonic-gate if (ufile == NULL) { 3257c478bd9Sstevel@tonic-gate option_error("unable to open user login data file %s", *argv); 3267c478bd9Sstevel@tonic-gate return 0; 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate check_access(ufile, *argv); 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate /* get username */ 3317c478bd9Sstevel@tonic-gate if (fgets(user, MAXNAMELEN - 1, ufile) == NULL 3327c478bd9Sstevel@tonic-gate || fgets(passwd, MAXSECRETLEN - 1, ufile) == NULL){ 3337c478bd9Sstevel@tonic-gate option_error("unable to read user login data file %s", *argv); 3347c478bd9Sstevel@tonic-gate return 0; 3357c478bd9Sstevel@tonic-gate } 3367c478bd9Sstevel@tonic-gate (void) fclose(ufile); 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate /* get rid of newlines */ 3397c478bd9Sstevel@tonic-gate l = strlen(user); 3407c478bd9Sstevel@tonic-gate if (l > 0 && user[l-1] == '\n') 3417c478bd9Sstevel@tonic-gate user[l-1] = '\0'; 3427c478bd9Sstevel@tonic-gate l = strlen(passwd); 3437c478bd9Sstevel@tonic-gate if (l > 0 && passwd[l-1] == '\n') 3447c478bd9Sstevel@tonic-gate passwd[l-1] = '\0'; 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate return (1); 3477c478bd9Sstevel@tonic-gate } 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate /* 3517c478bd9Sstevel@tonic-gate * privgroup - allow members of the group to have privileged access. 3527c478bd9Sstevel@tonic-gate */ 3537c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3547c478bd9Sstevel@tonic-gate static int 3557c478bd9Sstevel@tonic-gate privgroup(argv, opt) 3567c478bd9Sstevel@tonic-gate char **argv; 3577c478bd9Sstevel@tonic-gate option_t *opt; 3587c478bd9Sstevel@tonic-gate { 3597c478bd9Sstevel@tonic-gate struct group *g; 3607c478bd9Sstevel@tonic-gate int i; 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate g = getgrnam(*argv); 3637c478bd9Sstevel@tonic-gate if (g == NULL) { 3647c478bd9Sstevel@tonic-gate option_error("group %s is unknown", *argv); 3657c478bd9Sstevel@tonic-gate return 0; 3667c478bd9Sstevel@tonic-gate } 3677c478bd9Sstevel@tonic-gate for (i = 0; i < ngroups; ++i) { 3687c478bd9Sstevel@tonic-gate if (groups[i] == g->gr_gid) { 3697c478bd9Sstevel@tonic-gate privileged = 1; 3707c478bd9Sstevel@tonic-gate break; 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate } 3737c478bd9Sstevel@tonic-gate return 1; 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate /* 3787c478bd9Sstevel@tonic-gate * set_noauth_addr - set address(es) that can be used without authentication. 3797c478bd9Sstevel@tonic-gate * Equivalent to specifying an entry like `"" * "" addr' in pap-secrets. 3807c478bd9Sstevel@tonic-gate */ 3817c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3827c478bd9Sstevel@tonic-gate static int 3837c478bd9Sstevel@tonic-gate set_noauth_addr(argv, opt) 3847c478bd9Sstevel@tonic-gate char **argv; 3857c478bd9Sstevel@tonic-gate option_t *opt; 3867c478bd9Sstevel@tonic-gate { 3877c478bd9Sstevel@tonic-gate char *addr = *argv; 3887c478bd9Sstevel@tonic-gate int l = strlen(addr); 3897c478bd9Sstevel@tonic-gate struct wordlist *wp; 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l + 1); 3927c478bd9Sstevel@tonic-gate if (wp == NULL) 3937c478bd9Sstevel@tonic-gate novm("allow-ip argument"); 3947c478bd9Sstevel@tonic-gate wp->word = (char *) (wp + 1); 3957c478bd9Sstevel@tonic-gate wp->next = noauth_addrs; 3967c478bd9Sstevel@tonic-gate (void) strcpy(wp->word, addr); 3977c478bd9Sstevel@tonic-gate noauth_addrs = wp; 3987c478bd9Sstevel@tonic-gate return 1; 3997c478bd9Sstevel@tonic-gate } 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate /* 4027c478bd9Sstevel@tonic-gate * An Open on LCP has requested a change from Dead to Establish phase. 4037c478bd9Sstevel@tonic-gate * Do what's necessary to bring the physical layer up. 4047c478bd9Sstevel@tonic-gate */ 4057c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4067c478bd9Sstevel@tonic-gate void 4077c478bd9Sstevel@tonic-gate link_required(unit) 4087c478bd9Sstevel@tonic-gate int unit; 4097c478bd9Sstevel@tonic-gate { 4107c478bd9Sstevel@tonic-gate } 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate /* 4137c478bd9Sstevel@tonic-gate * LCP has terminated the link; go to the Dead phase and take the 4147c478bd9Sstevel@tonic-gate * physical layer down. 4157c478bd9Sstevel@tonic-gate */ 4167c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4177c478bd9Sstevel@tonic-gate void 4187c478bd9Sstevel@tonic-gate link_terminated(unit) 4197c478bd9Sstevel@tonic-gate int unit; 4207c478bd9Sstevel@tonic-gate { 4217c478bd9Sstevel@tonic-gate const char *pn1, *pn2; 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate if (phase == PHASE_DEAD) 4247c478bd9Sstevel@tonic-gate return; 4257c478bd9Sstevel@tonic-gate if (pap_logout_hook != NULL) { 4267c478bd9Sstevel@tonic-gate (*pap_logout_hook)(); 4277c478bd9Sstevel@tonic-gate } else { 4287c478bd9Sstevel@tonic-gate if (logged_in) 4297c478bd9Sstevel@tonic-gate plogout(); 4307c478bd9Sstevel@tonic-gate } 4317c478bd9Sstevel@tonic-gate new_phase(PHASE_DEAD); 4327c478bd9Sstevel@tonic-gate if (peer_nak_auth) { 4337c478bd9Sstevel@tonic-gate if ((pn1 = protocol_name(nak_auth_orig)) == NULL) 4347c478bd9Sstevel@tonic-gate pn1 = "?"; 4357c478bd9Sstevel@tonic-gate if ((pn2 = protocol_name(nak_auth_proto)) == NULL) 4367c478bd9Sstevel@tonic-gate pn2 = "?"; 4377c478bd9Sstevel@tonic-gate warn("Peer sent Configure-Nak for 0x%x (%s) to suggest 0x%x (%s)", 4387c478bd9Sstevel@tonic-gate nak_auth_orig, pn1, nak_auth_proto, pn2); 4397c478bd9Sstevel@tonic-gate } 4407c478bd9Sstevel@tonic-gate if (unsolicited_nak_auth) { 4417c478bd9Sstevel@tonic-gate if ((pn1 = protocol_name(unsolicit_auth_proto)) == NULL) 4427c478bd9Sstevel@tonic-gate pn1 = "?"; 4437c478bd9Sstevel@tonic-gate warn("Peer unexpectedly asked us to authenticate with 0x%x (%s)", 4447c478bd9Sstevel@tonic-gate unsolicit_auth_proto, pn1); 4457c478bd9Sstevel@tonic-gate } 4467c478bd9Sstevel@tonic-gate if (peer_reject_auth) { 4477c478bd9Sstevel@tonic-gate if ((pn1 = protocol_name(reject_auth_proto)) == NULL) 4487c478bd9Sstevel@tonic-gate pn1 = "?"; 4497c478bd9Sstevel@tonic-gate warn("Peer rejected our demand for 0x%x (%s)", 4507c478bd9Sstevel@tonic-gate reject_auth_proto, pn1); 4517c478bd9Sstevel@tonic-gate } 4527c478bd9Sstevel@tonic-gate if (naked_peers_auth) { 4537c478bd9Sstevel@tonic-gate if ((pn1 = protocol_name(naked_auth_orig)) == NULL) 4547c478bd9Sstevel@tonic-gate pn1 = "?"; 4557c478bd9Sstevel@tonic-gate if ((pn2 = protocol_name(naked_auth_proto)) == NULL) 4567c478bd9Sstevel@tonic-gate pn2 = "?"; 4577c478bd9Sstevel@tonic-gate warn("We set Configure-Nak for 0x%x (%s) to suggest 0x%x (%s)", 4587c478bd9Sstevel@tonic-gate naked_auth_orig, pn1, naked_auth_proto, pn2); 4597c478bd9Sstevel@tonic-gate } 4607c478bd9Sstevel@tonic-gate if (rejected_peers_auth) { 4617c478bd9Sstevel@tonic-gate if ((pn1 = protocol_name(rejected_auth_proto)) == NULL) 4627c478bd9Sstevel@tonic-gate pn1 = "?"; 4637c478bd9Sstevel@tonic-gate warn("We rejected the peer's demand for 0x%x (%s)", 4647c478bd9Sstevel@tonic-gate rejected_auth_proto, pn1); 4657c478bd9Sstevel@tonic-gate } 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate peer_nak_auth = unsolicited_nak_auth = peer_reject_auth = 4687c478bd9Sstevel@tonic-gate rejected_peers_auth = naked_peers_auth = 0; 4697c478bd9Sstevel@tonic-gate nak_auth_proto = nak_auth_orig = unsolicit_auth_proto = reject_auth_proto = 4707c478bd9Sstevel@tonic-gate rejected_auth_proto = naked_auth_orig = naked_auth_proto = 0; 4717c478bd9Sstevel@tonic-gate notice("Connection terminated."); 4727c478bd9Sstevel@tonic-gate } 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate /* 4757c478bd9Sstevel@tonic-gate * LCP has gone down; it will either die or try to re-establish. 4767c478bd9Sstevel@tonic-gate */ 4777c478bd9Sstevel@tonic-gate void 4787c478bd9Sstevel@tonic-gate link_down(unit) 4797c478bd9Sstevel@tonic-gate int unit; 4807c478bd9Sstevel@tonic-gate { 4817c478bd9Sstevel@tonic-gate int i; 4827c478bd9Sstevel@tonic-gate struct protent *protp; 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate auth_state = s_down; 4857c478bd9Sstevel@tonic-gate if (auth_script_state == s_up && auth_script_pid == 0) { 4867c478bd9Sstevel@tonic-gate update_link_stats(unit); 4877c478bd9Sstevel@tonic-gate auth_script_state = s_down; 4887c478bd9Sstevel@tonic-gate auth_script(_PATH_AUTHDOWN); 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate for (i = 0; (protp = protocols[i]) != NULL; ++i) { 4917c478bd9Sstevel@tonic-gate if (!protp->enabled_flag) 4927c478bd9Sstevel@tonic-gate continue; 4937c478bd9Sstevel@tonic-gate if (protp->protocol != PPP_LCP && protp->lowerdown != NULL) 4947c478bd9Sstevel@tonic-gate (*protp->lowerdown)(unit); 4957c478bd9Sstevel@tonic-gate if (protp->protocol < 0xC000 && protp->close != NULL) 4967c478bd9Sstevel@tonic-gate (*protp->close)(unit, "LCP down"); 4977c478bd9Sstevel@tonic-gate } 4987c478bd9Sstevel@tonic-gate num_np_open = 0; 4997c478bd9Sstevel@tonic-gate num_np_up = 0; 5007c478bd9Sstevel@tonic-gate if (phase != PHASE_DEAD) 5017c478bd9Sstevel@tonic-gate new_phase(PHASE_TERMINATE); 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate /* 5057c478bd9Sstevel@tonic-gate * The link is established. 5067c478bd9Sstevel@tonic-gate * Proceed to the Dead, Authenticate or Network phase as appropriate. 5077c478bd9Sstevel@tonic-gate */ 5087c478bd9Sstevel@tonic-gate void 5097c478bd9Sstevel@tonic-gate link_established(unit) 5107c478bd9Sstevel@tonic-gate int unit; 5117c478bd9Sstevel@tonic-gate { 5127c478bd9Sstevel@tonic-gate int auth; 5137c478bd9Sstevel@tonic-gate lcp_options *wo = &lcp_wantoptions[unit]; 5147c478bd9Sstevel@tonic-gate lcp_options *go = &lcp_gotoptions[unit]; 5157c478bd9Sstevel@tonic-gate lcp_options *ho = &lcp_hisoptions[unit]; 5167c478bd9Sstevel@tonic-gate int i; 5177c478bd9Sstevel@tonic-gate struct protent *protp; 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate /* 5207c478bd9Sstevel@tonic-gate * Tell higher-level protocols that LCP is up. 5217c478bd9Sstevel@tonic-gate */ 5227c478bd9Sstevel@tonic-gate for (i = 0; (protp = protocols[i]) != NULL; ++i) 5237c478bd9Sstevel@tonic-gate if (protp->protocol != PPP_LCP && protp->enabled_flag 5247c478bd9Sstevel@tonic-gate && protp->lowerup != NULL) 5257c478bd9Sstevel@tonic-gate (*protp->lowerup)(unit); 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate if (auth_required && !(go->neg_chap || go->neg_mschap || 5287c478bd9Sstevel@tonic-gate go->neg_mschapv2 || go->neg_upap)) { 5297c478bd9Sstevel@tonic-gate /* 5307c478bd9Sstevel@tonic-gate * We wanted the peer to authenticate itself, and it refused: 5317c478bd9Sstevel@tonic-gate * if we have some address(es) it can use without auth, fine, 5327c478bd9Sstevel@tonic-gate * otherwise treat it as though it authenticated with PAP using 5337c478bd9Sstevel@tonic-gate * a username * of "" and a password of "". If that's not OK, 5347c478bd9Sstevel@tonic-gate * boot it out. 5357c478bd9Sstevel@tonic-gate */ 5367c478bd9Sstevel@tonic-gate if (noauth_addrs != NULL) { 5377c478bd9Sstevel@tonic-gate set_allowed_addrs(unit, noauth_addrs, NULL); 5387c478bd9Sstevel@tonic-gate } else if (!wo->neg_upap || !null_login(unit)) { 5397c478bd9Sstevel@tonic-gate warn("peer refused to authenticate: terminating link"); 5407c478bd9Sstevel@tonic-gate lcp_close(unit, "peer refused to authenticate"); 5417c478bd9Sstevel@tonic-gate status = EXIT_PEER_AUTH_FAILED; 5427c478bd9Sstevel@tonic-gate return; 5437c478bd9Sstevel@tonic-gate } 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate new_phase(PHASE_AUTHENTICATE); 5477c478bd9Sstevel@tonic-gate auth = 0; 5487c478bd9Sstevel@tonic-gate if (go->neg_chap || go->neg_mschap || go->neg_mschapv2) { 5497c478bd9Sstevel@tonic-gate if (go->neg_chap) { 5507c478bd9Sstevel@tonic-gate if (debug) 5517c478bd9Sstevel@tonic-gate dbglog("Authenticating peer with standard CHAP"); 5527c478bd9Sstevel@tonic-gate go->chap_mdtype = CHAP_DIGEST_MD5; 5537c478bd9Sstevel@tonic-gate } else if (go->neg_mschap) { 5547c478bd9Sstevel@tonic-gate if (debug) 5557c478bd9Sstevel@tonic-gate dbglog("Authenticating peer with MS-CHAPv1"); 5567c478bd9Sstevel@tonic-gate go->chap_mdtype = CHAP_MICROSOFT; 5577c478bd9Sstevel@tonic-gate } else { 5587c478bd9Sstevel@tonic-gate if (debug) 5597c478bd9Sstevel@tonic-gate dbglog("Authenticating peer with MS-CHAPv2"); 5607c478bd9Sstevel@tonic-gate go->chap_mdtype = CHAP_MICROSOFT_V2; 5617c478bd9Sstevel@tonic-gate } 5627c478bd9Sstevel@tonic-gate ChapAuthPeer(unit, our_name, go->chap_mdtype); 5637c478bd9Sstevel@tonic-gate auth |= CHAP_PEER; 5647c478bd9Sstevel@tonic-gate } else if (go->neg_upap) { 5657c478bd9Sstevel@tonic-gate if (debug) 5667c478bd9Sstevel@tonic-gate dbglog("Authenticating peer with PAP"); 5677c478bd9Sstevel@tonic-gate upap_authpeer(unit); 5687c478bd9Sstevel@tonic-gate auth |= PAP_PEER; 5697c478bd9Sstevel@tonic-gate } 5707c478bd9Sstevel@tonic-gate if (ho->neg_chap || ho->neg_mschap || ho->neg_mschapv2) { 5717c478bd9Sstevel@tonic-gate switch (ho->chap_mdtype) { 5727c478bd9Sstevel@tonic-gate case CHAP_DIGEST_MD5: 5737c478bd9Sstevel@tonic-gate if (debug) 5747c478bd9Sstevel@tonic-gate dbglog("Authenticating to peer with standard CHAP"); 5757c478bd9Sstevel@tonic-gate break; 5767c478bd9Sstevel@tonic-gate case CHAP_MICROSOFT: 5777c478bd9Sstevel@tonic-gate if (debug) 5787c478bd9Sstevel@tonic-gate dbglog("Authenticating to peer with MS-CHAPv1"); 5797c478bd9Sstevel@tonic-gate break; 5807c478bd9Sstevel@tonic-gate case CHAP_MICROSOFT_V2: 5817c478bd9Sstevel@tonic-gate if (debug) 5827c478bd9Sstevel@tonic-gate dbglog("Authenticating to peer with MS-CHAPv2"); 5837c478bd9Sstevel@tonic-gate break; 5847c478bd9Sstevel@tonic-gate default: 5857c478bd9Sstevel@tonic-gate if (debug) 5867c478bd9Sstevel@tonic-gate dbglog("Authenticating to peer with CHAP 0x%x", ho->chap_mdtype); 5877c478bd9Sstevel@tonic-gate break; 5887c478bd9Sstevel@tonic-gate } 5897c478bd9Sstevel@tonic-gate ChapAuthWithPeer(unit, user, ho->chap_mdtype); 5907c478bd9Sstevel@tonic-gate auth |= CHAP_WITHPEER; 5917c478bd9Sstevel@tonic-gate } else if (ho->neg_upap) { 5927c478bd9Sstevel@tonic-gate if (passwd[0] == '\0') { 5937c478bd9Sstevel@tonic-gate passwd_from_file = 1; 5947c478bd9Sstevel@tonic-gate if (!get_pap_passwd(passwd)) 5957c478bd9Sstevel@tonic-gate error("No secret found for PAP login"); 5967c478bd9Sstevel@tonic-gate } 5977c478bd9Sstevel@tonic-gate if (debug) 5987c478bd9Sstevel@tonic-gate dbglog("Authenticating to peer with PAP"); 5997c478bd9Sstevel@tonic-gate upap_authwithpeer(unit, user, passwd); 6007c478bd9Sstevel@tonic-gate auth |= PAP_WITHPEER; 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate auth_pending[unit] = auth; 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate if (!auth) 6057c478bd9Sstevel@tonic-gate network_phase(unit); 6067c478bd9Sstevel@tonic-gate } 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate /* 6097c478bd9Sstevel@tonic-gate * Proceed to the network phase. 6107c478bd9Sstevel@tonic-gate */ 6117c478bd9Sstevel@tonic-gate static void 6127c478bd9Sstevel@tonic-gate network_phase(unit) 6137c478bd9Sstevel@tonic-gate int unit; 6147c478bd9Sstevel@tonic-gate { 6157c478bd9Sstevel@tonic-gate lcp_options *go = &lcp_gotoptions[unit]; 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gate /* 6187c478bd9Sstevel@tonic-gate * If the peer had to authenticate, run the auth-up script now. 6197c478bd9Sstevel@tonic-gate */ 6207c478bd9Sstevel@tonic-gate if (go->neg_chap || go->neg_mschap || go->neg_mschapv2 || go->neg_upap) { 6217c478bd9Sstevel@tonic-gate auth_state = s_up; 6227c478bd9Sstevel@tonic-gate if (auth_script_state == s_down && auth_script_pid == 0) { 6237c478bd9Sstevel@tonic-gate auth_script_state = s_up; 6247c478bd9Sstevel@tonic-gate auth_script(_PATH_AUTHUP); 6257c478bd9Sstevel@tonic-gate } 6267c478bd9Sstevel@tonic-gate } 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate /* 6297c478bd9Sstevel@tonic-gate * Process extra options from the secrets file 6307c478bd9Sstevel@tonic-gate */ 6317c478bd9Sstevel@tonic-gate if (extra_options != NULL) { 6327c478bd9Sstevel@tonic-gate option_source = (char *)extra_opt_filename; 6337c478bd9Sstevel@tonic-gate option_line = extra_opt_line; 6347c478bd9Sstevel@tonic-gate (void) options_from_list(extra_options, 1); 6357c478bd9Sstevel@tonic-gate free_wordlist(extra_options); 6367c478bd9Sstevel@tonic-gate extra_options = NULL; 6377c478bd9Sstevel@tonic-gate } 6387c478bd9Sstevel@tonic-gate 6397c478bd9Sstevel@tonic-gate #ifdef CBCP_SUPPORT 6407c478bd9Sstevel@tonic-gate /* 6417c478bd9Sstevel@tonic-gate * If we negotiated callback, do it now. 6427c478bd9Sstevel@tonic-gate */ 6437c478bd9Sstevel@tonic-gate if (go->neg_cbcp) { 6447c478bd9Sstevel@tonic-gate new_phase(PHASE_CALLBACK); 6457c478bd9Sstevel@tonic-gate (*cbcp_protent.open)(unit); 6467c478bd9Sstevel@tonic-gate return; 6477c478bd9Sstevel@tonic-gate } 6487c478bd9Sstevel@tonic-gate #endif 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate start_networks(); 6517c478bd9Sstevel@tonic-gate } 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate void 6547c478bd9Sstevel@tonic-gate start_networks() 6557c478bd9Sstevel@tonic-gate { 6567c478bd9Sstevel@tonic-gate int i; 6577c478bd9Sstevel@tonic-gate struct protent *protp; 6587c478bd9Sstevel@tonic-gate 6597c478bd9Sstevel@tonic-gate new_phase(PHASE_NETWORK); 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate #ifdef HAVE_MULTILINK 6627c478bd9Sstevel@tonic-gate if (multilink) { 6637c478bd9Sstevel@tonic-gate if (mp_join_bundle()) { 6647c478bd9Sstevel@tonic-gate if (updetach && !nodetach) 6657c478bd9Sstevel@tonic-gate detach(); 6667c478bd9Sstevel@tonic-gate return; 6677c478bd9Sstevel@tonic-gate } 6687c478bd9Sstevel@tonic-gate } 6697c478bd9Sstevel@tonic-gate #endif /* HAVE_MULTILINK */ 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate #if 0 6727c478bd9Sstevel@tonic-gate if (!demand) 6737c478bd9Sstevel@tonic-gate set_filters(&pass_filter, &active_filter); 6747c478bd9Sstevel@tonic-gate #endif 6757c478bd9Sstevel@tonic-gate for (i = 0; (protp = protocols[i]) != NULL; ++i) 6767c478bd9Sstevel@tonic-gate if (protp->protocol < 0xC000 && protp->enabled_flag 6777c478bd9Sstevel@tonic-gate && protp->open != NULL) { 6787c478bd9Sstevel@tonic-gate (*protp->open)(0); 6797c478bd9Sstevel@tonic-gate if (protp->protocol != PPP_CCP) 6807c478bd9Sstevel@tonic-gate ++num_np_open; 6817c478bd9Sstevel@tonic-gate } 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate if (num_np_open == 0) 6847c478bd9Sstevel@tonic-gate /* nothing to do */ 6857c478bd9Sstevel@tonic-gate lcp_close(0, "No network protocols running"); 6867c478bd9Sstevel@tonic-gate } 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate /* 6897c478bd9Sstevel@tonic-gate * The peer has failed to authenticate himself using `protocol'. 6907c478bd9Sstevel@tonic-gate */ 6917c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 6927c478bd9Sstevel@tonic-gate void 6937c478bd9Sstevel@tonic-gate auth_peer_fail(unit, protocol) 6947c478bd9Sstevel@tonic-gate int unit, protocol; 6957c478bd9Sstevel@tonic-gate { 6967c478bd9Sstevel@tonic-gate /* 6977c478bd9Sstevel@tonic-gate * Authentication failure: take the link down 6987c478bd9Sstevel@tonic-gate */ 6997c478bd9Sstevel@tonic-gate lcp_close(unit, "Authentication failed"); 7007c478bd9Sstevel@tonic-gate status = EXIT_PEER_AUTH_FAILED; 7017c478bd9Sstevel@tonic-gate } 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate /* 7047c478bd9Sstevel@tonic-gate * The peer has been successfully authenticated using `protocol'. 7057c478bd9Sstevel@tonic-gate */ 7067c478bd9Sstevel@tonic-gate void 7077c478bd9Sstevel@tonic-gate auth_peer_success(unit, protocol, name, namelen) 7087c478bd9Sstevel@tonic-gate int unit, protocol; 7097c478bd9Sstevel@tonic-gate char *name; 7107c478bd9Sstevel@tonic-gate int namelen; 7117c478bd9Sstevel@tonic-gate { 7127c478bd9Sstevel@tonic-gate int bit; 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate switch (protocol) { 7157c478bd9Sstevel@tonic-gate case PPP_CHAP: 7167c478bd9Sstevel@tonic-gate bit = CHAP_PEER; 7177c478bd9Sstevel@tonic-gate break; 7187c478bd9Sstevel@tonic-gate case PPP_PAP: 7197c478bd9Sstevel@tonic-gate bit = PAP_PEER; 7207c478bd9Sstevel@tonic-gate break; 7217c478bd9Sstevel@tonic-gate default: 7227c478bd9Sstevel@tonic-gate warn("auth_peer_success: unknown protocol %x", protocol); 7237c478bd9Sstevel@tonic-gate return; 7247c478bd9Sstevel@tonic-gate } 7257c478bd9Sstevel@tonic-gate 7267c478bd9Sstevel@tonic-gate /* 7277c478bd9Sstevel@tonic-gate * Save the authenticated name of the peer for later. 7287c478bd9Sstevel@tonic-gate */ 7297c478bd9Sstevel@tonic-gate if (namelen > sizeof(peer_authname) - 1) 7307c478bd9Sstevel@tonic-gate namelen = sizeof(peer_authname) - 1; 7317c478bd9Sstevel@tonic-gate BCOPY(name, peer_authname, namelen); 7327c478bd9Sstevel@tonic-gate peer_authname[namelen] = '\0'; 7337c478bd9Sstevel@tonic-gate script_setenv("PEERNAME", peer_authname, 0); 7347c478bd9Sstevel@tonic-gate 7357c478bd9Sstevel@tonic-gate /* 7367c478bd9Sstevel@tonic-gate * If there is no more authentication still to be done, 7377c478bd9Sstevel@tonic-gate * proceed to the network (or callback) phase. 7387c478bd9Sstevel@tonic-gate */ 7397c478bd9Sstevel@tonic-gate if ((auth_pending[unit] &= ~bit) == 0) 7407c478bd9Sstevel@tonic-gate network_phase(unit); 7417c478bd9Sstevel@tonic-gate } 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate /* 7447c478bd9Sstevel@tonic-gate * We have failed to authenticate ourselves to the peer using `protocol'. 7457c478bd9Sstevel@tonic-gate */ 7467c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 7477c478bd9Sstevel@tonic-gate void 7487c478bd9Sstevel@tonic-gate auth_withpeer_fail(unit, protocol) 7497c478bd9Sstevel@tonic-gate int unit, protocol; 7507c478bd9Sstevel@tonic-gate { 7517c478bd9Sstevel@tonic-gate if (passwd_from_file) 7527c478bd9Sstevel@tonic-gate BZERO(passwd, MAXSECRETLEN); 7537c478bd9Sstevel@tonic-gate /* 7547c478bd9Sstevel@tonic-gate * We've failed to authenticate ourselves to our peer. 7557c478bd9Sstevel@tonic-gate * Some servers keep sending CHAP challenges, but there 7567c478bd9Sstevel@tonic-gate * is no point in persisting without any way to get updated 7577c478bd9Sstevel@tonic-gate * authentication secrets. 7587c478bd9Sstevel@tonic-gate */ 7597c478bd9Sstevel@tonic-gate lcp_close(unit, "Failed to authenticate ourselves to peer"); 7607c478bd9Sstevel@tonic-gate status = EXIT_AUTH_TOPEER_FAILED; 7617c478bd9Sstevel@tonic-gate } 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate /* 7647c478bd9Sstevel@tonic-gate * We have successfully authenticated ourselves with the peer using `protocol'. 7657c478bd9Sstevel@tonic-gate */ 7667c478bd9Sstevel@tonic-gate void 7677c478bd9Sstevel@tonic-gate auth_withpeer_success(unit, protocol) 7687c478bd9Sstevel@tonic-gate int unit, protocol; 7697c478bd9Sstevel@tonic-gate { 7707c478bd9Sstevel@tonic-gate int bit; 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate switch (protocol) { 7737c478bd9Sstevel@tonic-gate case PPP_CHAP: 7747c478bd9Sstevel@tonic-gate bit = CHAP_WITHPEER; 7757c478bd9Sstevel@tonic-gate break; 7767c478bd9Sstevel@tonic-gate case PPP_PAP: 7777c478bd9Sstevel@tonic-gate if (passwd_from_file) 7787c478bd9Sstevel@tonic-gate BZERO(passwd, MAXSECRETLEN); 7797c478bd9Sstevel@tonic-gate bit = PAP_WITHPEER; 7807c478bd9Sstevel@tonic-gate break; 7817c478bd9Sstevel@tonic-gate default: 7827c478bd9Sstevel@tonic-gate warn("auth_withpeer_success: unknown protocol %x", protocol); 7837c478bd9Sstevel@tonic-gate bit = 0; 7847c478bd9Sstevel@tonic-gate } 7857c478bd9Sstevel@tonic-gate 7867c478bd9Sstevel@tonic-gate /* 7877c478bd9Sstevel@tonic-gate * If there is no more authentication still being done, 7887c478bd9Sstevel@tonic-gate * proceed to the network (or callback) phase. 7897c478bd9Sstevel@tonic-gate */ 7907c478bd9Sstevel@tonic-gate if ((auth_pending[unit] &= ~bit) == 0) 7917c478bd9Sstevel@tonic-gate network_phase(unit); 7927c478bd9Sstevel@tonic-gate } 7937c478bd9Sstevel@tonic-gate 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate /* 7967c478bd9Sstevel@tonic-gate * np_up - a network protocol has come up. 7977c478bd9Sstevel@tonic-gate */ 7987c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 7997c478bd9Sstevel@tonic-gate void 8007c478bd9Sstevel@tonic-gate np_up(unit, proto) 8017c478bd9Sstevel@tonic-gate int unit, proto; 8027c478bd9Sstevel@tonic-gate { 8037c478bd9Sstevel@tonic-gate int tlim; 8047c478bd9Sstevel@tonic-gate 8057c478bd9Sstevel@tonic-gate if (num_np_up == 0) { 8067c478bd9Sstevel@tonic-gate /* 8077c478bd9Sstevel@tonic-gate * At this point we consider that the link has come up successfully. 8087c478bd9Sstevel@tonic-gate */ 8097c478bd9Sstevel@tonic-gate status = EXIT_OK; 8107c478bd9Sstevel@tonic-gate unsuccess = 0; 8117c478bd9Sstevel@tonic-gate 8127c478bd9Sstevel@tonic-gate peer_nak_auth = unsolicited_nak_auth = peer_reject_auth = 8137c478bd9Sstevel@tonic-gate rejected_peers_auth = naked_peers_auth = 0; 8147c478bd9Sstevel@tonic-gate nak_auth_proto = nak_auth_orig = unsolicit_auth_proto = 8157c478bd9Sstevel@tonic-gate reject_auth_proto = rejected_auth_proto = naked_auth_orig = 8167c478bd9Sstevel@tonic-gate naked_auth_proto = 0; 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate new_phase(PHASE_RUNNING); 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate if (idle_time_hook != NULL) 8217c478bd9Sstevel@tonic-gate tlim = (*idle_time_hook)(NULL); 8227c478bd9Sstevel@tonic-gate else 8237c478bd9Sstevel@tonic-gate tlim = idle_time_limit; 8247c478bd9Sstevel@tonic-gate if (tlim > 0) 8257c478bd9Sstevel@tonic-gate TIMEOUT(check_idle, NULL, tlim); 8267c478bd9Sstevel@tonic-gate 8277c478bd9Sstevel@tonic-gate /* 8287c478bd9Sstevel@tonic-gate * Set a timeout to close the connection once the maximum 8297c478bd9Sstevel@tonic-gate * connect time has expired. 8307c478bd9Sstevel@tonic-gate */ 8317c478bd9Sstevel@tonic-gate if (maxconnect > 0) { 8327c478bd9Sstevel@tonic-gate TIMEOUT(connect_time_expired, &lcp_fsm[unit], maxconnect); 8337c478bd9Sstevel@tonic-gate 8347c478bd9Sstevel@tonic-gate /* 8357c478bd9Sstevel@tonic-gate * Tell LCP to send Time-Remaining packets. One should be 8367c478bd9Sstevel@tonic-gate * sent out now, at maxconnect-300, at maxconnect-120, and 8377c478bd9Sstevel@tonic-gate * again at maxconnect-30. 8387c478bd9Sstevel@tonic-gate */ 8397c478bd9Sstevel@tonic-gate lcp_settimeremaining(unit, maxconnect, maxconnect); 8407c478bd9Sstevel@tonic-gate if (maxconnect > 300) 8417c478bd9Sstevel@tonic-gate lcp_settimeremaining(unit, maxconnect, 300); 8427c478bd9Sstevel@tonic-gate if (maxconnect > 120) 8437c478bd9Sstevel@tonic-gate lcp_settimeremaining(unit, maxconnect, 120); 8447c478bd9Sstevel@tonic-gate if (maxconnect > 30) 8457c478bd9Sstevel@tonic-gate lcp_settimeremaining(unit, maxconnect, 30); 8467c478bd9Sstevel@tonic-gate } 8477c478bd9Sstevel@tonic-gate 8487c478bd9Sstevel@tonic-gate /* 8497c478bd9Sstevel@tonic-gate * Detach now, if the updetach option was given. 8507c478bd9Sstevel@tonic-gate */ 8517c478bd9Sstevel@tonic-gate if (updetach && !nodetach) 8527c478bd9Sstevel@tonic-gate detach(); 8537c478bd9Sstevel@tonic-gate } 8547c478bd9Sstevel@tonic-gate ++num_np_up; 8557c478bd9Sstevel@tonic-gate } 8567c478bd9Sstevel@tonic-gate 8577c478bd9Sstevel@tonic-gate /* 8587c478bd9Sstevel@tonic-gate * np_down - a network protocol has gone down. 8597c478bd9Sstevel@tonic-gate */ 8607c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 8617c478bd9Sstevel@tonic-gate void 8627c478bd9Sstevel@tonic-gate np_down(unit, proto) 8637c478bd9Sstevel@tonic-gate int unit, proto; 8647c478bd9Sstevel@tonic-gate { 8657c478bd9Sstevel@tonic-gate if (--num_np_up == 0) { 8667c478bd9Sstevel@tonic-gate UNTIMEOUT(check_idle, NULL); 8677c478bd9Sstevel@tonic-gate new_phase(PHASE_NETWORK); 8687c478bd9Sstevel@tonic-gate } 8697c478bd9Sstevel@tonic-gate } 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate /* 8727c478bd9Sstevel@tonic-gate * np_finished - a network protocol has finished using the link. 8737c478bd9Sstevel@tonic-gate */ 8747c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 8757c478bd9Sstevel@tonic-gate void 8767c478bd9Sstevel@tonic-gate np_finished(unit, proto) 8777c478bd9Sstevel@tonic-gate int unit, proto; 8787c478bd9Sstevel@tonic-gate { 8797c478bd9Sstevel@tonic-gate if (--num_np_open <= 0) { 8807c478bd9Sstevel@tonic-gate /* no further use for the link: shut up shop. */ 8817c478bd9Sstevel@tonic-gate lcp_close(0, "No network protocols running"); 8827c478bd9Sstevel@tonic-gate } 8837c478bd9Sstevel@tonic-gate } 8847c478bd9Sstevel@tonic-gate 8857c478bd9Sstevel@tonic-gate /* 8867c478bd9Sstevel@tonic-gate * check_idle - check whether the link has been idle for long 8877c478bd9Sstevel@tonic-gate * enough that we can shut it down. 8887c478bd9Sstevel@tonic-gate */ 8897c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 8907c478bd9Sstevel@tonic-gate static void 8917c478bd9Sstevel@tonic-gate check_idle(arg) 8927c478bd9Sstevel@tonic-gate void *arg; 8937c478bd9Sstevel@tonic-gate { 8947c478bd9Sstevel@tonic-gate struct ppp_idle idle; 8957c478bd9Sstevel@tonic-gate time_t itime; 8967c478bd9Sstevel@tonic-gate int tlim; 8977c478bd9Sstevel@tonic-gate 8987c478bd9Sstevel@tonic-gate if (!get_idle_time(0, &idle)) 8997c478bd9Sstevel@tonic-gate return; 9007c478bd9Sstevel@tonic-gate if (idle_time_hook != NULL) { 9017c478bd9Sstevel@tonic-gate tlim = (*idle_time_hook)(&idle); 9027c478bd9Sstevel@tonic-gate } else { 9037c478bd9Sstevel@tonic-gate itime = MIN(idle.xmit_idle, idle.recv_idle); 9047c478bd9Sstevel@tonic-gate tlim = idle_time_limit - itime; 9057c478bd9Sstevel@tonic-gate } 9067c478bd9Sstevel@tonic-gate if (tlim <= 0) { 9077c478bd9Sstevel@tonic-gate /* link is idle: shut it down. */ 9087c478bd9Sstevel@tonic-gate notice("Terminating connection due to lack of activity."); 9097c478bd9Sstevel@tonic-gate lcp_close(0, "Link inactive"); 9107c478bd9Sstevel@tonic-gate need_holdoff = 0; 9117c478bd9Sstevel@tonic-gate status = EXIT_IDLE_TIMEOUT; 9127c478bd9Sstevel@tonic-gate } else { 9137c478bd9Sstevel@tonic-gate TIMEOUT(check_idle, NULL, tlim); 9147c478bd9Sstevel@tonic-gate } 9157c478bd9Sstevel@tonic-gate } 9167c478bd9Sstevel@tonic-gate 9177c478bd9Sstevel@tonic-gate /* 9187c478bd9Sstevel@tonic-gate * connect_time_expired - log a message and close the connection. 9197c478bd9Sstevel@tonic-gate */ 9207c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 9217c478bd9Sstevel@tonic-gate static void 9227c478bd9Sstevel@tonic-gate connect_time_expired(arg) 9237c478bd9Sstevel@tonic-gate void *arg; 9247c478bd9Sstevel@tonic-gate { 9257c478bd9Sstevel@tonic-gate fsm *f = (fsm *)arg; 9267c478bd9Sstevel@tonic-gate 9277c478bd9Sstevel@tonic-gate info("Connect time expired"); 9287c478bd9Sstevel@tonic-gate lcp_close(f->unit, "Connect time expired"); /* Close connection */ 9297c478bd9Sstevel@tonic-gate status = EXIT_CONNECT_TIME; 9307c478bd9Sstevel@tonic-gate } 9317c478bd9Sstevel@tonic-gate 9327c478bd9Sstevel@tonic-gate /* 9337c478bd9Sstevel@tonic-gate * auth_check_options - called to check authentication options. 9347c478bd9Sstevel@tonic-gate */ 9357c478bd9Sstevel@tonic-gate void 9367c478bd9Sstevel@tonic-gate auth_check_options() 9377c478bd9Sstevel@tonic-gate { 9387c478bd9Sstevel@tonic-gate lcp_options *wo = &lcp_wantoptions[0]; 9397c478bd9Sstevel@tonic-gate int can_auth; 9407c478bd9Sstevel@tonic-gate int lacks_ip; 9417c478bd9Sstevel@tonic-gate 9427c478bd9Sstevel@tonic-gate /* Default our_name to hostname, and user to our_name */ 9437c478bd9Sstevel@tonic-gate if (our_name[0] == '\0' || usehostname) 9447c478bd9Sstevel@tonic-gate (void) strlcpy(our_name, hostname, sizeof(our_name)); 9457c478bd9Sstevel@tonic-gate if (user[0] == '\0') 9467c478bd9Sstevel@tonic-gate (void) strlcpy(user, our_name, sizeof(user)); 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate /* 9497c478bd9Sstevel@tonic-gate * If we have a default route, require the peer to authenticate 9507c478bd9Sstevel@tonic-gate * unless the noauth option was given or the real user is root. 9517c478bd9Sstevel@tonic-gate */ 9527c478bd9Sstevel@tonic-gate if (!auth_required && !allow_any_ip && have_route_to(0) && !privileged) { 9537c478bd9Sstevel@tonic-gate auth_required = 1; 9547c478bd9Sstevel@tonic-gate default_auth = 1; 9557c478bd9Sstevel@tonic-gate } 9567c478bd9Sstevel@tonic-gate 9577c478bd9Sstevel@tonic-gate /* If authentication is required, ask peer for CHAP or PAP. */ 9587c478bd9Sstevel@tonic-gate if (auth_required) { 9597c478bd9Sstevel@tonic-gate if (!wo->neg_chap && !wo->neg_mschap && !wo->neg_mschapv2 && 9607c478bd9Sstevel@tonic-gate !wo->neg_upap) { 9617c478bd9Sstevel@tonic-gate wo->neg_chap = 1; 9627c478bd9Sstevel@tonic-gate #ifdef CHAPMS 9637c478bd9Sstevel@tonic-gate wo->neg_mschap = 1; 9647c478bd9Sstevel@tonic-gate #endif 9657c478bd9Sstevel@tonic-gate #ifdef CHAPMSV2 9667c478bd9Sstevel@tonic-gate wo->neg_mschapv2 = 1; 9677c478bd9Sstevel@tonic-gate #endif 9687c478bd9Sstevel@tonic-gate wo->chap_mdtype = CHAP_DIGEST_MD5; 9697c478bd9Sstevel@tonic-gate wo->neg_upap = 1; 9707c478bd9Sstevel@tonic-gate } 9717c478bd9Sstevel@tonic-gate } else { 9727c478bd9Sstevel@tonic-gate wo->neg_chap = 0; 9737c478bd9Sstevel@tonic-gate wo->neg_mschap = 0; 9747c478bd9Sstevel@tonic-gate wo->neg_mschapv2 = 0; 9757c478bd9Sstevel@tonic-gate wo->neg_upap = 0; 9767c478bd9Sstevel@tonic-gate } 9777c478bd9Sstevel@tonic-gate 9787c478bd9Sstevel@tonic-gate /* 9797c478bd9Sstevel@tonic-gate * Check whether we have appropriate secrets to use 9807c478bd9Sstevel@tonic-gate * to authenticate the peer. 9817c478bd9Sstevel@tonic-gate */ 9827c478bd9Sstevel@tonic-gate lacks_ip = 0; 9837c478bd9Sstevel@tonic-gate can_auth = wo->neg_upap && (uselogin || have_pap_secret(&lacks_ip)); 9847c478bd9Sstevel@tonic-gate if (!can_auth && (wo->neg_chap || wo->neg_mschap || wo->neg_mschapv2)) { 9857c478bd9Sstevel@tonic-gate can_auth = have_chap_secret((explicit_remote? remote_name: NULL), 9867c478bd9Sstevel@tonic-gate our_name, 1, &lacks_ip); 9877c478bd9Sstevel@tonic-gate } 9887c478bd9Sstevel@tonic-gate 9897c478bd9Sstevel@tonic-gate if (auth_required && !can_auth && noauth_addrs == NULL) { 9907c478bd9Sstevel@tonic-gate if (default_auth) { 9917c478bd9Sstevel@tonic-gate option_error( 9927c478bd9Sstevel@tonic-gate "By default the remote system is required to authenticate itself"); 9937c478bd9Sstevel@tonic-gate option_error( 9947c478bd9Sstevel@tonic-gate "(because this system has a default route to the Internet)"); 9957c478bd9Sstevel@tonic-gate } else if (explicit_remote) 9967c478bd9Sstevel@tonic-gate option_error( 9977c478bd9Sstevel@tonic-gate "The remote system (%s) is required to authenticate itself", 9987c478bd9Sstevel@tonic-gate remote_name); 9997c478bd9Sstevel@tonic-gate else 10007c478bd9Sstevel@tonic-gate option_error( 10017c478bd9Sstevel@tonic-gate "The remote system is required to authenticate itself"); 10027c478bd9Sstevel@tonic-gate option_error( 10037c478bd9Sstevel@tonic-gate "but I couldn't find any suitable secret (password) for it to use to do so."); 10047c478bd9Sstevel@tonic-gate if (lacks_ip) 10057c478bd9Sstevel@tonic-gate option_error( 10067c478bd9Sstevel@tonic-gate "(None of the available passwords would let it use an IP address.)"); 10077c478bd9Sstevel@tonic-gate 10087c478bd9Sstevel@tonic-gate exit(1); 10097c478bd9Sstevel@tonic-gate } 10107c478bd9Sstevel@tonic-gate } 10117c478bd9Sstevel@tonic-gate 10127c478bd9Sstevel@tonic-gate /* 10137c478bd9Sstevel@tonic-gate * auth_reset - called when LCP is starting negotiations to recheck 10147c478bd9Sstevel@tonic-gate * authentication options, i.e. whether we have appropriate secrets 10157c478bd9Sstevel@tonic-gate * to use for authenticating ourselves and/or the peer. 10167c478bd9Sstevel@tonic-gate */ 10177c478bd9Sstevel@tonic-gate void 10187c478bd9Sstevel@tonic-gate auth_reset(unit) 10197c478bd9Sstevel@tonic-gate int unit; 10207c478bd9Sstevel@tonic-gate { 10217c478bd9Sstevel@tonic-gate lcp_options *go = &lcp_gotoptions[unit]; 10227c478bd9Sstevel@tonic-gate lcp_options *ao = &lcp_allowoptions[unit]; 10237c478bd9Sstevel@tonic-gate int havesecret; 10247c478bd9Sstevel@tonic-gate 10257c478bd9Sstevel@tonic-gate ao->neg_upap = !refuse_pap && (passwd[0] != '\0' || get_pap_passwd(NULL)); 10267c478bd9Sstevel@tonic-gate 10277c478bd9Sstevel@tonic-gate havesecret = passwd[0] != '\0' || 10287c478bd9Sstevel@tonic-gate have_chap_secret(user, (explicit_remote? remote_name: NULL), 0, NULL); 10297c478bd9Sstevel@tonic-gate ao->neg_chap = !refuse_chap && havesecret; 10307c478bd9Sstevel@tonic-gate ao->neg_mschap = !refuse_mschap && havesecret; 10317c478bd9Sstevel@tonic-gate ao->neg_mschapv2 = !refuse_mschapv2 && havesecret; 10327c478bd9Sstevel@tonic-gate if (ao->neg_chap) 10337c478bd9Sstevel@tonic-gate ao->chap_mdtype = CHAP_DIGEST_MD5; 10347c478bd9Sstevel@tonic-gate else if (ao->neg_mschap) 10357c478bd9Sstevel@tonic-gate ao->chap_mdtype = CHAP_MICROSOFT; 10367c478bd9Sstevel@tonic-gate else 10377c478bd9Sstevel@tonic-gate ao->chap_mdtype = CHAP_MICROSOFT_V2; 10387c478bd9Sstevel@tonic-gate 10397c478bd9Sstevel@tonic-gate if (go->neg_upap && !uselogin && !have_pap_secret(NULL)) 10407c478bd9Sstevel@tonic-gate go->neg_upap = 0; 10417c478bd9Sstevel@tonic-gate if (go->neg_chap || go->neg_mschap || go->neg_mschapv2) { 10427c478bd9Sstevel@tonic-gate havesecret = have_chap_secret((explicit_remote? remote_name: NULL), 10437c478bd9Sstevel@tonic-gate our_name, 1, NULL); 10447c478bd9Sstevel@tonic-gate if (!havesecret) 10457c478bd9Sstevel@tonic-gate go->neg_chap = go->neg_mschap = go->neg_mschapv2 = 0; 10467c478bd9Sstevel@tonic-gate else if (go->neg_chap) 10477c478bd9Sstevel@tonic-gate go->chap_mdtype = CHAP_DIGEST_MD5; 10487c478bd9Sstevel@tonic-gate else if (go->neg_mschap) 10497c478bd9Sstevel@tonic-gate go->chap_mdtype = CHAP_MICROSOFT; 10507c478bd9Sstevel@tonic-gate else 10517c478bd9Sstevel@tonic-gate go->chap_mdtype = CHAP_MICROSOFT_V2; 10527c478bd9Sstevel@tonic-gate } 10537c478bd9Sstevel@tonic-gate } 10547c478bd9Sstevel@tonic-gate 10557c478bd9Sstevel@tonic-gate 10567c478bd9Sstevel@tonic-gate /* 10577c478bd9Sstevel@tonic-gate * check_passwd - Check the user name and passwd against the PAP secrets 10587c478bd9Sstevel@tonic-gate * file. If requested, also check against the system password database, 10597c478bd9Sstevel@tonic-gate * and login the user if OK. 10607c478bd9Sstevel@tonic-gate * 10617c478bd9Sstevel@tonic-gate * returns: 10627c478bd9Sstevel@tonic-gate * UPAP_AUTHNAK: Authentication failed. 10637c478bd9Sstevel@tonic-gate * UPAP_AUTHACK: Authentication succeeded. 10647c478bd9Sstevel@tonic-gate * In either case, msg points to an appropriate message. 10657c478bd9Sstevel@tonic-gate */ 10667c478bd9Sstevel@tonic-gate int 10677c478bd9Sstevel@tonic-gate check_passwd(unit, auser, userlen, apasswd, passwdlen, msg) 10687c478bd9Sstevel@tonic-gate int unit; 10697c478bd9Sstevel@tonic-gate char *auser; 10707c478bd9Sstevel@tonic-gate int userlen; 10717c478bd9Sstevel@tonic-gate char *apasswd; 10727c478bd9Sstevel@tonic-gate int passwdlen; 10737c478bd9Sstevel@tonic-gate char **msg; 10747c478bd9Sstevel@tonic-gate { 10757c478bd9Sstevel@tonic-gate int ret; 10767c478bd9Sstevel@tonic-gate char *filename; 10777c478bd9Sstevel@tonic-gate FILE *f; 10787c478bd9Sstevel@tonic-gate struct wordlist *addrs = NULL, *opts = NULL; 10797c478bd9Sstevel@tonic-gate char passwd[256], user[256]; 10807c478bd9Sstevel@tonic-gate char secret[MAXWORDLEN]; 10817c478bd9Sstevel@tonic-gate static int attempts = 0; 10827c478bd9Sstevel@tonic-gate 10837c478bd9Sstevel@tonic-gate /* 10847c478bd9Sstevel@tonic-gate * Make copies of apasswd and auser, then null-terminate them. 10857c478bd9Sstevel@tonic-gate * If there are unprintable characters in the password, make 10867c478bd9Sstevel@tonic-gate * them visible. 10877c478bd9Sstevel@tonic-gate */ 10887c478bd9Sstevel@tonic-gate (void) slprintf(passwd, sizeof(passwd), "%.*v", passwdlen, apasswd); 10897c478bd9Sstevel@tonic-gate (void) slprintf(user, sizeof(user), "%.*v", userlen, auser); 10907c478bd9Sstevel@tonic-gate *msg = ""; 10917c478bd9Sstevel@tonic-gate 10927c478bd9Sstevel@tonic-gate /* 10937c478bd9Sstevel@tonic-gate * Check if a plugin wants to handle this. 10947c478bd9Sstevel@tonic-gate */ 10957c478bd9Sstevel@tonic-gate if (pap_auth_hook != NULL) { 10967c478bd9Sstevel@tonic-gate /* Set a default and allow the plug-in to change it. */ 10977c478bd9Sstevel@tonic-gate extra_opt_filename = "plugin"; 10987c478bd9Sstevel@tonic-gate extra_opt_line = 0; 10997c478bd9Sstevel@tonic-gate ret = (*pap_auth_hook)(user, passwd, msg, &addrs, &opts); 11007c478bd9Sstevel@tonic-gate if (ret >= 0) { 11017c478bd9Sstevel@tonic-gate if (ret > 0) 11027c478bd9Sstevel@tonic-gate set_allowed_addrs(unit, addrs, opts); 11037c478bd9Sstevel@tonic-gate BZERO(passwd, sizeof(passwd)); 11047c478bd9Sstevel@tonic-gate if (addrs != NULL) 11057c478bd9Sstevel@tonic-gate free_wordlist(addrs); 11067c478bd9Sstevel@tonic-gate return ret? UPAP_AUTHACK: UPAP_AUTHNAK; 11077c478bd9Sstevel@tonic-gate } 11087c478bd9Sstevel@tonic-gate } 11097c478bd9Sstevel@tonic-gate 11107c478bd9Sstevel@tonic-gate /* 11117c478bd9Sstevel@tonic-gate * Open the file of pap secrets and scan for a suitable secret 11127c478bd9Sstevel@tonic-gate * for authenticating this user. 11137c478bd9Sstevel@tonic-gate */ 11147c478bd9Sstevel@tonic-gate filename = _PATH_UPAPFILE; 11157c478bd9Sstevel@tonic-gate addrs = opts = NULL; 11167c478bd9Sstevel@tonic-gate ret = UPAP_AUTHNAK; 11177c478bd9Sstevel@tonic-gate f = fopen(filename, "r"); 11187c478bd9Sstevel@tonic-gate if (f == NULL) { 11197c478bd9Sstevel@tonic-gate error("Can't open PAP password file %s: %m", filename); 11207c478bd9Sstevel@tonic-gate 11217c478bd9Sstevel@tonic-gate } else { 11227c478bd9Sstevel@tonic-gate check_access(f, filename); 11237c478bd9Sstevel@tonic-gate if (scan_authfile(f, user, our_name, secret, &addrs, &opts, filename) < 0) { 11247c478bd9Sstevel@tonic-gate warn("no PAP secret found for %s", user); 11257c478bd9Sstevel@tonic-gate if (scan_server_match_failed[0] != '\0') 11267c478bd9Sstevel@tonic-gate warn("possible configuration error: local name is %q, but " 11277c478bd9Sstevel@tonic-gate "found %q instead", our_name, scan_server_match_failed); 11287c478bd9Sstevel@tonic-gate } else if (secret[0] != '\0') { 11297c478bd9Sstevel@tonic-gate /* password given in pap-secrets - must match */ 11307c478bd9Sstevel@tonic-gate if ((!cryptpap && strcmp(passwd, secret) == 0) 11317c478bd9Sstevel@tonic-gate || strcmp(crypt(passwd, secret), secret) == 0) 11327c478bd9Sstevel@tonic-gate ret = UPAP_AUTHACK; 11337c478bd9Sstevel@tonic-gate else 11347c478bd9Sstevel@tonic-gate warn("PAP authentication failure for %s", user); 11357c478bd9Sstevel@tonic-gate } else if (uselogin) { 11367c478bd9Sstevel@tonic-gate /* empty password in pap-secrets and login option */ 11377c478bd9Sstevel@tonic-gate ret = plogin(user, passwd, msg); 11387c478bd9Sstevel@tonic-gate if (ret == UPAP_AUTHNAK) 11397c478bd9Sstevel@tonic-gate warn("PAP login failure for %s", user); 11407c478bd9Sstevel@tonic-gate } else { 11417c478bd9Sstevel@tonic-gate /* empty password in pap-secrets and login option not used */ 11427c478bd9Sstevel@tonic-gate ret = UPAP_AUTHACK; 11437c478bd9Sstevel@tonic-gate } 11447c478bd9Sstevel@tonic-gate (void) fclose(f); 11457c478bd9Sstevel@tonic-gate } 11467c478bd9Sstevel@tonic-gate 11477c478bd9Sstevel@tonic-gate if (ret == UPAP_AUTHNAK) { 11487c478bd9Sstevel@tonic-gate if (**msg == '\0') 11497c478bd9Sstevel@tonic-gate *msg = "Login incorrect"; 11507c478bd9Sstevel@tonic-gate /* 11517c478bd9Sstevel@tonic-gate * Frustrate passwd stealer programs. 11527c478bd9Sstevel@tonic-gate * Allow 10 tries, but start backing off after 3 (stolen from login). 11537c478bd9Sstevel@tonic-gate * On 10'th, drop the connection. 11547c478bd9Sstevel@tonic-gate */ 11557c478bd9Sstevel@tonic-gate if (attempts++ >= 10) { 11567c478bd9Sstevel@tonic-gate warn("%d LOGIN FAILURES ON %s, %s", attempts, devnam, user); 11577c478bd9Sstevel@tonic-gate lcp_close(unit, "login failed"); 11587c478bd9Sstevel@tonic-gate } 11597c478bd9Sstevel@tonic-gate if (attempts > 3) 11607c478bd9Sstevel@tonic-gate (void) sleep((u_int) (attempts - 3) * 5); 11617c478bd9Sstevel@tonic-gate if (opts != NULL) 11627c478bd9Sstevel@tonic-gate free_wordlist(opts); 11637c478bd9Sstevel@tonic-gate 11647c478bd9Sstevel@tonic-gate } else { 11657c478bd9Sstevel@tonic-gate attempts = 0; /* Reset count */ 11667c478bd9Sstevel@tonic-gate if (**msg == '\0') 11677c478bd9Sstevel@tonic-gate *msg = "Login ok"; 11687c478bd9Sstevel@tonic-gate set_allowed_addrs(unit, addrs, opts); 11697c478bd9Sstevel@tonic-gate } 11707c478bd9Sstevel@tonic-gate 11717c478bd9Sstevel@tonic-gate if (addrs != NULL) 11727c478bd9Sstevel@tonic-gate free_wordlist(addrs); 11737c478bd9Sstevel@tonic-gate BZERO(passwd, sizeof(passwd)); 11747c478bd9Sstevel@tonic-gate BZERO(secret, sizeof(secret)); 11757c478bd9Sstevel@tonic-gate 11767c478bd9Sstevel@tonic-gate return ret; 11777c478bd9Sstevel@tonic-gate } 11787c478bd9Sstevel@tonic-gate 11797c478bd9Sstevel@tonic-gate /* 11807c478bd9Sstevel@tonic-gate * This function is needed for PAM. 11817c478bd9Sstevel@tonic-gate */ 11827c478bd9Sstevel@tonic-gate 11837c478bd9Sstevel@tonic-gate #ifdef ALLOW_PAM 11847c478bd9Sstevel@tonic-gate /* Static variables used to communicate between the conversation function 11857c478bd9Sstevel@tonic-gate * and the server_login function 11867c478bd9Sstevel@tonic-gate */ 11877c478bd9Sstevel@tonic-gate static char *PAM_username; 11887c478bd9Sstevel@tonic-gate static char *PAM_password; 11897c478bd9Sstevel@tonic-gate static int PAM_error = 0; 11907c478bd9Sstevel@tonic-gate static pam_handle_t *pamh = NULL; 11917c478bd9Sstevel@tonic-gate 11927c478bd9Sstevel@tonic-gate /* PAM conversation function 11937c478bd9Sstevel@tonic-gate * Here we assume (for now, at least) that echo on means login name, and 11947c478bd9Sstevel@tonic-gate * echo off means password. 11957c478bd9Sstevel@tonic-gate */ 11967c478bd9Sstevel@tonic-gate 11977c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 11987c478bd9Sstevel@tonic-gate static int PAM_conv (int num_msg, 11997c478bd9Sstevel@tonic-gate #ifndef SOL2 12007c478bd9Sstevel@tonic-gate const 12017c478bd9Sstevel@tonic-gate #endif 12027c478bd9Sstevel@tonic-gate struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) 12037c478bd9Sstevel@tonic-gate { 12047c478bd9Sstevel@tonic-gate int replies = 0; 12057c478bd9Sstevel@tonic-gate struct pam_response *reply = NULL; 12067c478bd9Sstevel@tonic-gate 12077c478bd9Sstevel@tonic-gate #define COPY_STRING(s) (s) ? strdup(s) : NULL 12087c478bd9Sstevel@tonic-gate 12097c478bd9Sstevel@tonic-gate reply = malloc(sizeof(struct pam_response) * num_msg); 12107c478bd9Sstevel@tonic-gate if (reply == NULL) 12117c478bd9Sstevel@tonic-gate return PAM_CONV_ERR; 12127c478bd9Sstevel@tonic-gate 12137c478bd9Sstevel@tonic-gate for (replies = 0; replies < num_msg; replies++) { 12147c478bd9Sstevel@tonic-gate switch (msg[replies]->msg_style) { 12157c478bd9Sstevel@tonic-gate case PAM_PROMPT_ECHO_ON: 12167c478bd9Sstevel@tonic-gate reply[replies].resp_retcode = PAM_SUCCESS; 12177c478bd9Sstevel@tonic-gate reply[replies].resp = COPY_STRING(PAM_username); 12187c478bd9Sstevel@tonic-gate /* PAM frees resp */ 12197c478bd9Sstevel@tonic-gate break; 12207c478bd9Sstevel@tonic-gate case PAM_PROMPT_ECHO_OFF: 12217c478bd9Sstevel@tonic-gate reply[replies].resp_retcode = PAM_SUCCESS; 12227c478bd9Sstevel@tonic-gate reply[replies].resp = COPY_STRING(PAM_password); 12237c478bd9Sstevel@tonic-gate /* PAM frees resp */ 12247c478bd9Sstevel@tonic-gate break; 12257c478bd9Sstevel@tonic-gate case PAM_TEXT_INFO: 12267c478bd9Sstevel@tonic-gate /* fall through */ 12277c478bd9Sstevel@tonic-gate case PAM_ERROR_MSG: 12287c478bd9Sstevel@tonic-gate /* ignore it, but pam still wants a NULL response... */ 12297c478bd9Sstevel@tonic-gate reply[replies].resp_retcode = PAM_SUCCESS; 12307c478bd9Sstevel@tonic-gate reply[replies].resp = NULL; 12317c478bd9Sstevel@tonic-gate break; 12327c478bd9Sstevel@tonic-gate default: 12337c478bd9Sstevel@tonic-gate /* Must be an error of some sort... */ 12347c478bd9Sstevel@tonic-gate free (reply); 12357c478bd9Sstevel@tonic-gate PAM_error = 1; 12367c478bd9Sstevel@tonic-gate return PAM_CONV_ERR; 12377c478bd9Sstevel@tonic-gate } 12387c478bd9Sstevel@tonic-gate } 12397c478bd9Sstevel@tonic-gate *resp = reply; 12407c478bd9Sstevel@tonic-gate return PAM_SUCCESS; 12417c478bd9Sstevel@tonic-gate } 12427c478bd9Sstevel@tonic-gate 12437c478bd9Sstevel@tonic-gate static struct pam_conv PAM_conversation = { 12447c478bd9Sstevel@tonic-gate PAM_conv, NULL 12457c478bd9Sstevel@tonic-gate }; 12467c478bd9Sstevel@tonic-gate #endif /* ALLOW_PAM */ 12477c478bd9Sstevel@tonic-gate 12487c478bd9Sstevel@tonic-gate /* 12497c478bd9Sstevel@tonic-gate * plogin - Check the user name and password against the system 12507c478bd9Sstevel@tonic-gate * password database, and login the user if OK. 12517c478bd9Sstevel@tonic-gate * 12527c478bd9Sstevel@tonic-gate * returns: 12537c478bd9Sstevel@tonic-gate * UPAP_AUTHNAK: Login failed. 12547c478bd9Sstevel@tonic-gate * UPAP_AUTHACK: Login succeeded. 12557c478bd9Sstevel@tonic-gate * In either case, msg points to an appropriate message. 12567c478bd9Sstevel@tonic-gate */ 12577c478bd9Sstevel@tonic-gate 12587c478bd9Sstevel@tonic-gate static int 12597c478bd9Sstevel@tonic-gate plogin(user, passwd, msg) 12607c478bd9Sstevel@tonic-gate char *user; 12617c478bd9Sstevel@tonic-gate char *passwd; 12627c478bd9Sstevel@tonic-gate char **msg; 12637c478bd9Sstevel@tonic-gate { 12647c478bd9Sstevel@tonic-gate char *tty; 12657c478bd9Sstevel@tonic-gate #ifdef HAS_SHADOW 12667c478bd9Sstevel@tonic-gate struct spwd *spwd; 12677c478bd9Sstevel@tonic-gate #endif 12687c478bd9Sstevel@tonic-gate struct passwd *pw = NULL; 12697c478bd9Sstevel@tonic-gate 12707c478bd9Sstevel@tonic-gate #ifdef ALLOW_PAM 12717c478bd9Sstevel@tonic-gate int pam_error; 12727c478bd9Sstevel@tonic-gate 12737c478bd9Sstevel@tonic-gate if (use_pam) { 12747c478bd9Sstevel@tonic-gate if (debug) 12757c478bd9Sstevel@tonic-gate dbglog("using PAM for user authentication"); 12767c478bd9Sstevel@tonic-gate pam_error = pam_start ("ppp", user, &PAM_conversation, &pamh); 12777c478bd9Sstevel@tonic-gate if (pam_error != PAM_SUCCESS) { 12787c478bd9Sstevel@tonic-gate *msg = (char *) pam_strerror (pamh, pam_error); 12797c478bd9Sstevel@tonic-gate reopen_log(); 12807c478bd9Sstevel@tonic-gate return UPAP_AUTHNAK; 12817c478bd9Sstevel@tonic-gate } 12827c478bd9Sstevel@tonic-gate /* 12837c478bd9Sstevel@tonic-gate * Define the fields for the credential validation 12847c478bd9Sstevel@tonic-gate */ 12857c478bd9Sstevel@tonic-gate 12867c478bd9Sstevel@tonic-gate PAM_username = user; 12877c478bd9Sstevel@tonic-gate PAM_password = passwd; 12887c478bd9Sstevel@tonic-gate PAM_error = 0; 12897c478bd9Sstevel@tonic-gate /* this might be useful to some modules; required for Solaris */ 12907c478bd9Sstevel@tonic-gate tty = devnam; 12917c478bd9Sstevel@tonic-gate if (*tty == '\0') 12927c478bd9Sstevel@tonic-gate tty = ppp_devnam; 12937c478bd9Sstevel@tonic-gate (void) pam_set_item(pamh, PAM_TTY, tty); 12947c478bd9Sstevel@tonic-gate #ifdef PAM_RHOST 12957c478bd9Sstevel@tonic-gate (void) pam_set_item(pamh, PAM_RHOST, ""); 12967c478bd9Sstevel@tonic-gate #endif 12977c478bd9Sstevel@tonic-gate 12987c478bd9Sstevel@tonic-gate /* 12997c478bd9Sstevel@tonic-gate * Validate the user 13007c478bd9Sstevel@tonic-gate */ 13017c478bd9Sstevel@tonic-gate pam_error = pam_authenticate (pamh, PAM_SILENT); 13027c478bd9Sstevel@tonic-gate if (pam_error == PAM_SUCCESS && !PAM_error) { 13037c478bd9Sstevel@tonic-gate pam_error = pam_acct_mgmt (pamh, PAM_SILENT); 13047c478bd9Sstevel@tonic-gate if (pam_error == PAM_SUCCESS) 13057c478bd9Sstevel@tonic-gate (void) pam_open_session (pamh, PAM_SILENT); 13067c478bd9Sstevel@tonic-gate } 13077c478bd9Sstevel@tonic-gate 13087c478bd9Sstevel@tonic-gate *msg = (char *) pam_strerror (pamh, pam_error); 13097c478bd9Sstevel@tonic-gate 13107c478bd9Sstevel@tonic-gate /* 13117c478bd9Sstevel@tonic-gate * Clean up the mess 13127c478bd9Sstevel@tonic-gate */ 13137c478bd9Sstevel@tonic-gate reopen_log(); /* apparently the PAM stuff does closelog() */ 13147c478bd9Sstevel@tonic-gate PAM_username = NULL; 13157c478bd9Sstevel@tonic-gate PAM_password = NULL; 13167c478bd9Sstevel@tonic-gate if (pam_error != PAM_SUCCESS) 13177c478bd9Sstevel@tonic-gate return UPAP_AUTHNAK; 13187c478bd9Sstevel@tonic-gate } else 13197c478bd9Sstevel@tonic-gate #endif /* ALLOW_PAM */ 13207c478bd9Sstevel@tonic-gate 13217c478bd9Sstevel@tonic-gate { 13227c478bd9Sstevel@tonic-gate if (debug) { 13237c478bd9Sstevel@tonic-gate #ifdef HAS_SHADOW 13247c478bd9Sstevel@tonic-gate dbglog("using passwd/shadow for user authentication"); 13257c478bd9Sstevel@tonic-gate #else 13267c478bd9Sstevel@tonic-gate dbglog("using passwd for user authentication"); 13277c478bd9Sstevel@tonic-gate #endif 13287c478bd9Sstevel@tonic-gate } 13297c478bd9Sstevel@tonic-gate /* 13307c478bd9Sstevel@tonic-gate * Use the non-PAM methods directly 13317c478bd9Sstevel@tonic-gate */ 13327c478bd9Sstevel@tonic-gate 13337c478bd9Sstevel@tonic-gate pw = getpwnam(user); 13347c478bd9Sstevel@tonic-gate 13357c478bd9Sstevel@tonic-gate endpwent(); 13367c478bd9Sstevel@tonic-gate if (pw == NULL) 13377c478bd9Sstevel@tonic-gate return (UPAP_AUTHNAK); 13387c478bd9Sstevel@tonic-gate 13397c478bd9Sstevel@tonic-gate #ifdef HAS_SHADOW 13407c478bd9Sstevel@tonic-gate spwd = getspnam(user); 13417c478bd9Sstevel@tonic-gate endspent(); 13427c478bd9Sstevel@tonic-gate if (spwd != NULL) { 13437c478bd9Sstevel@tonic-gate /* check the age of the password entry */ 13447c478bd9Sstevel@tonic-gate long now = time(NULL) / 86400L; 13457c478bd9Sstevel@tonic-gate 13467c478bd9Sstevel@tonic-gate if ((spwd->sp_expire > 0 && now >= spwd->sp_expire) 13477c478bd9Sstevel@tonic-gate || ((spwd->sp_max >= 0 && spwd->sp_max < 10000) 13487c478bd9Sstevel@tonic-gate && spwd->sp_lstchg >= 0 13497c478bd9Sstevel@tonic-gate && now >= spwd->sp_lstchg + spwd->sp_max)) { 13507c478bd9Sstevel@tonic-gate warn("Password for %s has expired", user); 13517c478bd9Sstevel@tonic-gate return (UPAP_AUTHNAK); 13527c478bd9Sstevel@tonic-gate } 13537c478bd9Sstevel@tonic-gate pw->pw_passwd = spwd->sp_pwdp; 13547c478bd9Sstevel@tonic-gate } 13557c478bd9Sstevel@tonic-gate #endif 13567c478bd9Sstevel@tonic-gate 13577c478bd9Sstevel@tonic-gate /* 13587c478bd9Sstevel@tonic-gate * If no passwd, don't let them login. 13597c478bd9Sstevel@tonic-gate */ 13607c478bd9Sstevel@tonic-gate if (pw->pw_passwd == NULL || strlen(pw->pw_passwd) < 2 || 13617c478bd9Sstevel@tonic-gate strcmp(crypt(passwd, pw->pw_passwd), pw->pw_passwd) != 0) 13627c478bd9Sstevel@tonic-gate return (UPAP_AUTHNAK); 13637c478bd9Sstevel@tonic-gate } 13647c478bd9Sstevel@tonic-gate 13657c478bd9Sstevel@tonic-gate /* 13667c478bd9Sstevel@tonic-gate * Write a wtmp entry for this user. 13677c478bd9Sstevel@tonic-gate */ 13687c478bd9Sstevel@tonic-gate 13697c478bd9Sstevel@tonic-gate tty = devnam; 13707c478bd9Sstevel@tonic-gate if (strncmp(tty, "/dev/", 5) == 0) 13717c478bd9Sstevel@tonic-gate tty += 5; 13727c478bd9Sstevel@tonic-gate logwtmp(tty, user, remote_name); /* Add wtmp login entry */ 13737c478bd9Sstevel@tonic-gate 1374*2de0a7d6SDan McDonald #ifdef _PATH_LASTLOG 1375*2de0a7d6SDan McDonald if (!use_pam && pw != (struct passwd *)NULL) { 1376*2de0a7d6SDan McDonald struct lastlog ll; 1377*2de0a7d6SDan McDonald int fd; 1378*2de0a7d6SDan McDonald 1379*2de0a7d6SDan McDonald if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) { 1380*2de0a7d6SDan McDonald (void)lseek(fd, (off_t)(pw->pw_uid * sizeof(ll)), SEEK_SET); 1381*2de0a7d6SDan McDonald BZERO((void *)&ll, sizeof(ll)); 1382*2de0a7d6SDan McDonald (void)time(&ll.ll_time); 1383*2de0a7d6SDan McDonald (void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line)); 1384*2de0a7d6SDan McDonald (void)write(fd, (char *)&ll, sizeof(ll)); 1385*2de0a7d6SDan McDonald (void)close(fd); 1386*2de0a7d6SDan McDonald } 1387*2de0a7d6SDan McDonald } 1388*2de0a7d6SDan McDonald #endif /* _PATH_LASTLOG */ 1389*2de0a7d6SDan McDonald 13907c478bd9Sstevel@tonic-gate info("user %s logged in", user); 13917c478bd9Sstevel@tonic-gate logged_in = 1; 13927c478bd9Sstevel@tonic-gate 13937c478bd9Sstevel@tonic-gate return (UPAP_AUTHACK); 13947c478bd9Sstevel@tonic-gate } 13957c478bd9Sstevel@tonic-gate 13967c478bd9Sstevel@tonic-gate /* 13977c478bd9Sstevel@tonic-gate * plogout - Logout the user. 13987c478bd9Sstevel@tonic-gate */ 13997c478bd9Sstevel@tonic-gate static void 14007c478bd9Sstevel@tonic-gate plogout() 14017c478bd9Sstevel@tonic-gate { 14027c478bd9Sstevel@tonic-gate char *tty; 14037c478bd9Sstevel@tonic-gate 14047c478bd9Sstevel@tonic-gate #ifdef ALLOW_PAM 14057c478bd9Sstevel@tonic-gate int pam_error; 14067c478bd9Sstevel@tonic-gate 14077c478bd9Sstevel@tonic-gate if (use_pam) { 14087c478bd9Sstevel@tonic-gate if (pamh != NULL) { 14097c478bd9Sstevel@tonic-gate pam_error = pam_close_session (pamh, PAM_SILENT); 14107c478bd9Sstevel@tonic-gate (void) pam_end (pamh, pam_error); 14117c478bd9Sstevel@tonic-gate pamh = NULL; 14127c478bd9Sstevel@tonic-gate } 14137c478bd9Sstevel@tonic-gate /* Apparently the pam stuff does closelog(). */ 14147c478bd9Sstevel@tonic-gate reopen_log(); 14157c478bd9Sstevel@tonic-gate } else 14167c478bd9Sstevel@tonic-gate #endif /* ALLOW_PAM */ 14177c478bd9Sstevel@tonic-gate 14187c478bd9Sstevel@tonic-gate { 14197c478bd9Sstevel@tonic-gate tty = devnam; 14207c478bd9Sstevel@tonic-gate if (strncmp(tty, "/dev/", 5) == 0) 14217c478bd9Sstevel@tonic-gate tty += 5; 14227c478bd9Sstevel@tonic-gate /* Wipe out utmp logout entry */ 14237c478bd9Sstevel@tonic-gate logwtmp(tty, "", ""); 14247c478bd9Sstevel@tonic-gate } 14257c478bd9Sstevel@tonic-gate logged_in = 0; 14267c478bd9Sstevel@tonic-gate } 14277c478bd9Sstevel@tonic-gate 14287c478bd9Sstevel@tonic-gate 14297c478bd9Sstevel@tonic-gate /* 14307c478bd9Sstevel@tonic-gate * null_login - Check if a username of "" and a password of "" are 14317c478bd9Sstevel@tonic-gate * acceptable, and iff so, set the list of acceptable IP addresses 14327c478bd9Sstevel@tonic-gate * and return 1. 14337c478bd9Sstevel@tonic-gate */ 14347c478bd9Sstevel@tonic-gate static int 14357c478bd9Sstevel@tonic-gate null_login(unit) 14367c478bd9Sstevel@tonic-gate int unit; 14377c478bd9Sstevel@tonic-gate { 14387c478bd9Sstevel@tonic-gate char *filename; 14397c478bd9Sstevel@tonic-gate FILE *f; 14407c478bd9Sstevel@tonic-gate int i, ret; 14417c478bd9Sstevel@tonic-gate struct wordlist *addrs, *opts; 14427c478bd9Sstevel@tonic-gate char secret[MAXWORDLEN]; 14437c478bd9Sstevel@tonic-gate 14447c478bd9Sstevel@tonic-gate /* 14457c478bd9Sstevel@tonic-gate * Open the file of pap secrets and scan for a suitable secret. 14467c478bd9Sstevel@tonic-gate */ 14477c478bd9Sstevel@tonic-gate filename = _PATH_UPAPFILE; 14487c478bd9Sstevel@tonic-gate addrs = NULL; 14497c478bd9Sstevel@tonic-gate f = fopen(filename, "r"); 14507c478bd9Sstevel@tonic-gate if (f == NULL) 14517c478bd9Sstevel@tonic-gate return 0; 14527c478bd9Sstevel@tonic-gate check_access(f, filename); 14537c478bd9Sstevel@tonic-gate 14547c478bd9Sstevel@tonic-gate i = scan_authfile(f, "", our_name, secret, &addrs, &opts, filename); 14557c478bd9Sstevel@tonic-gate ret = i >= 0 && secret[0] == '\0'; 14567c478bd9Sstevel@tonic-gate BZERO(secret, sizeof(secret)); 14577c478bd9Sstevel@tonic-gate 14587c478bd9Sstevel@tonic-gate if (ret) 14597c478bd9Sstevel@tonic-gate set_allowed_addrs(unit, addrs, opts); 14607c478bd9Sstevel@tonic-gate else if (opts != NULL) 14617c478bd9Sstevel@tonic-gate free_wordlist(opts); 14627c478bd9Sstevel@tonic-gate if (addrs != NULL) 14637c478bd9Sstevel@tonic-gate free_wordlist(addrs); 14647c478bd9Sstevel@tonic-gate 14657c478bd9Sstevel@tonic-gate (void) fclose(f); 14667c478bd9Sstevel@tonic-gate return ret; 14677c478bd9Sstevel@tonic-gate } 14687c478bd9Sstevel@tonic-gate 14697c478bd9Sstevel@tonic-gate 14707c478bd9Sstevel@tonic-gate /* 14717c478bd9Sstevel@tonic-gate * get_pap_passwd - get a password for authenticating ourselves with 14727c478bd9Sstevel@tonic-gate * our peer using PAP. Returns 1 on success, 0 if no suitable password 14737c478bd9Sstevel@tonic-gate * could be found. 14747c478bd9Sstevel@tonic-gate * Assumes passwd points to MAXSECRETLEN bytes of space (if non-null). 14757c478bd9Sstevel@tonic-gate */ 14767c478bd9Sstevel@tonic-gate static int 14777c478bd9Sstevel@tonic-gate get_pap_passwd(passwd) 14787c478bd9Sstevel@tonic-gate char *passwd; 14797c478bd9Sstevel@tonic-gate { 14807c478bd9Sstevel@tonic-gate char *filename; 14817c478bd9Sstevel@tonic-gate FILE *f; 14827c478bd9Sstevel@tonic-gate int ret; 14837c478bd9Sstevel@tonic-gate char secret[MAXWORDLEN]; 14847c478bd9Sstevel@tonic-gate 14857c478bd9Sstevel@tonic-gate /* 14867c478bd9Sstevel@tonic-gate * Check whether a plugin wants to supply this. 14877c478bd9Sstevel@tonic-gate */ 14887c478bd9Sstevel@tonic-gate if (pap_passwd_hook != NULL) { 14897c478bd9Sstevel@tonic-gate ret = (*pap_passwd_hook)(user, passwd); 14907c478bd9Sstevel@tonic-gate if (ret >= 0) 14917c478bd9Sstevel@tonic-gate return ret; 14927c478bd9Sstevel@tonic-gate } 14937c478bd9Sstevel@tonic-gate 14947c478bd9Sstevel@tonic-gate filename = _PATH_UPAPFILE; 14957c478bd9Sstevel@tonic-gate f = fopen(filename, "r"); 14967c478bd9Sstevel@tonic-gate if (f == NULL) 14977c478bd9Sstevel@tonic-gate return 0; 14987c478bd9Sstevel@tonic-gate check_access(f, filename); 14997c478bd9Sstevel@tonic-gate ret = scan_authfile(f, user, 15007c478bd9Sstevel@tonic-gate (remote_name[0] != '\0' ? remote_name: NULL), 15017c478bd9Sstevel@tonic-gate secret, NULL, NULL, filename); 15027c478bd9Sstevel@tonic-gate (void) fclose(f); 15037c478bd9Sstevel@tonic-gate if (ret < 0) 15047c478bd9Sstevel@tonic-gate return 0; 15057c478bd9Sstevel@tonic-gate if (passwd != NULL) 15067c478bd9Sstevel@tonic-gate (void) strlcpy(passwd, secret, MAXSECRETLEN); 15077c478bd9Sstevel@tonic-gate BZERO(secret, sizeof(secret)); 15087c478bd9Sstevel@tonic-gate return 1; 15097c478bd9Sstevel@tonic-gate } 15107c478bd9Sstevel@tonic-gate 15117c478bd9Sstevel@tonic-gate 15127c478bd9Sstevel@tonic-gate /* 15137c478bd9Sstevel@tonic-gate * have_pap_secret - check whether we have a PAP file with any 15147c478bd9Sstevel@tonic-gate * secrets that we could possibly use for authenticating the peer. 15157c478bd9Sstevel@tonic-gate */ 15167c478bd9Sstevel@tonic-gate static int 15177c478bd9Sstevel@tonic-gate have_pap_secret(lacks_ipp) 15187c478bd9Sstevel@tonic-gate int *lacks_ipp; 15197c478bd9Sstevel@tonic-gate { 15207c478bd9Sstevel@tonic-gate FILE *f; 15217c478bd9Sstevel@tonic-gate int ret; 15227c478bd9Sstevel@tonic-gate char *filename; 15237c478bd9Sstevel@tonic-gate struct wordlist *addrs; 15247c478bd9Sstevel@tonic-gate 15257c478bd9Sstevel@tonic-gate /* let the plugin decide, if there is one */ 15267c478bd9Sstevel@tonic-gate if (pap_check_hook != NULL) { 15277c478bd9Sstevel@tonic-gate ret = (*pap_check_hook)(); 15287c478bd9Sstevel@tonic-gate if (ret >= 0) 15297c478bd9Sstevel@tonic-gate return ret; 15307c478bd9Sstevel@tonic-gate } 15317c478bd9Sstevel@tonic-gate 15327c478bd9Sstevel@tonic-gate filename = _PATH_UPAPFILE; 15337c478bd9Sstevel@tonic-gate f = fopen(filename, "r"); 15347c478bd9Sstevel@tonic-gate if (f == NULL) 15357c478bd9Sstevel@tonic-gate return 0; 15367c478bd9Sstevel@tonic-gate 15377c478bd9Sstevel@tonic-gate ret = scan_authfile(f, (explicit_remote? remote_name: NULL), our_name, 15387c478bd9Sstevel@tonic-gate NULL, &addrs, NULL, filename); 15397c478bd9Sstevel@tonic-gate (void) fclose(f); 15407c478bd9Sstevel@tonic-gate if (ret >= 0 && !some_ip_ok(addrs)) { 15417c478bd9Sstevel@tonic-gate if (lacks_ipp != NULL) 15427c478bd9Sstevel@tonic-gate *lacks_ipp = 1; 15437c478bd9Sstevel@tonic-gate ret = -1; 15447c478bd9Sstevel@tonic-gate } 15457c478bd9Sstevel@tonic-gate if (addrs != NULL) 15467c478bd9Sstevel@tonic-gate free_wordlist(addrs); 15477c478bd9Sstevel@tonic-gate 15487c478bd9Sstevel@tonic-gate return ret >= 0; 15497c478bd9Sstevel@tonic-gate } 15507c478bd9Sstevel@tonic-gate 15517c478bd9Sstevel@tonic-gate 15527c478bd9Sstevel@tonic-gate /* 15537c478bd9Sstevel@tonic-gate * have_chap_secret - check whether we have a CHAP file with a secret 15547c478bd9Sstevel@tonic-gate * that we could possibly use for authenticating `client' on `server'. 15557c478bd9Sstevel@tonic-gate * Either or both can be the null string, meaning we don't know the 15567c478bd9Sstevel@tonic-gate * identity yet. 15577c478bd9Sstevel@tonic-gate */ 15587c478bd9Sstevel@tonic-gate static int 15597c478bd9Sstevel@tonic-gate have_chap_secret(client, server, need_ip, lacks_ipp) 15607c478bd9Sstevel@tonic-gate char *client; 15617c478bd9Sstevel@tonic-gate char *server; 15627c478bd9Sstevel@tonic-gate int need_ip; 15637c478bd9Sstevel@tonic-gate int *lacks_ipp; 15647c478bd9Sstevel@tonic-gate { 15657c478bd9Sstevel@tonic-gate FILE *f; 15667c478bd9Sstevel@tonic-gate int ret; 15677c478bd9Sstevel@tonic-gate char *filename; 15687c478bd9Sstevel@tonic-gate struct wordlist *addrs; 15697c478bd9Sstevel@tonic-gate 15707c478bd9Sstevel@tonic-gate filename = _PATH_CHAPFILE; 15717c478bd9Sstevel@tonic-gate f = fopen(filename, "r"); 15727c478bd9Sstevel@tonic-gate if (f == NULL) 15737c478bd9Sstevel@tonic-gate return 0; 15747c478bd9Sstevel@tonic-gate 15757c478bd9Sstevel@tonic-gate if (client != NULL && client[0] == '\0') 15767c478bd9Sstevel@tonic-gate client = NULL; 15777c478bd9Sstevel@tonic-gate if (server != NULL && server[0] == '\0') 15787c478bd9Sstevel@tonic-gate server = NULL; 15797c478bd9Sstevel@tonic-gate 15807c478bd9Sstevel@tonic-gate ret = scan_authfile(f, client, server, NULL, &addrs, NULL, filename); 15817c478bd9Sstevel@tonic-gate (void) fclose(f); 15827c478bd9Sstevel@tonic-gate if (ret >= 0 && need_ip && !some_ip_ok(addrs)) { 15837c478bd9Sstevel@tonic-gate if (lacks_ipp != NULL) 15847c478bd9Sstevel@tonic-gate *lacks_ipp = 1; 15857c478bd9Sstevel@tonic-gate ret = -1; 15867c478bd9Sstevel@tonic-gate } 15877c478bd9Sstevel@tonic-gate if (addrs != NULL) 15887c478bd9Sstevel@tonic-gate free_wordlist(addrs); 15897c478bd9Sstevel@tonic-gate 15907c478bd9Sstevel@tonic-gate return ret >= 0; 15917c478bd9Sstevel@tonic-gate } 15927c478bd9Sstevel@tonic-gate 15937c478bd9Sstevel@tonic-gate 15947c478bd9Sstevel@tonic-gate /* 15957c478bd9Sstevel@tonic-gate * get_secret - open the CHAP secret file and return the secret 15967c478bd9Sstevel@tonic-gate * for authenticating the given client on the given server. 15977c478bd9Sstevel@tonic-gate * 15987c478bd9Sstevel@tonic-gate * "am_server" means that we're the authenticator (demanding 15997c478bd9Sstevel@tonic-gate * identity from the peer). 16007c478bd9Sstevel@tonic-gate * 16017c478bd9Sstevel@tonic-gate * "!am_server" means that we're the authenticatee (supplying 16027c478bd9Sstevel@tonic-gate * identity to the peer). 16037c478bd9Sstevel@tonic-gate */ 16047c478bd9Sstevel@tonic-gate int 16057c478bd9Sstevel@tonic-gate get_secret(unit, client, server, secret, secret_len, am_server) 16067c478bd9Sstevel@tonic-gate int unit; 16077c478bd9Sstevel@tonic-gate char *client; 16087c478bd9Sstevel@tonic-gate char *server; 16097c478bd9Sstevel@tonic-gate char *secret; 16107c478bd9Sstevel@tonic-gate int *secret_len; 16117c478bd9Sstevel@tonic-gate int am_server; 16127c478bd9Sstevel@tonic-gate { 16137c478bd9Sstevel@tonic-gate FILE *f; 16147c478bd9Sstevel@tonic-gate int ret, len; 16157c478bd9Sstevel@tonic-gate char *filename; 16167c478bd9Sstevel@tonic-gate struct wordlist *addrs, *opts; 16177c478bd9Sstevel@tonic-gate char secbuf[MAXWORDLEN]; 16187c478bd9Sstevel@tonic-gate 16197c478bd9Sstevel@tonic-gate /* 16207c478bd9Sstevel@tonic-gate * Support the 'password' option on authenticatee only in order to 16217c478bd9Sstevel@tonic-gate * avoid obvious security problem (authenticator and authenticatee 16227c478bd9Sstevel@tonic-gate * within a given implementation must never share secrets). 16237c478bd9Sstevel@tonic-gate */ 16247c478bd9Sstevel@tonic-gate if (!am_server && passwd[0] != '\0') { 16257c478bd9Sstevel@tonic-gate (void) strlcpy(secbuf, passwd, sizeof(secbuf)); 16267c478bd9Sstevel@tonic-gate } else { 16277c478bd9Sstevel@tonic-gate filename = _PATH_CHAPFILE; 16287c478bd9Sstevel@tonic-gate addrs = NULL; 16297c478bd9Sstevel@tonic-gate secbuf[0] = '\0'; 16307c478bd9Sstevel@tonic-gate 16317c478bd9Sstevel@tonic-gate f = fopen(filename, "r"); 16327c478bd9Sstevel@tonic-gate if (f == NULL) { 16337c478bd9Sstevel@tonic-gate error("Can't open chap secret file %s: %m", filename); 16347c478bd9Sstevel@tonic-gate return 0; 16357c478bd9Sstevel@tonic-gate } 16367c478bd9Sstevel@tonic-gate check_access(f, filename); 16377c478bd9Sstevel@tonic-gate 16387c478bd9Sstevel@tonic-gate ret = scan_authfile(f, client, server, secbuf, &addrs, &opts, 16397c478bd9Sstevel@tonic-gate filename); 16407c478bd9Sstevel@tonic-gate (void) fclose(f); 16417c478bd9Sstevel@tonic-gate if (ret < 0) { 16427c478bd9Sstevel@tonic-gate if (scan_server_match_failed[0] != '\0') 16437c478bd9Sstevel@tonic-gate warn("possible configuration error: local name is %q, but " 16447c478bd9Sstevel@tonic-gate "found %q instead", our_name, scan_server_match_failed); 16457c478bd9Sstevel@tonic-gate return 0; 16467c478bd9Sstevel@tonic-gate } 16477c478bd9Sstevel@tonic-gate 16487c478bd9Sstevel@tonic-gate /* Only the authenticator cares about limiting peer addresses. */ 16497c478bd9Sstevel@tonic-gate if (am_server) 16507c478bd9Sstevel@tonic-gate set_allowed_addrs(unit, addrs, opts); 16517c478bd9Sstevel@tonic-gate else if (opts != NULL) 16527c478bd9Sstevel@tonic-gate free_wordlist(opts); 16537c478bd9Sstevel@tonic-gate if (addrs != NULL) 16547c478bd9Sstevel@tonic-gate free_wordlist(addrs); 16557c478bd9Sstevel@tonic-gate } 16567c478bd9Sstevel@tonic-gate 16577c478bd9Sstevel@tonic-gate len = strlen(secbuf); 16587c478bd9Sstevel@tonic-gate if (len > MAXSECRETLEN) { 16597c478bd9Sstevel@tonic-gate error("Secret for %s on %s is too long", client, server); 16607c478bd9Sstevel@tonic-gate len = MAXSECRETLEN; 16617c478bd9Sstevel@tonic-gate } 16627c478bd9Sstevel@tonic-gate /* Do not leave a temporary copy of the secret on the stack. */ 16637c478bd9Sstevel@tonic-gate BCOPY(secbuf, secret, len); 16647c478bd9Sstevel@tonic-gate BZERO(secbuf, sizeof(secbuf)); 16657c478bd9Sstevel@tonic-gate *secret_len = len; 16667c478bd9Sstevel@tonic-gate 16677c478bd9Sstevel@tonic-gate return 1; 16687c478bd9Sstevel@tonic-gate } 16697c478bd9Sstevel@tonic-gate 16707c478bd9Sstevel@tonic-gate /* 16717c478bd9Sstevel@tonic-gate * set_allowed_addrs() - set the list of allowed addresses. 16727c478bd9Sstevel@tonic-gate * The caller must also look for `--' indicating options to apply for 16737c478bd9Sstevel@tonic-gate * this peer and leaves the following words in extra_options. 16747c478bd9Sstevel@tonic-gate */ 16757c478bd9Sstevel@tonic-gate static void 16767c478bd9Sstevel@tonic-gate set_allowed_addrs(unit, addrs, opts) 16777c478bd9Sstevel@tonic-gate int unit; 16787c478bd9Sstevel@tonic-gate struct wordlist *addrs; 16797c478bd9Sstevel@tonic-gate struct wordlist *opts; 16807c478bd9Sstevel@tonic-gate { 16817c478bd9Sstevel@tonic-gate int n; 16827c478bd9Sstevel@tonic-gate struct wordlist *ap, **pap; 16837c478bd9Sstevel@tonic-gate struct permitted_ip *ip; 16847c478bd9Sstevel@tonic-gate char *ptr_word, *ptr_mask; 16857c478bd9Sstevel@tonic-gate struct hostent *hp; 16867c478bd9Sstevel@tonic-gate struct netent *np; 16877c478bd9Sstevel@tonic-gate u_int32_t a, mask, newmask, ah, offset; 16887c478bd9Sstevel@tonic-gate struct ipcp_options *wo = &ipcp_wantoptions[unit]; 16897c478bd9Sstevel@tonic-gate u_int32_t suggested_ip = 0; 16907c478bd9Sstevel@tonic-gate int err_num; 16917c478bd9Sstevel@tonic-gate 16927c478bd9Sstevel@tonic-gate if (addresses[unit] != NULL) 16937c478bd9Sstevel@tonic-gate free(addresses[unit]); 16947c478bd9Sstevel@tonic-gate addresses[unit] = NULL; 16957c478bd9Sstevel@tonic-gate if (extra_options != NULL) 16967c478bd9Sstevel@tonic-gate free_wordlist(extra_options); 16977c478bd9Sstevel@tonic-gate extra_options = opts; 16987c478bd9Sstevel@tonic-gate 16997c478bd9Sstevel@tonic-gate /* 17007c478bd9Sstevel@tonic-gate * Count the number of IP addresses given. 17017c478bd9Sstevel@tonic-gate */ 17027c478bd9Sstevel@tonic-gate for (n = 0, pap = &addrs; (ap = *pap) != NULL; pap = &ap->next) 17037c478bd9Sstevel@tonic-gate ++n; 17047c478bd9Sstevel@tonic-gate if (n == 0) 17057c478bd9Sstevel@tonic-gate return; 17067c478bd9Sstevel@tonic-gate ip = (struct permitted_ip *) malloc((n + 1) * sizeof(struct permitted_ip)); 17077c478bd9Sstevel@tonic-gate if (ip == NULL) 17087c478bd9Sstevel@tonic-gate return; 17097c478bd9Sstevel@tonic-gate 17107c478bd9Sstevel@tonic-gate n = 0; 17117c478bd9Sstevel@tonic-gate for (ap = addrs; ap != NULL; ap = ap->next) { 17127c478bd9Sstevel@tonic-gate /* "-" means no addresses authorized, "*" means any address allowed */ 17137c478bd9Sstevel@tonic-gate ptr_word = ap->word; 17147c478bd9Sstevel@tonic-gate if (strcmp(ptr_word, "-") == 0) 17157c478bd9Sstevel@tonic-gate break; 17167c478bd9Sstevel@tonic-gate if (strcmp(ptr_word, "*") == 0) { 17177c478bd9Sstevel@tonic-gate ip[n].permit = 1; 17187c478bd9Sstevel@tonic-gate ip[n].base = ip[n].mask = 0; 17197c478bd9Sstevel@tonic-gate ++n; 17207c478bd9Sstevel@tonic-gate break; 17217c478bd9Sstevel@tonic-gate } 17227c478bd9Sstevel@tonic-gate 17237c478bd9Sstevel@tonic-gate ip[n].permit = 1; 17247c478bd9Sstevel@tonic-gate if (*ptr_word == '!') { 17257c478bd9Sstevel@tonic-gate ip[n].permit = 0; 17267c478bd9Sstevel@tonic-gate ++ptr_word; 17277c478bd9Sstevel@tonic-gate } 17287c478bd9Sstevel@tonic-gate 17297c478bd9Sstevel@tonic-gate mask = ~ (u_int32_t) 0; 17307c478bd9Sstevel@tonic-gate offset = 0; 17317c478bd9Sstevel@tonic-gate ptr_mask = strchr (ptr_word, '/'); 17327c478bd9Sstevel@tonic-gate if (ptr_mask != NULL) { 17337c478bd9Sstevel@tonic-gate int bit_count; 17347c478bd9Sstevel@tonic-gate char *endp; 17357c478bd9Sstevel@tonic-gate 17367c478bd9Sstevel@tonic-gate bit_count = (int) strtol (ptr_mask+1, &endp, 10); 17377c478bd9Sstevel@tonic-gate if (bit_count <= 0 || bit_count > 32) { 17387c478bd9Sstevel@tonic-gate warn("invalid address length %v in authorized address list", 17397c478bd9Sstevel@tonic-gate ptr_mask+1); 17407c478bd9Sstevel@tonic-gate continue; 17417c478bd9Sstevel@tonic-gate } 17427c478bd9Sstevel@tonic-gate bit_count = 32 - bit_count; /* # bits in host part */ 17437c478bd9Sstevel@tonic-gate if (*endp == '+') { 17447c478bd9Sstevel@tonic-gate offset = ifunit + 1; 17457c478bd9Sstevel@tonic-gate ++endp; 17467c478bd9Sstevel@tonic-gate } 17477c478bd9Sstevel@tonic-gate if (*endp != '\0') { 17487c478bd9Sstevel@tonic-gate warn("invalid address length syntax: %v", ptr_mask+1); 17497c478bd9Sstevel@tonic-gate continue; 17507c478bd9Sstevel@tonic-gate } 17517c478bd9Sstevel@tonic-gate *ptr_mask = '\0'; 17527c478bd9Sstevel@tonic-gate mask <<= bit_count; 17537c478bd9Sstevel@tonic-gate } 17547c478bd9Sstevel@tonic-gate 17557c478bd9Sstevel@tonic-gate /* Try to interpret value as host name or numeric address first */ 17567c478bd9Sstevel@tonic-gate hp = getipnodebyname(ptr_word, AF_INET, 0, &err_num); 17577c478bd9Sstevel@tonic-gate if (hp != NULL) { 17587c478bd9Sstevel@tonic-gate (void) memcpy(&a, hp->h_addr, sizeof(a)); 17597c478bd9Sstevel@tonic-gate freehostent(hp); 17607c478bd9Sstevel@tonic-gate } else { 17617c478bd9Sstevel@tonic-gate char *cp = ptr_word + strlen(ptr_word); 17627c478bd9Sstevel@tonic-gate if (cp > ptr_word) 17637c478bd9Sstevel@tonic-gate cp--; 17647c478bd9Sstevel@tonic-gate if (*cp == '+') { 17657c478bd9Sstevel@tonic-gate offset = ifunit + 1; 17667c478bd9Sstevel@tonic-gate *cp = '\0'; 17677c478bd9Sstevel@tonic-gate } 17687c478bd9Sstevel@tonic-gate np = getnetbyname (ptr_word); 17697c478bd9Sstevel@tonic-gate if (np != NULL && np->n_addrtype == AF_INET) { 17707c478bd9Sstevel@tonic-gate ah = np->n_net; 17717c478bd9Sstevel@tonic-gate newmask = (u_int32_t)~0; 17727c478bd9Sstevel@tonic-gate if ((ah & 0xff000000ul) == 0) 17737c478bd9Sstevel@tonic-gate ah <<= 8, newmask <<= 8; 17747c478bd9Sstevel@tonic-gate if ((ah & 0xff000000ul) == 0) 17757c478bd9Sstevel@tonic-gate ah <<= 8, newmask <<= 8; 17767c478bd9Sstevel@tonic-gate if ((ah & 0xff000000ul) == 0) 17777c478bd9Sstevel@tonic-gate ah <<= 8, newmask <<= 8; 17787c478bd9Sstevel@tonic-gate if (ptr_mask == NULL) 17797c478bd9Sstevel@tonic-gate mask = newmask; 17807c478bd9Sstevel@tonic-gate a = htonl(ah); 17817c478bd9Sstevel@tonic-gate } 17827c478bd9Sstevel@tonic-gate } 17837c478bd9Sstevel@tonic-gate 17847c478bd9Sstevel@tonic-gate if (ptr_mask != NULL) 17857c478bd9Sstevel@tonic-gate *ptr_mask = '/'; 17867c478bd9Sstevel@tonic-gate 17877c478bd9Sstevel@tonic-gate if (a == (u_int32_t)-1L) { 17887c478bd9Sstevel@tonic-gate warn("unknown host %s in auth. address list", ap->word); 17897c478bd9Sstevel@tonic-gate continue; 17907c478bd9Sstevel@tonic-gate } 17917c478bd9Sstevel@tonic-gate if (offset != 0) { 17927c478bd9Sstevel@tonic-gate if (offset >= ~mask) { 17937c478bd9Sstevel@tonic-gate warn("interface unit %d too large for subnet %v", 17947c478bd9Sstevel@tonic-gate ifunit, ptr_word); 17957c478bd9Sstevel@tonic-gate continue; 17967c478bd9Sstevel@tonic-gate } 17977c478bd9Sstevel@tonic-gate a = htonl((ntohl(a) & mask) + offset); 17987c478bd9Sstevel@tonic-gate mask = ~(u_int32_t)0; 17997c478bd9Sstevel@tonic-gate } 18007c478bd9Sstevel@tonic-gate ip[n].mask = htonl(mask); 18017c478bd9Sstevel@tonic-gate ip[n].base = a & ip[n].mask; 18027c478bd9Sstevel@tonic-gate ++n; 18037c478bd9Sstevel@tonic-gate if (~mask == 0 && suggested_ip == 0) 18047c478bd9Sstevel@tonic-gate suggested_ip = a; 18057c478bd9Sstevel@tonic-gate } 18067c478bd9Sstevel@tonic-gate 18077c478bd9Sstevel@tonic-gate /* Sentinel value at end of list */ 18087c478bd9Sstevel@tonic-gate ip[n].permit = 0; /* make the last entry forbid all addresses */ 18097c478bd9Sstevel@tonic-gate ip[n].base = 0; /* to terminate the list */ 18107c478bd9Sstevel@tonic-gate ip[n].mask = 0; 18117c478bd9Sstevel@tonic-gate 18127c478bd9Sstevel@tonic-gate addresses[unit] = ip; 18137c478bd9Sstevel@tonic-gate 18147c478bd9Sstevel@tonic-gate /* 18157c478bd9Sstevel@tonic-gate * If the address given for the peer isn't authorized, or if 18167c478bd9Sstevel@tonic-gate * the user hasn't given one, AND there is an authorized address 18177c478bd9Sstevel@tonic-gate * which is a single host, then use that if we find one. 18187c478bd9Sstevel@tonic-gate */ 18197c478bd9Sstevel@tonic-gate if (suggested_ip != 0 18207c478bd9Sstevel@tonic-gate && (wo->hisaddr == 0 || !auth_ip_addr(unit, wo->hisaddr))) 18217c478bd9Sstevel@tonic-gate wo->hisaddr = suggested_ip; 18227c478bd9Sstevel@tonic-gate } 18237c478bd9Sstevel@tonic-gate 18247c478bd9Sstevel@tonic-gate /* 18257c478bd9Sstevel@tonic-gate * auth_ip_addr - check whether the peer is authorized to use 18267c478bd9Sstevel@tonic-gate * a given IP address. Returns 1 if authorized, 0 otherwise. 18277c478bd9Sstevel@tonic-gate */ 18287c478bd9Sstevel@tonic-gate int 18297c478bd9Sstevel@tonic-gate auth_ip_addr(unit, addr) 18307c478bd9Sstevel@tonic-gate int unit; 18317c478bd9Sstevel@tonic-gate u_int32_t addr; 18327c478bd9Sstevel@tonic-gate { 18337c478bd9Sstevel@tonic-gate int ok; 18347c478bd9Sstevel@tonic-gate 18357c478bd9Sstevel@tonic-gate /* don't allow loopback or multicast address */ 18367c478bd9Sstevel@tonic-gate if (bad_ip_adrs(addr)) 18377c478bd9Sstevel@tonic-gate return 0; 18387c478bd9Sstevel@tonic-gate 18397c478bd9Sstevel@tonic-gate if (addresses[unit] != NULL) { 18407c478bd9Sstevel@tonic-gate ok = ip_addr_check(addr, addresses[unit]); 18417c478bd9Sstevel@tonic-gate if (ok >= 0) 18427c478bd9Sstevel@tonic-gate return ok; 18437c478bd9Sstevel@tonic-gate } 18447c478bd9Sstevel@tonic-gate if (auth_required) 18457c478bd9Sstevel@tonic-gate return 0; /* no addresses authorized */ 18467c478bd9Sstevel@tonic-gate return allow_any_ip || privileged || !have_route_to(addr); 18477c478bd9Sstevel@tonic-gate } 18487c478bd9Sstevel@tonic-gate 18497c478bd9Sstevel@tonic-gate static int 18507c478bd9Sstevel@tonic-gate ip_addr_check(addr, addrs) 18517c478bd9Sstevel@tonic-gate u_int32_t addr; 18527c478bd9Sstevel@tonic-gate struct permitted_ip *addrs; 18537c478bd9Sstevel@tonic-gate { 18547c478bd9Sstevel@tonic-gate /* This loop is safe because of the sentinel value in set_allowed_addrs */ 18557c478bd9Sstevel@tonic-gate for (; ; ++addrs) 18567c478bd9Sstevel@tonic-gate if ((addr & addrs->mask) == addrs->base) 18577c478bd9Sstevel@tonic-gate return addrs->permit; 18587c478bd9Sstevel@tonic-gate } 18597c478bd9Sstevel@tonic-gate 18607c478bd9Sstevel@tonic-gate /* 18617c478bd9Sstevel@tonic-gate * bad_ip_adrs - return 1 if the IP address is one we don't want 18627c478bd9Sstevel@tonic-gate * to use, such as an address in the loopback net or a multicast address. 18637c478bd9Sstevel@tonic-gate * addr is in network byte order. 18647c478bd9Sstevel@tonic-gate */ 18657c478bd9Sstevel@tonic-gate int 18667c478bd9Sstevel@tonic-gate bad_ip_adrs(addr) 18677c478bd9Sstevel@tonic-gate u_int32_t addr; 18687c478bd9Sstevel@tonic-gate { 18697c478bd9Sstevel@tonic-gate addr = ntohl(addr); 18707c478bd9Sstevel@tonic-gate return 18717c478bd9Sstevel@tonic-gate #ifndef ALLOW_127_NET 18727c478bd9Sstevel@tonic-gate (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET || 18737c478bd9Sstevel@tonic-gate #endif 18747c478bd9Sstevel@tonic-gate #ifndef ALLOW_0_NET 18757c478bd9Sstevel@tonic-gate ((addr >> IN_CLASSA_NSHIFT) == 0 && addr != 0) || 18767c478bd9Sstevel@tonic-gate #endif 18772a9459bdSsangeeta IN_MULTICAST(addr); 18787c478bd9Sstevel@tonic-gate } 18797c478bd9Sstevel@tonic-gate 18807c478bd9Sstevel@tonic-gate /* 18817c478bd9Sstevel@tonic-gate * some_ip_ok - check a wordlist to see if it authorizes any 18827c478bd9Sstevel@tonic-gate * IP address(es). 18837c478bd9Sstevel@tonic-gate */ 18847c478bd9Sstevel@tonic-gate static int 18857c478bd9Sstevel@tonic-gate some_ip_ok(addrs) 18867c478bd9Sstevel@tonic-gate struct wordlist *addrs; 18877c478bd9Sstevel@tonic-gate { 18887c478bd9Sstevel@tonic-gate for (; addrs != NULL; addrs = addrs->next) { 18897c478bd9Sstevel@tonic-gate if (addrs->word[0] == '-') 18907c478bd9Sstevel@tonic-gate break; 18917c478bd9Sstevel@tonic-gate if (addrs->word[0] != '!') 18927c478bd9Sstevel@tonic-gate return 1; /* some IP address is allowed */ 18937c478bd9Sstevel@tonic-gate } 18947c478bd9Sstevel@tonic-gate return 0; 18957c478bd9Sstevel@tonic-gate } 18967c478bd9Sstevel@tonic-gate 18977c478bd9Sstevel@tonic-gate /* 18987c478bd9Sstevel@tonic-gate * check_access - complain if a secret file has too-liberal permissions. 18997c478bd9Sstevel@tonic-gate */ 19007c478bd9Sstevel@tonic-gate static void 19017c478bd9Sstevel@tonic-gate check_access(f, filename) 19027c478bd9Sstevel@tonic-gate FILE *f; 19037c478bd9Sstevel@tonic-gate char *filename; 19047c478bd9Sstevel@tonic-gate { 19057c478bd9Sstevel@tonic-gate struct stat sbuf; 19067c478bd9Sstevel@tonic-gate 19077c478bd9Sstevel@tonic-gate if (fstat(fileno(f), &sbuf) < 0) { 19087c478bd9Sstevel@tonic-gate warn("cannot stat secret file %s: %m", filename); 19097c478bd9Sstevel@tonic-gate } else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) { 19107c478bd9Sstevel@tonic-gate warn("Warning - secret file %s has world and/or group access", 19117c478bd9Sstevel@tonic-gate filename); 19127c478bd9Sstevel@tonic-gate } 19137c478bd9Sstevel@tonic-gate } 19147c478bd9Sstevel@tonic-gate 19157c478bd9Sstevel@tonic-gate 19167c478bd9Sstevel@tonic-gate /* 19177c478bd9Sstevel@tonic-gate * scan_authfile - Scan an authorization file for a secret suitable 19187c478bd9Sstevel@tonic-gate * for authenticating `client' on `server'. The return value is -1 if 19197c478bd9Sstevel@tonic-gate * no secret is found, otherwise >= 0. The return value has 19207c478bd9Sstevel@tonic-gate * NONWILD_CLIENT set if the secret didn't have "*" for the client, 19217c478bd9Sstevel@tonic-gate * and NONWILD_SERVER set if the secret didn't have "*" for the 19227c478bd9Sstevel@tonic-gate * server. 19237c478bd9Sstevel@tonic-gate 19247c478bd9Sstevel@tonic-gate * Any following words on the line up to a "--" (i.e. address 19257c478bd9Sstevel@tonic-gate * authorization info) are placed in a wordlist and returned in 19267c478bd9Sstevel@tonic-gate * *addrs. Any following words (extra options) are placed in a 19277c478bd9Sstevel@tonic-gate * wordlist and returned in *opts. If opts is NULL, these are just 19287c478bd9Sstevel@tonic-gate * discarded. Otherwise, the extra_opt_* variables are set to 19297c478bd9Sstevel@tonic-gate * indicate the source of the options. 19307c478bd9Sstevel@tonic-gate * 19317c478bd9Sstevel@tonic-gate * We assume secret is NULL or points to MAXWORDLEN bytes of space. 19327c478bd9Sstevel@tonic-gate */ 19337c478bd9Sstevel@tonic-gate static int 19347c478bd9Sstevel@tonic-gate scan_authfile(f, client, server, secret, addrs, opts, filename) 19357c478bd9Sstevel@tonic-gate FILE *f; 19367c478bd9Sstevel@tonic-gate char *client; 19377c478bd9Sstevel@tonic-gate char *server; 19387c478bd9Sstevel@tonic-gate char *secret; 19397c478bd9Sstevel@tonic-gate struct wordlist **addrs; 19407c478bd9Sstevel@tonic-gate struct wordlist **opts; 19417c478bd9Sstevel@tonic-gate char *filename; 19427c478bd9Sstevel@tonic-gate { 19437c478bd9Sstevel@tonic-gate int newline, xxx, sline; 19447c478bd9Sstevel@tonic-gate int got_flag, best_flag; 19457c478bd9Sstevel@tonic-gate FILE *sf; 19467c478bd9Sstevel@tonic-gate struct wordlist *ap, *addr_list, *alist, **app; 19477c478bd9Sstevel@tonic-gate char word[MAXWORDLEN]; 19487c478bd9Sstevel@tonic-gate char atfile[MAXWORDLEN]; 19497c478bd9Sstevel@tonic-gate char lsecret[MAXWORDLEN]; 19507c478bd9Sstevel@tonic-gate 19517c478bd9Sstevel@tonic-gate scan_server_match_failed[0] = '\0'; 19527c478bd9Sstevel@tonic-gate 19537c478bd9Sstevel@tonic-gate if (addrs != NULL) 19547c478bd9Sstevel@tonic-gate *addrs = NULL; 19557c478bd9Sstevel@tonic-gate if (opts != NULL) 19567c478bd9Sstevel@tonic-gate *opts = NULL; 19577c478bd9Sstevel@tonic-gate addr_list = NULL; 19587c478bd9Sstevel@tonic-gate option_line = 0; 19597c478bd9Sstevel@tonic-gate if (!getword(f, word, &newline, filename)) { 19607c478bd9Sstevel@tonic-gate if (debug) 19617c478bd9Sstevel@tonic-gate dbglog("%s is apparently empty", filename); 19627c478bd9Sstevel@tonic-gate return -1; /* file is empty??? */ 19637c478bd9Sstevel@tonic-gate } 19647c478bd9Sstevel@tonic-gate newline = 1; 19657c478bd9Sstevel@tonic-gate best_flag = -1; 19667c478bd9Sstevel@tonic-gate for (;;) { 19677c478bd9Sstevel@tonic-gate /* 19687c478bd9Sstevel@tonic-gate * Skip until we find a word at the start of a line. 19697c478bd9Sstevel@tonic-gate */ 19707c478bd9Sstevel@tonic-gate while (!newline && getword(f, word, &newline, filename)) 19717c478bd9Sstevel@tonic-gate ; 19727c478bd9Sstevel@tonic-gate if (!newline) 19737c478bd9Sstevel@tonic-gate break; /* got to end of file */ 19747c478bd9Sstevel@tonic-gate 19757c478bd9Sstevel@tonic-gate sline = option_line; 19767c478bd9Sstevel@tonic-gate /* 19777c478bd9Sstevel@tonic-gate * Got a client - check if it's a match or a wildcard. 19787c478bd9Sstevel@tonic-gate */ 19797c478bd9Sstevel@tonic-gate got_flag = 0; 19807c478bd9Sstevel@tonic-gate if (client != NULL && strcmp(word, client) != 0 && !ISWILD(word)) { 19817c478bd9Sstevel@tonic-gate newline = 0; 19827c478bd9Sstevel@tonic-gate continue; 19837c478bd9Sstevel@tonic-gate } 19847c478bd9Sstevel@tonic-gate if (!ISWILD(word)) 19857c478bd9Sstevel@tonic-gate got_flag = NONWILD_CLIENT; 19867c478bd9Sstevel@tonic-gate 19877c478bd9Sstevel@tonic-gate /* 19887c478bd9Sstevel@tonic-gate * Now get a server and check if it matches. 19897c478bd9Sstevel@tonic-gate */ 19907c478bd9Sstevel@tonic-gate if (!getword(f, word, &newline, filename)) 19917c478bd9Sstevel@tonic-gate break; 19927c478bd9Sstevel@tonic-gate if (newline) 19937c478bd9Sstevel@tonic-gate continue; 19947c478bd9Sstevel@tonic-gate if (!ISWILD(word)) { 19957c478bd9Sstevel@tonic-gate if (server != NULL && strcmp(word, server) != 0) { 19967c478bd9Sstevel@tonic-gate (void) strcpy(scan_server_match_failed, word); 19977c478bd9Sstevel@tonic-gate continue; 19987c478bd9Sstevel@tonic-gate } 19997c478bd9Sstevel@tonic-gate got_flag |= NONWILD_SERVER; 20007c478bd9Sstevel@tonic-gate } 20017c478bd9Sstevel@tonic-gate 20027c478bd9Sstevel@tonic-gate /* 20037c478bd9Sstevel@tonic-gate * Got some sort of a match - see if it's better than what 20047c478bd9Sstevel@tonic-gate * we have already. 20057c478bd9Sstevel@tonic-gate */ 20067c478bd9Sstevel@tonic-gate if (got_flag <= best_flag) 20077c478bd9Sstevel@tonic-gate continue; 20087c478bd9Sstevel@tonic-gate 20097c478bd9Sstevel@tonic-gate /* 20107c478bd9Sstevel@tonic-gate * Get the secret. 20117c478bd9Sstevel@tonic-gate */ 20127c478bd9Sstevel@tonic-gate if (!getword(f, word, &newline, filename)) 20137c478bd9Sstevel@tonic-gate break; 20147c478bd9Sstevel@tonic-gate if (newline) 20157c478bd9Sstevel@tonic-gate continue; 20167c478bd9Sstevel@tonic-gate 20177c478bd9Sstevel@tonic-gate /* 20187c478bd9Sstevel@tonic-gate * Special syntax: @filename means read secret from file. 20197c478bd9Sstevel@tonic-gate * Because the secrets files are modifiable only by root, 20207c478bd9Sstevel@tonic-gate * it's safe to open this file as root. One small addition -- 20217c478bd9Sstevel@tonic-gate * if open fails, we try as the regular user; just in case 20227c478bd9Sstevel@tonic-gate * it's over NFS and not root-equivalent. 20237c478bd9Sstevel@tonic-gate */ 20247c478bd9Sstevel@tonic-gate if (word[0] == '@') { 20257c478bd9Sstevel@tonic-gate (void) strlcpy(atfile, word+1, sizeof(atfile)); 20267c478bd9Sstevel@tonic-gate if ((sf = fopen(atfile, "r")) == NULL) { 20277c478bd9Sstevel@tonic-gate (void) seteuid(getuid()); 20287c478bd9Sstevel@tonic-gate sf = fopen(atfile, "r"); 20297c478bd9Sstevel@tonic-gate (void) seteuid(0); 20307c478bd9Sstevel@tonic-gate } 20317c478bd9Sstevel@tonic-gate if (sf == NULL) { 20327c478bd9Sstevel@tonic-gate warn("can't open indirect secret file %s: %m", atfile); 20337c478bd9Sstevel@tonic-gate continue; 20347c478bd9Sstevel@tonic-gate } 20357c478bd9Sstevel@tonic-gate check_access(sf, atfile); 20367c478bd9Sstevel@tonic-gate if (!getword(sf, word, &xxx, atfile)) { 20377c478bd9Sstevel@tonic-gate warn("no secret in indirect secret file %s", atfile); 20387c478bd9Sstevel@tonic-gate (void) fclose(sf); 20397c478bd9Sstevel@tonic-gate continue; 20407c478bd9Sstevel@tonic-gate } 20417c478bd9Sstevel@tonic-gate (void) fclose(sf); 20427c478bd9Sstevel@tonic-gate } 20437c478bd9Sstevel@tonic-gate if (secret != NULL) 20447c478bd9Sstevel@tonic-gate (void) strlcpy(lsecret, word, sizeof(lsecret)); 20457c478bd9Sstevel@tonic-gate 20467c478bd9Sstevel@tonic-gate /* 20477c478bd9Sstevel@tonic-gate * Now read address authorization info and make a wordlist. 20487c478bd9Sstevel@tonic-gate */ 20497c478bd9Sstevel@tonic-gate app = &alist; 20507c478bd9Sstevel@tonic-gate for (;;) { 20517c478bd9Sstevel@tonic-gate if (!getword(f, word, &newline, filename) || newline) 20527c478bd9Sstevel@tonic-gate break; 20537c478bd9Sstevel@tonic-gate ap = (struct wordlist *) malloc(sizeof(struct wordlist)); 20547c478bd9Sstevel@tonic-gate if (ap == NULL) 20557c478bd9Sstevel@tonic-gate novm("authorized addresses"); 20567c478bd9Sstevel@tonic-gate ap->word = strdup(word); 20577c478bd9Sstevel@tonic-gate if (ap->word == NULL) 20587c478bd9Sstevel@tonic-gate novm("authorized addresses"); 20597c478bd9Sstevel@tonic-gate *app = ap; 20607c478bd9Sstevel@tonic-gate app = &ap->next; 20617c478bd9Sstevel@tonic-gate } 20627c478bd9Sstevel@tonic-gate *app = NULL; 20637c478bd9Sstevel@tonic-gate 20647c478bd9Sstevel@tonic-gate /* 20657c478bd9Sstevel@tonic-gate * This is the best so far; remember it. 20667c478bd9Sstevel@tonic-gate */ 20677c478bd9Sstevel@tonic-gate best_flag = got_flag; 20687c478bd9Sstevel@tonic-gate if (addr_list != NULL) 20697c478bd9Sstevel@tonic-gate free_wordlist(addr_list); 20707c478bd9Sstevel@tonic-gate addr_list = alist; 20717c478bd9Sstevel@tonic-gate if (secret != NULL) 20727c478bd9Sstevel@tonic-gate (void) strlcpy(secret, lsecret, MAXWORDLEN); 20737c478bd9Sstevel@tonic-gate 20747c478bd9Sstevel@tonic-gate if (opts != NULL) { 20757c478bd9Sstevel@tonic-gate extra_opt_filename = filename; 20767c478bd9Sstevel@tonic-gate extra_opt_line = sline; 20777c478bd9Sstevel@tonic-gate } 20787c478bd9Sstevel@tonic-gate 20797c478bd9Sstevel@tonic-gate if (!newline) 20807c478bd9Sstevel@tonic-gate break; 20817c478bd9Sstevel@tonic-gate } 20827c478bd9Sstevel@tonic-gate 20837c478bd9Sstevel@tonic-gate /* scan for a -- word indicating the start of options */ 20847c478bd9Sstevel@tonic-gate for (app = &addr_list; (ap = *app) != NULL; app = &ap->next) 20857c478bd9Sstevel@tonic-gate if (strcmp(ap->word, "--") == 0) 20867c478bd9Sstevel@tonic-gate break; 20877c478bd9Sstevel@tonic-gate /* ap = start of options */ 20887c478bd9Sstevel@tonic-gate if (ap != NULL) { 20897c478bd9Sstevel@tonic-gate ap = ap->next; /* first option */ 20907c478bd9Sstevel@tonic-gate free(*app); /* free the "--" word */ 20917c478bd9Sstevel@tonic-gate *app = NULL; /* terminate addr list */ 20927c478bd9Sstevel@tonic-gate } 20937c478bd9Sstevel@tonic-gate if (opts != NULL) 20947c478bd9Sstevel@tonic-gate *opts = ap; 20957c478bd9Sstevel@tonic-gate else if (ap != NULL) 20967c478bd9Sstevel@tonic-gate free_wordlist(ap); 20977c478bd9Sstevel@tonic-gate if (addrs != NULL) 20987c478bd9Sstevel@tonic-gate *addrs = addr_list; 20997c478bd9Sstevel@tonic-gate else if (addr_list != NULL) 21007c478bd9Sstevel@tonic-gate free_wordlist(addr_list); 21017c478bd9Sstevel@tonic-gate 21027c478bd9Sstevel@tonic-gate return best_flag; 21037c478bd9Sstevel@tonic-gate } 21047c478bd9Sstevel@tonic-gate 21057c478bd9Sstevel@tonic-gate /* 21067c478bd9Sstevel@tonic-gate * free_wordlist - release memory allocated for a wordlist. 21077c478bd9Sstevel@tonic-gate */ 21087c478bd9Sstevel@tonic-gate static void 21097c478bd9Sstevel@tonic-gate free_wordlist(wp) 21107c478bd9Sstevel@tonic-gate struct wordlist *wp; 21117c478bd9Sstevel@tonic-gate { 21127c478bd9Sstevel@tonic-gate struct wordlist *next; 21137c478bd9Sstevel@tonic-gate 21147c478bd9Sstevel@tonic-gate while (wp != NULL) { 21157c478bd9Sstevel@tonic-gate next = wp->next; 21167c478bd9Sstevel@tonic-gate free(wp); 21177c478bd9Sstevel@tonic-gate wp = next; 21187c478bd9Sstevel@tonic-gate } 21197c478bd9Sstevel@tonic-gate } 21207c478bd9Sstevel@tonic-gate 21217c478bd9Sstevel@tonic-gate /* 21227c478bd9Sstevel@tonic-gate * auth_script_done - called when the auth-up or auth-down script 21237c478bd9Sstevel@tonic-gate * has finished. 21247c478bd9Sstevel@tonic-gate */ 21257c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 21267c478bd9Sstevel@tonic-gate static void 21277c478bd9Sstevel@tonic-gate auth_script_done(arg, status) 21287c478bd9Sstevel@tonic-gate void *arg; 21297c478bd9Sstevel@tonic-gate int status; 21307c478bd9Sstevel@tonic-gate { 21317c478bd9Sstevel@tonic-gate auth_script_pid = 0; 21327c478bd9Sstevel@tonic-gate switch (auth_script_state) { 21337c478bd9Sstevel@tonic-gate case s_up: 21347c478bd9Sstevel@tonic-gate if (auth_state == s_down) { 21357c478bd9Sstevel@tonic-gate auth_script_state = s_down; 21367c478bd9Sstevel@tonic-gate auth_script(_PATH_AUTHDOWN); 21377c478bd9Sstevel@tonic-gate } 21387c478bd9Sstevel@tonic-gate break; 21397c478bd9Sstevel@tonic-gate case s_down: 21407c478bd9Sstevel@tonic-gate if (auth_state == s_up) { 21417c478bd9Sstevel@tonic-gate auth_script_state = s_up; 21427c478bd9Sstevel@tonic-gate auth_script(_PATH_AUTHUP); 21437c478bd9Sstevel@tonic-gate } 21447c478bd9Sstevel@tonic-gate break; 21457c478bd9Sstevel@tonic-gate } 21467c478bd9Sstevel@tonic-gate } 21477c478bd9Sstevel@tonic-gate 21487c478bd9Sstevel@tonic-gate /* 21497c478bd9Sstevel@tonic-gate * auth_script - execute a script with arguments 21507c478bd9Sstevel@tonic-gate * interface-name peer-name real-user tty speed 21517c478bd9Sstevel@tonic-gate */ 21527c478bd9Sstevel@tonic-gate static void 21537c478bd9Sstevel@tonic-gate auth_script(script) 21547c478bd9Sstevel@tonic-gate char *script; 21557c478bd9Sstevel@tonic-gate { 21567c478bd9Sstevel@tonic-gate char strspeed[32]; 21577c478bd9Sstevel@tonic-gate struct passwd *pw; 21587c478bd9Sstevel@tonic-gate char struid[32]; 21597c478bd9Sstevel@tonic-gate char *user_name; 21607c478bd9Sstevel@tonic-gate char *argv[8]; 21617c478bd9Sstevel@tonic-gate 21627c478bd9Sstevel@tonic-gate if ((pw = getpwuid(getuid())) != NULL && pw->pw_name != NULL) 21637c478bd9Sstevel@tonic-gate user_name = pw->pw_name; 21647c478bd9Sstevel@tonic-gate else { 21657c478bd9Sstevel@tonic-gate (void) slprintf(struid, sizeof(struid), "%d", getuid()); 21667c478bd9Sstevel@tonic-gate user_name = struid; 21677c478bd9Sstevel@tonic-gate } 21687c478bd9Sstevel@tonic-gate (void) slprintf(strspeed, sizeof(strspeed), "%d", baud_rate); 21697c478bd9Sstevel@tonic-gate 21707c478bd9Sstevel@tonic-gate argv[0] = script; 21717c478bd9Sstevel@tonic-gate argv[1] = ifname; 21727c478bd9Sstevel@tonic-gate argv[2] = peer_authname; 21737c478bd9Sstevel@tonic-gate argv[3] = user_name; 21747c478bd9Sstevel@tonic-gate argv[4] = devnam; 21757c478bd9Sstevel@tonic-gate argv[5] = strspeed; 21767c478bd9Sstevel@tonic-gate argv[6] = NULL; 21777c478bd9Sstevel@tonic-gate 21787c478bd9Sstevel@tonic-gate auth_script_pid = run_program(script, argv, 0, auth_script_done, NULL); 21797c478bd9Sstevel@tonic-gate } 2180