/*
* auth.c - PPP authentication and phase control.
*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Copyright (c) 1993 The Australian National University.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the Australian National University. The name of the University
* may not be used to endorse or promote products derived from this
* software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* Copyright (c) 1989 Carnegie Mellon University.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by Carnegie Mellon University. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/* Pull in crypt() definition. */
#define __EXTENSIONS__
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <string.h>
#include <utmp.h>
#include <fcntl.h>
#include <lastlog.h>
#endif
#include <crypt.h>
#endif
#include <netdb.h>
/* Backward compatibility with old Makefiles */
#define ALLOW_PAM
#endif
#ifdef ALLOW_PAM
#include <security/pam_appl.h>
#endif
#ifdef HAS_SHADOW
#include <shadow.h>
#ifndef PW_PPP
#endif
#endif
#include "pppd.h"
#include "fsm.h"
#include "lcp.h"
#include "ipcp.h"
#include "upap.h"
#include "chap.h"
#ifdef CBCP_SUPPORT
#include "cbcp.h"
#endif
#include "pathnames.h"
#endif
/* Bits in scan_authfile return value */
/* The name by which the peer authenticated itself to us. */
/* Records which authentication operations haven't completed yet. */
/* Set if we have successfully called plogin() */
static int logged_in;
/* List of addresses which the peer may use. */
/* Wordlist giving addresses which the peer may use
without authenticating itself. */
/* Extra options to apply, from the secrets file entry for the peer. */
/* Source of those extra options. */
static const char *extra_opt_filename;
static int extra_opt_line;
/* Number of network protocols which we have opened. */
static int num_np_open;
/* Number of network protocols which have come up. */
static int num_np_up;
/* Set if we got the contents of passwd[] from the pap-secrets file. */
static int passwd_from_file;
/* Set if we require authentication only because we have a default route. */
static bool default_auth;
/* Hook to enable a plugin to control the idle time limit */
/* Hook for a plugin to say whether we can possibly authenticate any peer */
/* Hook for a plugin to check the PAP user and password */
/* Hook for a plugin to know about the PAP user logout */
/* Hook for a plugin to get the PAP password for authenticating us */
/*
* script while one is already running.
*/
enum script_state {
};
/*
* This is set by scan_authfile if a client matches, but server doesn't
* (possible configuration error).
*/
/*
* Option variables.
*/
#ifdef CHAPMS
#else
#endif
#ifdef CHAPMSV2
#else
#endif
#ifdef USE_PAM
#else
#endif
/* Bits in auth_pending[] */
/* Prototypes for procedures local to this file. */
static void network_phase __P((int));
static void check_idle __P((void *));
static void connect_time_expired __P((void *));
static int null_login __P((int));
static int get_pap_passwd __P((char *));
static int have_pap_secret __P((int *));
static int have_chap_secret __P((char *, char *, int, int *));
char *));
static void auth_script __P((char *));
static void auth_script_done __P((void *, int));
/*
* Authentication-related options.
*/
"Don't agree to auth to peer with PAP", 1 },
"Don't allow PAP authentication with peer", 1 },
"Don't agree to auth to peer with CHAP", 1 },
"Don't allow CHAP authentication with peer", 1 },
"Set local name for authentication",
"Must use hostname for authentication", 1 },
"Set remote name for authentication", OPT_STATIC,
"Require authentication from peer", 1 },
"Use system password database for PAP", 1 },
"PAP passwords are encrypted", 1 },
"Get PAP user and password from file" },
"Password for authenticating us to the peer", OPT_STATIC,
NULL, MAXSECRETLEN },
"Allow group members to use privileged options", OPT_PRIV },
"Set peer IP address(es) usable without authentication",
OPT_PRIV },
#ifdef CHAPMS
"Don't agree to authenticate to peer with MS-CHAPv1", 1 },
#endif
#ifdef CHAPMSV2
"Don't agree to authenticate to peer with MS-CHAPv2", 1 },
#endif
#ifdef ALLOW_PAM
"Disable use of Pluggable Authentication Modules", OPT_PRIV|0 },
#endif
{ NULL }
};
/*
* setupapfile - specifies UPAP info for authenticating with peer.
*/
/*ARGSUSED*/
static int
char **argv;
{
int l;
/* open user info file */
(void) seteuid(0);
return 0;
}
/* get username */
return 0;
}
/* get rid of newlines */
return (1);
}
/*
* privgroup - allow members of the group to have privileged access.
*/
/*ARGSUSED*/
static int
char **argv;
{
struct group *g;
int i;
if (g == NULL) {
return 0;
}
for (i = 0; i < ngroups; ++i) {
privileged = 1;
break;
}
}
return 1;
}
/*
* set_noauth_addr - set address(es) that can be used without authentication.
* Equivalent to specifying an entry like `"" * "" addr' in pap-secrets.
*/
/*ARGSUSED*/
static int
char **argv;
{
novm("allow-ip argument");
noauth_addrs = wp;
return 1;
}
/*
* An Open on LCP has requested a change from Dead to Establish phase.
* Do what's necessary to bring the physical layer up.
*/
/*ARGSUSED*/
void
int unit;
{
}
/*
* LCP has terminated the link; go to the Dead phase and take the
* physical layer down.
*/
/*ARGSUSED*/
void
int unit;
{
if (phase == PHASE_DEAD)
return;
if (pap_logout_hook != NULL) {
(*pap_logout_hook)();
} else {
if (logged_in)
plogout();
}
if (peer_nak_auth) {
pn1 = "?";
pn2 = "?";
warn("Peer sent Configure-Nak for 0x%x (%s) to suggest 0x%x (%s)",
}
if (unsolicited_nak_auth) {
pn1 = "?";
warn("Peer unexpectedly asked us to authenticate with 0x%x (%s)",
}
if (peer_reject_auth) {
pn1 = "?";
warn("Peer rejected our demand for 0x%x (%s)",
}
if (naked_peers_auth) {
pn1 = "?";
pn2 = "?";
warn("We set Configure-Nak for 0x%x (%s) to suggest 0x%x (%s)",
}
if (rejected_peers_auth) {
pn1 = "?";
warn("We rejected the peer's demand for 0x%x (%s)",
}
notice("Connection terminated.");
}
/*
* LCP has gone down; it will either die or try to re-establish.
*/
void
int unit;
{
int i;
auth_state = s_down;
}
if (!protp->enabled_flag)
continue;
}
num_np_open = 0;
num_np_up = 0;
if (phase != PHASE_DEAD)
}
/*
* The link is established.
* Proceed to the Dead, Authenticate or Network phase as appropriate.
*/
void
int unit;
{
int auth;
int i;
/*
* Tell higher-level protocols that LCP is up.
*/
/*
* We wanted the peer to authenticate itself, and it refused:
* if we have some address(es) it can use without auth, fine,
* otherwise treat it as though it authenticated with PAP using
* a username * of "" and a password of "". If that's not OK,
* boot it out.
*/
if (noauth_addrs != NULL) {
warn("peer refused to authenticate: terminating link");
return;
}
}
auth = 0;
if (debug)
dbglog("Authenticating peer with standard CHAP");
} else if (go->neg_mschap) {
if (debug)
dbglog("Authenticating peer with MS-CHAPv1");
} else {
if (debug)
dbglog("Authenticating peer with MS-CHAPv2");
}
if (debug)
dbglog("Authenticating peer with PAP");
}
switch (ho->chap_mdtype) {
case CHAP_DIGEST_MD5:
if (debug)
dbglog("Authenticating to peer with standard CHAP");
break;
case CHAP_MICROSOFT:
if (debug)
dbglog("Authenticating to peer with MS-CHAPv1");
break;
case CHAP_MICROSOFT_V2:
if (debug)
dbglog("Authenticating to peer with MS-CHAPv2");
break;
default:
if (debug)
break;
}
auth |= CHAP_WITHPEER;
if (passwd[0] == '\0') {
passwd_from_file = 1;
if (!get_pap_passwd(passwd))
error("No secret found for PAP login");
}
if (debug)
dbglog("Authenticating to peer with PAP");
auth |= PAP_WITHPEER;
}
if (!auth)
}
/*
* Proceed to the network phase.
*/
static void
int unit;
{
/*
* If the peer had to authenticate, run the auth-up script now.
*/
auth_state = s_up;
}
}
/*
* Process extra options from the secrets file
*/
if (extra_options != NULL) {
option_source = (char *)extra_opt_filename;
}
#ifdef CBCP_SUPPORT
/*
* If we negotiated callback, do it now.
*/
return;
}
#endif
}
void
{
int i;
#ifdef HAVE_MULTILINK
if (multilink) {
if (mp_join_bundle()) {
detach();
return;
}
}
#endif /* HAVE_MULTILINK */
#if 0
if (!demand)
#endif
++num_np_open;
}
if (num_np_open == 0)
/* nothing to do */
lcp_close(0, "No network protocols running");
}
/*
* The peer has failed to authenticate himself using `protocol'.
*/
/*ARGSUSED*/
void
{
/*
* Authentication failure: take the link down
*/
}
/*
* The peer has been successfully authenticated using `protocol'.
*/
void
char *name;
int namelen;
{
int bit;
switch (protocol) {
case PPP_CHAP:
break;
case PPP_PAP:
break;
default:
return;
}
/*
* Save the authenticated name of the peer for later.
*/
/*
* If there is no more authentication still to be done,
* proceed to the network (or callback) phase.
*/
}
/*
* We have failed to authenticate ourselves to the peer using `protocol'.
*/
/*ARGSUSED*/
void
{
if (passwd_from_file)
/*
* We've failed to authenticate ourselves to our peer.
* Some servers keep sending CHAP challenges, but there
* is no point in persisting without any way to get updated
* authentication secrets.
*/
}
/*
* We have successfully authenticated ourselves with the peer using `protocol'.
*/
void
{
int bit;
switch (protocol) {
case PPP_CHAP:
bit = CHAP_WITHPEER;
break;
case PPP_PAP:
if (passwd_from_file)
bit = PAP_WITHPEER;
break;
default:
bit = 0;
}
/*
* If there is no more authentication still being done,
* proceed to the network (or callback) phase.
*/
}
/*
* np_up - a network protocol has come up.
*/
/*ARGSUSED*/
void
{
int tlim;
if (num_np_up == 0) {
/*
* At this point we consider that the link has come up successfully.
*/
unsuccess = 0;
naked_auth_proto = 0;
if (idle_time_hook != NULL)
else
if (tlim > 0)
/*
* Set a timeout to close the connection once the maximum
* connect time has expired.
*/
if (maxconnect > 0) {
/*
* Tell LCP to send Time-Remaining packets. One should be
* sent out now, at maxconnect-300, at maxconnect-120, and
* again at maxconnect-30.
*/
if (maxconnect > 300)
if (maxconnect > 120)
if (maxconnect > 30)
}
/*
* Detach now, if the updetach option was given.
*/
detach();
}
++num_np_up;
}
/*
* np_down - a network protocol has gone down.
*/
/*ARGSUSED*/
void
{
if (--num_np_up == 0) {
}
}
/*
* np_finished - a network protocol has finished using the link.
*/
/*ARGSUSED*/
void
{
if (--num_np_open <= 0) {
/* no further use for the link: shut up shop. */
lcp_close(0, "No network protocols running");
}
}
/*
* check_idle - check whether the link has been idle for long
* enough that we can shut it down.
*/
/*ARGSUSED*/
static void
void *arg;
{
int tlim;
if (!get_idle_time(0, &idle))
return;
if (idle_time_hook != NULL) {
} else {
}
if (tlim <= 0) {
/* link is idle: shut it down. */
notice("Terminating connection due to lack of activity.");
lcp_close(0, "Link inactive");
need_holdoff = 0;
} else {
}
}
/*
* connect_time_expired - log a message and close the connection.
*/
/*ARGSUSED*/
static void
void *arg;
{
info("Connect time expired");
}
/*
* auth_check_options - called to check authentication options.
*/
void
{
int can_auth;
int lacks_ip;
/* Default our_name to hostname, and user to our_name */
if (user[0] == '\0')
/*
* If we have a default route, require the peer to authenticate
* unless the noauth option was given or the real user is root.
*/
auth_required = 1;
default_auth = 1;
}
/* If authentication is required, ask peer for CHAP or PAP. */
if (auth_required) {
#ifdef CHAPMS
#endif
#ifdef CHAPMSV2
#endif
}
} else {
wo->neg_mschap = 0;
wo->neg_mschapv2 = 0;
}
/*
* Check whether we have appropriate secrets to use
* to authenticate the peer.
*/
lacks_ip = 0;
}
if (default_auth) {
"By default the remote system is required to authenticate itself");
"(because this system has a default route to the Internet)");
} else if (explicit_remote)
"The remote system (%s) is required to authenticate itself",
else
"The remote system is required to authenticate itself");
"but I couldn't find any suitable secret (password) for it to use to do so.");
if (lacks_ip)
"(None of the available passwords would let it use an IP address.)");
exit(1);
}
}
/*
* auth_reset - called when LCP is starting negotiations to recheck
* authentication options, i.e. whether we have appropriate secrets
*/
void
int unit;
{
int havesecret;
else if (ao->neg_mschap)
else
if (!havesecret)
else if (go->neg_mschap)
else
}
}
/*
* check_passwd - Check the user name and passwd against the PAP secrets
* file. If requested, also check against the system password database,
* and login the user if OK.
*
* returns:
* UPAP_AUTHNAK: Authentication failed.
* UPAP_AUTHACK: Authentication succeeded.
* In either case, msg points to an appropriate message.
*/
int
int unit;
char *auser;
int userlen;
char *apasswd;
int passwdlen;
char **msg;
{
int ret;
char *filename;
FILE *f;
static int attempts = 0;
/*
* Make copies of apasswd and auser, then null-terminate them.
* If there are unprintable characters in the password, make
* them visible.
*/
*msg = "";
/*
* Check if a plugin wants to handle this.
*/
if (pap_auth_hook != NULL) {
/* Set a default and allow the plug-in to change it. */
extra_opt_filename = "plugin";
extra_opt_line = 0;
if (ret >= 0) {
if (ret > 0)
}
}
/*
* Open the file of pap secrets and scan for a suitable secret
* for authenticating this user.
*/
ret = UPAP_AUTHNAK;
if (f == NULL) {
} else {
check_access(f, filename);
if (scan_server_match_failed[0] != '\0')
warn("possible configuration error: local name is %q, but "
} else if (secret[0] != '\0') {
/* password given in pap-secrets - must match */
ret = UPAP_AUTHACK;
else
} else if (uselogin) {
/* empty password in pap-secrets and login option */
if (ret == UPAP_AUTHNAK)
} else {
/* empty password in pap-secrets and login option not used */
ret = UPAP_AUTHACK;
}
(void) fclose(f);
}
if (ret == UPAP_AUTHNAK) {
if (**msg == '\0')
*msg = "Login incorrect";
/*
* Frustrate passwd stealer programs.
* Allow 10 tries, but start backing off after 3 (stolen from login).
* On 10'th, drop the connection.
*/
if (attempts++ >= 10) {
}
if (attempts > 3)
} else {
attempts = 0; /* Reset count */
if (**msg == '\0')
*msg = "Login ok";
}
return ret;
}
/*
* This function is needed for PAM.
*/
#ifdef ALLOW_PAM
/* Static variables used to communicate between the conversation function
* and the server_login function
*/
static char *PAM_username;
static char *PAM_password;
static int PAM_error = 0;
/* PAM conversation function
* Here we assume (for now, at least) that echo on means login name, and
* echo off means password.
*/
/*ARGSUSED*/
#ifndef SOL2
const
#endif
{
int replies = 0;
return PAM_CONV_ERR;
case PAM_PROMPT_ECHO_ON:
/* PAM frees resp */
break;
case PAM_PROMPT_ECHO_OFF:
/* PAM frees resp */
break;
case PAM_TEXT_INFO:
/* fall through */
case PAM_ERROR_MSG:
/* ignore it, but pam still wants a NULL response... */
break;
default:
/* Must be an error of some sort... */
PAM_error = 1;
return PAM_CONV_ERR;
}
}
return PAM_SUCCESS;
}
};
#endif /* ALLOW_PAM */
/*
* plogin - Check the user name and password against the system
* password database, and login the user if OK.
*
* returns:
* UPAP_AUTHNAK: Login failed.
* UPAP_AUTHACK: Login succeeded.
* In either case, msg points to an appropriate message.
*/
static int
char *user;
char *passwd;
char **msg;
{
char *tty;
#ifdef HAS_SHADOW
#endif
#ifdef ALLOW_PAM
int pam_error;
if (use_pam) {
if (debug)
dbglog("using PAM for user authentication");
if (pam_error != PAM_SUCCESS) {
reopen_log();
return UPAP_AUTHNAK;
}
/*
* Define the fields for the credential validation
*/
PAM_username = user;
PAM_error = 0;
/* this might be useful to some modules; required for Solaris */
if (*tty == '\0')
tty = ppp_devnam;
#ifdef PAM_RHOST
#endif
/*
* Validate the user
*/
if (pam_error == PAM_SUCCESS)
}
/*
* Clean up the mess
*/
reopen_log(); /* apparently the PAM stuff does closelog() */
PAM_username = NULL;
PAM_password = NULL;
if (pam_error != PAM_SUCCESS)
return UPAP_AUTHNAK;
} else
#endif /* ALLOW_PAM */
{
if (debug) {
#ifdef HAS_SHADOW
#else
dbglog("using passwd for user authentication");
#endif
}
/*
* Use the non-PAM methods directly
*/
endpwent();
return (UPAP_AUTHNAK);
#ifdef HAS_SHADOW
endspent();
/* check the age of the password entry */
return (UPAP_AUTHNAK);
}
}
#endif
/*
* If no passwd, don't let them login.
*/
return (UPAP_AUTHNAK);
}
/*
* Write a wtmp entry for this user.
*/
tty += 5;
#ifdef _PATH_LASTLOG
int fd;
}
}
#endif /* _PATH_LASTLOG */
logged_in = 1;
return (UPAP_AUTHACK);
}
/*
* plogout - Logout the user.
*/
static void
plogout()
{
char *tty;
#ifdef ALLOW_PAM
int pam_error;
if (use_pam) {
}
/* Apparently the pam stuff does closelog(). */
reopen_log();
} else
#endif /* ALLOW_PAM */
{
tty += 5;
/* Wipe out utmp logout entry */
}
logged_in = 0;
}
/*
* null_login - Check if a username of "" and a password of "" are
* acceptable, and iff so, set the list of acceptable IP addresses
* and return 1.
*/
static int
int unit;
{
char *filename;
FILE *f;
int i, ret;
/*
* Open the file of pap secrets and scan for a suitable secret.
*/
if (f == NULL)
return 0;
check_access(f, filename);
if (ret)
(void) fclose(f);
return ret;
}
/*
* get_pap_passwd - get a password for authenticating ourselves with
* our peer using PAP. Returns 1 on success, 0 if no suitable password
* could be found.
* Assumes passwd points to MAXSECRETLEN bytes of space (if non-null).
*/
static int
char *passwd;
{
char *filename;
FILE *f;
int ret;
/*
* Check whether a plugin wants to supply this.
*/
if (pap_passwd_hook != NULL) {
if (ret >= 0)
return ret;
}
if (f == NULL)
return 0;
check_access(f, filename);
(void) fclose(f);
if (ret < 0)
return 0;
return 1;
}
/*
* have_pap_secret - check whether we have a PAP file with any
* secrets that we could possibly use for authenticating the peer.
*/
static int
int *lacks_ipp;
{
FILE *f;
int ret;
char *filename;
/* let the plugin decide, if there is one */
if (pap_check_hook != NULL) {
ret = (*pap_check_hook)();
if (ret >= 0)
return ret;
}
if (f == NULL)
return 0;
(void) fclose(f);
*lacks_ipp = 1;
ret = -1;
}
return ret >= 0;
}
/*
* have_chap_secret - check whether we have a CHAP file with a secret
* that we could possibly use for authenticating `client' on `server'.
* Either or both can be the null string, meaning we don't know the
* identity yet.
*/
static int
char *client;
char *server;
int need_ip;
int *lacks_ipp;
{
FILE *f;
int ret;
char *filename;
if (f == NULL)
return 0;
(void) fclose(f);
*lacks_ipp = 1;
ret = -1;
}
return ret >= 0;
}
/*
* get_secret - open the CHAP secret file and return the secret
* for authenticating the given client on the given server.
*
* "am_server" means that we're the authenticator (demanding
* identity from the peer).
*
* "!am_server" means that we're the authenticatee (supplying
* identity to the peer).
*/
int
int unit;
char *client;
char *server;
char *secret;
int *secret_len;
int am_server;
{
FILE *f;
char *filename;
/*
* Support the 'password' option on authenticatee only in order to
* avoid obvious security problem (authenticator and authenticatee
* within a given implementation must never share secrets).
*/
} else {
secbuf[0] = '\0';
if (f == NULL) {
return 0;
}
check_access(f, filename);
filename);
(void) fclose(f);
if (ret < 0) {
if (scan_server_match_failed[0] != '\0')
warn("possible configuration error: local name is %q, but "
return 0;
}
/* Only the authenticator cares about limiting peer addresses. */
if (am_server)
}
if (len > MAXSECRETLEN) {
len = MAXSECRETLEN;
}
/* Do not leave a temporary copy of the secret on the stack. */
*secret_len = len;
return 1;
}
/*
* set_allowed_addrs() - set the list of allowed addresses.
* The caller must also look for `--' indicating options to apply for
* this peer and leaves the following words in extra_options.
*/
static void
int unit;
{
int n;
int err_num;
if (extra_options != NULL)
/*
* Count the number of IP addresses given.
*/
++n;
if (n == 0)
return;
return;
n = 0;
/* "-" means no addresses authorized, "*" means any address allowed */
break;
++n;
break;
}
if (*ptr_word == '!') {
++ptr_word;
}
offset = 0;
int bit_count;
char *endp;
warn("invalid address length %v in authorized address list",
ptr_mask+1);
continue;
}
if (*endp == '+') {
++endp;
}
if (*endp != '\0') {
continue;
}
*ptr_mask = '\0';
}
/* Try to interpret value as host name or numeric address first */
} else {
cp--;
if (*cp == '+') {
*cp = '\0';
}
if ((ah & 0xff000000ul) == 0)
if ((ah & 0xff000000ul) == 0)
if ((ah & 0xff000000ul) == 0)
}
}
*ptr_mask = '/';
if (a == (u_int32_t)-1L) {
continue;
}
if (offset != 0) {
warn("interface unit %d too large for subnet %v",
continue;
}
}
++n;
if (~mask == 0 && suggested_ip == 0)
suggested_ip = a;
}
/* Sentinel value at end of list */
/*
* If the address given for the peer isn't authorized, or if
* the user hasn't given one, AND there is an authorized address
* which is a single host, then use that if we find one.
*/
if (suggested_ip != 0
}
/*
* auth_ip_addr - check whether the peer is authorized to use
* a given IP address. Returns 1 if authorized, 0 otherwise.
*/
int
int unit;
{
int ok;
/* don't allow loopback or multicast address */
if (bad_ip_adrs(addr))
return 0;
if (ok >= 0)
return ok;
}
if (auth_required)
return 0; /* no addresses authorized */
}
static int
struct permitted_ip *addrs;
{
/* This loop is safe because of the sentinel value in set_allowed_addrs */
for (; ; ++addrs)
}
/*
* bad_ip_adrs - return 1 if the IP address is one we don't want
* to use, such as an address in the loopback net or a multicast address.
* addr is in network byte order.
*/
int
{
return
#ifndef ALLOW_127_NET
#endif
#ifndef ALLOW_0_NET
#endif
}
/*
* some_ip_ok - check a wordlist to see if it authorizes any
* IP address(es).
*/
static int
{
break;
return 1; /* some IP address is allowed */
}
return 0;
}
/*
* check_access - complain if a secret file has too-liberal permissions.
*/
static void
FILE *f;
char *filename;
{
filename);
}
}
/*
* scan_authfile - Scan an authorization file for a secret suitable
* for authenticating `client' on `server'. The return value is -1 if
* no secret is found, otherwise >= 0. The return value has
* NONWILD_CLIENT set if the secret didn't have "*" for the client,
* and NONWILD_SERVER set if the secret didn't have "*" for the
* server.
* Any following words on the line up to a "--" (i.e. address
* authorization info) are placed in a wordlist and returned in
* *addrs. Any following words (extra options) are placed in a
* wordlist and returned in *opts. If opts is NULL, these are just
* discarded. Otherwise, the extra_opt_* variables are set to
* indicate the source of the options.
*
* We assume secret is NULL or points to MAXWORDLEN bytes of space.
*/
static int
FILE *f;
char *client;
char *server;
char *secret;
char *filename;
{
scan_server_match_failed[0] = '\0';
option_line = 0;
if (debug)
return -1; /* file is empty??? */
}
newline = 1;
best_flag = -1;
for (;;) {
/*
* Skip until we find a word at the start of a line.
*/
;
if (!newline)
break; /* got to end of file */
sline = option_line;
/*
* Got a client - check if it's a match or a wildcard.
*/
got_flag = 0;
newline = 0;
continue;
}
/*
* Now get a server and check if it matches.
*/
break;
if (newline)
continue;
continue;
}
}
/*
* Got some sort of a match - see if it's better than what
* we have already.
*/
continue;
/*
* Get the secret.
*/
break;
if (newline)
continue;
/*
* Special syntax: @filename means read secret from file.
* Because the secrets files are modifiable only by root,
* it's safe to open this file as root. One small addition --
* if open fails, we try as the regular user; just in case
* it's over NFS and not root-equivalent.
*/
if (word[0] == '@') {
(void) seteuid(0);
}
continue;
}
continue;
}
}
/*
* Now read address authorization info and make a wordlist.
*/
for (;;) {
break;
novm("authorized addresses");
novm("authorized addresses");
}
/*
* This is the best so far; remember it.
*/
}
if (!newline)
break;
}
/* scan for a -- word indicating the start of options */
break;
/* ap = start of options */
}
return best_flag;
}
/*
* free_wordlist - release memory allocated for a wordlist.
*/
static void
{
}
}
/*
* auth_script_done - called when the auth-up or auth-down script
* has finished.
*/
/*ARGSUSED*/
static void
void *arg;
int status;
{
auth_script_pid = 0;
switch (auth_script_state) {
case s_up:
if (auth_state == s_down) {
}
break;
case s_down:
if (auth_state == s_up) {
}
break;
}
}
/*
* auth_script - execute a script with arguments
* interface-name peer-name real-user tty speed
*/
static void
char *script;
{
char *user_name;
else {
}
}