ipa_access.c revision 056901f031d8df43ec4fc7e67bc43dd5d967de71
/*
SSSD
IPA Backend Module -- Access control
Authors:
Sumit Bose <sbose@redhat.com>
Copyright (C) 2009 Red Hat
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <security/pam_modules.h>
#include "providers/ldap/sdap_async.h"
#include "providers/ipa/ipa_common.h"
#include "providers/ipa/ipa_access.h"
#include "providers/ipa/ipa_timerules.h"
#define OBJECTCLASS "objectclass"
#define IPA_MEMBEROF "memberOf"
#define IPA_HOST_SERVERHOSTNAME "serverHostName"
#define IPA_HOST_FQDN "fqdn"
#define IPA_ACCESS_RULE_TYPE "accessRuleType"
#define IPA_MEMBER_USER "memberUser"
#define IPA_USER_CATEGORY "userCategory"
#define IPA_SERVICE_NAME "serviceName"
#define IPA_SOURCE_HOST "sourceHost"
#define IPA_SOURCE_HOST_CATEGORY "sourceHostCategory"
#define IPA_EXTERNAL_HOST "externalHost"
#define IPA_ACCESS_TIME "accessTime"
#define IPA_UNIQUE_ID "ipauniqueid"
#define IPA_ENABLED_FLAG "ipaenabledflag"
#define IPA_MEMBER_HOST "memberHost"
#define IPA_HOST_CATEGORY "hostCategory"
#define IPA_CN "cn"
#define IPA_MEMBER_SERVICE "memberService"
#define IPA_SERVICE_CATEGORY "serviceCategory"
#define IPA_HOST_BASE_TMPL "cn=computers,cn=accounts,%s"
#define IPA_HBAC_BASE_TMPL "cn=hbac,%s"
#define IPA_SERVICES_BASE_TMPL "cn=hbacservices,cn=accounts,%s"
#define HBAC_RULES_SUBDIR "hbac_rules"
#define HBAC_HOSTS_SUBDIR "hbac_hosts"
#define HBAC_SERVICES_SUBDIR "hbac_services"
struct ldb_message **msgs,
struct sysdb_attrs ***attrs)
{
int i;
struct sysdb_attrs **a;
if (a == NULL) {
return ENOMEM;
}
for (i = 0; i < count; i++) {
a[i] = talloc(a, struct sysdb_attrs);
if (a[i] == NULL) {
talloc_free(a);
return ENOMEM;
}
}
*attrs = a;
return EOK;
}
struct sysdb_attrs **list)
{
int ret;
int i;
for (i = 0; i < count; i++) {
return ret;
}
}
return EOK;
}
struct sysdb_attrs ***attrs)
{
int ret;
return ret;
}
return ret;
}
return EOK;
}
struct sss_domain_info *domain,
const char *filter,
const char *subtree_name,
const char **search_attrs,
struct sysdb_attrs ***reply_attrs)
{
int ret;
struct ldb_message **msgs;
return ret;
}
return ret;
}
return EOK;
}
{
/* destroy HBAC context now to release all used resources and LDAP connection */
} else {
}
}
struct hbac_get_service_data_state {
const char *basedn;
bool offline;
char *services_filter;
char *services_search_base;
const char **services_attrs;
struct sysdb_attrs **services_reply_list;
};
const char *basedn)
{
struct hbac_get_service_data_state *state;
struct sdap_handle *sdap_handle;
int ret;
return NULL;
}
state->services_reply_count = 0;
state->current_item = 0;
basedn);
goto fail;
}
goto fail;
}
"(objectclass=ipaHBACService)");
goto fail;
}
if (ret) {
goto fail;
}
return req;
}
if (sdap_handle == NULL) {
goto fail;
}
NULL, 0);
goto fail;
}
return req;
fail:
return req;
}
{
struct tevent_req);
struct hbac_get_service_data_state);
struct sss_domain_info *domain;
int ret;
bool in_transaction = false;
int i;
struct ldb_message_element *el;
char *object_name;
return;
}
return;
}
return;
}
in_transaction = true;
goto fail;
}
if (ret) {
goto fail;
}
for (i = 0; i < state->services_reply_count; i++) {
&el);
goto fail;
}
if (el->num_values == 0) {
goto fail;
}
if (object_name == NULL) {
goto fail;
}
state->services_reply_list[i]);
if (ret) {
goto fail;
}
}
if (ret) {
goto fail;
}
in_transaction = false;
return;
fail:
if (in_transaction) {
}
return;
}
struct sysdb_attrs ***hbac_services_list)
{
struct hbac_get_service_data_state);
int i;
for (i = 0; i < state->services_reply_count; i++) {
}
return EOK;
}
const char *user,
const char **user_dn,
const char ***_groups)
{
struct ldb_message *user_msg;
const char *user_orig_dn;
struct ldb_message **msgs;
const char **groups;
int ret;
int i;
if (!tmpctx) {
return ENOMEM;
}
goto fail;
}
if (user_orig_dn == NULL) {
goto fail;
}
user_orig_dn, user));
goto fail;
}
if (count == 0) {
goto fail;
}
*groups_count = 0;
return EOK;
}
goto fail;
}
for(i = 0; i < count; i++) {
goto fail;
}
goto fail;
}
goto fail;
}
}
goto fail;
}
*groups_count = count;
return EOK;
fail:
return ret;
}
struct hbac_get_host_info_state {
char *host_filter;
char *host_search_base;
const char **host_attrs;
struct sysdb_attrs **host_reply_list;
struct hbac_host_info **hbac_host_info;
};
const char *basedn,
const char **hostnames)
{
struct hbac_get_host_info_state *state;
struct sdap_handle *sdap_handle;
int ret;
int i;
return NULL;
}
return NULL;
}
state->host_reply_count = 0;
state->current_item = 0;
goto fail;
}
"(&(objectclass=ipaHost)"
"(|(fqdn=%s)(serverhostname=%s)))",
goto fail;
}
}
goto fail;
}
basedn);
goto fail;
}
goto fail;
}
&state->host_reply_list);
if (ret) {
goto fail;
}
hbac_get_host_memberof(req, true);
return req;
}
if (sdap_handle == NULL) {
goto fail;
}
NULL, 0);
goto fail;
}
return req;
fail:
return req;
}
{
struct tevent_req);
struct hbac_get_host_info_state);
int ret;
&state->host_reply_list);
return;
}
hbac_get_host_memberof(req, false);
}
{
struct hbac_get_host_info_state *state =
bool in_transaction = false;
int ret;
int i;
struct ldb_message_element *el;
struct hbac_host_info **hhi;
char *object_name;
if (state->host_reply_count == 0) {
goto fail;
}
goto fail;
}
for (i = 0; i < state->host_reply_count; i++) {
goto fail;
}
goto fail;
}
if (el->num_values == 0) {
goto fail;
}
goto fail;
}
goto fail;
}
if (el->num_values == 0) {
goto fail;
}
goto fail;
}
IPA_HOST_FQDN, &el);
goto fail;
}
if (el->num_values == 0) {
goto fail;
}
goto fail;
}
goto fail;
}
goto fail;
}
}
}
if (offline) {
return;
}
return;
}
in_transaction = true;
for (i = 0; i < state->host_reply_count; i++) {
IPA_HOST_FQDN, &el);
goto fail;
}
if (el->num_values == 0) {
goto fail;
}
if (object_name == NULL) {
goto fail;
}
state->host_reply_list[i]);
if (ret) {
goto fail;
}
}
if (ret) {
goto fail;
}
in_transaction = false;
return;
fail:
if (in_transaction) {
}
return;
}
struct hbac_host_info ***hhi)
{
struct hbac_get_host_info_state);
return EOK;
}
struct hbac_get_rules_state {
const char *host_dn;
const char **memberof;
char *hbac_filter;
char *hbac_search_base;
const char **hbac_attrs;
struct ldb_message *old_rules;
struct sysdb_attrs **hbac_reply_list;
int current_item;
};
const char *basedn,
const char *host_dn,
const char **memberof)
{
struct hbac_get_rules_state *state;
struct sdap_handle *sdap_handle;
int ret;
int i;
return NULL;
}
return NULL;
}
state->hbac_reply_count = 0;
state->current_item = 0;
basedn);
goto fail;
}
goto fail;
}
"(&(objectclass=ipaHBACRule)"
"(|(%s=%s)(%s=%s)",
IPA_HOST_CATEGORY, "all",
goto fail;
}
"(%s=%s)",
memberof[i]);
goto fail;
}
}
goto fail;
}
&state->hbac_reply_list);
if (ret) {
goto fail;
}
hbac_rule_get(req, true);
return req;
}
if (sdap_handle == NULL) {
goto fail;
}
NULL, 0);
goto fail;
}
return req;
fail:
return req;
}
{
struct tevent_req);
struct hbac_get_rules_state);
int ret;
&state->hbac_reply_list);
return;
}
hbac_rule_get(req, false);
}
{
struct hbac_get_rules_state *state =
bool in_transaction = false;
struct sss_domain_info *domain;
int ret;
int i;
struct ldb_message_element *el;
struct ldb_dn *hbac_base_dn;
char *object_name;
for (i = 0; i < state->hbac_reply_count; i++) {
goto fail;
}
if (el->num_values == 0) {
goto fail;
}
}
return;
}
return;
}
in_transaction = true;
if (hbac_base_dn == NULL) {
goto fail;
}
if (ret) {
goto fail;
}
for (i = 0; i < state->hbac_reply_count; i++) {
IPA_UNIQUE_ID, &el);
goto fail;
}
if (el->num_values == 0) {
goto fail;
}
if (object_name == NULL) {
goto fail;
}
state->hbac_reply_list[i]);
if (ret) {
goto fail;
}
}
if (ret) {
goto fail;
}
in_transaction = false;
return;
fail:
if (in_transaction) {
}
return;
}
struct sysdb_attrs ***hbac_rule_list)
{
struct hbac_get_rules_state);
/* we do not need to steal each hbac_reply_list[i]
* as it belongs to hbac_reply_list memory block */
return EOK;
}
enum hbac_result {
HBAC_ALLOW = 1,
};
enum check_result {
RULE_APPLICABLE = 0,
};
struct ldb_message_element **mof)
{
int ret;
int i;
int j;
struct ldb_message_element *el;
for (i = 0; i < count; i++) {
return ENOENT;
}
if (el->num_values == 0) {
return ENOENT;
} else {
for (j = 0; j < el->num_values; j++) {
return ret;
}
return ret;
}
return EOK;
}
}
}
}
return ENOENT;
}
struct sysdb_attrs *rule_attrs)
{
int ret;
int i;
int g;
struct ldb_message_element *el;
const char *service_dn;
struct ldb_message_element *service_memberof;
return RULE_ERROR;
}
return RULE_ERROR;
}
if (el->num_values == 0) {
} else {
for (i = 0; i < el->num_values; i++) {
return RULE_APPLICABLE;
}
}
}
return RULE_ERROR;
}
service_dn));
return RULE_ERROR;
}
if (el->num_values == 0) {
return RULE_NOT_APPLICABLE;
}
for (i = 0; i < el->num_values; i++) {
return RULE_APPLICABLE;
}
for (g = 0; g < service_memberof->num_values; g++) {
return RULE_APPLICABLE;
}
}
}
return RULE_NOT_APPLICABLE;
}
struct sysdb_attrs *rule_attrs)
{
int ret;
int i;
struct ldb_message_element *el;
char *rule;
bool result;
return RULE_ERROR;
}
return RULE_ERROR;
}
if (el->num_values == 0) {
return RULE_APPLICABLE;
} else {
return RULE_ERROR;
}
for (i = 0; i < el->num_values; i++) {
ret = RULE_ERROR;
goto done;
}
if (result) {
goto done;
}
}
}
done:
return ret;
}
struct sysdb_attrs *rule_attrs)
{
int ret;
int i;
int g;
struct ldb_message_element *el;
return RULE_ERROR;
}
return RULE_ERROR;
}
if (el->num_values == 0) {
} else {
for (i = 0; i < el->num_values; i++) {
return RULE_APPLICABLE;
}
}
}
return RULE_ERROR;
}
if (el->num_values == 0) {
return RULE_NOT_APPLICABLE;
} else {
for (i = 0; i < el->num_values; i++) {
return RULE_APPLICABLE;
}
for (g = 0; g < hbac_ctx->groups_count; g++) {
return RULE_APPLICABLE;
}
}
}
return RULE_NOT_APPLICABLE;
}
return RULE_ERROR;
}
struct hbac_host_info *hhi,
struct sysdb_attrs *rule_attrs)
{
int ret;
int i;
int m;
struct ldb_message_element *cat_el;
struct ldb_message_element *src_el;
struct ldb_message_element *ext_el;
return RULE_ERROR;
}
return RULE_ERROR;
}
if (cat_el->num_values == 0) {
} else {
for(i = 0; i < cat_el->num_values; i++) {
"rule applies.\n"));
return RULE_APPLICABLE;
}
}
}
return RULE_ERROR;
}
return RULE_ERROR;
}
return RULE_NOT_APPLICABLE;
} else {
for (i = 0; i < src_el->num_values; i++) {
return RULE_APPLICABLE;
}
return RULE_APPLICABLE;
}
}
}
}
for (i = 0; i < ext_el->num_values; i++) {
rhost));
return RULE_APPLICABLE;
}
}
}
return RULE_NOT_APPLICABLE;
}
return RULE_ERROR;
}
struct sysdb_attrs *rule_attrs,
enum hbac_result *result) {
int ret;
struct ldb_message_element *el;
enum hbac_result rule_type;
char *rule_name;
return ret;
}
if (el->num_values == 0) {
} else {
}
return ENOMEM;
}
"assuming it is enabled.\n"));
} else {
if (el->num_values == 0) {
"assuming it is enabled.\n"));
} else {
return EOK;
}
}
}
/* rule type */
return ret;
}
if (el->num_values == 0) {
} else {
}
} else {
el->num_values));
return EINVAL;
}
if (ret != RULE_APPLICABLE) {
goto not_applicable;
}
if (ret != RULE_APPLICABLE) {
goto not_applicable;
}
if (ret != RULE_APPLICABLE) {
goto not_applicable;
}
if (ret != RULE_APPLICABLE) {
goto not_applicable;
}
return EOK;
if (ret == RULE_NOT_APPLICABLE) {
} else {
}
return EOK;
}
bool *access_allowed)
{
bool allow_matched = false;
enum hbac_result result;
int ret;
int i;
*access_allowed = false;
for (i = 0; i < hbac_ctx->hbac_rule_count ; i++) {
&result);
return ret;
}
switch (result) {
case HBAC_DENY:
return EOK;
break;
case HBAC_ALLOW:
allow_matched = true;
break;
default:
}
}
return EOK;
}
{
int pam_status = PAM_SYSTEM_ERR;
struct ipa_access_ctx *ipa_access_ctx;
bool offline;
int ret;
goto fail;
}
struct ipa_access_ctx);
&hbac_ctx->ldap_basedn);
goto fail;
}
if (!offline) {
goto fail;
}
}
goto fail;
}
return;
fail:
}
{
struct tevent_req *subreq;
int ret;
if (hbac_ctx_is_offline(hbac_ctx)) {
return hbac_get_host_info_step(hbac_ctx);
}
if (!subreq) {
return ret;
}
return EOK;
}
{
if (dp_error == DP_ERR_OFFLINE) {
/* switching to offline mode */
goto fail;
}
goto fail;
}
return;
fail:
}
/* Check the step result code and continue, retry, get offline result or abort accordingly */
{
int dp_error;
return true;
}
if (hbac_ctx_is_offline(hbac_ctx)) {
/* already offline => the error is fatal */
return false;
}
if (dp_error == DP_ERR_OFFLINE) {
/* switching to offline mode */
}
/* retry */
return false;
}
}
return false;
}
{
const char *hostlist[3];
struct tevent_req *subreq;
return EINVAL;
}
} else {
}
hostlist);
if (!subreq) {
return ENOMEM;
}
return EOK;
}
{
int ret;
int pam_status = PAM_SYSTEM_ERR;
const char *ipa_hostname;
int i;
return;
}
if (ipa_hostname == NULL) {
goto fail;
}
ipa_hostname) == 0) {
}
}
}
}
goto fail;
}
goto fail;
}
return;
fail:
}
{
int ret;
int pam_status = PAM_SYSTEM_ERR;
hbac_ctx->hbac_rule_count = 0;
return;
}
goto failed;
}
return;
}
{
int ret;
int pam_status = PAM_SYSTEM_ERR;
bool access_allowed = false;
hbac_ctx->hbac_services_count = 0;
return;
}
}
hbac_ctx->groups_count = 0;
goto failed;
}
goto failed;
}
if (access_allowed) {
} else {
}
}