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

📄 rlm_pam.c

📁 RADIUS认证协议
💻 C
字号:
/* * pam.c	Functions to access the PAM library. This was taken *		from the hacks that miguel a.l. paraz <map@iphil.net> *		did on radiusd-cistron-1.5.3 and migrated to a *		separate file. * *		That, in fact, was again based on the original stuff *		from Jeph Blaize <jblaize@kiva.net> done in May 1997. * * Version:	$Id: rlm_pam.c,v 1.32 2004/02/26 19:04:33 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 1997  Jeph Blaize <jblaize@kiva.net> * Copyright 1999  miguel a.l. paraz <map@iphil.net> */#include	"autoconf.h"#include	"libradius.h"#include	"config.h"#include	<stdio.h>#include	<stdlib.h>#include	<string.h>#ifdef HAVE_SECURITY_PAM_APPL_H#include	<security/pam_appl.h>#endif#ifdef HAVE_PAM_PAM_APPL_H#include	<pam/pam_appl.h>#endif#ifdef HAVE_SYSLOG_H#include	<syslog.h>#endif#include	"radiusd.h"#include	"modules.h"typedef struct rlm_pam_t {	const char *pam_auth_name;} rlm_pam_t;static CONF_PARSER module_config[] = {	{ "pam_auth",    PW_TYPE_STRING_PTR, offsetof(rlm_pam_t,pam_auth_name),	  NULL, "radiusd" },	{ NULL, -1, 0, NULL, NULL }};/* *	(Re-)read radiusd.conf into memory. */static int pam_instantiate(CONF_SECTION *conf, void **instance){	rlm_pam_t *data;	data = rad_malloc(sizeof(*data));	if (!data) {		return -1;	}	memset(data, 0, sizeof(*data));	if (cf_section_parse(conf, data, module_config) < 0) {		free(data);		return -1;	}	*instance = data;	return 0;}/* *	Clean up. */static int pam_detach(void *instance){	rlm_pam_t *data = (rlm_pam_t *) instance;	free((char *) data->pam_auth_name);        free((char *) data);	return 0;}/************************************************************************* * *	Function: PAM_conv * *	Purpose: Dialogue between RADIUS and PAM modules. * * jab - stolen from pop3d * * Alan DeKok: modified to use PAM's appdata_ptr, so that we're *             multi-threaded safe, and don't have any nasty static *             variables hanging around. * *************************************************************************/typedef struct my_PAM {  const char *username;  const char *password;  int         error;} my_PAM;static int PAM_conv (int num_msg,                     const struct pam_message **msg,                     struct pam_response **resp,                     void *appdata_ptr) {  int count = 0, replies = 0;  struct pam_response *reply = NULL;  int size = sizeof(struct pam_response);  my_PAM *pam_config = (my_PAM *) appdata_ptr;#define GET_MEM if (reply) realloc(reply, size); else reply = rad_malloc(size); \  size += sizeof(struct pam_response)#define COPY_STRING(s) ((s) ? strdup(s) : NULL)  for (count = 0; count < num_msg; count++) {    switch (msg[count]->msg_style) {    case PAM_PROMPT_ECHO_ON:      GET_MEM;      reply[replies].resp_retcode = PAM_SUCCESS;      reply[replies++].resp = COPY_STRING(pam_config->username);      /* PAM frees resp */      break;    case PAM_PROMPT_ECHO_OFF:      GET_MEM;      reply[replies].resp_retcode = PAM_SUCCESS;      reply[replies++].resp = COPY_STRING(pam_config->password);      /* PAM frees resp */      break;    case PAM_TEXT_INFO:      /* ignore it... */      break;    case PAM_ERROR_MSG:    default:      /* Must be an error of some sort... */      free (reply);      pam_config->error = 1;      return PAM_CONV_ERR;    }  }  if (reply) *resp = reply;  return PAM_SUCCESS;}/************************************************************************* * *	Function: pam_pass * *	Purpose: Check the users password against the standard UNIX *		 password table + PAM. * * jab start 19970529 *************************************************************************//* cjd 19980706 * * for most flexibility, passing a pamauth type to this function * allows you to have multiple authentication types (i.e. multiple * files associated with radius in /etc/pam.d) */static int pam_pass(const char *name, const char *passwd, const char *pamauth){    pam_handle_t *pamh=NULL;    int retval;    my_PAM pam_config;    struct pam_conv conv;    /*     *  Initialize the structures.     */    conv.conv = PAM_conv;    conv.appdata_ptr = &pam_config;    pam_config.username = name;    pam_config.password = passwd;    pam_config.error = 0;    DEBUG("pam_pass: using pamauth string <%s> for pam.conf lookup", pamauth);    retval = pam_start(pamauth, name, &conv, &pamh);    if (retval != PAM_SUCCESS) {      DEBUG("pam_pass: function pam_start FAILED for <%s>. Reason: %s",	    name, pam_strerror(pamh, retval));      return -1;    }    retval = pam_authenticate(pamh, 0);    if (retval != PAM_SUCCESS) {      DEBUG("pam_pass: function pam_authenticate FAILED for <%s>. Reason: %s",	    name, pam_strerror(pamh, retval));      pam_end(pamh, retval);      return -1;    }    /*     * FreeBSD 3.x doesn't have account and session management     * functions in PAM, while 4.0 does.     */#if !defined(__FreeBSD_version) || (__FreeBSD_version >= 400000)    retval = pam_acct_mgmt(pamh, 0);    if (retval != PAM_SUCCESS) {      DEBUG("pam_pass: function pam_acct_mgmt FAILED for <%s>. Reason: %s",	    name, pam_strerror(pamh, retval));      pam_end(pamh, retval);      return -1;    }#endif    DEBUG("pam_pass: authentication succeeded for <%s>", name);    pam_end(pamh, retval);    return 0;}/* translate between function declarations */static int pam_auth(void *instance, REQUEST *request){	int	r;	VALUE_PAIR *pair;	rlm_pam_t *data = (rlm_pam_t *) instance;	const char *pam_auth_string = data->pam_auth_name;	/*	 *	We can only authenticate user requests which HAVE	 *	a User-Name attribute.	 */	if (!request->username) {		radlog(L_AUTH, "rlm_pam: Attribute \"User-Name\" is required for authentication.");		return RLM_MODULE_INVALID;	}	/*	 *	We can only authenticate user requests which HAVE	 *	a User-Password attribute.	 */	if (!request->password) {		radlog(L_AUTH, "rlm_pam: Attribute \"User-Password\" is required for authentication.");		return RLM_MODULE_INVALID;	}	/*	 *  Ensure that we're being passed a plain-text password,	 *  and not anything else.	 */	if (request->password->attribute != PW_PASSWORD) {		radlog(L_AUTH, "rlm_pam: Attribute \"User-Password\" is required for authentication.  Cannot use \"%s\".", request->password->name);		return RLM_MODULE_INVALID;	}	/*	 *	Let the 'users' file over-ride the PAM auth name string,	 *	for backwards compatibility.	 */	pair = pairfind(request->config_items, PAM_AUTH_ATTR);	if (pair) pam_auth_string = (char *)pair->strvalue;	r = pam_pass((char *)request->username->strvalue,		     (char *)request->password->strvalue,		     pam_auth_string);#ifdef HAVE_SYSLOG_H	if (!strcmp(radlog_dir, "syslog")) {		openlog(progname, LOG_PID, syslog_facility);	}#endif	if (r == 0) {		return RLM_MODULE_OK;	}	return RLM_MODULE_REJECT;}module_t rlm_pam = {  "Pam",  RLM_TYPE_THREAD_UNSAFE,	/* The PAM libraries are not thread-safe */  NULL,				/* initialize */  pam_instantiate,		/* instantiation */  {	  pam_auth,		/* authenticate */	  NULL,			/* authorize */	  NULL,			/* pre-accounting */	  NULL,			/* accounting */	  NULL,			/* checksimul */	  NULL,			/* pre-proxy */	  NULL,			/* post-proxy */	  NULL			/* post-auth */  },  pam_detach,			/* detach */  NULL,				/* destroy */};

⌨️ 快捷键说明

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