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 e01e74ca5..81691ca1b 100644 --- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom.h +++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom.h @@ -63,6 +63,7 @@ #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 EXOP_EXTDOM_V2_OID "2.16.840.1.113730.3.8.10.4.2" #define IPA_EXTDOM_PLUGIN_NAME "ipa-extdom-extop" #define IPA_EXTDOM_FEATURE_DESC "IPA trusted domain ID mapper" @@ -72,7 +73,8 @@ enum extdom_version { EXTDOM_V0 = 0, - EXTDOM_V1 + EXTDOM_V1, + EXTDOM_V2 }; enum input_types { @@ -80,7 +82,9 @@ enum input_types { INP_NAME, INP_POSIX_UID, INP_POSIX_GID, - INP_CERT + INP_CERT, + INP_USERNAME, + INP_GROUPNAME }; enum request_types { 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 65c723ce6..92a7bea70 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 @@ -271,7 +271,9 @@ int parse_request_data(struct berval *req_val, struct extdom_req **_req) * sid (1), * name (2), * posix uid (3), - * posix gid (3) + * posix gid (4), + * username (5), + * groupname (6) * }, * requestType ENUMERATED { * simple (1), @@ -337,6 +339,8 @@ int parse_request_data(struct berval *req_val, struct extdom_req **_req) switch (req->input_type) { case INP_NAME: + case INP_USERNAME: + case INP_GROUPNAME: tag = ber_scanf(ber, "{aa}}", &req->data.name.domain_name, &req->data.name.object_name); break; @@ -378,6 +382,8 @@ void free_req_data(struct extdom_req *req) switch (req->input_type) { case INP_NAME: + case INP_USERNAME: + case INP_GROUPNAME: ber_memfree(req->data.name.domain_name); ber_memfree(req->data.name.object_name); break; @@ -407,6 +413,12 @@ int check_request(struct extdom_req *req, enum extdom_version version) } } + if (version == EXTDOM_V0 || version == EXTDOM_V1) { + if (req->input_type == INP_USERNAME || req->input_type == INP_GROUPNAME) { + return LDAP_PROTOCOL_ERROR; + } + } + return LDAP_SUCCESS; } @@ -1157,17 +1169,46 @@ done: return ret; } -static int handle_name_request(struct ipa_extdom_ctx *ctx, - struct extdom_req *req, - enum request_types request_type, - const char *name, const char *domain_name, - struct berval **berval) + +static int handle_simple_request(struct extdom_req *req, + const char *fq_name, + struct berval **berval) +{ + int ret; + char *sid_str = NULL; + enum sss_id_type id_type; + + ret = sss_nss_getsidbyname(fq_name, &sid_str, &id_type); + switch(ret) { + case 0: + ret = pack_ber_sid(sid_str, berval); + break; + case ENOENT: + ret = LDAP_NO_SUCH_OBJECT; + break; + case ETIMEDOUT: + case ETIME: + ret = LDAP_TIMELIMIT_EXCEEDED; + break; + default: + set_err_msg(req, "Failed to lookup SID by name"); + ret = LDAP_OPERATIONS_ERROR; + break; + } + + free(sid_str); + return ret; +} + +static int handle_username_request(struct ipa_extdom_ctx *ctx, + struct extdom_req *req, + enum request_types request_type, + const char *name, const char *domain_name, + struct berval **berval) { int ret; char *fq_name = NULL; struct passwd pwd; - struct group grp; - char *sid_str = NULL; enum sss_id_type id_type; size_t buf_len; char *buf = NULL; @@ -1189,104 +1230,156 @@ static int handle_name_request(struct ipa_extdom_ctx *ctx, } if (request_type == REQ_SIMPLE) { - ret = sss_nss_getsidbyname(fq_name, &sid_str, &id_type); - if (ret != 0) { - if (ret == ENOENT) { - ret = LDAP_NO_SUCH_OBJECT; - } else if (ret == ETIMEDOUT || ret == ETIME) { - ret = LDAP_TIMELIMIT_EXCEEDED; - } else { - set_err_msg(req, "Failed to lookup SID by name"); - ret = LDAP_OPERATIONS_ERROR; - } - goto done; - } + /* REQ_SIMPLE */ + ret = handle_simple_request(req, fq_name, berval); + goto done; + } - ret = pack_ber_sid(sid_str, berval); - } else { - ret = get_buffer(&buf_len, &buf); - if (ret != LDAP_SUCCESS) { - goto done; - } + /* REQ_FULL || REQ_FULL_WITH_GROUPS */ + ret = get_buffer(&buf_len, &buf); + if (ret != LDAP_SUCCESS) { + goto done; + } - ret = getpwnam_r_wrapper(ctx, fq_name, &pwd, &buf, &buf_len); - if (ret == 0) { - if (request_type == REQ_FULL_WITH_GROUPS) { - ret = sss_nss_getorigbyname(pwd.pw_name, &kv_list, &id_type); - if (ret != 0 || !(id_type == SSS_ID_TYPE_UID - || id_type == SSS_ID_TYPE_BOTH)) { - set_err_msg(req, "Failed to read original data"); - if (ret == ENOENT) { - ret = LDAP_NO_SUCH_OBJECT; - } else if (ret == ETIMEDOUT || ret == ETIME) { - ret = LDAP_TIMELIMIT_EXCEEDED; - } else { - ret = LDAP_OPERATIONS_ERROR; - } - goto done; - } - } - ret = pack_ber_user(ctx, - (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, kv_list, berval); - } else if (ret == ENOMEM || ret == ERANGE) { - ret = LDAP_OPERATIONS_ERROR; - goto done; - } else if (ret == ETIMEDOUT) { - ret = LDAP_TIMELIMIT_EXCEEDED; - goto done; - } else { /* no user entry found */ - /* according to the getpwnam() 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. */ - ret = getgrnam_r_wrapper(ctx, fq_name, &grp, &buf, &buf_len); - if (ret != 0) { + ret = getpwnam_r_wrapper(ctx, fq_name, &pwd, &buf, &buf_len); + switch(ret) { + case 0: + if (request_type == REQ_FULL_WITH_GROUPS) { + ret = sss_nss_getorigbyname(pwd.pw_name, &kv_list, &id_type); + if (ret != 0 || !(id_type == SSS_ID_TYPE_UID + || id_type == SSS_ID_TYPE_BOTH)) { + set_err_msg(req, "Failed to read original data"); if (ret == ENOENT) { ret = LDAP_NO_SUCH_OBJECT; - } else if (ret == ETIMEDOUT) { + } else if (ret == ETIMEDOUT || ret == ETIME) { ret = LDAP_TIMELIMIT_EXCEEDED; } else { ret = LDAP_OPERATIONS_ERROR; } goto done; } - - if (request_type == REQ_FULL_WITH_GROUPS) { - ret = sss_nss_getorigbyname(grp.gr_name, &kv_list, &id_type); - if (ret != 0 || !(id_type == SSS_ID_TYPE_GID - || id_type == SSS_ID_TYPE_BOTH)) { - if (ret == ENOENT) { - ret = LDAP_NO_SUCH_OBJECT; - } else if (ret == ETIMEDOUT || ret == ETIME) { - ret = LDAP_TIMELIMIT_EXCEEDED; - } else { - set_err_msg(req, "Failed to read original data"); - ret = LDAP_OPERATIONS_ERROR; - } - 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, kv_list, berval); } + ret = pack_ber_user(ctx, + (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, kv_list, berval); + break; + case ENOMEM: + case ERANGE: + ret = LDAP_OPERATIONS_ERROR; + break; + case ETIMEDOUT: + ret = LDAP_TIMELIMIT_EXCEEDED; + break; + default: + ret = LDAP_NO_SUCH_OBJECT; + break; } done: sss_nss_free_kv(kv_list); free(fq_name); - free(sid_str); free(buf); return ret; } +static int handle_groupname_request(struct ipa_extdom_ctx *ctx, + struct extdom_req *req, + enum request_types request_type, + const char *name, const char *domain_name, + struct berval **berval) +{ + int ret; + char *fq_name = NULL; + struct group grp; + enum sss_id_type id_type; + size_t buf_len; + char *buf = NULL; + struct sss_nss_kv *kv_list = NULL; + + /* with groups we can be sure that name doesn't contain the domain_name */ + ret = asprintf(&fq_name, "%s%c%s", name, SSSD_DOMAIN_SEPARATOR, + domain_name); + if (ret == -1) { + ret = LDAP_OPERATIONS_ERROR; + set_err_msg(req, "Failed to create fully qualified name"); + fq_name = NULL; /* content is undefined according to + asprintf(3) */ + goto done; + } + + if (request_type == REQ_SIMPLE) { + /* REQ_SIMPLE */ + ret = handle_simple_request(req, fq_name, berval); + goto done; + } + + /* REQ_FULL || REQ_FULL_WITH_GROUPS */ + ret = get_buffer(&buf_len, &buf); + if (ret != LDAP_SUCCESS) { + goto done; + } + + ret = getgrnam_r_wrapper(ctx, fq_name, &grp, &buf, &buf_len); + if (ret != 0) { + if (ret == ENOMEM || ret == ERANGE) { + ret = LDAP_OPERATIONS_ERROR; + } else { + ret = LDAP_NO_SUCH_OBJECT; + } + goto done; + } + + if (request_type == REQ_FULL_WITH_GROUPS) { + ret = sss_nss_getorigbyname(grp.gr_name, &kv_list, &id_type); + if (ret != 0 || !(id_type == SSS_ID_TYPE_GID + || id_type == SSS_ID_TYPE_BOTH)) { + if (ret == ENOENT) { + ret = LDAP_NO_SUCH_OBJECT; + } else { + set_err_msg(req, "Failed to read original data"); + ret = LDAP_OPERATIONS_ERROR; + } + 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, kv_list, berval); + +done: + sss_nss_free_kv(kv_list); + free(fq_name); + free(buf); + + return ret; +} + +static int handle_name_request(struct ipa_extdom_ctx *ctx, + struct extdom_req *req, + enum request_types request_type, + const char *name, const char *domain_name, + struct berval **berval) +{ + int ret; + + + ret = handle_username_request(ctx, req, request_type, + name, domain_name, berval); + if (ret == LDAP_NO_SUCH_OBJECT) { + ret = handle_groupname_request(ctx, req, request_type, + name, domain_name, berval); + } + + return ret; +} + + int handle_request(struct ipa_extdom_ctx *ctx, struct extdom_req *req, struct berval **berval) { @@ -1318,6 +1411,18 @@ int handle_request(struct ipa_extdom_ctx *ctx, struct extdom_req *req, req->data.name.object_name, req->data.name.domain_name, berval); + break; + case INP_GROUPNAME: + ret = handle_groupname_request(ctx, req, req->request_type, + req->data.name.object_name, + req->data.name.domain_name, berval); + + break; + case INP_USERNAME: + ret = handle_username_request(ctx, req, req->request_type, + req->data.name.object_name, + req->data.name.domain_name, berval); + break; default: set_err_msg(req, "Unknown input type"); 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 48fcecc1e..5f9714f98 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 @@ -54,6 +54,7 @@ Slapi_PluginDesc ipa_extdom_plugin_desc = { static char *ipa_extdom_oid_list[] = { EXOP_EXTDOM_OID, EXOP_EXTDOM_V1_OID, + EXOP_EXTDOM_V2_OID, NULL }; @@ -196,6 +197,8 @@ static int ipa_extdom_extop(Slapi_PBlock *pb) version = EXTDOM_V0; } else if (strcasecmp(oid, EXOP_EXTDOM_V1_OID) == 0) { version = EXTDOM_V1; + } else if (strcasecmp(oid, EXOP_EXTDOM_V2_OID) == 0) { + version = EXTDOM_V2; } else { return SLAPI_PLUGIN_EXTENDED_NOT_HANDLED; }