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

📄 pam_radius.c

📁 gnu 的radius服务器很好用的
💻 C
📖 第 1 页 / 共 2 页
字号:
/* This file is part of GNU Radius.   Copyright (C) 2001,2002,2003,2004 Free Software Foundation, Inc.   Written by Sergey Poznyakoff    GNU Radius is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.    GNU Radius is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.    You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software Foundation,    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */#if defined(HAVE_CONFIG_H)# include <config.h>#endif#ifdef HAVE__PAM_ACONF_H#include <security/_pam_aconf.h>#endif#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <ctype.h>#include <syslog.h>#include <errno.h>#include <common.h> #include <radius/radutmp.h>/* indicate the following groups are defined */#define PAM_SM_AUTH#define PAM_SM_SESSION#ifndef LINUX_PAM#include <security/pam_appl.h>#endif                          /* LINUX_PAM */#include <security/pam_modules.h>#ifndef PAM_CONV_AGAIN# define PAM_CONV_AGAIN PAM_TRY_AGAIN#endif#ifndef PAM_AUTHTOK_RECOVER_ERR# define PAM_AUTHTOK_RECOVER_ERR PAM_AUTHTOK_RECOVERY_ERR#endif#ifndef PAM_EXTERN# define PAM_EXTERN#endif#define PAM_OVERWRITE(s)        \  do {                           \        register char *p;        \        if  ((p = s) != NULL)    \            while (*p) *p++ = 0; \  } while (0) #define PAM_DROP_REPLY(reply, nrepl)                 \  do {                                                \        int i;                                        \        for (i=0; i<nrepl; i++) {                     \            PAM_OVERWRITE(reply[i].resp);             \            free(reply[i].resp);                      \        }                                             \        if (reply)                                    \            free(reply);                              \  } while (0)        static void_pam_delete(char *x){        PAM_OVERWRITE(x);        free(x);}static void_cleanup_string(pam_handle_t *pamh, void *x, int error_status){        _pam_delete(x);}/* Clean up the temporary A/V pair list */static void_cleanup_fake_pairlist(grad_avp_t *p){	grad_avp_t *next;	while (p) {		next = p->next;		grad_free(p);		p = next;	}}static void_cleanup_pairlist(pam_handle_t *pamh, void *x, int error_status){	_cleanup_fake_pairlist(x); }/* logging */static void_pam_vlog(int err, const char *format, va_list args){        openlog("pam_radius", LOG_CONS|LOG_PID, LOG_AUTH);        vsyslog(err, format, args);        closelog();}static void_pam_log(int err, const char *format, ...){        va_list args;        va_start(args, format);        _pam_vlog(err, format, args);        va_end(args);}static void_pam_debug(char *format, ...){        va_list args;	va_start(args, format);        _pam_vlog(LOG_DEBUG, format, args);        va_end(args);}/* Maps radius priorities into syslog ones */int priority[] = {        LOG_EMERG,        LOG_ALERT,        LOG_CRIT,        LOG_ERR,        LOG_WARNING,        LOG_NOTICE,        LOG_INFO,        LOG_DEBUG};voidvlog(int level,     const grad_request_t *req,     const grad_locus_t *loc,     const char *func_name, int en,     const char *fmt, va_list ap){        openlog("pam_radius", LOG_CONS|LOG_PID, LOG_AUTH);        vsyslog(priority[level & L_PRIMASK], fmt, ap);        if (en)                syslog(priority[level & L_PRIMASK], "syserr: %s (%d)",                       strerror(en), en);        closelog();}#define CNTL_DEBUG       0x0001#define CNTL_AUDIT       0x0002#define CNTL_AUTHTOK     0x0004#define CNTL_HANG_OFF         8#define CNTL_HANG()           ((cntl_flags>>CNTL_HANG_OFF) & 0xff)#define CNTL_SET_HANG(cntl,n) (cntl |= (((n) & 0xff)<<CNTL_HANG_OFF))#define CNTL_DEBUG_OFF   16#define CNTL_DEBUG_LEV() ((cntl_flags>>CNTL_DEBUG_OFF) & 0xff)#define CNTL_SET_DEBUG_LEV(cntl,n) (cntl |= (((n) & 0xff)<<CNTL_DEBUG_OFF))/* Hang modes */#define HANG_START 1#define HANG_STOP  2static int cntl_flags;static char *radius_confdir = RADDB_DIR;static char *service_type = NULL;#define DEBUG(m,c) if (CNTL_DEBUG_LEV()>=(m)) _pam_debug c#define AUDIT(c) if (cntl_flags&CNTL_AUDIT) _pam_debug c#define XSTRDUP(s) (s) ? strdup(s) : NULLstatic voidmake_str(pam_handle_t *pamh, const char *str, const char *name, char **ret){        int retval;        char *newstr = XSTRDUP(str);        retval = pam_set_data(pamh, name, (void *)newstr, _cleanup_string);        if (retval != PAM_SUCCESS) {                _pam_log(LOG_CRIT,                          "can't keep data [%s]: %s",                         name,                         pam_strerror(pamh, retval));                _pam_delete(newstr);        } else {                *ret = newstr;                newstr = NULL;        }}#define MAKE_STR(pamh, str, var) \ make_str(pamh,str,#var,&var)        static void_pam_parse(pam_handle_t *pamh, int argc, const char **argv){        int ctrl=0;	int in_attr = 0;	grad_avp_t *head = NULL, *tail = NULL;	        /* step through arguments */        for (ctrl=0; argc-- > 0; ++argv) {				if (in_attr) {			char *p = strchr(*argv, '=');			grad_avp_t *pair;						if (!p) {				_pam_log(LOG_ERR,					 "pam_parse: error near %s", *argv);				continue;			}			*p++ = 0;						pair = grad_emalloc(sizeof(*pair));			pair->next = NULL;			pair->name = (char *) *argv;			pair->avp_strvalue = p;			if (tail)				tail->next = pair;			else				head = pair;			tail = pair;		}		else if (!strcmp(*argv,"attr:"))			in_attr = 1;		                /* generic options */                else if (!strncmp(*argv,"debug",5)) {                        ctrl |= CNTL_DEBUG;                        if ((*argv)[5] == '=')                                 CNTL_SET_DEBUG_LEV(ctrl,atoi(*argv+6));                        else                                CNTL_SET_DEBUG_LEV(ctrl,1);                } else if (!strcmp(*argv,"audit"))                        ctrl |= CNTL_AUDIT;                else if (!strcmp(*argv,"waitdebug"))                        CNTL_SET_HANG(ctrl,HANG_START|HANG_STOP);		else if (!strncmp(*argv,"hang=",5)) 			CNTL_SET_HANG(ctrl,(*argv)[6] - '0');		else if (!strcmp(*argv,"hang"))			CNTL_SET_HANG(ctrl,HANG_START|HANG_STOP);                else if (!strcmp(*argv,"use_authtok"))                        ctrl |= CNTL_AUTHTOK;                else if (!strncmp(*argv,"confdir=",8))                         MAKE_STR(pamh, *argv+8, radius_confdir);		else if (!strncmp(*argv,"utmpdir=",8))			MAKE_STR(pamh, *argv+8, radlog_dir);                else if (!strncmp(*argv,"service_type=",13))                         MAKE_STR(pamh, *argv+13, service_type);                else {                        _pam_log(LOG_ERR,"pam_parse: unknown option; %s",				 *argv);                }        }	if (head) {		int retval = pam_set_data(pamh, "radius_pairlist",					  head, _cleanup_pairlist);		if (retval != PAM_SUCCESS) {			_pam_log(LOG_CRIT, 				 "can't keep data [%s]: %s",				 "radius_pairlist",				 pam_strerror(pamh, retval));			_cleanup_fake_pairlist(head);		}	}        cntl_flags = ctrl;}static void_cleanup_server_queue(pam_handle_t *pamh, void *x, int error_status){        grad_client_destroy_queue(x);}static void_cleanup_request(pam_handle_t *pamh, void *x, int error_status){        grad_request_free((grad_request_t*)x);}int_read_client_config(pam_handle_t *pamh){        int errcnt = 0;        grad_server_queue_t *queue;                queue = grad_client_create_queue(1, 0, 0);        if (!queue)                return -1;        /*         * Consistency check         */        if (grad_list_count(queue->servers) == 0) {                _pam_log(LOG_ERR, "config: no server selected");                errcnt++;        }        if (queue->timeout == 0) {                _pam_log(LOG_ERR, "config: zero timeout value");                errcnt++;        }        if (errcnt) {                /* free allocated memory */                grad_client_destroy_queue(queue);        } else {                errcnt = pam_set_data(pamh,                                      "radius_server_queue",                                       (void *)queue,                                      _cleanup_server_queue);                if (errcnt != PAM_SUCCESS) {                        _pam_log(LOG_CRIT,                                  "can't keep data [%s]: %s",                                 "radius_server_queue",                                 pam_strerror(pamh, errcnt));                        grad_client_destroy_queue(queue);                        errcnt = 1;                }        }        return errcnt;}static int_pam_init_radius_client(pam_handle_t *pamh){        int rc = 0;                DEBUG(100,("enter _pam_init_radius_client"));        radius_dir = radius_confdir;        grad_path_init();        if (grad_dict_init()) {                _pam_log(LOG_CRIT, "grad_dict_init failed");                return 1;        }        rc = _read_client_config(pamh);                DEBUG(100,("exit _pam_init_radius_client"));        return rc;}static int_radius_auth(pam_handle_t *pamh, char *name, char *password){        grad_server_queue_t *queue;        int retval;        grad_avp_t *pairs, *namepair, *add_pair = NULL;        grad_request_t *authreq;        grad_dict_value_t *dv;	grad_locus_t loc = { __FILE__, __LINE__ }; /* FIXME */        retval = pam_get_data(pamh,                              "radius_server_queue",                               (const void **)&queue);        if (retval != PAM_SUCCESS) {                _pam_log(LOG_CRIT,                          "can't get [radius_server_queue]: %s",                         pam_strerror(pamh, retval));                return PAM_AUTHINFO_UNAVAIL;        }        retval = pam_get_data(pamh,                              "radius_pairlist",                               (const void **)&add_pair);        if (retval != PAM_SUCCESS && retval != PAM_NO_MODULE_DATA) {                _pam_log(LOG_CRIT,                          "can't get [radius_attrlist]: %s",                         pam_strerror(pamh, retval));                return PAM_AUTHINFO_UNAVAIL;        }        /*         * Create authentication request         */        pairs = NULL;	namepair = grad_avp_create_string(DA_USER_NAME, name);        grad_avl_add_pair(&pairs, namepair);        grad_avl_add_pair(&pairs,			  grad_avp_create_string(DA_USER_PASSWORD, password));        grad_avl_add_pair(&pairs,			  grad_avp_create_integer(DA_NAS_IP_ADDRESS,						  queue->source_ip));	/* Add any additional attributes */	for (; add_pair; add_pair = add_pair->next) {		grad_avp_t *p = grad_create_pair(&loc,						 add_pair->name, 						 grad_operator_equal,						 add_pair->avp_strvalue);		grad_avl_add_pair(&pairs, p);	}	/* For compatibility with previous versions handle service_type */        if (service_type &&            (dv = grad_value_name_to_value(service_type, DA_SERVICE_TYPE))) {                DEBUG(10, ("adding Service-Type=%d", dv->value));                grad_avl_add_pair(&pairs,				  grad_avp_create_integer(DA_SERVICE_TYPE,							  dv->value));        }        authreq = grad_client_send(queue,				   GRAD_PORT_AUTH, RT_ACCESS_REQUEST, pairs);        if (authreq == NULL) {                _pam_log(LOG_ERR,                         "no response from radius server");                grad_avl_free(pairs);                return PAM_AUTHINFO_UNAVAIL;        }        switch (authreq->code) {        case RT_ACCESS_ACCEPT:                break;		        case RT_ACCESS_REJECT:                /* FIXME: radius may have returned Reply-Message attribute.                 * we should return it to the caller                 */                grad_request_free(authreq);                return PAM_USER_UNKNOWN;		        default:                _pam_log(LOG_CRIT,                         "received unexpected response: %d", authreq->code);                grad_request_free(authreq);                return PAM_AUTH_ERR;        }        /*         * authentity acknowledged.         * Preserve returned attributes;         */        retval = pam_set_data(pamh, "authreq",                              (void *)authreq,                              _cleanup_request);        if (retval != PAM_SUCCESS) {                _pam_log(LOG_CRIT,                          "can't keep data authreq: %s",                         pam_strerror(pamh, retval));                grad_request_free(authreq);        }        /* add username to the response (do we need it still?) */        grad_avl_add_pair(&authreq->avlist, grad_avp_dup(namepair));

⌨️ 快捷键说明

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