mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
ipa-cldap: Decode CLDAP request.
This commit is contained in:
parent
d709dcf8f5
commit
046c416e90
@ -68,6 +68,17 @@ struct ipa_cldap_ctx {
|
||||
int sd;
|
||||
};
|
||||
|
||||
struct kvp {
|
||||
struct berval attr;
|
||||
struct berval value;
|
||||
};
|
||||
|
||||
struct kvp_list {
|
||||
struct kvp *pairs;
|
||||
int allocated;
|
||||
int top;
|
||||
};
|
||||
|
||||
struct ipa_cldap_req {
|
||||
int fd;
|
||||
|
||||
@ -76,6 +87,11 @@ struct ipa_cldap_req {
|
||||
|
||||
char dgram[MAX_DG_SIZE];
|
||||
size_t dgsize;
|
||||
|
||||
ber_int_t id;
|
||||
|
||||
/* filter members */
|
||||
struct kvp_list kvps;
|
||||
};
|
||||
|
||||
void *ipa_cldap_worker(struct ipa_cldap_ctx *ctx);
|
||||
|
@ -39,10 +39,185 @@
|
||||
|
||||
#include "ipa_cldap.h"
|
||||
#include <poll.h>
|
||||
#include <lber.h>
|
||||
|
||||
/* pre allocate some space for answers, default to increment 3 at a time */
|
||||
static int ipa_cldap_more_kvps(struct kvp_list *kvps)
|
||||
{
|
||||
struct kvp *pairs;
|
||||
|
||||
if (kvps->allocated - kvps->top > 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
pairs = realloc(kvps->pairs, (kvps->allocated + 3) * sizeof(struct kvp));
|
||||
if (!pairs) {
|
||||
return ENOMEM;
|
||||
}
|
||||
kvps->pairs = pairs;
|
||||
kvps->allocated += 3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ipa_cldap_free_kvps(struct kvp_list *kvps)
|
||||
{
|
||||
free(kvps->pairs);
|
||||
kvps->pairs = NULL;
|
||||
kvps->allocated = 0;
|
||||
kvps->top = 0;
|
||||
}
|
||||
|
||||
static int ipa_cldap_get_kvp(BerElement *be, struct kvp_list *kvps)
|
||||
{
|
||||
ber_tag_t tag;
|
||||
int ret;
|
||||
|
||||
ret = ipa_cldap_more_kvps(kvps);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
tag = ber_scanf(be, "{mm}",
|
||||
&(kvps->pairs[kvps->top].attr),
|
||||
&(kvps->pairs[kvps->top].value));
|
||||
if (tag == LBER_ERROR) {
|
||||
LOG_TRACE("Invalid filter\n");
|
||||
ret = EINVAL;
|
||||
} else {
|
||||
kvps->top++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ipa_cldap_get_tree(BerElement *be, struct kvp_list *kvps)
|
||||
{
|
||||
ber_tag_t tag;
|
||||
ber_tag_t len;
|
||||
char *cookie;
|
||||
int ret;
|
||||
|
||||
tag = ber_first_element(be, &len, &cookie);
|
||||
while (tag != LBER_DEFAULT) {
|
||||
tag = ber_peek_tag(be, &len);
|
||||
switch (tag) {
|
||||
case LDAP_FILTER_EQUALITY:
|
||||
ret = ipa_cldap_get_kvp(be, kvps);
|
||||
break;
|
||||
case LDAP_FILTER_AND:
|
||||
ret = ipa_cldap_get_tree(be, kvps);
|
||||
break;
|
||||
default:
|
||||
LOG_TRACE("Unsupported filter\n");
|
||||
ret = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
tag = ber_next_element(be, &len, cookie);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipa_cldap_decode(struct ipa_cldap_req *req)
|
||||
{
|
||||
struct berval bv;
|
||||
BerElement *be;
|
||||
ber_tag_t tag;
|
||||
ber_len_t len;
|
||||
ber_int_t scope;
|
||||
ber_int_t deref;
|
||||
ber_int_t sizelimit;
|
||||
ber_int_t timelimit;
|
||||
ber_int_t typesonly;
|
||||
struct berval base;
|
||||
struct berval attr;
|
||||
int ret = EINVAL;
|
||||
|
||||
bv.bv_val = req->dgram;
|
||||
bv.bv_len = req->dgsize;
|
||||
|
||||
be = ber_alloc_t(0);
|
||||
if (!be) {
|
||||
LOG_FATAL("Out of memory!\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
ber_init2(be, &bv, 0);
|
||||
|
||||
tag = ber_skip_tag(be, &len);
|
||||
if (tag != LDAP_TAG_MESSAGE) {
|
||||
LOG_TRACE("Invalid message (%d)\n", (int)tag);
|
||||
goto done;
|
||||
}
|
||||
|
||||
tag = ber_get_int(be, &req->id);
|
||||
if (tag != LDAP_TAG_MSGID) {
|
||||
LOG_TRACE("Failed to get id\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
tag = ber_peek_tag(be, &len);
|
||||
if (tag != LDAP_REQ_SEARCH) {
|
||||
LOG_TRACE("Unexpected message type (%d)\n", (int)tag);
|
||||
goto done;
|
||||
}
|
||||
|
||||
tag = ber_scanf(be, "{meeiib",
|
||||
&base, &scope, &deref, &sizelimit, &timelimit, &typesonly);
|
||||
if (tag == LBER_ERROR) {
|
||||
LOG_TRACE("Failed to parse message\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((base.bv_len != 0) ||
|
||||
(scope != 0) ||
|
||||
(typesonly != 0)){
|
||||
LOG_TRACE("Unexpected request\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = ipa_cldap_get_tree(be, &req->kvps);
|
||||
if (ret) {
|
||||
LOG_TRACE("Failed to parse filter\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
tag = ber_scanf(be, "{m}}", &attr);
|
||||
if (tag == LBER_ERROR) {
|
||||
LOG_TRACE("Failed to parse message\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (strncasecmp(attr.bv_val, "netlogon", attr.bv_len) != 0) {
|
||||
LOG_TRACE("Unexpected request\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
ber_free(be, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ipa_cldap_process(struct ipa_cldap_ctx *ctx,
|
||||
struct ipa_cldap_req *req)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ipa_cldap_decode(req);
|
||||
if (ret) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
LOG_TRACE("CLDAP Request received");
|
||||
|
||||
done:
|
||||
ipa_cldap_free_kvps(&req->kvps);
|
||||
free(req);
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user