diff options
author | Sumit Bose <sbose@redhat.com> | 2014-09-23 15:55:43 +0200 |
---|---|---|
committer | Martin Kosek <mkosek@redhat.com> | 2014-09-30 08:29:59 +0200 |
commit | 3c75b9171e5721097f6ba2855e41f0e4129b907b (patch) | |
tree | 189082c2abf4c65d9340eae8b8e4741baff93f78 | |
parent | 35ec0f7e3d9832c9b687bb01561a10e0304dfa74 (diff) | |
download | freeipa-3c75b9171e5721097f6ba2855e41f0e4129b907b.tar.gz freeipa-3c75b9171e5721097f6ba2855e41f0e4129b907b.tar.xz freeipa-3c75b9171e5721097f6ba2855e41f0e4129b907b.zip |
extdom: add support for new version
Currently the extdom plugin is basically used to translate SIDs of AD
users and groups to names and POSIX IDs.
With this patch a new version is added which will return the full member
list for groups and the full list of group memberships for a user.
Additionally the gecos field, the home directory and the login shell of a
user are returned and an optional list of key-value pairs which
currently will contain the SID of the requested object if available.
https://fedorahosted.org/freeipa/ticket/4031
Reviewed-By: Jakub Hrozek <jhrozek@redhat.com>
3 files changed, 603 insertions, 252 deletions
diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom.h b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom.h index 5f834a047..90f8390d8 100644 --- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom.h +++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom.h @@ -64,6 +64,7 @@ #include <sss_nss_idmap.h> #define EXOP_EXTDOM_OID "2.16.840.1.113730.3.8.10.4" +#define EXOP_EXTDOM_V1_OID "2.16.840.1.113730.3.8.10.4.1" #define IPA_EXTDOM_PLUGIN_NAME "ipa-extdom-extop" #define IPA_EXTDOM_FEATURE_DESC "IPA trusted domain ID mapper" @@ -71,6 +72,11 @@ #define IPA_PLUGIN_NAME IPA_EXTDOM_PLUGIN_NAME +enum extdom_version { + EXTDOM_V0 = 0, + EXTDOM_V1 +}; + enum input_types { INP_SID = 1, INP_NAME, @@ -80,14 +86,17 @@ enum input_types { enum request_types { REQ_SIMPLE = 1, - REQ_FULL + REQ_FULL, + REQ_FULL_WITH_GROUPS }; enum response_types { RESP_SID = 1, RESP_NAME, RESP_USER, - RESP_GROUP + RESP_GROUP, + RESP_USER_GROUPLIST, + RESP_GROUP_MEMBERS }; struct extdom_req { @@ -123,11 +132,18 @@ struct extdom_res { char *user_name; uid_t uid; gid_t gid; + char *gecos; + char *home; + char *shell; + size_t ngroups; + char **groups; } user; struct { char *domain_name; char *group_name; gid_t gid; + size_t nmembers; + char **members; } group; } data; }; @@ -150,15 +166,14 @@ struct pwd_grp { struct passwd pwd; struct group grp; } data; + int ngroups; + gid_t *groups; }; int parse_request_data(struct berval *req_val, struct extdom_req **_req); void free_req_data(struct extdom_req *req); +int check_request(struct extdom_req *req, enum extdom_version version); int handle_request(struct ipa_extdom_ctx *ctx, struct extdom_req *req, - struct extdom_res **res); -int create_response(struct extdom_req *req, struct pwd_grp *pg_data, - const char *sid_str, enum sss_id_type id_type, - const char *domain_name, struct extdom_res **_res); -void free_resp_data(struct extdom_res *res); + struct berval **berval); int pack_response(struct extdom_res *res, struct berval **ret_val); #endif /* _IPA_EXTDOM_H_ */ diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c index 025d37dc5..d1d214ae7 100644 --- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c +++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c @@ -70,6 +70,7 @@ int parse_request_data(struct berval *req_val, struct extdom_req **_req) * requestType ENUMERATED { * simple (1), * full (2) + * full_with_groups (3) * }, * data InputData * } @@ -179,23 +180,23 @@ void free_req_data(struct extdom_req *req) free(req); } -int handle_request(struct ipa_extdom_ctx *ctx, struct extdom_req *req, - struct extdom_res **res) +int check_request(struct extdom_req *req, enum extdom_version version) +{ + if (version == EXTDOM_V0) { + if (req->request_type == REQ_FULL_WITH_GROUPS) { + return LDAP_PROTOCOL_ERROR; + } + } + + return LDAP_SUCCESS; +} + +static int get_buffer(size_t *_buf_len, char **_buf) { - int ret; - char *domain_name = NULL; - char *sid_str = NULL; - size_t buf_len; - char *buf = NULL; long pw_max; long gr_max; - struct pwd_grp pg_data; - struct passwd *pwd_result = NULL; - struct group *grp_result = NULL; - enum sss_id_type id_type; - char *fq_name = NULL; - char *sep; - + size_t buf_len; + char *buf; pw_max = sysconf(_SC_GETPW_R_SIZE_MAX); gr_max = sysconf(_SC_GETGR_R_SIZE_MAX); @@ -211,301 +212,632 @@ int handle_request(struct ipa_extdom_ctx *ctx, struct extdom_req *req, return LDAP_OPERATIONS_ERROR; } - switch (req->input_type) { - case INP_POSIX_UID: - if (req->request_type == REQ_SIMPLE) { - ret = sss_nss_getsidbyid(req->data.posix_uid.uid, &sid_str, - &id_type); - } else { - id_type = SSS_ID_TYPE_UID; - ret = getpwuid_r(req->data.posix_uid.uid, &pg_data.data.pwd, buf, - buf_len, &pwd_result); + *_buf_len = buf_len; + *_buf = buf; + + return LDAP_SUCCESS; +} + +static int get_user_grouplist(const char *name, gid_t gid, + size_t *_ngroups, gid_t **_groups ) +{ + int ret; + int ngroups; + gid_t *groups; + gid_t *new_groups; + + ngroups = 128; + groups = malloc(ngroups * sizeof(gid_t)); + if (groups == NULL) { + return LDAP_OPERATIONS_ERROR; + } + + ret = getgrouplist(name, gid, groups, &ngroups); + if (ret == -1) { + new_groups = realloc(groups, ngroups); + if (new_groups == NULL) { + free(groups); + return LDAP_OPERATIONS_ERROR; } + groups = new_groups; - domain_name = strdup(req->data.posix_uid.domain_name); - break; - case INP_POSIX_GID: - if (req->request_type == REQ_SIMPLE) { - ret = sss_nss_getsidbyid(req->data.posix_uid.uid, &sid_str, - &id_type); + ret = getgrouplist(name, gid, groups, &ngroups); + if (ret == -1) { + free(groups); + return LDAP_OPERATIONS_ERROR; + } + } + + *_ngroups = ngroups; + *_groups = groups; + + return LDAP_SUCCESS; +} + +static int pack_ber_sid(const char *sid, struct berval **berval) +{ + BerElement *ber = NULL; + int ret; + + ber = ber_alloc_t( LBER_USE_DER ); + if (ber == NULL) { + return LDAP_OPERATIONS_ERROR; + } + + ret = ber_printf(ber,"{es}", RESP_SID, sid); + if (ret == -1) { + ber_free(ber, 1); + return LDAP_OPERATIONS_ERROR; + } + + ret = ber_flatten(ber, berval); + ber_free(ber, 1); + if (ret == -1) { + return LDAP_OPERATIONS_ERROR; + } + + return LDAP_SUCCESS; +} + +#define SSSD_SYSDB_SID_STR "objectSIDString" + +static int pack_ber_user(enum response_types response_type, + const char *domain_name, const char *user_name, + uid_t uid, gid_t gid, + const char *gecos, const char *homedir, + const char *shell, const char *sid_str, + struct berval **berval) +{ + BerElement *ber = NULL; + int ret; + size_t ngroups; + gid_t *groups = NULL; + size_t buf_len; + char *buf = NULL; + struct group grp; + struct group *grp_result; + size_t c; + char *locat; + char *short_user_name = NULL; + const char *single_value_string_array[] = {NULL, NULL}; + + short_user_name = strdup(user_name); + if ((locat = strchr(short_user_name, SSSD_DOMAIN_SEPARATOR)) != NULL) { + if (strcasecmp(locat+1, domain_name) == 0 ) { + locat[0] = '\0'; } else { - id_type = SSS_ID_TYPE_GID; - ret = getgrgid_r(req->data.posix_gid.gid, &pg_data.data.grp, buf, - buf_len, &grp_result); + ret = LDAP_NO_SUCH_OBJECT; + goto done; } + } - domain_name = strdup(req->data.posix_gid.domain_name); - break; - case INP_SID: - ret = sss_nss_getnamebysid(req->data.sid, &fq_name, &id_type); - if (ret != 0) { - ret = LDAP_OPERATIONS_ERROR; + ber = ber_alloc_t( LBER_USE_DER ); + if (ber == NULL) { + return LDAP_OPERATIONS_ERROR; + } + + ret = ber_printf(ber,"{e{ssii", response_type, domain_name, short_user_name, + uid, gid); + if (ret == -1) { + ret = LDAP_OPERATIONS_ERROR; + goto done; + } + + if (response_type == RESP_USER_GROUPLIST) { + ret = get_user_grouplist(user_name, gid, &ngroups, &groups); + if (ret != LDAP_SUCCESS) { goto done; } - sep = strrchr(fq_name, SSSD_DOMAIN_SEPARATOR); - if (sep == NULL) { + ret = get_buffer(&buf_len, &buf); + if (ret != LDAP_SUCCESS) { + goto done; + } + + ret = ber_printf(ber,"sss", gecos, homedir, shell); + if (ret == -1) { ret = LDAP_OPERATIONS_ERROR; goto done; } - ret = asprintf(&domain_name, "%s", sep+1); + ret = ber_printf(ber,"{"); if (ret == -1) { ret = LDAP_OPERATIONS_ERROR; - domain_name = NULL; /* content is undefined according to - asprintf(3) */ goto done; } - switch(id_type) { - case SSS_ID_TYPE_UID: - case SSS_ID_TYPE_BOTH: - ret = getpwnam_r(fq_name, &pg_data.data.pwd, buf, buf_len, - &pwd_result); - break; - case SSS_ID_TYPE_GID: - ret = getgrnam_r(fq_name, &pg_data.data.grp, buf, buf_len, - &grp_result); - break; - default: + for (c = 0; c < ngroups; c++) { + ret = getgrgid_r(groups[c], &grp, buf, buf_len, &grp_result); + if (ret != 0) { + ret = LDAP_NO_SUCH_OBJECT; + goto done; + } + if (grp_result == NULL) { + ret = LDAP_NO_SUCH_OBJECT; + goto done; + } + + ret = ber_printf(ber, "s", grp.gr_name); + if (ret == -1) { + ret = LDAP_OPERATIONS_ERROR; + goto done; + } + } + + ret = ber_printf(ber,"}"); + if (ret == -1) { ret = LDAP_OPERATIONS_ERROR; goto done; } - break; - case INP_NAME: - ret = asprintf(&fq_name, "%s%c%s", req->data.name.object_name, - SSSD_DOMAIN_SEPARATOR, - req->data.name.domain_name); + + single_value_string_array[0] = sid_str; + ret = ber_printf(ber,"{{s{v}}}", SSSD_SYSDB_SID_STR, + single_value_string_array); if (ret == -1) { ret = LDAP_OPERATIONS_ERROR; - fq_name = NULL; /* content is undefined according to - asprintf(3) */ goto done; } + } + + ret = ber_printf(ber,"}}"); + if (ret == -1) { + ret = LDAP_OPERATIONS_ERROR; + goto done; + } - if (req->request_type == REQ_SIMPLE) { - ret = sss_nss_getsidbyname(fq_name, &sid_str, &id_type); + ret = ber_flatten(ber, berval); + if (ret == -1) { + ret = LDAP_OPERATIONS_ERROR; + goto done; + } + + ret = LDAP_SUCCESS; +done: + free(short_user_name); + free(groups); + free(buf); + ber_free(ber, 1); + return ret; +} + +static int pack_ber_group(enum response_types response_type, + const char *domain_name, const char *group_name, + gid_t gid, char **members, const char *sid_str, + struct berval **berval) +{ + BerElement *ber = NULL; + int ret; + size_t c; + char *locat; + char *short_group_name = NULL; + const char *single_value_string_array[] = {NULL, NULL}; + + short_group_name = strdup(group_name); + if ((locat = strchr(short_group_name, SSSD_DOMAIN_SEPARATOR)) != NULL) { + if (strcasecmp(locat+1, domain_name) == 0 ) { + locat[0] = '\0'; } else { - id_type = SSS_ID_TYPE_UID; - ret = getpwnam_r(fq_name, &pg_data.data.pwd, buf, buf_len, - &pwd_result); - if (ret == 0 && pwd_result == NULL) { /* no user entry found */ - id_type = SSS_ID_TYPE_GID; - ret = getgrnam_r(fq_name, &pg_data.data.grp, buf, buf_len, - &grp_result); + ret = LDAP_NO_SUCH_OBJECT; + goto done; + } + } + + ber = ber_alloc_t( LBER_USE_DER ); + if (ber == NULL) { + return LDAP_OPERATIONS_ERROR; + } + + ret = ber_printf(ber,"{e{ssi", response_type, domain_name, short_group_name, + gid); + if (ret == -1) { + ber_free(ber, 1); + return LDAP_OPERATIONS_ERROR; + } + + if (response_type == RESP_GROUP_MEMBERS) { + ret = ber_printf(ber,"{"); + if (ret == -1) { + ret = LDAP_OPERATIONS_ERROR; + goto done; + } + + for (c = 0; members[c] != NULL; c++) { + ret = ber_printf(ber, "s", members[c]); + if (ret == -1) { + ret = LDAP_OPERATIONS_ERROR; + goto done; } } - domain_name = strdup(req->data.name.domain_name); - break; - default: - ret = LDAP_PROTOCOL_ERROR; + + ret = ber_printf(ber,"}"); + if (ret == -1) { + ret = LDAP_OPERATIONS_ERROR; + goto done; + } + + single_value_string_array[0] = sid_str; + ret = ber_printf(ber,"{{s{v}}}", SSSD_SYSDB_SID_STR, + single_value_string_array); + if (ret == -1) { + ret = LDAP_OPERATIONS_ERROR; + goto done; + } + + } + + ret = ber_printf(ber,"}}"); + if (ret == -1) { + ret = LDAP_OPERATIONS_ERROR; goto done; } - if (ret != 0) { + ret = ber_flatten(ber, berval); + if (ret == -1) { ret = LDAP_OPERATIONS_ERROR; goto done; - } else if (ret == 0 && pwd_result == NULL && grp_result == NULL && - sid_str == NULL) { - ret = LDAP_NO_SUCH_OBJECT; + } + + ret = LDAP_SUCCESS; + +done: + free(short_group_name); + ber_free(ber, 1); + return ret; +} + +static int pack_ber_name(const char *domain_name, const char *name, + struct berval **berval) +{ + BerElement *ber = NULL; + int ret; + + ber = ber_alloc_t( LBER_USE_DER ); + if (ber == NULL) { + return LDAP_OPERATIONS_ERROR; + } + + ret = ber_printf(ber,"{e{ss}}", RESP_NAME, domain_name, name); + if (ret == -1) { + ber_free(ber, 1); + return LDAP_OPERATIONS_ERROR; + } + + ret = ber_flatten(ber, berval); + ber_free(ber, 1); + if (ret == -1) { + return LDAP_OPERATIONS_ERROR; + } + + return LDAP_SUCCESS; +} + +static int handle_uid_request(enum request_types request_type, uid_t uid, + const char *domain_name, struct berval **berval) +{ + int ret; + struct passwd pwd; + struct passwd *pwd_result = NULL; + char *sid_str = NULL; + enum sss_id_type id_type; + size_t buf_len; + char *buf = NULL; + + ret = get_buffer(&buf_len, &buf); + if (ret != LDAP_SUCCESS) { + return ret; + } + + if (request_type == REQ_SIMPLE || request_type == REQ_FULL_WITH_GROUPS) { + ret = sss_nss_getsidbyid(uid, &sid_str, &id_type); + if (ret != 0 || !(id_type == SSS_ID_TYPE_UID + || id_type == SSS_ID_TYPE_BOTH)) { + if (ret == ENOENT) { + ret = LDAP_NO_SUCH_OBJECT; + } else { + ret = LDAP_OPERATIONS_ERROR; + } + goto done; + } + } + + if (request_type == REQ_SIMPLE) { + ret = pack_ber_sid(sid_str, berval); + } else { + ret = getpwuid_r(uid, &pwd, buf, buf_len, &pwd_result); + if (ret != 0) { + ret = LDAP_NO_SUCH_OBJECT; + goto done; + } + if (pwd_result == NULL) { + ret = LDAP_NO_SUCH_OBJECT; + goto done; + } + + ret = pack_ber_user((request_type == REQ_FULL ? RESP_USER + : RESP_USER_GROUPLIST), + domain_name, pwd.pw_name, pwd.pw_uid, + pwd.pw_gid, pwd.pw_gecos, pwd.pw_dir, + pwd.pw_shell, sid_str, berval); + } + +done: + free(sid_str); + free(buf); + return ret; +} + +static int handle_gid_request(enum request_types request_type, gid_t gid, + const char *domain_name, struct berval **berval) +{ + int ret; + struct group grp; + struct group *grp_result = NULL; + char *sid_str = NULL; + enum sss_id_type id_type; + size_t buf_len; + char *buf = NULL; + + ret = get_buffer(&buf_len, &buf); + if (ret != LDAP_SUCCESS) { + return ret; + } + + if (request_type == REQ_SIMPLE || request_type == REQ_FULL_WITH_GROUPS) { + ret = sss_nss_getsidbyid(gid, &sid_str, &id_type); + if (ret != 0 || id_type != SSS_ID_TYPE_GID) { + if (ret == ENOENT) { + ret = LDAP_NO_SUCH_OBJECT; + } else { + ret = LDAP_OPERATIONS_ERROR; + } + goto done; + } + } + + if (request_type == REQ_SIMPLE) { + ret = pack_ber_sid(sid_str, berval); + } else { + ret = getgrgid_r(gid, &grp, buf, buf_len, &grp_result); + if (ret != 0) { + ret = LDAP_NO_SUCH_OBJECT; + goto done; + } + if (grp_result == NULL) { + ret = LDAP_NO_SUCH_OBJECT; + goto done; + } + + ret = pack_ber_group((request_type == REQ_FULL ? RESP_GROUP + : RESP_GROUP_MEMBERS), + domain_name, grp.gr_name, grp.gr_gid, + grp.gr_mem, sid_str, berval); + } + +done: + free(sid_str); + free(buf); + return ret; +} + +static int handle_sid_request(enum request_types request_type, const char *sid, + struct berval **berval) +{ + int ret; + struct passwd pwd; + struct passwd *pwd_result = NULL; + struct group grp; + struct group *grp_result = NULL; + char *domain_name = NULL; + char *fq_name = NULL; + char *object_name = NULL; + char *sep; + size_t buf_len; + char *buf = NULL; + enum sss_id_type id_type; + + ret = sss_nss_getnamebysid(sid, &fq_name, &id_type); + if (ret != 0) { + if (ret == ENOENT) { + ret = LDAP_NO_SUCH_OBJECT; + } else { + ret = LDAP_OPERATIONS_ERROR; + } goto done; } - if (domain_name == NULL) { + sep = strchr(fq_name, SSSD_DOMAIN_SEPARATOR); + if (sep == NULL) { ret = LDAP_OPERATIONS_ERROR; goto done; } - ret = create_response(req, &pg_data, sid_str, id_type, domain_name, res); - if (ret != 0) { + object_name = strndup(fq_name, (sep - fq_name)); + domain_name = strdup(sep + 1); + if (object_name == NULL || domain_name == NULL) { ret = LDAP_OPERATIONS_ERROR; goto done; } + if (request_type == REQ_SIMPLE) { + ret = pack_ber_name(domain_name, object_name, berval); + goto done; + } - ret = LDAP_SUCCESS; + ret = get_buffer(&buf_len, &buf); + if (ret != LDAP_SUCCESS) { + return ret; + } + + switch(id_type) { + case SSS_ID_TYPE_UID: + case SSS_ID_TYPE_BOTH: + ret = getpwnam_r(fq_name, &pwd, buf, buf_len, &pwd_result); + if (ret != 0) { + ret = LDAP_NO_SUCH_OBJECT; + goto done; + } + + if (pwd_result == NULL) { + ret = LDAP_NO_SUCH_OBJECT; + goto done; + } + + ret = pack_ber_user((request_type == REQ_FULL ? RESP_USER + : RESP_USER_GROUPLIST), + domain_name, pwd.pw_name, pwd.pw_uid, + pwd.pw_gid, pwd.pw_gecos, pwd.pw_dir, + pwd.pw_shell, sid, berval); + break; + case SSS_ID_TYPE_GID: + ret = getgrnam_r(fq_name, &grp, buf, buf_len, &grp_result); + if (ret != 0) { + ret = LDAP_NO_SUCH_OBJECT; + goto done; + } + + if (grp_result == NULL) { + ret = LDAP_NO_SUCH_OBJECT; + goto done; + } + + ret = pack_ber_group((request_type == REQ_FULL ? RESP_GROUP + : RESP_GROUP_MEMBERS), + domain_name, grp.gr_name, grp.gr_gid, + grp.gr_mem, sid, berval); + break; + default: + ret = LDAP_OPERATIONS_ERROR; + goto done; + } done: - free(buf); free(fq_name); + free(object_name); free(domain_name); - free(sid_str); + free(buf); return ret; } -int create_response(struct extdom_req *req, struct pwd_grp *pg_data, - const char *sid_str, enum sss_id_type id_type, - const char *domain_name, struct extdom_res **_res) +static int handle_name_request(enum request_types request_type, + const char *name, const char *domain_name, + struct berval **berval) { - int ret = EFAULT; - char *locat = NULL; - struct extdom_res *res; - - res = calloc(1, sizeof(struct extdom_res)); - if (res == NULL) { - return ENOMEM; - } - - switch (req->request_type) { - case REQ_SIMPLE: - switch (req->input_type) { - case INP_SID: - res->response_type = RESP_NAME; - res->data.name.domain_name = strdup(domain_name); - switch(id_type) { - case SSS_ID_TYPE_UID: - case SSS_ID_TYPE_BOTH: - if ((locat = strchr(pg_data->data.pwd.pw_name, SSSD_DOMAIN_SEPARATOR)) != NULL) { - if (strcasecmp(locat+1, domain_name) == 0 ) { - locat[0] = 0; - } else { - ret = LDAP_NO_SUCH_OBJECT; - goto done; - } - } - res->data.name.object_name = - strdup(pg_data->data.pwd.pw_name); - break; - case SSS_ID_TYPE_GID: - if ((locat = strchr(pg_data->data.grp.gr_name, SSSD_DOMAIN_SEPARATOR)) != NULL) { - if (strcasecmp(locat+1, domain_name) == 0) { - locat[0] = 0; - } else { - ret = LDAP_NO_SUCH_OBJECT; - goto done; - } - } - res->data.name.object_name = - strdup(pg_data->data.grp.gr_name); - break; - default: - ret = EINVAL; - goto done; - } - - if (res->data.name.domain_name == NULL - || res->data.name.object_name == NULL) { - ret = ENOMEM; - goto done; - } - break; - case INP_NAME: - case INP_POSIX_UID: - case INP_POSIX_GID: - res->response_type = RESP_SID; - res->data.sid = strdup(sid_str); - if (res->data.sid == NULL) { - ret = ENOMEM; - goto done; - } - break; - default: - ret = EINVAL; - goto done; - } - break; - case REQ_FULL: - switch (id_type) { - case SSS_ID_TYPE_UID: - case SSS_ID_TYPE_BOTH: - res->response_type = RESP_USER; - res->data.user.domain_name = strdup(domain_name); - if ((locat = strchr(pg_data->data.pwd.pw_name, SSSD_DOMAIN_SEPARATOR)) != NULL) { - if (strcasecmp(locat+1, domain_name) == 0) { - locat[0] = 0; - } else { - ret = LDAP_NO_SUCH_OBJECT; - goto done; - } - } - res->data.user.user_name = - strdup(pg_data->data.pwd.pw_name); - - if (res->data.user.domain_name == NULL - || res->data.user.user_name == NULL) { - ret = ENOMEM; - goto done; - } - - res->data.user.uid = pg_data->data.pwd.pw_uid; - res->data.user.gid = pg_data->data.pwd.pw_gid; - break; - case SSS_ID_TYPE_GID: - res->response_type = RESP_GROUP; - res->data.group.domain_name = strdup(domain_name); - if ((locat = strchr(pg_data->data.grp.gr_name, SSSD_DOMAIN_SEPARATOR)) != NULL) { - if (strcasecmp(locat+1, domain_name) == 0) { - locat[0] = 0; - } else { - ret = LDAP_NO_SUCH_OBJECT; - goto done; - } - } - res->data.group.group_name = - strdup(pg_data->data.grp.gr_name); - - if (res->data.group.domain_name == NULL - || res->data.group.group_name == NULL) { - ret = ENOMEM; - goto done; - } - - res->data.group.gid = pg_data->data.grp.gr_gid; - break; - default: - ret = EINVAL; - goto done; - } - break; - default: - ret = EINVAL; - goto done; + int ret; + char *fq_name = NULL; + struct passwd pwd; + struct passwd *pwd_result = NULL; + struct group grp; + struct group *grp_result = NULL; + char *sid_str = NULL; + enum sss_id_type id_type; + size_t buf_len; + char *buf = NULL; + + ret = asprintf(&fq_name, "%s%c%s", name, SSSD_DOMAIN_SEPARATOR, + domain_name); + if (ret == -1) { + ret = LDAP_OPERATIONS_ERROR; + fq_name = NULL; /* content is undefined according to + asprintf(3) */ + goto done; } - ret = 0; + if (request_type == REQ_SIMPLE || request_type == REQ_FULL_WITH_GROUPS) { + ret = sss_nss_getsidbyname(fq_name, &sid_str, &id_type); + if (ret != 0) { + if (ret == ENOENT) { + ret = LDAP_NO_SUCH_OBJECT; + } else { + ret = LDAP_OPERATIONS_ERROR; + } + goto done; + } + } -done: - if (ret == 0) { - *_res = res; + if (request_type == REQ_SIMPLE) { + ret = pack_ber_sid(sid_str, berval); } else { - free_resp_data(res); - } + ret = get_buffer(&buf_len, &buf); + if (ret != LDAP_SUCCESS) { + goto done; + } - if (locat != NULL) { - locat[0] = SSSD_DOMAIN_SEPARATOR; + ret = getpwnam_r(fq_name, &pwd, buf, buf_len, &pwd_result); + if (ret != 0) { + /* according to the man page there are a couple of error codes + * which can indicate that the user was not found. To be on the + * safe side we fail back to the group lookup on all errors. */ + pwd_result = NULL; + } + + if (pwd_result != NULL) { + ret = pack_ber_user((request_type == REQ_FULL ? RESP_USER + : RESP_USER_GROUPLIST), + domain_name, pwd.pw_name, pwd.pw_uid, + pwd.pw_gid, pwd.pw_gecos, pwd.pw_dir, + pwd.pw_shell, sid_str, berval); + } else { /* no user entry found */ + ret = getgrnam_r(fq_name, &grp, buf, buf_len, &grp_result); + if (ret != 0) { + ret = LDAP_NO_SUCH_OBJECT; + goto done; + } + + if (grp_result == NULL) { + ret = LDAP_NO_SUCH_OBJECT; + goto done; + } + + ret = pack_ber_group((request_type == REQ_FULL ? RESP_GROUP + : RESP_GROUP_MEMBERS), + domain_name, grp.gr_name, grp.gr_gid, + grp.gr_mem, sid_str, berval); + } } +done: + free(fq_name); + free(sid_str); + free(buf); + return ret; } -void free_resp_data(struct extdom_res *res) +int handle_request(struct ipa_extdom_ctx *ctx, struct extdom_req *req, + struct berval **berval) { - if (res == NULL) { - return; - } + int ret; + + switch (req->input_type) { + case INP_POSIX_UID: + ret = handle_uid_request(req->request_type, req->data.posix_uid.uid, + req->data.posix_uid.domain_name, berval); - switch (res->response_type) { - case RESP_SID: - free(res->data.sid); break; - case RESP_NAME: - free(res->data.name.domain_name); - free(res->data.name.object_name); + case INP_POSIX_GID: + ret = handle_gid_request(req->request_type, req->data.posix_gid.gid, + req->data.posix_uid.domain_name, berval); + break; - case RESP_USER: - free(res->data.user.domain_name); - free(res->data.user.user_name); + case INP_SID: + ret = handle_sid_request(req->request_type, req->data.sid, berval); break; - case RESP_GROUP: - free(res->data.group.domain_name); - free(res->data.group.group_name); + case INP_NAME: + ret = handle_name_request(req->request_type, req->data.name.object_name, + req->data.name.domain_name, berval); + break; + default: + ret = LDAP_PROTOCOL_ERROR; + goto done; } - free(res); -} +done: + + return ret; +} int pack_response(struct extdom_res *res, struct berval **ret_val) { diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_extop.c b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_extop.c index 9315da260..aa66c145b 100644 --- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_extop.c +++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_extop.c @@ -49,6 +49,7 @@ Slapi_PluginDesc ipa_extdom_plugin_desc = { static char *ipa_extdom_oid_list[] = { EXOP_EXTDOM_OID, + EXOP_EXTDOM_V1_OID, NULL }; @@ -71,8 +72,8 @@ static int ipa_extdom_extop(Slapi_PBlock *pb) struct berval *req_val = NULL; struct berval *ret_val = NULL; struct extdom_req *req = NULL; - struct extdom_res *res = NULL; struct ipa_extdom_ctx *ctx; + enum extdom_version version; ret = slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &oid); if (ret != 0) { @@ -82,7 +83,11 @@ static int ipa_extdom_extop(Slapi_PBlock *pb) } LOG("Received extended operation request with OID %s\n", oid); - if (strcasecmp(oid, EXOP_EXTDOM_OID) != 0) { + if (strcasecmp(oid, EXOP_EXTDOM_OID) == 0) { + version = EXTDOM_V0; + } else if (strcasecmp(oid, EXOP_EXTDOM_V1_OID) == 0) { + version = EXTDOM_V1; + } else { return SLAPI_PLUGIN_EXTENDED_NOT_HANDLED; } @@ -107,21 +112,21 @@ static int ipa_extdom_extop(Slapi_PBlock *pb) goto done; } - ret = handle_request(ctx, req, &res); + ret = check_request(req, version); if (ret != LDAP_SUCCESS) { - rc = LDAP_OPERATIONS_ERROR; - err_msg = "Failed to handle the request.\n"; + rc = LDAP_UNWILLING_TO_PERFORM; + err_msg = "Error in request data.\n"; goto done; } - ret = pack_response(res, &ret_val); + ret = handle_request(ctx, req, &ret_val); if (ret != LDAP_SUCCESS) { rc = LDAP_OPERATIONS_ERROR; - err_msg = "Failed to pack the response.\n"; + err_msg = "Failed to handle the request.\n"; goto done; } - ret = slapi_pblock_set(pb, SLAPI_EXT_OP_RET_OID, EXOP_EXTDOM_OID); + ret = slapi_pblock_set(pb, SLAPI_EXT_OP_RET_OID, oid); if (ret != 0) { rc = LDAP_OPERATIONS_ERROR; err_msg = "Failed to set the OID for the response.\n"; @@ -139,7 +144,6 @@ static int ipa_extdom_extop(Slapi_PBlock *pb) done: free_req_data(req); - free_resp_data(res); if (err_msg != NULL) { LOG("%s", err_msg); } |