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

📄 radius.c

📁 linux下的ppp协议簇开源代码; 可以进行linux内核级的pppoe拨号
💻 C
📖 第 1 页 / 共 3 页
字号:
/************************************************************************* radius.c** RADIUS plugin for pppd.  Performs PAP, CHAP, MS-CHAP, MS-CHAPv2* authentication using RADIUS.** Copyright (C) 2002 Roaring Penguin Software Inc.** Based on a patch for ipppd, which is:*    Copyright (C) 1996, Matjaz Godec <gody@elgo.si>*    Copyright (C) 1996, Lars Fenneberg <in5y050@public.uni-hamburg.de>*    Copyright (C) 1997, Miguel A.L. Paraz <map@iphil.net>** Uses radiusclient library, which is:*    Copyright (C) 1995,1996,1997,1998 Lars Fenneberg <lf@elemental.net>*    Copyright (C) 2002 Roaring Penguin Software Inc.** MPPE support is by Ralf Hofmann, <ralf.hofmann@elvido.net>, with* modification from Frank Cusack, <frank@google.com>.** This plugin may be distributed according to the terms of the GNU* General Public License, version 2 or (at your option) any later version.************************************************************************/static char const RCSID[] ="$Id: radius.c,v 1.28 2004/11/14 10:27:57 paulus Exp $";#include "pppd.h"#include "chap-new.h"#ifdef CHAPMS#include "chap_ms.h"#ifdef MPPE#include "md5.h"#endif#endif#include "radiusclient.h"#include "fsm.h"#include "ipcp.h"#include <syslog.h>#include <sys/types.h>#include <sys/time.h>#include <string.h>#include <netinet/in.h>#include <stdlib.h>#define BUF_LEN 1024#define MD5_HASH_SIZE	16static char *config_file = NULL;static int add_avp(char **);static struct avpopt {    char *vpstr;    struct avpopt *next;} *avpopt = NULL;static bool portnummap = 0;static option_t Options[] = {    { "radius-config-file", o_string, &config_file },    { "avpair", o_special, add_avp },    { "map-to-ttyname", o_bool, &portnummap,	"Set Radius NAS-Port attribute value via libradiusclient library", OPT_PRIO | 1 },    { "map-to-ifname", o_bool, &portnummap,	"Set Radius NAS-Port attribute to number as in interface name (Default)", OPT_PRIOSUB | 0 },    { NULL }};static int radius_secret_check(void);static int radius_pap_auth(char *user,			   char *passwd,			   char **msgp,			   struct wordlist **paddrs,			   struct wordlist **popts);static int radius_chap_verify(char *user, char *ourname, int id,			      struct chap_digest_type *digest,			      unsigned char *challenge,			      unsigned char *response,			      char *message, int message_space);static void radius_ip_up(void *opaque, int arg);static void radius_ip_down(void *opaque, int arg);static void make_username_realm(char *user);static int radius_setparams(VALUE_PAIR *vp, char *msg, REQUEST_INFO *req_info,			    struct chap_digest_type *digest,			    unsigned char *challenge,			    char *message, int message_space);static void radius_choose_ip(u_int32_t *addrp);static int radius_init(char *msg);static int get_client_port(char *ifname);static int radius_allowed_address(u_int32_t addr);static void radius_acct_interim(void *);#ifdef MPPEstatic int radius_setmppekeys(VALUE_PAIR *vp, REQUEST_INFO *req_info,			      unsigned char *);static int radius_setmppekeys2(VALUE_PAIR *vp, REQUEST_INFO *req_info);#endif#ifndef MAXSESSIONID#define MAXSESSIONID 32#endif#ifndef MAXCLASSLEN#define MAXCLASSLEN 500#endifstruct radius_state {    int accounting_started;    int initialized;    int client_port;    int choose_ip;    int any_ip_addr_ok;    int done_chap_once;    u_int32_t ip_addr;    char user[MAXNAMELEN];    char config_file[MAXPATHLEN];    char session_id[MAXSESSIONID + 1];    time_t start_time;    int acct_interim_interval;    SERVER *authserver;		/* Authentication server to use */    SERVER *acctserver;		/* Accounting server to use */    int class_len;    char class[MAXCLASSLEN];    VALUE_PAIR *avp;	/* Additional (user supplied) vp's to send to server */};void (*radius_attributes_hook)(VALUE_PAIR *) = NULL;/* The pre_auth_hook MAY set authserver and acctserver if it wants.   In that case, they override the values in the radiusclient.conf file */void (*radius_pre_auth_hook)(char const *user,			     SERVER **authserver,			     SERVER **acctserver) = NULL;static struct radius_state rstate;char pppd_version[] = VERSION;/*********************************************************************** %FUNCTION: plugin_init* %ARGUMENTS:*  None* %RETURNS:*  Nothing* %DESCRIPTION:*  Initializes RADIUS plugin.***********************************************************************/voidplugin_init(void){    pap_check_hook = radius_secret_check;    pap_auth_hook = radius_pap_auth;    chap_check_hook = radius_secret_check;    chap_verify_hook = radius_chap_verify;    ip_choose_hook = radius_choose_ip;    allowed_address_hook = radius_allowed_address;    add_notifier(&ip_up_notifier, radius_ip_up, NULL);    add_notifier(&ip_down_notifier, radius_ip_down, NULL);    memset(&rstate, 0, sizeof(rstate));    strlcpy(rstate.config_file, "/etc/radiusclient/radiusclient.conf",	    sizeof(rstate.config_file));    add_options(Options);    info("RADIUS plugin initialized.");}/*********************************************************************** %FUNCTION: add_avp* %ARGUMENTS:*  argv -- the <attribute=value> pair to add* %RETURNS:*  1* %DESCRIPTION:*  Adds an av pair to be passed on to the RADIUS server on each request.***********************************************************************/static intadd_avp(char **argv){    struct avpopt *p = malloc(sizeof(struct avpopt));    /* Append to a list of vp's for later parsing */    p->vpstr = strdup(*argv);    p->next = avpopt;    avpopt = p;    return 1;}/*********************************************************************** %FUNCTION: radius_secret_check* %ARGUMENTS:*  None* %RETURNS:*  1 -- we are ALWAYS willing to supply a secret. :-)* %DESCRIPTION:* Tells pppd that we will try to authenticate the peer, and not to* worry about looking in /etc/ppp/*-secrets***********************************************************************/static intradius_secret_check(void){    return 1;}/*********************************************************************** %FUNCTION: radius_choose_ip* %ARGUMENTS:*  addrp -- where to store the IP address* %RETURNS:*  Nothing* %DESCRIPTION:*  If RADIUS server has specified an IP address, it is stored in *addrp.***********************************************************************/static voidradius_choose_ip(u_int32_t *addrp){    if (rstate.choose_ip) {	*addrp = rstate.ip_addr;    }}/*********************************************************************** %FUNCTION: radius_pap_auth* %ARGUMENTS:*  user -- user-name of peer*  passwd -- password supplied by peer*  msgp -- Message which will be sent in PAP response*  paddrs -- set to a list of possible peer IP addresses*  popts -- set to a list of additional pppd options* %RETURNS:*  1 if we can authenticate, -1 if we cannot.* %DESCRIPTION:* Performs PAP authentication using RADIUS***********************************************************************/static intradius_pap_auth(char *user,		char *passwd,		char **msgp,		struct wordlist **paddrs,		struct wordlist **popts){    VALUE_PAIR *send, *received;    UINT4 av_type;    int result;    static char radius_msg[BUF_LEN];    radius_msg[0] = 0;    *msgp = radius_msg;    if (radius_init(radius_msg) < 0) {	return 0;    }    /* Put user with potentially realm added in rstate.user */    make_username_realm(user);    if (radius_pre_auth_hook) {	radius_pre_auth_hook(rstate.user,			     &rstate.authserver,			     &rstate.acctserver);    }    send = NULL;    received = NULL;    /* Hack... the "port" is the ppp interface number.  Should really be       the tty */    rstate.client_port = get_client_port(portnummap ? devnam : ifname);    av_type = PW_FRAMED;    rc_avpair_add(&send, PW_SERVICE_TYPE, &av_type, 0, VENDOR_NONE);    av_type = PW_PPP;    rc_avpair_add(&send, PW_FRAMED_PROTOCOL, &av_type, 0, VENDOR_NONE);    rc_avpair_add(&send, PW_USER_NAME, rstate.user , 0, VENDOR_NONE);    rc_avpair_add(&send, PW_USER_PASSWORD, passwd, 0, VENDOR_NONE);    if (*remote_number) {	rc_avpair_add(&send, PW_CALLING_STATION_ID, remote_number, 0,		       VENDOR_NONE);    } else if (ipparam)	rc_avpair_add(&send, PW_CALLING_STATION_ID, ipparam, 0, VENDOR_NONE);    /* Add user specified vp's */    if (rstate.avp)	rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp));    if (rstate.authserver) {	result = rc_auth_using_server(rstate.authserver,				      rstate.client_port, send,				      &received, radius_msg, NULL);    } else {	result = rc_auth(rstate.client_port, send, &received, radius_msg, NULL);    }    if (result == OK_RC) {	if (radius_setparams(received, radius_msg, NULL, NULL, NULL, NULL, 0) < 0) {	    result = ERROR_RC;	}    }    /* free value pairs */    rc_avpair_free(received);    rc_avpair_free(send);    return (result == OK_RC) ? 1 : 0;}/*********************************************************************** %FUNCTION: radius_chap_verify* %ARGUMENTS:*  user -- name of the peer*  ourname -- name for this machine*  id -- the ID byte in the challenge*  digest -- points to the structure representing the digest type*  challenge -- the challenge string we sent (length in first byte)*  response -- the response (hash) the peer sent back (length in 1st byte)*  message -- space for a message to be returned to the peer*  message_space -- number of bytes available at *message.* %RETURNS:*  1 if the response is good, 0 if it is bad* %DESCRIPTION:* Performs CHAP, MS-CHAP and MS-CHAPv2 authentication using RADIUS.***********************************************************************/static intradius_chap_verify(char *user, char *ourname, int id,		   struct chap_digest_type *digest,		   unsigned char *challenge, unsigned char *response,		   char *message, int message_space){    VALUE_PAIR *send, *received;    UINT4 av_type;    static char radius_msg[BUF_LEN];    int result;    int challenge_len, response_len;    u_char cpassword[MAX_RESPONSE_LEN + 1];#ifdef MPPE    /* Need the RADIUS secret and Request Authenticator to decode MPPE */    REQUEST_INFO request_info, *req_info = &request_info;#else    REQUEST_INFO *req_info = NULL;#endif    challenge_len = *challenge++;    response_len = *response++;    radius_msg[0] = 0;    if (radius_init(radius_msg) < 0) {	error("%s", radius_msg);	return 0;    }    /* return error for types we can't handle */    if ((digest->code != CHAP_MD5)#ifdef CHAPMS	&& (digest->code != CHAP_MICROSOFT)	&& (digest->code != CHAP_MICROSOFT_V2)#endif	) {	error("RADIUS: Challenge type %u unsupported", digest->code);	return 0;    }    /* Put user with potentially realm added in rstate.user */    if (!rstate.done_chap_once) {	make_username_realm(user);	rstate.client_port = get_client_port (portnummap ? devnam : ifname);	if (radius_pre_auth_hook) {	    radius_pre_auth_hook(rstate.user,				 &rstate.authserver,				 &rstate.acctserver);	}    }    send = received = NULL;    av_type = PW_FRAMED;    rc_avpair_add (&send, PW_SERVICE_TYPE, &av_type, 0, VENDOR_NONE);    av_type = PW_PPP;    rc_avpair_add (&send, PW_FRAMED_PROTOCOL, &av_type, 0, VENDOR_NONE);    rc_avpair_add (&send, PW_USER_NAME, rstate.user , 0, VENDOR_NONE);    /*     * add the challenge and response fields     */    switch (digest->code) {    case CHAP_MD5:	/* CHAP-Challenge and CHAP-Password */	if (response_len != MD5_HASH_SIZE)	    return 0;	cpassword[0] = id;	memcpy(&cpassword[1], response, MD5_HASH_SIZE);	rc_avpair_add(&send, PW_CHAP_CHALLENGE,		      challenge, challenge_len, VENDOR_NONE);	rc_avpair_add(&send, PW_CHAP_PASSWORD,		      cpassword, MD5_HASH_SIZE + 1, VENDOR_NONE);	break;#ifdef CHAPMS    case CHAP_MICROSOFT:    {	/* MS-CHAP-Challenge and MS-CHAP-Response */	MS_ChapResponse *rmd = (MS_ChapResponse *) response;	u_char *p = cpassword;	if (response_len != MS_CHAP_RESPONSE_LEN)	    return 0;	*p++ = id;	/* The idiots use a different field order in RADIUS than PPP */	memcpy(p, rmd->UseNT, sizeof(rmd->UseNT));	p += sizeof(rmd->UseNT);	memcpy(p, rmd->LANManResp, sizeof(rmd->LANManResp));	p += sizeof(rmd->LANManResp);	memcpy(p, rmd->NTResp, sizeof(rmd->NTResp));	rc_avpair_add(&send, PW_MS_CHAP_CHALLENGE,		      challenge, challenge_len, VENDOR_MICROSOFT);	rc_avpair_add(&send, PW_MS_CHAP_RESPONSE,		      cpassword, MS_CHAP_RESPONSE_LEN + 1, VENDOR_MICROSOFT);	break;    }    case CHAP_MICROSOFT_V2:    {	/* MS-CHAP-Challenge and MS-CHAP2-Response */	MS_Chap2Response *rmd = (MS_Chap2Response *) response;

⌨️ 快捷键说明

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