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

📄 rlm_unix.c

📁 free radius编程。完成AAA的实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * rlm_unix.c	authentication: Unix user authentication *		accounting:     Functions to write radwtmp file. *		Also contains handler for "Group". * * Version:	$Id: rlm_unix.c,v 1.63 2004/02/26 19:04:37 aland Exp $ * *   This program 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. * *   This program 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 * * Copyright 2000  The FreeRADIUS server project * Copyright 2000  Jeff Carneal <jeff@apex.net> * Copyright 2000  Alan Curry <pacman@world.std.com> */static const char rcsid[] = "$Id: rlm_unix.c,v 1.63 2004/02/26 19:04:37 aland Exp $";#include	"autoconf.h"#include	"libradius.h"#include	<stdlib.h>#include	<string.h>#include	<grp.h>#include	<pwd.h>#include	<sys/types.h>#include	<sys/stat.h>#include "config.h"#ifdef HAVE_SHADOW_H#  include	<shadow.h>#endif#ifdef OSFC2#  include	<sys/security.h>#  include	<prot.h>#endif#ifdef OSFSIA#  include	<sia.h>#  include	<siad.h>#endif#include	"radiusd.h"#include	"modules.h"#include	"sysutmp.h"#include	"cache.h"#include	"conffile.h"#include	"compat.h"static char trans[64] =   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";#define ENC(c) trans[c]struct unix_instance {	int cache_passwd;	const char *passwd_file;	const char *shadow_file;	const char *group_file;	const char *radwtmp;	int usegroup;	struct pwcache *cache;	time_t cache_reload;	time_t next_reload;	time_t last_reload;};static CONF_PARSER module_config[] = {	/*	 *	Cache the password by default.	 */	{ "cache",    PW_TYPE_BOOLEAN,	  offsetof(struct unix_instance,cache_passwd), NULL, "no" },	{ "passwd",   PW_TYPE_STRING_PTR,	  offsetof(struct unix_instance,passwd_file), NULL,  NULL },	{ "shadow",   PW_TYPE_STRING_PTR,	  offsetof(struct unix_instance,shadow_file), NULL,  NULL },	{ "group",    PW_TYPE_STRING_PTR,	  offsetof(struct unix_instance,group_file), NULL,   NULL },	{ "radwtmp",  PW_TYPE_STRING_PTR,	  offsetof(struct unix_instance,radwtmp), NULL,   "NULL" },	{ "usegroup", PW_TYPE_BOOLEAN,	  offsetof(struct unix_instance,usegroup), NULL,     "no" },	{ "cache_reload", PW_TYPE_INTEGER,	  offsetof(struct unix_instance,cache_reload), NULL, "600" },	{ NULL, -1, 0, NULL, NULL }		/* end the list */};/* * groupcmp is part of autz. But it uses the data from an auth instance. So * here is where it gets it. By default this will be the first configured * auth instance. That can be changed by putting "usegroup = yes" inside an * auth instance to explicitly bind all Group checks to it. *//* binds "Group=" to an instance (a particular passwd file) */static struct unix_instance *group_inst;/* Tells if the above binding was explicit (usegroup=yes specified in config * file) or not ("Group=" was bound to the first instance of rlm_unix */static int group_inst_explicit;#ifdef HAVE_GETSPNAM#if defined(M_UNIX)static inline const char *get_shadow_name(shadow_pwd_t *spwd) {	if (spwd == NULL) return NULL;	return (spwd->pw_name);}static inline const char *get_shadow_encrypted_pwd(shadow_pwd_t *spwd) {	if (spwd == NULL) return NULL;	return (spwd->pw_passwd);}#else /* M_UNIX */	static inline const char *get_shadow_name(shadow_pwd_t *spwd) {		if (spwd == NULL) return NULL;		return (spwd->sp_namp);	}	static inline const char *get_shadow_encrypted_pwd(shadow_pwd_t *spwd) {		if (spwd == NULL) return NULL;		return (spwd->sp_pwdp);	}#endif	/* M_UNIX */#endif	/* HAVE_GETSPNAM */static struct passwd *fgetpwnam(const char *fname, const char *name) {	FILE		*file = fopen(fname, "ro");	struct passwd	*pwd = NULL;	if(file == NULL) return NULL;	do {		pwd = fgetpwent(file);		if(pwd == NULL) {			fclose(file);			return NULL;		}	} while (strcmp(name, pwd->pw_name) != 0);	fclose(file);	return pwd;}static struct group *fgetgrnam(const char *fname, const char *name) {	FILE		*file = fopen(fname, "ro");	struct group	*grp = NULL;	if(file == NULL) return NULL;	do {		grp = fgetgrent(file);		if(grp == NULL) {			fclose(file);			return NULL;		}	} while(strcmp(name, grp->gr_name) != 0);	fclose(file);	return grp;}#ifdef HAVE_GETSPNAMstatic shadow_pwd_t *fgetspnam(const char *fname, const char *name) {	FILE		*file = fopen(fname, "ro");	shadow_pwd_t	*spwd = NULL;	if(file == NULL) return NULL;	do {		spwd = fgetspent(file);		if(spwd == NULL) {			fclose(file);			return NULL;		}	} while(strcmp(name, get_shadow_name(spwd)) != 0);	fclose(file);	return spwd;}#endif/* *	The Group = handler. */static int groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request,		    VALUE_PAIR *check, VALUE_PAIR *check_pairs,		    VALUE_PAIR **reply_pairs){	struct passwd	*pwd;	struct group	*grp;	char		**member;	char		*username;	int		retval;	VALUE_PAIR	*vp;	instance = instance;	check_pairs = check_pairs;	reply_pairs = reply_pairs;	if (!group_inst) {		radlog(L_ERR, "groupcmp: no group list known.");		return 1;	}	/*	 *	No user name, doesn't compare.	 */	vp = pairfind(request, PW_STRIPPED_USER_NAME);	if (!vp) {		vp = pairfind(request, PW_USER_NAME);		if (!vp) {			return -1;		}	}	username = (char *)vp->strvalue;	if (group_inst->cache_passwd &&	    (retval = H_groupcmp(group_inst->cache, check, username)) != -2)		return retval;	if (group_inst->passwd_file)		pwd = fgetpwnam(group_inst->passwd_file, username);	else		pwd = getpwnam(username);	if (pwd == NULL)		return -1;	if (group_inst->group_file)		grp = fgetgrnam(group_inst->group_file, (char *)check->strvalue);	else		grp = getgrnam((char *)check->strvalue);	if (grp == NULL)		return -1;	retval = (pwd->pw_gid == grp->gr_gid) ? 0 : -1;	if (retval < 0) {		for (member = grp->gr_mem; *member && retval; member++) {			if (strcmp(*member, pwd->pw_name) == 0)				retval = 0;		}	}	return retval;}/* *	FIXME:	We really should have an 'init' which makes *	System auth == Unix */static int unix_init(void){	/* FIXME - delay these until a group file has been read so we know	 * groupcmp can actually do something */	paircompare_register(PW_GROUP, PW_USER_NAME, groupcmp, NULL);#ifdef PW_GROUP_NAME /* compat */	paircompare_register(PW_GROUP_NAME, PW_USER_NAME, groupcmp, NULL);#endif	return 0;}static int unix_instantiate(CONF_SECTION *conf, void **instance){	struct unix_instance *inst;	/*	 *	Allocate room for the instance.	 */	inst = *instance = rad_malloc(sizeof(*inst));	if (!inst) {		return -1;	}	memset(inst, 0, sizeof(*inst));	/*	 *	Parse the configuration, failing if we can't do so.	 */	if (cf_section_parse(conf, inst, module_config) < 0) {		free(inst);		return -1;	}	if (inst->cache_passwd) {		radlog(L_INFO, "HASH:  Reinitializing hash structures "			"and lists for caching...");		if ((inst->cache = unix_buildpwcache(inst->passwd_file,						     inst->shadow_file,						     inst->group_file))==NULL)                {			radlog(L_ERR, "HASH:  unable to create user "				"hash table.  disable caching and run debugs");			if (inst->passwd_file)				free((char *) inst->passwd_file);			if (inst->shadow_file)				free((char *) inst->shadow_file);			if (inst->group_file)				free((char *) inst->group_file);			if (inst->radwtmp)				free((char *) inst->radwtmp);			free(inst);			return -1;		}		if (inst->cache_reload) {			inst->last_reload = 0;			inst->next_reload = time(NULL) + inst->cache_reload;		}	} else {		inst->cache = NULL;	}	if (inst->usegroup) {		if (group_inst_explicit) {			radlog(L_ERR, "Only one group list may be active");		} else {			group_inst = inst;			group_inst_explicit = 1;		}	} else if (!group_inst) {		group_inst = inst;	}#undef inst	return 0;}/* *	Detach. */static int unix_detach(void *instance){#define inst ((struct unix_instance *)instance)	if (group_inst == inst) {		group_inst = NULL;		group_inst_explicit = 0;	}	if (inst->passwd_file)		free((char *) inst->passwd_file);	if (inst->shadow_file)		free((char *) inst->shadow_file);	if (inst->group_file)		free((char *) inst->group_file);	if (inst->radwtmp)		free((char *) inst->radwtmp);	if (inst->cache) {		unix_freepwcache(inst->cache);	}#undef inst	free(instance);	return 0;}static int unix_destroy(void){	paircompare_unregister(PW_GROUP, groupcmp);#ifdef PW_GROUP_NAME	paircompare_unregister(PW_GROUP_NAME, groupcmp);#endif	return 0;}/* *	Check the users password against the standard UNIX *	password table. */static int unix_authenticate(void *instance, REQUEST *request){#define inst ((struct unix_instance *)instance)	char *name, *passwd;	struct passwd	*pwd;	const char	*encrypted_pass;	int		ret;#ifdef HAVE_GETSPNAM	shadow_pwd_t	*spwd = NULL;#endif#ifdef OSFC2	struct pr_passwd *pr_pw;#endif#ifdef OSFSIA	char		*info[2];	char		*progname = "radius";	SIAENTITY	*ent = NULL;#endif#ifdef HAVE_GETUSERSHELL	char		*shell;#endif	/* See if we should refresh the cache */	if (inst->cache && inst->cache_reload	 && (inst->next_reload < request->timestamp)) {		/* Time to refresh, maybe ? */		int must_reload = 0;		struct stat statbuf;		DEBUG2("rlm_users : Time to refresh cache.");		/* Check if any of the files has changed */		if (inst->passwd_file		 && (stat(inst->passwd_file, &statbuf) != -1)		 && (statbuf.st_mtime > inst->last_reload)) {			must_reload++;		}		if (inst->shadow_file		 && (stat(inst->shadow_file, &statbuf) != -1)		 && (statbuf.st_mtime > inst->last_reload)) {			must_reload++;		}		if (inst->group_file		 && (stat(inst->group_file, &statbuf) != -1)		 && (statbuf.st_mtime > inst->last_reload)) {			must_reload++;		}

⌨️ 快捷键说明

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