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

📄 rlm_ldap.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
}/***************************************************************************** * *	Function: rlm_ldap_authenticate * *	Purpose: Check the user's password against ldap database * *****************************************************************************/static int ldap_authenticate(void *instance, REQUEST * request){	LDAP           *ld_user;	LDAPMessage    *result, *msg;	ldap_instance  *inst = instance;	char           *user_dn, *attrs[] = {"uid", NULL};	char		filter[MAX_FILTER_STR_LEN];	char		basedn[MAX_FILTER_STR_LEN];	int		res;	VALUE_PAIR     *vp_user_dn;	VALUE_PAIR      *module_fmsg_vp;	char            module_fmsg[MAX_STRING_LEN];	LDAP_CONN	*conn;	int		conn_id = -1;#ifdef NOVELL	char		*err = NULL;#endif	DEBUG("rlm_ldap: - authenticate");	/*	 * Ensure that we're being passed a plain-text password, and not	 * anything else.	 */	if (!request->username) {		radlog(L_AUTH, "rlm_ldap: Attribute \"User-Name\" is required for authentication.\n");		return RLM_MODULE_INVALID;	}	if (!request->password){		radlog(L_AUTH, "rlm_ldap: Attribute \"User-Password\" is required for authentication.");		DEBUG2("  You seem to have set \"Auth-Type := LDAP\" somewhere.");		DEBUG2("  THAT CONFIGURATION IS WRONG.  DELETE IT.");		DEBUG2("  YOU ARE PREVENTING THE SERVER FROM WORKING PROPERLY.");		return RLM_MODULE_INVALID;	}	if(request->password->attribute != PW_USER_PASSWORD) {		radlog(L_AUTH, "rlm_ldap: Attribute \"User-Password\" is required for authentication. Cannot use \"%s\".", request->password->name);		return RLM_MODULE_INVALID;	}	if (request->password->length == 0) {		snprintf(module_fmsg,sizeof(module_fmsg),"rlm_ldap: empty password supplied");		module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ);		pairadd(&request->packet->vps, module_fmsg_vp);		return RLM_MODULE_INVALID;	}	/*	 * Check that we don't have any failed connections. If we do there's no real need	 * of runing. Also give it another chance if we have a lot of failed connections.	 */	if (inst->failed_conns > MAX_FAILED_CONNS_END)		inst->failed_conns = 0;	if (inst->failed_conns > MAX_FAILED_CONNS_START){		inst->failed_conns++;		return RLM_MODULE_FAIL;	}	DEBUG("rlm_ldap: login attempt by \"%s\" with password \"%s\"",	       request->username->vp_strvalue, request->password->vp_strvalue);	while ((vp_user_dn = pairfind(request->config_items,				      PW_LDAP_USERDN)) == NULL) {		if (!radius_xlat(filter, sizeof(filter), inst->filter,				request, ldap_escape_func)) {			radlog (L_ERR, "rlm_ldap: unable to create filter.\n");			return RLM_MODULE_INVALID;		}		if (!radius_xlat(basedn, sizeof(basedn), inst->basedn,		 		request, ldap_escape_func)) {			radlog (L_ERR, "rlm_ldap: unable to create basedn.\n");			return RLM_MODULE_INVALID;		}		if ((conn_id = ldap_get_conn(inst->conns,&conn,inst)) == -1){			radlog(L_ERR, "rlm_ldap: All ldap connections are in use");			return RLM_MODULE_FAIL;		}		if ((res = perform_search(instance, conn, basedn, LDAP_SCOPE_SUBTREE, filter, attrs, &result)) != RLM_MODULE_OK) {			if (res == RLM_MODULE_NOTFOUND){				snprintf(module_fmsg,sizeof(module_fmsg),"rlm_ldap: User not found");				module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ);				pairadd(&request->packet->vps, module_fmsg_vp);			}			ldap_release_conn(conn_id,inst->conns);			return (res);		}		if ((msg = ldap_first_entry(conn->ld, result)) == NULL) {			ldap_msgfree(result);			ldap_release_conn(conn_id,inst->conns);			return RLM_MODULE_FAIL;		}		if ((user_dn = ldap_get_dn(conn->ld, msg)) == NULL) {			DEBUG("rlm_ldap: ldap_get_dn() failed");			ldap_msgfree(result);			ldap_release_conn(conn_id,inst->conns);			return RLM_MODULE_FAIL;		}		ldap_release_conn(conn_id,inst->conns);		pairadd(&request->config_items, pairmake("Ldap-UserDn", user_dn, T_OP_EQ));		ldap_memfree(user_dn);		ldap_msgfree(result);	}	user_dn = vp_user_dn->vp_strvalue;	DEBUG("rlm_ldap: user DN: %s", user_dn);#ifndef NOVELL	ld_user = ldap_connect(instance, user_dn, request->password->vp_strvalue,			       1, &res, NULL);#else	/* Don't perform eDirectory APC again after attempting to bind here. */	{		int apc_attr;		DICT_ATTR *dattr;		VALUE_PAIR *vp_apc;		VALUE_PAIR      *vp_auth_opt, *vp_state;		int auth_opt_attr;		char seq[256];		char host_ipaddr[32];		LDAP_CONN       *conn1;		int auth_state = -1;		char            *challenge = NULL;		int             challenge_len = MAX_CHALLENGE_LEN;		char            *state = NULL;		dattr = dict_attrbyname("eDir-APC");		apc_attr = dattr->attr;		vp_apc = pairfind(request->config_items, apc_attr);		if(vp_apc && vp_apc->vp_strvalue[0] == '2')			vp_apc->vp_strvalue[0] = '3';		res = 0;		dattr = dict_attrbyname("eDir-Auth-Option");		auth_opt_attr = dattr->attr;		vp_auth_opt = pairfind(request->config_items, auth_opt_attr);		if(vp_auth_opt )		{			DEBUG("rlm_ldap: ldap auth option = %s", vp_auth_opt->vp_strvalue);			strncpy(seq, vp_auth_opt->vp_strvalue, vp_auth_opt->length);			seq[vp_auth_opt->length] = '\0';			if( strcmp(seq, "<No Default>") ){				/* Get the client IP address to check for packet validity */				inet_ntop(AF_INET, &request->packet->src_ipaddr, host_ipaddr, sizeof(host_ipaddr));				/* challenge variable is used to receive the challenge from the				 * Token method (if any) and also to send the state attribute				 * in case the request packet is a reply to a challenge				 */				challenge = rad_malloc(MAX_CHALLENGE_LEN);				/*  If state attribute present in request it is a reply to challenge. */				if((vp_state = pairfind(request->packet->vps, PW_STATE))!= NULL ){					DEBUG("rlm_ldap: Response to Access-Challenge");					strncpy(challenge, vp_state->vp_strvalue, sizeof(challenge));					challenge_len = vp_state->length;					challenge[challenge_len] = 0;					auth_state = -2;				}				if ((conn_id = ldap_get_conn(inst->conns, &conn1, inst)) == -1){					radlog(L_ERR, "rlm_ldap: All ldap connections are in use");					res =  RLM_MODULE_FAIL;				}				if(!conn1){					radlog(L_ERR, "rlm_ldap: NULL connection handle passed");					return RLM_MODULE_FAIL;				}				if (conn1->failed_conns > MAX_FAILED_CONNS_START){					conn1->failed_conns++;					if (conn1->failed_conns >= MAX_FAILED_CONNS_END){						conn1->failed_conns = MAX_FAILED_CONNS_RESTART;						conn1->bound = 0;					}				}retry:				if (!conn1->bound || conn1->ld == NULL) {					DEBUG2("rlm_ldap: attempting LDAP reconnection");					if (conn1->ld){						DEBUG2("rlm_ldap: closing existing LDAP connection");						ldap_unbind_s(conn1->ld);					}					if ((conn1->ld = ldap_connect(instance, inst->login,inst->password, 0, &res, NULL)) == NULL) {						radlog(L_ERR, "rlm_ldap: (re)connection attempt failed");						conn1->failed_conns++;						return (RLM_MODULE_FAIL);					}					conn1->bound = 1;					conn1->failed_conns = 0;				}				DEBUG("rlm_ldap: Performing NMAS Authentication for user: %s, seq: %s \n", user_dn,seq);				res = radLdapXtnNMASAuth(conn1->ld, user_dn, request->password->vp_strvalue, seq, host_ipaddr, &challenge_len, challenge, &auth_state );				switch(res){					case LDAP_SUCCESS:						ldap_release_conn(conn_id,inst->conns);						if ( auth_state == -1)							res = RLM_MODULE_FAIL;						if ( auth_state != REQUEST_CHALLENGED){							if (auth_state == REQUEST_ACCEPTED){								DEBUG("rlm_ldap: user %s authenticated succesfully",request->username->vp_strvalue);								res = RLM_MODULE_OK;							}else if(auth_state == REQUEST_REJECTED){								DEBUG("rlm_ldap: user %s authentication failed",request->username->vp_strvalue);								res = RLM_MODULE_REJECT;							}						}else{							/* Request challenged. Generate Reply-Message attribute with challenge data */							pairadd(&request->reply->vps,pairmake("Reply-Message", challenge, T_OP_EQ));							/* Generate state attribute */							state = rad_malloc(MAX_CHALLENGE_LEN);							(void) sprintf(state, "%s%s", challenge, challenge);							vp_state = paircreate(PW_STATE, PW_TYPE_OCTETS);							memcpy(vp_state->vp_strvalue, state, strlen(state));							vp_state->length = strlen(state);							pairadd(&request->reply->vps, vp_state);							free(state);							/* Mark the packet as a Acceess-Challenge Packet */							request->reply->code = PW_ACCESS_CHALLENGE;							DEBUG("rlm_ldap: Sending Access-Challenge.");							res = RLM_MODULE_HANDLED;						}						if(challenge)							free(challenge);						return res;					case LDAP_SERVER_DOWN:						radlog(L_ERR, "rlm_ldap: nmas authentication failed: LDAP connection lost.");                                                conn->failed_conns++;						if (conn->failed_conns <= MAX_FAILED_CONNS_START){							radlog(L_INFO, "rlm_ldap: Attempting reconnect");							conn->bound = 0;							goto retry;						}						if(challenge)							free(challenge);						return RLM_MODULE_FAIL;					default:						ldap_release_conn(conn_id,inst->conns);						if(challenge)							free(challenge);						return RLM_MODULE_FAIL;				}			}		} 	}	ld_user = ldap_connect(instance, user_dn, request->password->vp_strvalue,			1, &res, &err);	if(err != NULL){		/* 'err' contains the LDAP connection error description */		DEBUG("rlm_ldap: %s", err);		pairadd(&request->reply->vps, pairmake("Reply-Message", err, T_OP_EQ));		ldap_memfree((void *)err);	}#endif	if (ld_user == NULL){		if (res == RLM_MODULE_REJECT){			inst->failed_conns = 0;			snprintf(module_fmsg,sizeof(module_fmsg),"rlm_ldap: Bind as user failed");			module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ);			pairadd(&request->packet->vps, module_fmsg_vp);		}		if (res == RLM_MODULE_FAIL){			DEBUG("rlm_ldap: ldap_connect() failed");			inst->failed_conns++;		}		return (res);	}	DEBUG("rlm_ldap: user %s authenticated succesfully",	      request->username->vp_strvalue);	ldap_unbind_s(ld_user);	inst->failed_conns = 0;	return RLM_MODULE_OK;}#ifdef NOVELL/***************************************************************************** * *	Function: rlm_ldap_postauth * *	Purpose: Perform eDirectory account policy check and failed-login reporting *	to eDirectory. * *****************************************************************************/static int ldap_postauth(void *instance, REQUEST * request){	int res = RLM_MODULE_FAIL;	int inst_attr, apc_attr;	char password[UNIVERSAL_PASS_LEN];	ldap_instance  *inst = instance;	LDAP_CONN	*conn;	VALUE_PAIR *vp_inst, *vp_apc;	DICT_ATTR *dattr;	dattr = dict_attrbyname("LDAP-Instance");	inst_attr = dattr->attr;	dattr = dict_attrbyname("eDir-APC");	apc_attr = dattr->attr;	vp_inst = pairfind(request->config_items, inst_attr);	/*	 * Check if the password in the config items list is the user's UP which has	 * been read in the authorize method of this instance of the LDAP module.	 */	if((vp_inst == NULL) || strcmp(vp_inst->vp_strvalue, inst->xlat_name))		return RLM_MODULE_NOOP;	vp_apc = pairfind(request->config_items, apc_attr);	switch(vp_apc->vp_strvalue[0]){		case '1':			/* Account policy check not enabled */		case '3':			/* Account policy check has been completed */			res = RLM_MODULE_NOOP;			break;		case '2':			{				int err, conn_id = -1;				char *error_msg = NULL;				VALUE_PAIR *vp_fdn, *vp_pwd;				DICT_ATTR *da;				if (request->reply->code == PW_AUTHENTICATION_REJECT) {				  /* Bind to eDirectory as the RADIUS user with a wrong password. */				  vp_pwd = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD);				  strcpy(password, vp_pwd->vp_strvalue);				  if (strlen(password) > 0) {					  if (password[0] != 'a') {						  password[0] = 'a';					  } else {						  password[0] = 'b';					  }				  } else {					  strcpy(password, "dummy_password");				  }				  res = RLM_MODULE_REJECT;				} else {					/* Bind to eDirectory as the RADIUS user using the user's UP */					vp_pwd = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD);					if (vp_pwd == NULL) {						DEBUG("rlm_ldap: User's Universal Password not in config items list.");						return RLM_MODULE_FAIL;					}					strcpy(password, vp_pwd->vp_strvalue);				}				if ((da = dict_attrbyname("Ldap-UserDn")) == NULL) {					DEBUG("rlm_ldap: Attribute for user FDN not found in dictionary. Unable to proceed");					return RLM_MODULE_FAIL;				}				vp_fdn = pairfind(request->config_items, da->attr);				if (vp_fdn == NULL) {					DEBUG("rlm_ldap: User's FQDN not in config items list.");					return RLM_MODULE_FAIL;				}				if ((conn_id = ldap_get_conn(inst->apc_conns, &conn, inst)) == -1){					radlog(L_ERR, "rlm_ldap: All ldap connections are in use");					return RLM_MODULE_FAIL;				}				/*				 *	If there is an existing LDAP				 *	connection to the directory,				 *	bind over it. Otherwise,				 *	establish a new connection.				 */			postauth_reconnect:				if (!conn->bound || conn->ld == NULL) {					DEBUG2("rlm_ldap: attempting LDAP reconnection");					if (conn->ld){						DEBUG2("rlm_ldap: closing existing LDAP connection");						ldap_unbind_s(conn->ld);					}					if ((conn->ld = ldap_connect(instance, (char *)vp_fdn->vp_strvalue, password, 0, &res, &error_msg)) == NULL) {						radlog(L_ERR, "rlm_ldap: eDirectory account policy check failed.");						if (error_msg != NULL) {							DEBUG("rlm_ldap: %s", error_msg);							pairadd(&request->reply->vps, pairmake("Reply-Message", error_msg, T_OP_EQ));							ldap_memfree((void *)error_msg);						}						vp_apc->vp_strvalue[0] = '3';						ldap_release_conn(conn_id, inst->apc_conns);						return RLM_MODULE_REJECT;					}					conn->bound = 1;				} else if((err = ldap_simple_bind_s(conn->ld, (char *)vp_fdn->vp_strvalue, password)) != LDAP_SUCCESS) {					if (err == LDAP_SERVER_DOWN) {						conn->bound = 0;						goto postauth_reconnect;					}					DEBUG("rlm_ldap: eDirectory account policy check failed.");					l

⌨️ 快捷键说明

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