auth.c

来自「RTEMS (Real-Time Executive for Multiproc」· C语言 代码 · 共 1,122 行 · 第 1/2 页

C
1,122
字号
/* * 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. */#define RCSID	"$Id: auth.c,v 1.5.2.1 2003/04/10 13:09:09 joel Exp $"#include <stdio.h>#include <stddef.h>#include <stdlib.h>#include <unistd.h>#include <pwd.h>#include <grp.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/socket.h>#include <fcntl.h>#if defined(_PATH_LASTLOG) && defined(_linux_)#include <lastlog.h>#endif#include <netdb.h>#include <netinet/in.h>#include <arpa/inet.h>#ifdef USE_PAM#include <security/pam_appl.h>#endif#ifdef HAS_SHADOW#include <shadow.h>#ifndef PW_PPP#define PW_PPP PW_LOGIN#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"static const char rcsid[] = RCSID;/* The name by which the peer authenticated itself to us. */char peer_authname[MAXNAMELEN];/* Records which authentication operations haven't completed yet. */static int auth_pending[NUM_PPP];/* List of addresses which the peer may use. */static struct permitted_ip *addresses[NUM_PPP];/* Wordlist giving addresses which the peer may use   without authenticating itself. */static struct wordlist *noauth_addrs;/* Extra options to apply, from the secrets file entry for the peer. */static struct wordlist *extra_options;/* 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 for a link status */void (*auth_linkup_hook)__P((void)) = NULL;void (*auth_linkdown_hook)__P((void)) = NULL;/* Hook to enable a plugin to control the idle time limit */int (*idle_time_hook) __P((struct ppp_idle *)) = NULL;/* Hook for a plugin to say whether we can possibly authenticate any peer */int (*pap_check_hook) __P((void)) = NULL;/* Hook for a plugin to check the PAP user and password */int (*pap_auth_hook) __P((char *user, char *passwd/*, char **msgp,			  struct wordlist **paddrs,			  struct wordlist **popts*/)) = NULL;/* Hook for a plugin to know about the PAP user logout */void (*pap_logout_hook) __P((void)) = NULL;/* Hook for a plugin to get the PAP password for authenticating us */int (*pap_passwd_hook) __P((char *user, char *passwd)) = NULL;/* * This is used to ensure that we don't start an auth-up/down * script while one is already running. */enum script_state {    s_down,    s_up};static enum script_state auth_state = s_down;static enum script_state auth_script_state = s_down;/* * Option variables. */bool uselogin = 0;		/* Use /etc/passwd for checking PAP */bool cryptpap = 0;		/* Passwords in pap-secrets are encrypted */bool refuse_pap = 0;		/* Don't wanna auth. ourselves with PAP */bool refuse_chap = 0;		/* Don't wanna auth. ourselves with CHAP */bool usehostname = 0;		/* Use hostname for our_name */bool auth_required = 0;		/* Always require authentication from peer */bool allow_any_ip = 0;		/* Allow peer to use any IP address */bool explicit_remote = 0;	/* User specified explicit remote name */char remote_name[MAXNAMELEN];	/* Peer's name for authentication *//* Bits in auth_pending[] */#define PAP_WITHPEER	1#define PAP_PEER	2#define CHAP_WITHPEER	4#define CHAP_PEER	8extern 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 *));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 *));#if 0static int  ip_addr_check __P((u_int32_t, struct permitted_ip *));#endifstatic void free_wordlist __P((struct wordlist *));static void auth_script __P((enum script_state s));static void set_allowed_addrs __P((int, struct wordlist *, struct wordlist *));/* * Authentication-related options. */option_t auth_options[] = {    { "require-pap", o_bool, &lcp_wantoptions[0].neg_upap,      "Require PAP authentication from peer", 1, &auth_required },    { "+pap", o_bool, &lcp_wantoptions[0].neg_upap,      "Require PAP authentication from peer", 1, &auth_required },    { "refuse-pap", o_bool, &refuse_pap,      "Don't agree to auth to peer with PAP", 1 },    { "-pap", o_bool, &refuse_pap,      "Don't allow PAP authentication with peer", 1 },    { "require-chap", o_bool, &lcp_wantoptions[0].neg_chap,      "Require CHAP authentication from peer", 1, &auth_required },    { "+chap", o_bool, &lcp_wantoptions[0].neg_chap,      "Require CHAP authentication from peer", 1, &auth_required },    { "refuse-chap", o_bool, &refuse_chap,      "Don't agree to auth to peer with CHAP", 1 },    { "-chap", o_bool, &refuse_chap,      "Don't allow CHAP authentication with peer", 1 },    { "name", o_string, our_name,      "Set local name for authentication",      OPT_PRIV|OPT_STATIC, NULL, MAXNAMELEN },    { "user", o_string, user,      "Set name for auth with peer", OPT_STATIC, NULL, MAXNAMELEN },    { "usehostname", o_bool, &usehostname,      "Must use hostname for authentication", 1 },    { "remotename", o_string, remote_name,      "Set remote name for authentication", OPT_STATIC,      &explicit_remote, MAXNAMELEN },    { "auth", o_bool, &auth_required,      "Require authentication from peer", 1 },    { "noauth", o_bool, &auth_required,      "Don't require peer to authenticate", OPT_PRIV, &allow_any_ip },    {  "login", o_bool, &uselogin,      "Use system password database for PAP", 1 },    { "papcrypt", o_bool, &cryptpap,      "PAP passwords are encrypted", 1 },/* Removed for RTEMS PORT    { "+ua", o_special, setupapfile,      "Get PAP user and password from file" },*/    { "password", o_string, passwd,      "Password for authenticating us to the peer", OPT_STATIC,      NULL, MAXSECRETLEN },/* Removed for RTEMS_PORT    { "privgroup", o_special, privgroup,      "Allow group members to use privileged options", OPT_PRIV },    { "allow-ip", o_special, set_noauth_addr,      "Set IP address(es) which can be used without authentication",      OPT_PRIV },*/    { NULL }};/* * An Open on LCP has requested a change from Dead to Establish phase. * Do what's necessary to bring the physical layer up. */voidlink_required(unit)    int unit;{}/* * LCP has terminated the link; go to the Dead phase and take the * physical layer down. */voidlink_terminated(unit)    int unit;{    if (pppd_phase == PHASE_DEAD)	return;    if (pap_logout_hook) {	pap_logout_hook();    }    new_phase(PHASE_DEAD);    notice("Connection terminated.");}/* * LCP has gone down; it will either die or try to re-establish. */voidlink_down(unit)    int unit;{    int i;    struct protent *protp;    auth_state = s_down;    if (auth_script_state == s_up) {	update_link_stats(unit);	auth_script(s_down);    }    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 (pppd_phase != PHASE_DEAD)	new_phase(PHASE_TERMINATE);}/* * The link is established. * Proceed to the Dead, Authenticate or Network phase as appropriate. */voidlink_established(unit)    int unit;{    int auth;    lcp_options *wo = &lcp_wantoptions[unit];    lcp_options *go = &lcp_gotoptions[unit];    lcp_options *ho = &lcp_hisoptions[unit];    int i;    struct protent *protp;    /*     * 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:	 * 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) {	    set_allowed_addrs(unit, noauth_addrs, NULL);	} else if (!wo->neg_upap || !null_login(unit)) {	    warn("peer refused to authenticate: terminating link");	    lcp_close(unit, "peer refused to authenticate");	    pppd_status = EXIT_PEER_AUTH_FAILED;	    return;	}    }    new_phase(PHASE_AUTHENTICATE);    auth = 0;    if (go->neg_chap) {	ChapAuthPeer(unit, our_name, go->chap_mdtype);	auth |= CHAP_PEER;    } else if (go->neg_upap) {	upap_authpeer(unit);	auth |= PAP_PEER;    }    if (ho->neg_chap) {	ChapAuthWithPeer(unit, user, ho->chap_mdtype);	auth |= CHAP_WITHPEER;    } else if (ho->neg_upap) {	if (passwd[0] == 0) {	    passwd_from_file = 1;	    if (!get_pap_passwd(passwd))		error("No secret found for PAP login");	}	upap_authwithpeer(unit, user, passwd);	auth |= PAP_WITHPEER;    }    auth_pending[unit] = auth;    if (!auth)	network_phase(unit);}/* * Proceed to the network phase. */static voidnetwork_phase(unit)    int unit;{#ifdef CBCP_SUPPORT    lcp_options *go = &lcp_gotoptions[unit];#endif    /* always run the auth-up script */    auth_state = s_up;    if (auth_script_state == s_down) {        auth_script(s_up);    }#ifdef CBCP_SUPPORT    /*     * If we negotiated callback, do it now.     */    if (go->neg_cbcp) {	new_phase(PHASE_CALLBACK);	(*cbcp_protent.open)(unit);	return;    }#endif    /*     * Process extra options from the secrets file     */    if (extra_options) {	options_from_list(extra_options, 1);	free_wordlist(extra_options);	extra_options = 0;    }    start_networks();}voidstart_networks(){    int i;    struct protent *protp;    new_phase(PHASE_NETWORK);    for (i = 0; (protp = protocols[i]) != NULL; ++i)        if (protp->protocol < 0xC000 && protp->enabled_flag	    && protp->open != NULL) {	    (*protp->open)(0);	    if (protp->protocol != PPP_CCP)		++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'. */voidauth_peer_fail(unit, protocol)    int unit, protocol;{    /*     * Authentication failure: take the link down     */    lcp_close(unit, "Authentication failed");    pppd_status = EXIT_PEER_AUTH_FAILED;}/* * The peer has been successfully authenticated using `protocol'. */voidauth_peer_success(unit, protocol, name, namelen)    int unit, protocol;    char *name;    int namelen;{    int bit;    switch (protocol) {    case PPP_CHAP:	bit = CHAP_PEER;	break;    case PPP_PAP:	bit = PAP_PEER;	break;    default:	warn("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'. */voidauth_withpeer_fail(unit, protocol)    int unit, protocol;{    if (passwd_from_file)	BZERO(passwd, MAXSECRETLEN);    /*     * 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.     */    lcp_close(unit, "Failed to authenticate ourselves to peer");    pppd_status = EXIT_AUTH_TOPEER_FAILED;}/* * We have successfully authenticated ourselves with the peer using `protocol'. */voidauth_withpeer_success(unit, protocol)    int unit, protocol;{    int bit;    switch (protocol) {    case PPP_CHAP:	bit = CHAP_WITHPEER;	break;    case PPP_PAP:	if (passwd_from_file)	    BZERO(passwd, MAXSECRETLEN);	bit = PAP_WITHPEER;	break;    default:	warn("auth_withpeer_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);}/* * np_up - a network protocol has come up. */voidnp_up(unit, proto)    int unit, proto;{    int tlim;    if (num_np_up == 0) {	/*	 * At this point we consider that the link has come up successfully.	 */	pppd_status = EXIT_OK;	unsuccess = 0;	new_phase(PHASE_RUNNING);	if (idle_time_hook != 0)	    tlim = (*idle_time_hook)(NULL);	else	    tlim = idle_time_limit;	if (tlim > 0)	    TIMEOUT(check_idle, NULL, tlim);	/*	 * 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;}/* * np_down - a network protocol has gone down. */voidnp_down(unit, proto)    int unit, proto;{

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?