Пример #1
0
/** Expand values in an attribute map where needed
 *
 */
int rlm_ldap_map_xlat(REQUEST *request, value_pair_map_t const *maps, rlm_ldap_map_xlat_t *expanded)
{
	value_pair_map_t const *map;
	unsigned int total = 0;

	VALUE_PAIR *found, **from = NULL;
	REQUEST *context;

	for (map = maps; map != NULL; map = map->next) {
		switch (map->src->type) {
		case VPT_TYPE_XLAT:
		{
			ssize_t len;
			char *exp = NULL;

			len = radius_xlat(exp, 0, request, map->src->name, NULL, NULL);
			if (len < 0) {
				RDEBUG("Expansion of LDAP attribute \"%s\" failed", map->src->name);

				goto error;
			}

			expanded->attrs[total++] = exp;
			break;
		}

		case VPT_TYPE_ATTR:
			context = request;

			if (radius_request(&context, map->src->vpt_request) == 0) {
				from = radius_list(context, map->src->vpt_list);
			}
			if (!from) continue;

			found = pairfind(*from, map->src->vpt_da->attr, map->src->vpt_da->vendor, TAG_ANY);
			if (!found) continue;

			expanded->attrs[total++] = talloc_typed_strdup(request, found->vp_strvalue);
			break;

		case VPT_TYPE_EXEC:
		{
			char answer[1024];
			VALUE_PAIR **input_pairs = NULL;
			int result;

			input_pairs = radius_list(request, PAIR_LIST_REQUEST);
			result = radius_exec_program(request, map->src->name, true, true, answer,
						     sizeof(answer), EXEC_TIMEOUT,
						     input_pairs ? *input_pairs : NULL, NULL);
			if (result != 0) {
				return -1;
			}

			expanded->attrs[total++] = talloc_typed_strdup(request, answer);
		}
			break;

		case VPT_TYPE_LITERAL:
			expanded->attrs[total++] = map->src->name;
			break;

		default:
			rad_assert(0);
		error:
			expanded->attrs[total] = NULL;

			rlm_ldap_map_xlat_free(expanded);

			return -1;
		}
	}

	rad_assert(total < LDAP_MAX_ATTRMAP);

	expanded->attrs[total] = NULL;
	expanded->count = total;
	expanded->maps = maps;

	return 0;
}
Пример #2
0
static rlm_rcode_t CC_HINT(nonnull) mod_authorize(void *instance, REQUEST *request)
{
	rlm_rcode_t	rcode = RLM_MODULE_OK;
	ldap_rcode_t	status;
	int		ldap_errno;
	int		i;
	ldap_instance_t	*inst = instance;
	struct berval	**values;
	VALUE_PAIR	*vp;
	ldap_handle_t	*conn;
	LDAPMessage	*result, *entry;
	char const 	*dn = NULL;
	rlm_ldap_map_xlat_t	expanded; /* faster than mallocing every time */

	if (!request->username) {
		RDEBUG2("Attribute \"User-Name\" is required for authorization");

		return RLM_MODULE_NOOP;
	}

	/*
	 *	Check for valid input, zero length names not permitted
	 */
	if (request->username->vp_length == 0) {
		RDEBUG2("Zero length username not permitted");

		return RLM_MODULE_INVALID;
	}

	if (rlm_ldap_map_xlat(request, inst->user_map, &expanded) < 0) {
		return RLM_MODULE_FAIL;
	}

	conn = mod_conn_get(inst, request);
	if (!conn) return RLM_MODULE_FAIL;

	/*
	 *	Add any additional attributes we need for checking access, memberships, and profiles
	 */
	if (inst->userobj_access_attr) {
		expanded.attrs[expanded.count++] = inst->userobj_access_attr;
	}

	if (inst->userobj_membership_attr && (inst->cacheable_group_dn || inst->cacheable_group_name)) {
		expanded.attrs[expanded.count++] = inst->userobj_membership_attr;
	}

	if (inst->profile_attr) {
		expanded.attrs[expanded.count++] = inst->profile_attr;
	}

	if (inst->valuepair_attr) {
		expanded.attrs[expanded.count++] = inst->valuepair_attr;
	}

	expanded.attrs[expanded.count] = NULL;

	dn = rlm_ldap_find_user(inst, request, &conn, expanded.attrs, true, &result, &rcode);
	if (!dn) {
		goto finish;
	}

	entry = ldap_first_entry(conn->handle, result);
	if (!entry) {
		ldap_get_option(conn->handle, LDAP_OPT_RESULT_CODE, &ldap_errno);
		REDEBUG("Failed retrieving entry: %s", ldap_err2string(ldap_errno));

		goto finish;
	}

	/*
	 *	Check for access.
	 */
	if (inst->userobj_access_attr) {
		rcode = rlm_ldap_check_access(inst, request, conn, entry);
		if (rcode != RLM_MODULE_OK) {
			goto finish;
		}
	}

	/*
	 *	Check if we need to cache group memberships
	 */
	if (inst->cacheable_group_dn || inst->cacheable_group_name) {
		if (inst->userobj_membership_attr) {
			rcode = rlm_ldap_cacheable_userobj(inst, request, &conn, entry, inst->userobj_membership_attr);
			if (rcode != RLM_MODULE_OK) {
				goto finish;
			}
		}

		rcode = rlm_ldap_cacheable_groupobj(inst, request, &conn);
		if (rcode != RLM_MODULE_OK) {
			goto finish;
		}
	}

#ifdef WITH_EDIR
	/*
	 *	We already have a Cleartext-Password.  Skip edir.
	 */
	if (pairfind(request->config_items, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) {
		goto skip_edir;
	}

	/*
	 *      Retrieve Universal Password if we use eDirectory
	 */
	if (inst->edir) {
		int res = 0;
		char password[256];
		size_t pass_size = sizeof(password);

		/*
		 *	Retrive universal password
		 */
		res = nmasldap_get_password(conn->handle, dn, password, &pass_size);
		if (res != 0) {
			REDEBUG("Failed to retrieve eDirectory password: (%i) %s", res, edir_errstr(res));
			rcode = RLM_MODULE_FAIL;

			goto finish;
		}

		/*
		 *	Add Cleartext-Password attribute to the request
		 */
		vp = radius_paircreate(request, &request->config_items, PW_CLEARTEXT_PASSWORD, 0);
		pairstrcpy(vp, password);
		vp->vp_length = pass_size;

		if (RDEBUG_ENABLED3) {
			RDEBUG3("Added eDirectory password.  control:%s += '%s'", vp->da->name, vp->vp_strvalue);
		} else {
			RDEBUG2("Added eDirectory password");
		}

		if (inst->edir_autz) {
			RDEBUG2("Binding as user for eDirectory authorization checks");
			/*
			 *	Bind as the user
			 */
			conn->rebound = true;
			status = rlm_ldap_bind(inst, request, &conn, dn, vp->vp_strvalue, true);
			switch (status) {
			case LDAP_PROC_SUCCESS:
				rcode = RLM_MODULE_OK;
				RDEBUG("Bind as user '%s' was successful", dn);
				break;

			case LDAP_PROC_NOT_PERMITTED:
				rcode = RLM_MODULE_USERLOCK;
				goto finish;

			case LDAP_PROC_REJECT:
				rcode = RLM_MODULE_REJECT;
				goto finish;

			case LDAP_PROC_BAD_DN:
				rcode = RLM_MODULE_INVALID;
				goto finish;

			case LDAP_PROC_NO_RESULT:
				rcode = RLM_MODULE_NOTFOUND;
				goto finish;

			default:
				rcode = RLM_MODULE_FAIL;
				goto finish;
			};
		}
	}

skip_edir:
#endif

	/*
	 *	Apply ONE user profile, or a default user profile.
	 */
	if (inst->default_profile) {
		char profile[1024];

		if (radius_xlat(profile, sizeof(profile), request, inst->default_profile, NULL, NULL) < 0) {
			REDEBUG("Failed creating default profile string");

			rcode = RLM_MODULE_INVALID;
			goto finish;
		}

		rlm_ldap_map_profile(inst, request, &conn, profile, &expanded);
	}

	/*
	 *	Apply a SET of user profiles.
	 */
	if (inst->profile_attr) {
		values = ldap_get_values_len(conn->handle, entry, inst->profile_attr);
		if (values != NULL) {
			for (i = 0; values[i] != NULL; i++) {
				char *value;

				value = rlm_ldap_berval_to_string(request, values[i]);
				rlm_ldap_map_profile(inst, request, &conn, value, &expanded);
				talloc_free(value);
			}
			ldap_value_free_len(values);
		}
	}

	if (inst->user_map || inst->valuepair_attr) {
		RDEBUG("Processing user attributes");
		RINDENT();
		rlm_ldap_map_do(inst, request, conn->handle, &expanded, entry);
		REXDENT();
		rlm_ldap_check_reply(inst, request);
	}

finish:
	rlm_ldap_map_xlat_free(&expanded);
	if (result) ldap_msgfree(result);
	mod_conn_release(inst, conn);

	return rcode;
}
Пример #3
0
/** Expand values in an attribute map where needed
 *
 */
int rlm_ldap_map_xlat(REQUEST *request, value_pair_map_t const *maps, rlm_ldap_map_xlat_t *expanded)
{
	const value_pair_map_t *map;
	unsigned int total = 0;
	size_t len;
	
	VALUE_PAIR *found, **from = NULL;
	REQUEST *context;

	for (map = maps; map != NULL; map = map->next) {
		switch (map->src->type) {
		case VPT_TYPE_XLAT:
			{
				char *exp = NULL;
			
				len = radius_xlat(exp, 0, request, map->src->name, NULL, NULL);		  
				if (len <= 0) {
					RDEBUG("Expansion of LDAP attribute \"%s\" failed", map->src->name);
				       
					goto error;
				}
			
				expanded->attrs[total++] = exp;
				break;
			}

		case VPT_TYPE_ATTR:
			context = request;
			
			if (radius_request(&context, map->src->request) == 0) {
				from = radius_list(context, map->src->list);
			}
			if (!from) continue;
			
			found = pairfind(*from, map->src->da->attr, map->src->da->vendor, TAG_ANY);
			if (!found) continue;
			
			expanded->attrs[total++] = talloc_strdup(request, found->vp_strvalue);
			break;
			
		case VPT_TYPE_LITERAL:
			expanded->attrs[total++] = map->src->name;
			break;
		default:
			rad_assert(0);
		error:
			expanded->attrs[total] = NULL;
			
			rlm_ldap_map_xlat_free(expanded);
			
			return -1;
		}
			
	}
	
	rad_assert(total < LDAP_MAX_ATTRMAP);
	
	expanded->attrs[total] = NULL;
	expanded->count = total;
	expanded->maps = maps;
	
	return 0;
}