?? netauth.c
字號:
/*****************************************************************************
* netauth.c - Network Authentication and Phase Control program file.
*
* 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
*
* 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 "netconf.h"
#include <string.h>
#include "net.h"
#include "netbuf.h"
#include "nettimer.h"
#include "netfsm.h"
#include "netlcp.h"
#include "netpap.h"
#include "netchap.h"
#include "netauth.h"
#include "netppp.h"
#include "netipcp.h"
#include "netos.h"
#if CBCP_SUPPORT > 0
#include "netcbcp.h"
#endif
#include <malloc.h>
#include <stdio.h>
#include "netdebug.h"
/*************************/
/*** LOCAL DEFINITIONS ***/
/*************************/
/* Bits in auth_pending[] */
#define PAP_WITHPEER 1
#define PAP_PEER 2
#define CHAP_WITHPEER 4
#define CHAP_PEER 8
/************************/
/*** LOCAL DATA TYPES ***/
/************************/
/* Used for storing a sequence of words. Usually malloced. */
struct wordlist {
struct wordlist *next;
char word[1];
};
/***********************************/
/*** LOCAL FUNCTION DECLARATIONS ***/
/***********************************/
extern char *crypt __P((const char *, const char *));
/* 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 *));
#ifdef XXX
static int login __P((char *, char *, char **, int *));
#endif
static void logout __P((void));
static int null_login __P((int));
static int get_pap_passwd __P((int));
static int have_pap_secret __P((void));
static int have_chap_secret __P((char *, char *, u_int32_t));
static int ip_addr_check __P((u_int32_t, struct wordlist *));
#if PAP_SUPPORT > 0 || CHAP_SUPPORT > 0
static void set_allowed_addrs(int unit, struct wordlist *addrs);
static void free_wordlist __P((struct wordlist *));
#endif
#if CBCP_SUPPORT > 0
static void callback_phase __P((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. */
static char peer_authname[MAXNAMELEN];
#endif
/* Records which authentication operations haven't completed yet. */
static int auth_pending[NUM_PPP];
/* Set if we have successfully called login() */
static int logged_in;
/* Set if we have run the /etc/ppp/auth-up script. */
static int did_authup;
/* List of addresses which the peer may use. */
static struct wordlist *addresses[NUM_PPP];
/* 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.
*/
#pragma argsused
void link_required(int unit)
{
AUTHDEBUG((LOG_INFO, "link_required: %d", unit));
}
/*
* LCP has terminated the link; go to the Dead phase and take the
* physical layer down.
*/
#pragma argsused
void link_terminated(int unit)
{
AUTHDEBUG((LOG_INFO, "link_terminated: %d", unit));
if (lcp_phase[unit] == PHASE_DEAD)
return;
if (logged_in)
logout();
lcp_phase[unit] = PHASE_DEAD;
trace(LOG_NOTICE, "Connection terminated.");
}
/*
* LCP has gone down; it will either die or try to re-establish.
*/
void link_down(int unit)
{
int i;
struct protent *protp;
AUTHDEBUG((LOG_INFO, "link_down: %d", unit));
if (did_authup) {
/* XXX Do link down processing. */
did_authup = 0;
}
for (i = 0; (protp = protocols[i]) != NULL; ++i) {
if (!protp->enabled_flag)
continue;
if (protp->protocol != PPP_LCP && protp->lowerdown != NULL)
(*protp->lowerdown)(unit);
if (protp->protocol < 0xC000 && protp->close != NULL)
(*protp->close)(unit, "LCP down");
}
num_np_open = 0;
num_np_up = 0;
if (lcp_phase[unit] != PHASE_DEAD)
lcp_phase[unit] = PHASE_TERMINATE;
}
/*
* The link is established.
* Proceed to the Dead, Authenticate or Network phase as appropriate.
*/
void link_established(int unit)
{
int auth;
int i;
struct protent *protp;
lcp_options *wo = &lcp_wantoptions[unit];
lcp_options *go = &lcp_gotoptions[unit];
#if PAP_SUPPORT > 0 || CHAP_SUPPORT > 0
lcp_options *ho = &lcp_hisoptions[unit];
#endif
AUTHDEBUG((LOG_INFO, "link_established: %d", unit));
/*
* Tell higher-level protocols that LCP is up.
*/
for (i = 0; (protp = protocols[i]) != NULL; ++i)
if (protp->protocol != PPP_LCP && protp->enabled_flag
&& protp->lowerup != NULL)
(*protp->lowerup)(unit);
if (auth_required && !(go->neg_chap || go->neg_upap)) {
/*
* 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.
*/
if (!wo->neg_upap || !null_login(unit)) {
trace(LOG_WARNING, "peer refused to authenticate");
lcp_close(unit, "peer refused to authenticate");
return;
}
}
lcp_phase[unit] = PHASE_AUTHENTICATE;
auth = 0;
#if CHAP_SUPPORT > 0
if (go->neg_chap) {
ChapAuthPeer(unit, our_name, go->chap_mdtype);
auth |= CHAP_PEER;
}
#endif
#if PAP_SUPPORT > 0 && CHAP_SUPPORT > 0
else
#endif
#if PAP_SUPPORT > 0
if (go->neg_upap) {
upap_authpeer(unit);
auth |= PAP_PEER;
}
#endif
#if CHAP_SUPPORT > 0
if (ho->neg_chap) {
ChapAuthWithPeer(unit, user, ho->chap_mdtype);
auth |= CHAP_WITHPEER;
}
#endif
#if PAP_SUPPORT > 0 && CHAP_SUPPORT > 0
else
#endif
#if PAP_SUPPORT > 0
if (ho->neg_upap) {
if (passwd[0] == 0) {
passwd_from_file = 1;
if (!get_pap_passwd(unit))
trace(LOG_ERR, "No secret found for PAP login");
}
upap_authwithpeer(unit, user, passwd);
auth |= PAP_WITHPEER;
}
#endif
auth_pending[unit] = auth;
if (!auth)
network_phase(unit);
}
/*
* The peer has failed to authenticate himself using `protocol'.
*/
#pragma argsused
void auth_peer_fail(int unit, int protocol)
{
AUTHDEBUG((LOG_INFO, "auth_peer_fail: %d proto=%X", unit, protocol));
/*
* Authentication failure: take the link down
*/
lcp_close(unit, "Authentication failed");
}
#if PAP_SUPPORT > 0 || CHAP_SUPPORT > 0
/*
* The peer has been successfully authenticated using `protocol'.
*/
void auth_peer_success(int unit, int protocol, char *name, int namelen)
{
int bit;
AUTHDEBUG((LOG_INFO, "auth_peer_success: %d proto=%X", unit, protocol));
switch (protocol) {
case PPP_CHAP:
bit = CHAP_PEER;
break;
case PPP_PAP:
bit = PAP_PEER;
break;
default:
trace(LOG_WARNING, "auth_peer_success: unknown protocol %x",
protocol);
return;
}
/*
* Save the authenticated name of the peer for later.
*/
if (namelen > sizeof(peer_authname) - 1)
namelen = sizeof(peer_authname) - 1;
BCOPY(name, peer_authname, namelen);
peer_authname[namelen] = 0;
/*
* If there is no more authentication still to be done,
* proceed to the network (or callback) phase.
*/
if ((auth_pending[unit] &= ~bit) == 0)
network_phase(unit);
}
/*
* We have failed to authenticate ourselves to the peer using `protocol'.
*/
#pragma argsused
void auth_withpeer_fail(int unit, int protocol)
{
int errCode = PPPERR_AUTHFAIL;
AUTHDEBUG((LOG_INFO, "auth_withpeer_fail: %d proto=%X", unit, protocol));
if (passwd_from_file)
BZERO(passwd, MAXSECRETLEN);
/*
* 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.
*/
pppIOCtl(unit, PPPCTLS_ERRCODE, &errCode);
/*
* 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'.
*/
void auth_withpeer_success(int unit, int protocol)
{
int bit;
AUTHDEBUG((LOG_INFO, "auth_withpeer_success: %d proto=%X", unit, protocol));
switch (protocol) {
case PPP_CHAP:
bit = CHAP_WITHPEER;
break;
case PPP_PAP:
if (passwd_from_file)
BZERO(passwd, MAXSECRETLEN);
bit = PAP_WITHPEER;
break;
default:
trace(LOG_WARNING, "auth_peer_success: unknown protocol %x",
protocol);
bit = 0;
}
/*
* If there is no more authentication still being done,
* proceed to the network (or callback) phase.
*/
if ((auth_pending[unit] &= ~bit) == 0)
network_phase(unit);
}
#endif
/*
* np_up - a network protocol has come up.
*/
#pragma argsused
void np_up(int unit, int proto)
{
AUTHDEBUG((LOG_INFO, "np_up: %d proto=%X", unit, proto));
if (num_np_up == 0) {
AUTHDEBUG((LOG_INFO, "np_up: maxconnect=%d idle_time_limit=%d",maxconnect,idle_time_limit));
/*
* At this point we consider that the link has come up successfully.
*/
if (idle_time_limit > 0)
TIMEOUT(check_idle, NULL, idle_time_limit);
/*
* Set a timeout to close the connection once the maximum
* connect time has expired.
*/
if (maxconnect > 0)
TIMEOUT(connect_time_expired, 0, maxconnect);
}
++num_np_up;
}
/*
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -