/*****************************************************************************
* auth.c - Network Authentication and Phase Control program file.
*
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
* Copyright (c) 1997 by Global Election Systems Inc. All rights reserved.
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice and the following disclaimer are included verbatim in any
* distributions. No written agreement, license, or royalty fee is required
* for any of the authorized uses.
*
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
* REVISION HISTORY
*
* 03-01-01 Marc Boucher <marc@mbsi.ca>
* Ported to lwIP.
* 97-12-08 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
* Ported from public pppd code.
*****************************************************************************/
/*
* auth.c - PPP authentication and phase control.
*
* 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.
*/
#include "ppp.h"
#if PPP_SUPPORT > 0
#include "fsm.h"
#include "lcp.h"
#include "pap.h"
#include "chap.h"
#include "auth.h"
#include "ipcp.h"
#if CBCP_SUPPORT > 0
#include "cbcp.h"
#endif
#include "pppdebug.h"
/*************************/
/*** LOCAL DEFINITIONS ***/
/*************************/
/* Bits in auth_pending[] */
/************************/
/*** LOCAL DATA TYPES ***/
/************************/
/* Used for storing a sequence of words. Usually malloced. */
struct wordlist {
};
/***********************************/
/*** LOCAL FUNCTION DECLARATIONS ***/
/***********************************/
extern char *crypt (const char *, const char *);
/* Prototypes for procedures local to this file. */
static void network_phase (int);
static void check_idle (void *);
static void connect_time_expired (void *);
#if 0
static int login (char *, char *, char **, int *);
#endif
static void logout (void);
static int null_login (int);
static int get_pap_passwd (int, char *, char *);
static int have_pap_secret (void);
static int have_chap_secret (char *, char *, u32_t);
#if 0 /* PAP_SUPPORT > 0 || CHAP_SUPPORT > 0 */
static void free_wordlist (struct wordlist *);
#endif
#if CBCP_SUPPORT > 0
static void callback_phase (int);
#endif
/******************************/
/*** PUBLIC DATA STRUCTURES ***/
/******************************/
/*****************************/
/*** LOCAL DATA STRUCTURES ***/
/*****************************/
#if PAP_SUPPORT > 0 || CHAP_SUPPORT > 0
/* The name by which the peer authenticated itself to us. */
#endif
/* Records which authentication operations haven't completed yet. */
/* Set if we have successfully called login() */
static int logged_in;
static int did_authup;
/* List of addresses which the peer may use. */
/* 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;
#if PAP_SUPPORT > 0 || CHAP_SUPPORT > 0
/* Set if we got the contents of passwd[] from the pap-secrets file. */
static int passwd_from_file;
#endif
/***********************************/
/*** PUBLIC FUNCTION DEFINITIONS ***/
/***********************************/
/*
* An Open on LCP has requested a change from Dead to Establish phase.
* Do what's necessary to bring the physical layer up.
*/
{
}
/*
* LCP has terminated the link; go to the Dead phase and take the
* physical layer down.
*/
{
return;
if (logged_in)
logout();
}
/*
* LCP has gone down; it will either die or try to re-establish.
*/
{
int i;
if (did_authup) {
/* XXX Do link down processing. */
did_authup = 0;
}
if (!protp->enabled_flag)
continue;
}
num_np_open = 0;
num_np_up = 0;
}
/*
* The link is established.
* Proceed to the Dead, Authenticate or Network phase as appropriate.
*/
{
int auth;
int i;
#if PAP_SUPPORT > 0 || CHAP_SUPPORT > 0
#endif
/*
* Tell higher-level protocols that LCP is up.
*/
/*
* We wanted the peer to authenticate itself, and it refused:
* treat it as though it authenticated with PAP using a username
* of "" and a password of "". If that's not OK, boot it out.
*/
return;
}
}
auth = 0;
#if CHAP_SUPPORT > 0
}
#endif
#if PAP_SUPPORT > 0 && CHAP_SUPPORT > 0
else
#endif
#if PAP_SUPPORT > 0
}
#endif
#if CHAP_SUPPORT > 0
auth |= CHAP_WITHPEER;
}
#endif
#if PAP_SUPPORT > 0 && CHAP_SUPPORT > 0
else
#endif
#if PAP_SUPPORT > 0
if (ppp_settings.passwd[0] == 0) {
passwd_from_file = 1;
}
auth |= PAP_WITHPEER;
}
#endif
if (!auth)
}
/*
* The peer has failed to authenticate himself using `protocol'.
*/
{
/*
* Authentication failure: take the link down
*/
}
#if PAP_SUPPORT > 0 || CHAP_SUPPORT > 0
/*
* The peer has been successfully authenticated using `protocol'.
*/
{
int pbit;
switch (protocol) {
case PPP_CHAP:
break;
case PPP_PAP:
break;
default:
protocol));
return;
}
/*
* Save the authenticated name of the peer for later.
*/
peer_authname[namelen] = 0;
/*
* 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'.
*/
{
if (passwd_from_file)
/*
* XXX Warning: the unit number indicates the interface which is
* not necessarily the PPP connection. It works here as long
* as we are only supporting PPP interfaces.
*/
/*
* We've failed to authenticate ourselves to our peer.
* He'll probably take the link down, and there's not much
* we can do except wait for that.
*/
}
/*
* We have successfully authenticated ourselves with the peer using `protocol'.
*/
{
int pbit;
switch (protocol) {
case PPP_CHAP:
break;
case PPP_PAP:
if (passwd_from_file)
pbit = PAP_WITHPEER;
break;
default:
protocol));
pbit = 0;
}
/*
* If there is no more authentication still being done,
* proceed to the network (or callback) phase.
*/
}
#endif
/*
* np_up - a network protocol has come up.
*/
{
if (num_np_up == 0) {
AUTHDEBUG((LOG_INFO, "np_up: maxconnect=%d idle_time_limit=%d\n",ppp_settings.maxconnect,ppp_settings.idle_time_limit));
/*
* At this point we consider that the link has come up successfully.
*/
if (ppp_settings.idle_time_limit > 0)
/*
* Set a timeout to close the connection once the maximum
* connect time has expired.
*/
if (ppp_settings.maxconnect > 0)
}
++num_np_up;
}
/*
* np_down - a network protocol has gone down.
*/
{
}
}
/*
* np_finished - a network protocol has finished using the link.
*/
{
if (--num_np_open <= 0) {
/* no further use for the link: shut up shop. */
lcp_close(0, "No network protocols running");
}
}
/*
* auth_reset - called when LCP is starting negotiations to recheck
* authentication options, i.e. whether we have appropriate secrets
*/
{
ao->neg_upap = !ppp_settings.refuse_pap && (ppp_settings.passwd[0] != 0 || get_pap_passwd(unit, NULL, NULL));
ao->neg_chap = !ppp_settings.refuse_chap && ppp_settings.passwd[0] != 0 /*have_chap_secret(ppp_settings.user, ppp_settings.remote_name, (u32_t)0)*/;
}
}
#if PAP_SUPPORT > 0
/*
* 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 check_passwd(
int unit,
char *auser,
int userlen,
char *apasswd,
int passwdlen,
char **msg,
int *msglen
)
{
#if 1
*msg = (char *) 0;
return UPAP_AUTHACK; /* XXX Assume all entries OK. */
#else
int ret = 0;
char secret[MAXWORDLEN];
/*
* Make copies of apasswd and auser, then null-terminate them.
*/
*msg = (char *) 0;
/* XXX Validate user name and password. */
if (ret == UPAP_AUTHNAK) {
if (*msg == (char *) 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) {
/*ppp_panic("Excess Bad Logins");*/
}
if (attempts > 3) {
}
}
} else {
attempts = 0; /* Reset count */
if (*msg == (char *) 0)
*msg = "Login ok";
}
return ret;
#endif
}
#endif
/*
* auth_ip_addr - check whether the peer is authorized to use
* a given IP address. Returns 1 if authorized, 0 otherwise.
*/
{
}
/*
* 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.
*/
{
}
#if CHAP_SUPPORT > 0
/*
* get_secret - open the CHAP secret file and return the secret
* for authenticating the given client on the given server.
* (We could be either client or server).
*/
int get_secret(
int unit,
char *client,
char *server,
char *secret,
int *secret_len,
int save_addrs
)
{
#if 1
int len;
return 0;
}
if (len > MAXSECRETLEN) {
len = MAXSECRETLEN;
}
*secret_len = len;
return 1;
#else
char secbuf[MAXWORDLEN];
secbuf[0] = 0;
/* XXX Find secret. */
if (ret < 0)
return 0;
if (save_addrs)
if (len > MAXSECRETLEN) {
len = MAXSECRETLEN;
}
*secret_len = len;
return 1;
#endif
}
#endif
#if 0 /* UNUSED */
/*
* auth_check_options - called to check authentication options.
*/
void auth_check_options(void)
{
int can_auth;
/* Default our_name to hostname, and user to our_name */
if (ppp_settings.user[0] == 0)
/* If authentication is required, ask peer for CHAP or PAP. */
}
/*
* Check whether we have appropriate secrets to use
* to authenticate the peer.
*/
}
ppp_panic("No auth secret");
}
}
#endif
/**********************************/
/*** LOCAL FUNCTION DEFINITIONS ***/
/**********************************/
/*
* Proceed to the network phase.
*/
{
int i;
/*
* If the peer had to authenticate, run the auth-up script now.
*/
/* XXX Do setup for peer authentication. */
did_authup = 1;
}
#if CBCP_SUPPORT > 0
/*
* If we negotiated callback, do it now.
*/
return;
}
#endif
++num_np_open;
}
if (num_np_open == 0)
/* nothing to do */
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.
*/
{
(void)arg;
if (!get_idle_time(0, &idle))
return;
/* link is idle: shut it down. */
lcp_close(0, "Link inactive");
} else {
}
}
/*
* connect_time_expired - log a message and close the connection.
*/
{
(void)arg;
}
#if 0
/*
* login - 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.
*/
{
/* XXX Fail until we decide that we want to support logins. */
return (UPAP_AUTHNAK);
}
#endif
/*
* logout - Logout the user.
*/
static void logout(void)
{
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.
*/
{
(void)unit;
/* XXX Fail until we decide that we want to support logins. */
return 0;
}
/*
* 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.
*/
{
/* normally we would reject PAP if no password is provided,
but this causes problems with some providers (like CHT in Taiwan)
*/
if(user)
if(passwd)
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 have_pap_secret(void)
{
/* XXX Fail until we set up our passwords. */
return 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 can be the null string, meaning we don't
* know the identity yet.
*/
{
(void)client;
(void)server;
(void)remote;
/* XXX Fail until we set up our passwords. */
return 0;
}
#if 0 /* PAP_SUPPORT > 0 || CHAP_SUPPORT > 0 */
/*
* set_allowed_addrs() - set the list of allowed addresses.
*/
{
#if 0
/*
* If there's only one authorized address we might as well
* ask our peer for that one right away
*/
u32_t a;
hp = gethostbyname(p);
else
a = inet_addr(p);
if (a != (u32_t) -1)
}
}
#endif
}
#endif
{
/* don't allow loopback or multicast address */
if (bad_ip_adrs(addr))
return 0;
/* XXX All other addresses allowed. */
return 1;
}
#if 0 /* PAP_SUPPORT > 0 || CHAP_SUPPORT */
/*
* free_wordlist - release memory allocated for a wordlist.
*/
{
}
}
#endif
#endif /* PPP_SUPPORT */