⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 auth.c

📁 Unix/Linux NAPT协议解析源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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. */#ifndef lintstatic char rcsid[] = "$Id: auth.c,v 1.15 1995/05/19 03:16:12 paulus Exp $";#endif#include <stdio.h>#include <stddef.h>/* #include <stdlib.h> */#include <syslog.h>#include <pwd.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#ifdef HAS_SHADOW#include <shadow.h>#include <shadow/pwauth.h>#ifndef PW_PPP#define PW_PPP PW_LOGIN#endif#endif#include "pppd.h"#include "fsm.h"#include "lcp.h"#include "upap.h"#include "chap.h"#include "ipcp.h"#include "ccp.h"#include "pathnames.h"#if defined(sun) && defined(sparc)#include <alloca.h>#endif /*sparc*/extern char *crypt _P((const char *, const char *));/* Used for storing a sequence of words.  Usually malloced. */struct wordlist {    struct wordlist	*next;    char		word[1];};/* Bits in scan_authfile return value */#define NONWILD_SERVER	1#define NONWILD_CLIENT	2#define ISWILD(word)	(word[0] == '*' && word[1] == 0)#undef FALSE#define FALSE	0#undef TRUE#define TRUE	1#ifndef IN_LOOPBACKNET#define IN_LOOPBACKNET 127#endif#ifndef IN_MULTICAST#define IN_MULTICAST(i) (((long)(i) & 0xf0000000) == 0xe0000000)#endif#ifndef IN_BADCLASS#define IN_BADCLASS(i) (((long)(i) & 0xf0000000) == 0xf0000000)#endif/* Records which authentication operations haven't completed yet. */static int auth_pending[NUM_PPP];static int logged_in;static struct wordlist *addresses[NUM_PPP];/* Bits in auth_pending[] */#define UPAP_WITHPEER	1#define UPAP_PEER	2#define CHAP_WITHPEER	4#define CHAP_PEER	8/* Prototypes */void check_access __P((FILE *, char *));static void network_phase __P((int));static int  login __P((char *, char *, char **, int *));static void logout __P((void));static int  null_login __P((int));static int  get_upap_passwd __P((void));static int  have_upap_secret __P((void));static int  have_chap_secret __P((char *, char *));static int  scan_authfile __P((FILE *, char *, char *, char *, int, 				  struct wordlist **, char *));static void free_wordlist __P((struct wordlist *));/* * 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 (phase == PHASE_DEAD)	return;    if (logged_in)	logout();    phase = PHASE_DEAD;    do_syslog(LOG_NOTICE, "Connection terminated.");    if (ppp_exit)	slirp_exit(0);}/* * LCP has gone down; it will either die or try to re-establish. */voidlink_down(unit)    int unit;{    ipcp_close(0);    ccp_close(0);    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];    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)) {	    do_syslog(LOG_WARNING, "peer refused to authenticate");	    lcp_close(unit);	    phase = PHASE_TERMINATE;	    return;	}    }    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 |= UPAP_PEER;    }    if (ho->neg_chap) {	ChapAuthWithPeer(unit, our_name, ho->chap_mdtype);	auth |= CHAP_WITHPEER;    } else if (ho->neg_upap) {	upap_authwithpeer(unit, user, passwd);	auth |= UPAP_WITHPEER;    }    auth_pending[unit] = auth;    if (!auth)	network_phase(unit);}/* * Proceed to the network phase. */static voidnetwork_phase(unit)    int unit;{    phase = PHASE_NETWORK;    ipcp_open(unit);    ccp_open(unit);}/* * 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);    phase = PHASE_TERMINATE;}/* * The peer has been successfully authenticated using `protocol'. */voidauth_peer_success(unit, protocol)    int unit, protocol;{    int bit;    switch (protocol) {    case PPP_CHAP:	bit = CHAP_PEER;	break;    case PPP_PAP:	bit = UPAP_PEER;	break;    default:	do_syslog(LOG_WARNING, "auth_peer_success: unknown protocol %x",	       protocol);	return;    }    /*     * If there is no more authentication still to be done,     * proceed to the network phase.     */    if ((auth_pending[unit] &= ~bit) == 0) {	phase = PHASE_NETWORK;	ipcp_open(unit);	ccp_open(unit);    }}/* * We have failed to authenticate ourselves to the peer using `protocol'. */voidauth_withpeer_fail(unit, protocol)    int unit, protocol;{    /*     * 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'. */voidauth_withpeer_success(unit, protocol)    int unit, protocol;{    int bit;    switch (protocol) {    case PPP_CHAP:	bit = CHAP_WITHPEER;	break;    case PPP_PAP:	bit = UPAP_WITHPEER;	break;    default:	do_syslog(LOG_WARNING, "auth_peer_success: unknown protocol %x",	       protocol);	bit = 0;    }    /*     * If there is no more authentication still being done,     * proceed to the network phase.     */    if ((auth_pending[unit] &= ~bit) == 0)	network_phase(unit);}/* * check_auth_options - called to check authentication options. */voidcheck_auth_options(){    lcp_options *wo = &lcp_wantoptions[0];    lcp_options *ao = &lcp_allowoptions[0];    /* Default our_name to hostname, and user to our_name */    if (our_name[0] == 0 || usehostname)	strncpy2(our_name, hostname, sizeof(our_name));    if (user[0] == 0)	strncpy2(user, our_name, sizeof(user));    /* If authentication is required, ask peer for CHAP or PAP. */    if (auth_required && !wo->neg_chap && !wo->neg_upap) {	wo->neg_chap = 1;	wo->neg_upap = 1;    }    /*     * Check whether we have appropriate secrets to use     * to authenticate ourselves and/or the peer.     */    if (ao->neg_upap && passwd[0] == 0 && !get_upap_passwd())	ao->neg_upap = 0;    if (wo->neg_upap && !uselogin && !have_upap_secret())	wo->neg_upap = 0;    if (ao->neg_chap && !have_chap_secret(our_name, remote_name))	ao->neg_chap = 0;    if (wo->neg_chap && !have_chap_secret(remote_name, our_name))	wo->neg_chap = 0;    if (auth_required && !wo->neg_chap && !wo->neg_upap) {	fprintf(stderr, "\pppd: peer authentication required but no authentication files accessible\n");	exit(1);    }}/* * 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. */intcheck_passwd(unit, auser, userlen, apasswd, passwdlen, msg, msglen)    int unit;    char *auser;    int userlen;    char *apasswd;    int passwdlen;    char **msg;    int *msglen;{    int ret;    char *filename;    FILE *f;    struct wordlist *addrs;    char passwd[256], user[256];    char secret[MAXWORDLEN];    static int attempts = 0;    /*     * Make copies of apasswd and auser, then null-terminate them.     */    BCOPY(apasswd, passwd, passwdlen);    passwd[passwdlen] = '\0';    BCOPY(auser, user, userlen);    user[userlen] = '\0';    /*     * Open the file of upap secrets and scan for a suitable secret     * for authenticating this user.     */    filename = _PATH_UPAPFILE;    addrs = NULL;    ret = UPAP_AUTHACK;    f = fopen(filename, "r");    if (f == NULL) {	if (!uselogin) {	    do_syslog(LOG_ERR, "Can't open upap password file %s: %m", filename);	    ret = UPAP_AUTHNAK;	}    } else {	check_access(f, filename);	if (scan_authfile(f, user, our_name, secret, sizeof(secret), &addrs, filename) < 0	    || (secret[0] != 0 && (cryptpap || strcmp(passwd, secret) != 0)		&& strcmp(crypt(passwd, secret), secret) != 0)) {	    do_syslog(LOG_WARNING, "upap authentication failure for %s", user);	    ret = UPAP_AUTHNAK;	}	fclose(f);    }    if (uselogin && ret == UPAP_AUTHACK) {	ret = login(user, passwd, msg, msglen);	if (ret == UPAP_AUTHNAK) {	    do_syslog(LOG_WARNING, "upap login failure for %s", user);	}    }    if (ret == UPAP_AUTHNAK) {	*msg = "Login incorrect";	*msglen = strlen(*msg);	/*	 * 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) {	    do_syslog(LOG_WARNING, "%d LOGIN FAILURES ON %s, %s",		   attempts, devnam, user);	    quit();	}	if (attempts > 3)	    sleep((u_int) (attempts - 3) * 5);	if (addrs != NULL)	    free_wordlist(addrs);    } else {	attempts = 0;			/* Reset count */	*msg = "Login ok";	*msglen = strlen(*msg);	if (addresses[unit] != NULL)	    free_wordlist(addresses[unit]);	addresses[unit] = addrs;    }    return ret;}/* * 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. */static intlogin(user, passwd, msg, msglen)    char *user;    char *passwd;    char **msg;    int *msglen;{    struct passwd *pw;    char *epasswd;    char *tty;

⌨️ 快捷键说明

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