extdom: improve cert request

Certificates can be assigned to multiple user so the extdom plugin must
use sss_nss_getlistbycert() instead of sss_nss_getnamebycert() and
return a list of fully-qualified user names.

Due to issues on the SSSD side the current version of lookups by
certificates didn't work at all and the changes here won't break
existing clients.

Related to https://pagure.io/freeipa/issue/6826

Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
Reviewed-By: David Kupka <dkupka@redhat.com>
This commit is contained in:
Sumit Bose 2017-03-17 14:48:50 +01:00 committed by Tomas Krizek
parent ee455f163d
commit 8960398a57
No known key found for this signature in database
GPG Key ID: 22A2A94B5E49415A
3 changed files with 143 additions and 19 deletions

View File

@ -95,7 +95,8 @@ enum response_types {
RESP_USER,
RESP_GROUP,
RESP_USER_GROUPLIST,
RESP_GROUP_MEMBERS
RESP_GROUP_MEMBERS,
RESP_NAME_LIST
};
struct extdom_req {

View File

@ -698,6 +698,90 @@ done:
return ret;
}
int pack_ber_name_list(struct extdom_req *req, char **fq_name_list,
struct berval **berval)
{
BerElement *ber = NULL;
int ret;
char *sep;
size_t c;
size_t len;
size_t name_len;
/* count the names */
for (c = 0; fq_name_list[c] != NULL; c++);
if (c == 0) {
set_err_msg(req, "Empty name list");
return LDAP_NO_SUCH_OBJECT;
}
ber = ber_alloc_t( LBER_USE_DER );
if (ber == NULL) {
set_err_msg(req, "BER alloc failed");
return LDAP_OPERATIONS_ERROR;
}
ret = ber_printf(ber,"{e{", RESP_NAME_LIST);
if (ret == -1) {
set_err_msg(req, "BER start failed");
ber_free(ber, 1);
return LDAP_OPERATIONS_ERROR;
}
for (c = 0; fq_name_list[c] != NULL; c++) {
len = strlen(fq_name_list[c]);
if (len < 3) {
set_err_msg(req, "Fully qualified name too short");
ber_free(ber, 1);
return LDAP_OPERATIONS_ERROR;
}
sep = strrchr(fq_name_list[c], SSSD_DOMAIN_SEPARATOR);
if (sep == NULL) {
set_err_msg(req, "Failed to split fully qualified name");
ber_free(ber, 1);
return LDAP_OPERATIONS_ERROR;
}
name_len = sep - fq_name_list[c];
if (name_len == 0) {
set_err_msg(req, "Missing name.");
ber_free(ber, 1);
return LDAP_OPERATIONS_ERROR;
}
if (name_len + 1 == len) {
set_err_msg(req, "Missing domain.");
ber_free(ber, 1);
return LDAP_OPERATIONS_ERROR;
}
ret = ber_printf(ber,"{oo}", (sep + 1), len - name_len -1,
fq_name_list[c], name_len);
if (ret == -1) {
set_err_msg(req, "BER list item failed");
ber_free(ber, 1);
return LDAP_OPERATIONS_ERROR;
}
}
ret = ber_printf(ber,"}}");
if (ret == -1) {
set_err_msg(req, "BER end failed");
ber_free(ber, 1);
return LDAP_OPERATIONS_ERROR;
}
ret = ber_flatten(ber, berval);
ber_free(ber, 1);
if (ret == -1) {
set_err_msg(req, "BER flatten failed");
return LDAP_OPERATIONS_ERROR;
}
return LDAP_SUCCESS;
}
int pack_ber_name(const char *domain_name, const char *name,
struct berval **berval)
{
@ -867,12 +951,56 @@ done:
return ret;
}
static int handle_sid_or_cert_request(struct ipa_extdom_ctx *ctx,
struct extdom_req *req,
enum request_types request_type,
enum input_types input_type,
const char *input,
struct berval **berval)
static int handle_cert_request(struct ipa_extdom_ctx *ctx,
struct extdom_req *req,
enum request_types request_type,
enum input_types input_type,
const char *input,
struct berval **berval)
{
int ret;
char **fq_names = NULL;
enum sss_id_type *id_types = NULL;
size_t c;
if (request_type != REQ_SIMPLE) {
set_err_msg(req, "Only simple request type allowed "
"for lookups by certificate");
ret = LDAP_PROTOCOL_ERROR;
goto done;
}
ret = sss_nss_getlistbycert(input, &fq_names, &id_types);
if (ret != 0) {
if (ret == ENOENT) {
ret = LDAP_NO_SUCH_OBJECT;
} else {
set_err_msg(req, "Failed to lookup name by certificate");
ret = LDAP_OPERATIONS_ERROR;
}
goto done;
}
ret = pack_ber_name_list(req, fq_names, berval);
done:
if (fq_names != NULL) {
for (c = 0; fq_names[c] != NULL; c++) {
free(fq_names[c]);
}
free(fq_names);
}
free(id_types);
return ret;
}
static int handle_sid_request(struct ipa_extdom_ctx *ctx,
struct extdom_req *req,
enum request_types request_type,
enum input_types input_type,
const char *input,
struct berval **berval)
{
int ret;
struct passwd pwd;
@ -886,11 +1014,7 @@ static int handle_sid_or_cert_request(struct ipa_extdom_ctx *ctx,
enum sss_id_type id_type;
struct sss_nss_kv *kv_list = NULL;
if (input_type == INP_SID) {
ret = sss_nss_getnamebysid(input, &fq_name, &id_type);
} else {
ret = sss_nss_getnamebycert(input, &fq_name, &id_type);
}
ret = sss_nss_getnamebysid(input, &fq_name, &id_type);
if (ret != 0) {
if (ret == ENOENT) {
ret = LDAP_NO_SUCH_OBJECT;
@ -1147,13 +1271,12 @@ int handle_request(struct ipa_extdom_ctx *ctx, struct extdom_req *req,
break;
case INP_SID:
ret = handle_sid_request(ctx, req, req->request_type,
req->input_type, req->data.sid, berval);
break;
case INP_CERT:
ret = handle_sid_or_cert_request(ctx, req, req->request_type,
req->input_type,
req->input_type == INP_SID ?
req->data.sid :
req->data.cert,
berval);
ret = handle_cert_request(ctx, req, req->request_type,
req->input_type, req->data.cert, berval);
break;
case INP_NAME:
ret = handle_name_request(ctx, req, req->request_type,

View File

@ -28,7 +28,7 @@ DIRSRV_CFLAGS="$DIRSRV_CFLAGS $NSPR_CFLAGS"
dnl -- sss_idmap is needed by the extdom exop --
PKG_CHECK_MODULES([SSSIDMAP], [sss_idmap])
PKG_CHECK_MODULES([SSSNSSIDMAP], [sss_nss_idmap >= 1.13.90])
PKG_CHECK_MODULES([SSSNSSIDMAP], [sss_nss_idmap >= 1.15.2])
dnl -- sss_certmap and certauth.h are needed by the IPA KDB certauth plugin --
PKG_CHECK_EXISTS([sss_certmap],