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

📄 rlm_ldap.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		 */		group_name = rad_malloc((strlen(xlat_name) + 1 + 11) * sizeof(char));		sprintf(group_name,"%s-Ldap-Group",xlat_name);		DEBUG("rlm_ldap: Creating new attribute %s",group_name);		dict_addattr(group_name, 0, PW_TYPE_STRING, -1, flags);		dattr = dict_attrbyname(group_name);		if (dattr == NULL){			radlog(L_ERR, "rlm_ldap: Failed to create attribute %s",group_name);			free(group_name);			free(inst);	/* FIXME: detach */			return -1;		}		DEBUG("rlm_ldap: Registering ldap_groupcmp for %s",group_name);		paircompare_register(dattr->attr, PW_USER_NAME, ldap_groupcmp, inst);		free(group_name);	}	else {		xlat_name = cf_section_name1(conf);		rad_assert(xlat_name != NULL); /* or all hell breaks loose */	}	inst->xlat_name = strdup(xlat_name);	DEBUG("rlm_ldap: Registering ldap_xlat with xlat_name %s",xlat_name);	xlat_register(xlat_name,ldap_xlat,inst);	/*	 *	Over-ride set_auth_type if there's no Auth-Type of our name.	 *	This automagically catches the case where LDAP is listed	 *	in "authorize", but not "authenticate".	 */	if (inst->set_auth_type) {		DICT_VALUE *dv = dict_valbyname(PW_AUTH_TYPE, xlat_name);		if (!dv) {			DEBUG2("rlm_ldap: Over-riding set_auth_type, as there is no module %s listed in the \"authenticate\" section.", xlat_name);			inst->set_auth_type = 0;		}	} /* else no need to look up the value */#ifdef NOVELL	/*	 *	(LDAP_Instance, V1) attribute-value pair in the config	 *	items list means that the 'authorize' method of the	 *	instance 'V1' of the LDAP module has processed this	 *	request.	 */	dict_addattr("LDAP-Instance", 0, PW_TYPE_STRING, -1, flags);	/*	 *	('eDir-APC', '1') in config items list	 *	Do not perform eDirectory account policy check (APC)	 *	 *	('eDir-APC', '2') in config items list	 *	Perform eDirectory APC	 *	 *	('eDir-APC', '3') in config items list	 *	eDirectory APC has been completed	 */	dict_addattr("eDir-APC", 0, PW_TYPE_STRING, -1, flags);	/*	 *	eDir-Auth-Option allows for a different NMAS Authentication method to be used instead of password	 */	dict_addattr("eDir-Auth-Option", 0, PW_TYPE_STRING, -1, flags);#endif	if (inst->num_conns <= 0){		radlog(L_ERR, "rlm_ldap: Invalid ldap connections number passed.");		free(inst);	/* FIXME: detach */		return -1;	}	inst->conns = malloc(sizeof(*(inst->conns))*inst->num_conns);	if (inst->conns == NULL){		radlog(L_ERR, "rlm_ldap: Could not allocate memory. Aborting.");		free(inst);	/* FIXME: detach */		return -1;	}	for(i = 0; i < inst->num_conns; i++){		inst->conns[i].bound = 0;		inst->conns[i].locked = 0;		inst->conns[i].failed_conns = 0;		inst->conns[i].ld = NULL;		pthread_mutex_init(&inst->conns[i].mutex, NULL);	}#ifdef NOVELL	/*	 *	'inst->apc_conns' is a separate connection pool to be	 *	used for performing eDirectory account policy check in	 *	the 'postauth' method. This avoids changing the	 *	(RADIUS server) credentials associated with the	 *	'inst->conns' connection pool.	 */	inst->apc_conns = malloc(sizeof(*(inst->apc_conns))*inst->num_conns);	if (inst->apc_conns == NULL){		radlog(L_ERR, "rlm_ldap: Could not allocate memory. Aborting.");		free(inst);	/* FIXME: detach */		return -1;	}	for(i = 0; i < inst->num_conns; i++){		inst->apc_conns[i].bound = 0;		inst->apc_conns[i].locked = 0;		inst->apc_conns[i].failed_conns = 0;		inst->apc_conns[i].ld = NULL;		pthread_mutex_init(&inst->apc_conns[i].mutex, NULL);	}#endif	if (read_mappings(inst) != 0) {		radlog(L_ERR, "rlm_ldap: Reading dictionary mappings from file %s failed",		       inst->dictionary_mapping);		free(inst);	/* FIXME: detach */		return -1;	}	if ((inst->check_item_map == NULL) &&	    (inst->reply_item_map == NULL)) {		radlog(L_ERR, "rlm_ldap: dictionary mappings file %s did not contain any mappings",			inst->dictionary_mapping);		free(inst);	/* FIXME: detach */		return -1;	}	pair = inst->check_item_map;	while(pair != NULL){		atts_num++;		pair = pair->next;	}	check_map_num = (atts_num - 1);	pair = inst->reply_item_map;	while(pair != NULL){		atts_num++;		pair = pair->next;	}	reply_map_num = (atts_num - 1);	if (inst->profile_attr)		atts_num++;	if (inst->passwd_attr)		atts_num++;	if (inst->access_attr)		atts_num++;#ifdef NOVELL		atts_num++;	/* eDirectory Authentication Option attribute */#endif	inst->atts = (char **)malloc(sizeof(char *)*(atts_num + 1));	if (inst->atts == NULL){		radlog(L_ERR, "rlm_ldap: Could not allocate memory. Aborting.");		free(inst);	/* FIXME: detach */		return -1;	}	pair = inst->check_item_map;	if (pair == NULL)		pair = inst->reply_item_map;#ifdef NOVELL	for(i=0;i<atts_num - 1;i++){#else 	for(i=0;i<atts_num;i++){#endif		if (i <= check_map_num ){			inst->atts[i] = pair->attr;			if (i == check_map_num)				pair = inst->reply_item_map;			else				pair = pair->next;		}		else if (i <= reply_map_num){			inst->atts[i] = pair->attr;			pair = pair->next;		}		else{			if (inst->profile_attr && !att_map[0]){				inst->atts[i] = inst->profile_attr;				att_map[0] = 1;			}			else if (inst->passwd_attr && !att_map[1]){				inst->atts[i] = inst->passwd_attr;				att_map[1] = 1;			}			else if (inst->access_attr && !att_map[2]){				inst->atts[i] = inst->access_attr;				att_map[2] = 1;			}		}	}#ifdef NOVELL	inst->atts[atts_num - 1] = "sasdefaultloginsequence";#endif	inst->atts[atts_num] = NULL;	DEBUG("conns: %p",inst->conns);	*instance = inst;	return 0;}/* *	read_mappings(...) reads a ldap<->radius mappings file to *	inst->reply_item_map and inst->check_item_map */#define MAX_LINE_LEN 160#define GENERIC_ATTRIBUTE_ID "$GENERIC$"static intread_mappings(ldap_instance* inst){	FILE* mapfile;	char *filename;	/*	 *	All buffers are of MAX_LINE_LEN so we can use sscanf	 *	without being afraid of buffer overflows	 */	char buf[MAX_LINE_LEN], itemType[MAX_LINE_LEN];	char radiusAttribute[MAX_LINE_LEN], ldapAttribute[MAX_LINE_LEN];	int linenumber;	FR_TOKEN operator;	char opstring[MAX_LINE_LEN];	/* open the mappings file for reading */	filename = inst->dictionary_mapping;	DEBUG("rlm_ldap: reading ldap<->radius mappings from file %s", filename);	mapfile = fopen(filename, "r");	if (mapfile == NULL) {		radlog(L_ERR, "rlm_ldap: Opening file %s failed: %s",		       filename, strerror(errno));		return -1; /* error */	}	/*	 *	read file line by line. Note that if line length	 *	exceeds MAX_LINE_LEN, line numbers will be mixed up	 */	linenumber = 0;	while (fgets(buf, sizeof buf, mapfile)!=NULL) {		char* ptr;		int token_count;		TLDAP_RADIUS* pair;		linenumber++;		/* strip comments */		ptr = strchr(buf, '#');		if (ptr) *ptr = 0;		/* empty line */		if (buf[0] == 0) continue;		/* extract tokens from the string */		token_count = sscanf(buf, "%s %s %s %s",				     itemType, radiusAttribute,				     ldapAttribute, opstring);		if (token_count <= 0) /* no tokens */			continue;		if ((token_count < 3) || (token_count > 4)) {			radlog(L_ERR, "rlm_ldap: Skipping %s line %i: %s",			       filename, linenumber, buf);			radlog(L_ERR, "rlm_ldap: Expected 3 to 4 tokens "			       "(Item type, RADIUS Attribute and LDAP Attribute) but found only %i", token_count);			continue;		}		if (token_count == 3) {			operator = T_OP_INVALID; /* use defaults */		} else {			ptr = opstring;			operator = gettoken(&ptr, buf, sizeof(buf));			if ((operator < T_OP_ADD) || (operator > T_OP_CMP_EQ)) {				radlog(L_ERR, "rlm_ldap: file %s: skipping line %i: unknown or invalid operator %s",				       filename, linenumber, opstring);				continue;			}		}		/* create new TLDAP_RADIUS list node */		pair = rad_malloc(sizeof(*pair));		pair->attr = strdup(ldapAttribute);		pair->radius_attr = strdup(radiusAttribute);		pair->operator = operator;		if ( (pair->attr == NULL) || (pair->radius_attr == NULL) ) {			radlog(L_ERR, "rlm_ldap: Out of memory");			if (pair->attr) free(pair->attr);			if (pair->radius_attr) free(pair->radius_attr);			free(pair);			fclose(mapfile);			return -1;		}		/* push node to correct list */		if (strcasecmp(itemType, "checkItem") == 0) {			pair->next = inst->check_item_map;			inst->check_item_map = pair;		} else if (strcasecmp(itemType, "replyItem") == 0) {			pair->next = inst->reply_item_map;			inst->reply_item_map = pair;		} else {			radlog(L_ERR, "rlm_ldap: file %s: skipping line %i: unknown itemType %s",			       filename, linenumber, itemType);			free(pair->attr);			free(pair->radius_attr);			free(pair);			continue;		}		DEBUG("rlm_ldap: LDAP %s mapped to RADIUS %s",		      pair->attr, pair->radius_attr);	}	fclose(mapfile);	return 0; /* success */}static int perform_search(void *instance, LDAP_CONN *conn,			  char *search_basedn, int scope, char *filter,			  char **attrs, LDAPMessage ** result){	int             res = RLM_MODULE_OK;	int		ldap_errno = 0;	ldap_instance  *inst = instance;	int		search_retry = 0;	struct timeval  tv;	*result = NULL;	if (!conn){		radlog(L_ERR, "rlm_ldap: NULL connection handle passed");		return RLM_MODULE_FAIL;	}	if (conn->failed_conns > MAX_FAILED_CONNS_START){		conn->failed_conns++;		if (conn->failed_conns >= MAX_FAILED_CONNS_END){			conn->failed_conns = MAX_FAILED_CONNS_RESTART;			conn->bound = 0;		}	}retry:	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, inst->login,					     inst->password, 0, &res, NULL)) == NULL) {			radlog(L_ERR, "rlm_ldap: (re)connection attempt failed");			if (search_retry == 0)				conn->failed_conns++;			return (RLM_MODULE_FAIL);		}		conn->bound = 1;		conn->failed_conns = 0;	}	tv.tv_sec = inst->timeout;	tv.tv_usec = 0;	DEBUG2("rlm_ldap: performing search in %s, with filter %s",	       search_basedn ? search_basedn : "(null)" , filter);	switch (ldap_search_st(conn->ld, search_basedn, scope, filter,			       attrs, 0, &tv, result)) {	case LDAP_SUCCESS:	case LDAP_NO_SUCH_OBJECT:		break;	case LDAP_SERVER_DOWN:		radlog(L_ERR, "rlm_ldap: ldap_search() failed: LDAP connection lost.");		conn->failed_conns++;		if (search_retry == 0){			if (conn->failed_conns <= MAX_FAILED_CONNS_START){				radlog(L_INFO, "rlm_ldap: Attempting reconnect");				search_retry = 1;				conn->bound = 0;				ldap_msgfree(*result);				goto retry;			}		}		ldap_msgfree(*result);		return RLM_MODULE_FAIL;	case LDAP_INSUFFICIENT_ACCESS:		radlog(L_ERR, "rlm_ldap: ldap_search() failed: Insufficient access. Check the identity and password configuration directives.");		ldap_msgfree(*result);		return RLM_MODULE_FAIL;	case LDAP_TIMEOUT:		radlog(L_ERR, "rlm_ldap: ldap_search() failed: Timed out while waiting for server to respond. Please increase the timeout.");		ldap_msgfree(*result);		return RLM_MODULE_FAIL;	case LDAP_FILTER_ERROR:		radlog(L_ERR, "rlm_ldap: ldap_search() failed: Bad search filter: %s",filter);		ldap_msgfree(*result);		return RLM_MODULE_FAIL;	case LDAP_TIMELIMIT_EXCEEDED:	case LDAP_BUSY:	case LDAP_UNAVAILABLE:		/* We don't need to reconnect in these cases so we don't set conn->bound */		ldap_get_option(conn->ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno);		radlog(L_ERR, "rlm_ldap: ldap_search() failed: %s",		       ldap_err2string(ldap_errno));		ldap_msgfree(*result);		return (RLM_MODULE_FAIL);	default:		ldap_get_option(conn->ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno);		radlog(L_ERR, "rlm_ldap: ldap_search() failed: %s",		       ldap_err2string(ldap_errno));		conn->bound = 0;		ldap_msgfree(*result);		return (RLM_MODULE_FAIL);	}	if ((ldap_count_entries(conn->ld, *result)) != 1) {		DEBUG("rlm_ldap: object not found or got ambiguous search result");		res = RLM_MODULE_NOTFOUND;		ldap_msgfree(*result);	}	return res;}/* *	Translate the LDAP queries. */static size_t ldap_escape_func(char *out, size_t outlen, const char *in){	size_t len = 0;

⌨️ 快捷键说明

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