Example #1
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;
}
static char *
getpassword(char *login, char *realm)
{
    LDAPMessage *res = NULL;
    LDAPMessage *entry;
    char **values = NULL;
    char **value = NULL;
    char *password = NULL;
    int retry = 0;
    char filter[8192];
    char searchbase[8192];
    char *universal_password = NULL;
    size_t universal_password_len = UNIVERSAL_PASS_LEN;
    int nmas_res = 0;
    int rc = -1;
    if (ld) {
	if (usersearchfilter) {
	    char escaped_login[1024];
	    snprintf(searchbase, sizeof(searchbase), "%s", userbasedn);
	    ldap_escape_value(escaped_login, sizeof(escaped_login), login);
	    snprintf(filter, sizeof(filter), usersearchfilter, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login);

	  retrysrch:
	    if (debug)
		fprintf(stderr, "user filter '%s', searchbase '%s'\n", filter, searchbase);

	    rc = ldap_search_s(ld, searchbase, searchscope, filter, NULL, 0, &res);
	    if (rc != LDAP_SUCCESS) {
		if (noreferrals && rc == LDAP_PARTIAL_RESULTS) {
		    /* Everything is fine. This is expected when referrals
		     * are disabled.
		     */
		    rc = LDAP_SUCCESS;
		} else {
		    fprintf(stderr, PROGRAM_NAME " WARNING, LDAP search error '%s'\n", ldap_err2string(rc));
#if defined(NETSCAPE_SSL)
		    if (sslpath && ((rc == LDAP_SERVER_DOWN) || (rc == LDAP_CONNECT_ERROR))) {
			int sslerr = PORT_GetError();
			fprintf(stderr, PROGRAM_NAME ": WARNING, SSL error %d (%s)\n", sslerr, ldapssl_err2string(sslerr));
		    }
#endif
		    fprintf(stderr, PROGRAM_NAME " WARNING, LDAP search error, trying to recover'%s'\n", ldap_err2string(rc));
		    ldap_msgfree(res);
		    /* try to connect to the LDAP server agin, maybe my persisten conexion failed. */
		    if (!retry) {
			retry++;
			ldap_unbind(ld);
			ld = NULL;
			ldapconnect();
			goto retrysrch;
		    }
		    return NULL;

		}
	    }
	} else if (userdnattr) {
	    sprintf(searchbase, "%s=%s, %s", userdnattr, login, userbasedn);

	  retrydnattr:
	    if (debug)
		fprintf(stderr, "searchbase '%s'\n", searchbase);
	    rc = ldap_search_s(ld, searchbase, searchscope, NULL, NULL, 0, &res);
	}
	if (rc == LDAP_SUCCESS) {
	    entry = ldap_first_entry(ld, res);
	    if (entry) {
		if (debug)
		    printf("ldap dn: %s\n", ldap_get_dn(ld, entry));
		if (edir_universal_passwd) {

		    /* allocate some memory for the universal password returned by NMAS */
		    universal_password = malloc(universal_password_len);
		    memset(universal_password, 0, universal_password_len);
		    values = malloc(sizeof(char *));

		    /* actually talk to NMAS to get a password */
		    nmas_res = nmasldap_get_password(ld, ldap_get_dn(ld, entry), &universal_password_len, universal_password);
		    if (nmas_res == NMAS_SUCCESS && universal_password) {
			if (debug)
			    printf("NMAS returned value %s\n", universal_password);
			values[0] = universal_password;
		    } else {
			if (debug)
			    printf("Error reading Universal Password: %d = %s\n", nmas_res, ldap_err2string(nmas_res));
		    }
		} else {
		    values = ldap_get_values(ld, entry, passattr);
		}
	    } else {
		ldap_msgfree(res);
		return NULL;
	    }
	    if (!values) {
		if (debug)
		    printf("No attribute value found\n");
		if (edir_universal_passwd)
		    free(universal_password);
		ldap_msgfree(res);
		return NULL;
	    }
	    value = values;
	    while (*value) {
		if (encrpass) {
		    if (strcmp(strtok(*value, delimiter), realm) == 0) {
			password = strtok(NULL, delimiter);
			break;
		    }
		} else {
		    password = *value;
		    break;
		}
		value++;
	    }
	    if (debug)
		printf("password: %s\n", password);
	    if (password)
		password = strdup(password);
	    if (edir_universal_passwd) {
		free(values);
		free(universal_password);
	    } else {
		ldap_value_free(values);
	    }
	    ldap_msgfree(res);
	    return password;
	} else {
	    fprintf(stderr, PROGRAM_NAME " WARNING, LDAP error '%s'\n", ldap_err2string(rc));
	    /* try to connect to the LDAP server agin, maybe my persisten conexion failed. */
	    if (!retry) {
		retry++;
		ldap_unbind(ld);
		ld = NULL;
		ldapconnect();
		goto retrydnattr;
	    }
	    return NULL;
	}
    }
    return NULL;
}