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

📄 rlm_ldap.c

📁 RADIUS 服务器介绍 RADIUS服务器支持标准的RADIUS协议
💻 C
📖 第 1 页 / 共 4 页
字号:
				att_map[1] = 1;			}			else if (inst->access_attr && !att_map[2]){				inst->atts[i] = inst->access_attr;				att_map[2] = 1;			}		}	}	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], radiusAttribute[MAX_LINE_LEN], ldapAttribute[MAX_LINE_LEN];	int linenumber;	/* 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", filename);		return -1; /* error */	}	/* read file line by line. Note that if line length exceed 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", itemType, radiusAttribute, ldapAttribute);		if (token_count <= 0) /* no tokens */						continue;		if (token_count != 3) {			radlog(L_ERR, "rlm_ldap: Skipping %s line %i: %s", filename, linenumber, buf);			radlog(L_ERR, "rlm_ldap: Expected 3 tokens "			       "(Item type, RADIUS Attribute and LDAP Attribute) but found only %i", token_count);			continue;		}		/* create new TLDAP_RADIUS list node */		pair = rad_malloc(sizeof(TLDAP_RADIUS));		pair->attr = strdup(ldapAttribute);		pair->radius_attr = strdup(radiusAttribute);		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;	*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) {			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;	}	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, &(inst->timeout), 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_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 int ldap_escape_func(char *out, int outlen, const char *in){	int len = 0;		while (in[0]) {		/*		 *  Only one byte left.		 */		if (outlen <= 1) {			break;		}				if (strchr("*", *in)) {			in++;			outlen--;			continue;		}				/*		 *	Else it's a nice character.		 */		*out = *in;		out++;		in++;		outlen--;		len++;	}	*out = '\0';	return len;}/* * ldap_groupcmp(). Implement the Ldap-Group == "group" filter */static int ldap_groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check,                VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs){        char            filter[MAX_FILTER_STR_LEN];        char            gr_filter[MAX_FILTER_STR_LEN];        int             res;        LDAPMessage     *result = NULL;        LDAPMessage     *msg = NULL;        char            basedn[MAX_FILTER_STR_LEN];	char		*attrs[] = {"dn",NULL};	char		**vals;        ldap_instance   *inst = instance;	char		*group_attrs[] = {inst->groupmemb_attr,NULL};	LDAP_CONN	*conn;	int		conn_id = -1;	VALUE_PAIR	*vp_user_dn;	VALUE_PAIR      **request_pairs;	request_pairs = &req->packet->vps;	DEBUG("rlm_ldap: Entering ldap_groupcmp()");	if (check->strvalue == NULL || check->length == 0){                DEBUG("rlm_ldap::ldap_groupcmp: Illegal group name");                return 1;        }        if (req == NULL){                DEBUG("rlm_ldap::ldap_groupcmp: NULL request");                return 1;        }        if (!radius_xlat(basedn, sizeof(basedn), inst->basedn, req, NULL)) {                DEBUG("rlm_ldap::ldap_groupcmp: unable to create basedn.");                return 1;        }        while((vp_user_dn = pairfind(*request_pairs, PW_LDAP_USERDN)) == NULL){                char            *user_dn = NULL;                if (!radius_xlat(filter, sizeof(filter), inst->filter,					req, ldap_escape_func)){                        DEBUG("rlm_ldap::ldap_groupcmp: unable to create filter");                        return 1;                }		if ((conn_id = ldap_get_conn(inst->conns,&conn,inst)) == -1){			radlog(L_ERR, "rlm_ldap: All ldap connections are in use");			return 1;		}                if ((res = perform_search(inst, conn, basedn, LDAP_SCOPE_SUBTREE,					filter, attrs, &result)) != RLM_MODULE_OK){                        DEBUG("rlm_ldap::ldap_groupcmp: search failed");			ldap_release_conn(conn_id,inst->conns);                        return 1;                }                if ((msg = ldap_first_entry(conn->ld, result)) == NULL) {                        DEBUG("rlm_ldap::ldap_groupcmp: ldap_first_entry() failed");			ldap_release_conn(conn_id,inst->conns);                        ldap_msgfree(result);                        return 1;                }                if ((user_dn = ldap_get_dn(conn->ld, msg)) == NULL) {                        DEBUG("rlm_ldap:ldap_groupcmp:: ldap_get_dn() failed");			ldap_release_conn(conn_id,inst->conns);                        ldap_msgfree(result);                        return 1;                }		ldap_release_conn(conn_id,inst->conns);                /*                * Adding new attribute containing DN for LDAP object associated with                * given username                */                pairadd(request_pairs, pairmake("Ldap-UserDn", user_dn, T_OP_EQ));                ldap_memfree(user_dn);                ldap_msgfree(result);        }        if(!radius_xlat(gr_filter, sizeof(gr_filter), inst->groupmemb_filt, req, NULL)){                DEBUG("rlm_ldap::ldap_groupcmp: unable to create filter.");                return 1;        }	if (strchr((char *)check->strvalue,',') != NULL) {		/* This looks like a DN */		snprintf(filter,sizeof(filter), "%s",gr_filter);		snprintf(basedn,sizeof(basedn), "%s",(char *)check->strvalue);	} else 		snprintf(filter,sizeof(filter), "(&(%s=%s)%s)",inst->groupname_attr,(char *)check->strvalue,gr_filter);	if ((conn_id = ldap_get_conn(inst->conns,&conn,inst)) == -1){		radlog(L_ERR, "rlm_ldap: All ldap connections are in use");		return 1;	}		if ((res = perform_search(inst, conn, basedn, LDAP_SCOPE_SUBTREE,				filter, attrs, &result)) == RLM_MODULE_OK){		DEBUG("rlm_ldap::ldap_groupcmp: User found in group %s",				(char *)check->strvalue);		ldap_msgfree(result);		ldap_release_conn(conn_id,inst->conns);        	return 0;	}		ldap_release_conn(conn_id,inst->conns);	if (res != RLM_MODULE_NOTFOUND ) {		DEBUG("rlm_ldap::ldap_groupcmp: Search returned error");		return 1;	}	if (inst->groupmemb_attr == NULL){		/* search returned NOTFOUND and searching for membership 		 * using user object attributes is not specified in config		 * file		 */		DEBUG("rlm_ldap::ldap_groupcmp: Group %s not found or user is not a member.",(char *)check->strvalue);		return 1;	}	snprintf(filter,sizeof(filter), "(objectclass=*)");	if ((conn_id = ldap_get_conn(inst->conns,&conn,inst)) == -1){		radlog(L_ERR, "rlm_ldap: Add ldap connections are in use");		return 1;	}	if ((res = perform_search(inst, conn, vp_user_dn->strvalue, LDAP_SCOPE_BASE,					filter, group_attrs,&result)) != RLM_MODULE_OK){		DEBUG("rlm_ldap::ldap_groupcmp: Search returned error");		ldap_release_conn(conn_id, inst->conns);		return 1;	}			if ((msg = ldap_first_entry(conn->ld, result)) == NULL) {		DEBUG("rlm_ldap::ldap_groupcmp: ldap_first_entry() failed");		ldap_release_conn(conn_id,inst->conns);		ldap_msgfree(result);		return 1;	}	if ((vals = ldap_get_values(conn->ld, msg, inst->groupmemb_attr)) != NULL) {		unsigned int i = 0;		char found = 0;		for (;i < ldap_count_values(vals);i++){			if (strchr(vals[i],',') != NULL){ 				/* This looks like a DN */				LDAPMessage *gr_result = NULL;				snprintf(filter,sizeof(filter), "(%s=%s)",					inst->groupname_attr,					(char *)check->strvalue);				if ((res = perform_search(inst, conn, vals[i],						LDAP_SCOPE_BASE, filter,						attrs, &gr_result)) != RLM_MODULE_OK){					if (res != RLM_MODULE_NOTFOUND){						DEBUG("rlm_ldap::ldap_groupcmp: \							Search returned error");						ldap_value_free(vals);						ldap_msgfree(result);						ldap_release_conn(conn_id,inst->conns);						return 1;					}				} else {					ldap_msgfree(gr_result);					found = 1;					break;				}			} else {				if (strcmp(vals[i],(char *)check->strvalue) == 0){					found = 1;					break;				}			}		}		ldap_value_free(vals);		ldap_msgfree(result);		if (found == 0){			DEBUG("rlm_ldap::groupcmp: Group %s not found \				or user not a member",				(char *)check->strvalue);			ldap_release_conn(conn_id,inst->conns);			return 1;		}	} else {			DEBUG("rlm_ldap::ldap_groupcmp: ldap_get_values() failed");			ldap_msgfree(result);			ldap_release_conn(conn_id,inst->conns);			return 1;	}	DEBUG("rlm_ldap::ldap_groupcmp: User found in group %s",(char *)check->strvalue);	ldap_release_conn(conn_id,inst->conns);        return 0;}/* * ldap_xlat()

⌨️ 快捷键说明

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