From 2542d54e9384302c6c9a7b2b2bf4be07b6d95f9c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 11 May 2005 14:38:13 +0000 Subject: r6732: - move sasl send recv code to the ldap lib - support 'modrdn' ldif metze (This used to be commit b6a1734699953964fcde6fe6ea7048496492eb33) --- source4/libcli/ldap/ldap_client.c | 131 +++++++++++++++++++++++++++++++++- source4/libcli/ldap/ldap_ldif.c | 58 +++++++++++++++ source4/torture/ldap/basic.c | 37 +++++----- source4/torture/ldap/common.c | 146 ++++---------------------------------- 4 files changed, 219 insertions(+), 153 deletions(-) diff --git a/source4/libcli/ldap/ldap_client.c b/source4/libcli/ldap/ldap_client.c index 71b57e116e..8867344de3 100644 --- a/source4/libcli/ldap/ldap_client.c +++ b/source4/libcli/ldap/ldap_client.c @@ -548,9 +548,138 @@ struct ldap_message *ldap_receive(struct ldap_connection *conn, int msgid, return NULL; } +/* + Write data to a fd +*/ +static ssize_t write_data(int fd, char *buffer, size_t N) +{ + size_t total=0; + ssize_t ret; + + while (total < N) { + ret = sys_write(fd,buffer + total,N - total); + + if (ret == -1) { + DEBUG(0,("write_data: write failure. Error = %s\n", strerror(errno) )); + return -1; + } + if (ret == 0) + return total; + + total += ret; + } + + return (ssize_t)total; +} + + +/* + Read data from the client, reading exactly N bytes +*/ +static ssize_t read_data(int fd, char *buffer, size_t N) +{ + ssize_t ret; + size_t total=0; + + while (total < N) { + + ret = sys_read(fd,buffer + total,N - total); + + if (ret == 0) { + DEBUG(10,("read_data: read of %d returned 0. Error = %s\n", + (int)(N - total), strerror(errno) )); + return 0; + } + + if (ret == -1) { + DEBUG(0,("read_data: read failure for %d. Error = %s\n", + (int)(N - total), strerror(errno) )); + return -1; + } + total += ret; + } + + return (ssize_t)total; +} + +static struct ldap_message *ldap_transaction_sasl(struct ldap_connection *conn, struct ldap_message *req) +{ + NTSTATUS status; + DATA_BLOB request; + BOOL result; + DATA_BLOB wrapped; + int len; + char length[4]; + struct asn1_data asn1; + struct ldap_message *rep; + + req->messageid = conn->next_msgid++; + + if (!ldap_encode(req, &request)) + return NULL; + + status = gensec_wrap(conn->gensec, + req->mem_ctx, + &request, + &wrapped); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("gensec_wrap: %s\n",nt_errstr(status))); + return NULL; + } + + RSIVAL(length, 0, wrapped.length); + + result = (write_data(conn->sock, length, 4) == 4); + if (!result) + return NULL; + + result = (write_data(conn->sock, wrapped.data, wrapped.length) == wrapped.length); + if (!result) + return NULL; + + wrapped = data_blob(NULL, 0x4000); + data_blob_clear(&wrapped); + + result = (read_data(conn->sock, length, 4) == 4); + if (!result) + return NULL; + + len = RIVAL(length,0); + + result = (read_data(conn->sock, wrapped.data, MIN(wrapped.length,len)) == len); + if (!result) + return NULL; + + wrapped.length = len; + + status = gensec_unwrap(conn->gensec, + req->mem_ctx, + &wrapped, + &request); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("gensec_unwrap: %s\n",nt_errstr(status))); + return NULL; + } + + rep = new_ldap_message(req->mem_ctx); + + asn1_load(&asn1, request); + if (!ldap_decode(&asn1, rep)) { + return NULL; + } + + return rep; +} + struct ldap_message *ldap_transaction(struct ldap_connection *conn, struct ldap_message *request) { + if ((request->type != LDAP_TAG_BindRequest) && conn->gensec && + (gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) || + gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN))) { + return ldap_transaction_sasl(conn, request); + } + if (!ldap_send_msg(conn, request, NULL)) return False; @@ -624,7 +753,7 @@ int ldap_bind_sasl(struct ldap_connection *conn, struct cli_credentials *creds) return result; } - gensec_want_feature(conn->gensec, GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL); + gensec_want_feature(conn->gensec, 0 | GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL); status = gensec_set_credentials(conn->gensec, creds); if (!NT_STATUS_IS_OK(status)) { diff --git a/source4/libcli/ldap/ldap_ldif.c b/source4/libcli/ldap/ldap_ldif.c index e5e5cdd6df..c36106e116 100644 --- a/source4/libcli/ldap/ldap_ldif.c +++ b/source4/libcli/ldap/ldap_ldif.c @@ -305,6 +305,53 @@ static BOOL fill_mods(struct ldap_message *msg, char **chunk) return True; } +static BOOL fill_modrdn(struct ldap_message *msg, char **chunk) +{ + struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest; + const char *attr_name; + struct ldap_val value; + + r->newrdn = NULL; + r->deleteolddn = False; + r->newsuperior = NULL; + + if (next_attr(chunk, &attr_name, &value) != 0) { + return False; + } + + if (!strequal(attr_name, "newrdn")) { + return False; + } + + r->newrdn = value.data; + + if (next_attr(chunk, &attr_name, &value) != 0) { + return False; + } + + if (!strequal(attr_name, "deleteoldrdn")) { + return False; + } + + if (value.data && (((char *)value.data)[0] != '0')) { + r->deleteolddn = True; + } + + if (next_attr(chunk, &attr_name, &value) != 0) { + /* newsuperior is optional */ + return True; + } + + if (!strequal(attr_name, "newsuperior")) { + return False; + } + + r->newsuperior = value.data; + + return True; +} + + /* read from a LDIF source, creating a ldap_message */ @@ -381,6 +428,17 @@ static struct ldap_message *ldif_read(TALLOC_CTX *mem_ctx, int (*fgetc_fn)(void return msg; } + if (strequal(value.data, "modrdn")) { + msg->type = LDAP_TAG_ModifyDNRequest; + + msg->r.ModifyDNRequest.dn = dn; + + if (!fill_modrdn(msg, &s)) + goto failed; + + return msg; + } + DEBUG(3, ("changetype %s not supported\n", (char *)value.data)); failed: diff --git a/source4/torture/ldap/basic.c b/source4/torture/ldap/basic.c index b53515fdbc..7114aa2576 100644 --- a/source4/torture/ldap/basic.c +++ b/source4/torture/ldap/basic.c @@ -137,8 +137,7 @@ static BOOL test_search_rootDSE(struct ldap_connection *conn, char **basedn) static BOOL test_compare_sasl(struct ldap_connection *conn, const char *basedn) { - BOOL ret = True; - struct ldap_message *msg, *result; + struct ldap_message *req, *rep; const char *val; printf("Testing SASL Compare: %s\n", basedn); @@ -149,37 +148,33 @@ static BOOL test_compare_sasl(struct ldap_connection *conn, const char *basedn) conn->next_msgid = 55; - msg = new_ldap_message(conn); - if (!msg) { + req = new_ldap_message(conn); + if (!req) { return False; } - msg->type = LDAP_TAG_CompareRequest; - msg->r.CompareRequest.dn = basedn; - msg->r.CompareRequest.attribute = talloc_strdup(msg->mem_ctx, "objectClass"); + req->type = LDAP_TAG_CompareRequest; + req->r.CompareRequest.dn = basedn; + req->r.CompareRequest.attribute = talloc_strdup(req->mem_ctx, "objectClass"); val = "domain"; - msg->r.CompareRequest.value = data_blob_talloc(msg->mem_ctx, val, strlen(val)); + req->r.CompareRequest.value = data_blob_talloc(req->mem_ctx, val, strlen(val)); - if (!ldap_sasl_send_msg(conn, msg, NULL)) { + rep = ldap_transaction(conn, req); + if (!rep) { return False; } DEBUG(5,("Code: %d DN: [%s] ERROR:[%s] REFERRAL:[%s]\n", - msg->r.CompareResponse.resultcode, - msg->r.CompareResponse.dn, - msg->r.CompareResponse.errormessage, - msg->r.CompareResponse.referral)); - - return True; - if (!result) { - return False; - } + rep->r.CompareResponse.resultcode, + rep->r.CompareResponse.dn, + rep->r.CompareResponse.errormessage, + rep->r.CompareResponse.referral)); - if (result->type != LDAP_TAG_CompareResponse) { + if (rep->type != LDAP_TAG_CompareResponse) { return False; } - return ret; + return True; } BOOL torture_ldap_basic(void) @@ -199,7 +194,7 @@ BOOL torture_ldap_basic(void) url = talloc_asprintf(mem_ctx, "ldap://%s/", host); - status = torture_ldap_connection(mem_ctx, &conn, url, userdn, secret); + status = torture_ldap_connection2(mem_ctx, &conn, url, userdn, secret); if (!NT_STATUS_IS_OK(status)) { return False; } diff --git a/source4/torture/ldap/common.c b/source4/torture/ldap/common.c index 9dbe2557eb..a65d24804c 100644 --- a/source4/torture/ldap/common.c +++ b/source4/torture/ldap/common.c @@ -24,6 +24,7 @@ #include "includes.h" #include "asn_1.h" #include "libcli/ldap/ldap.h" +#include "auth/gensec/gensec.h" NTSTATUS torture_ldap_bind(struct ldap_connection *conn, const char *userdn, const char *password) { @@ -70,10 +71,9 @@ NTSTATUS torture_ldap_bind_sasl(struct ldap_connection *conn, /* open a ldap connection to a server */ NTSTATUS torture_ldap_connection(TALLOC_CTX *mem_ctx, struct ldap_connection **conn, - const char *url, const char *userdn, const char *password) + const char *url) { NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - int ret; if (!url) { printf("You must specify a url string\n"); @@ -86,6 +86,19 @@ NTSTATUS torture_ldap_connection(TALLOC_CTX *mem_ctx, struct ldap_connection **c return status; } + return NT_STATUS_OK; +} + +/* open a ldap connection to a server */ +NTSTATUS torture_ldap_connection2(TALLOC_CTX *mem_ctx, struct ldap_connection **conn, + const char *url, const char *userdn, const char *password) +{ + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + int ret; + + status = torture_ldap_connection(mem_ctx, conn, url); + NT_STATUS_NOT_OK_RETURN(status); + ret = ldap_bind_simple(*conn, userdn, password); if (ret != LDAP_SUCCESS) { printf("Failed to connect with url [%s]\n", url); @@ -104,132 +117,3 @@ NTSTATUS torture_ldap_close(struct ldap_connection *conn) :-) sss */ return NT_STATUS_OK; } - - -/* - Write data to a fd -*/ -static ssize_t write_data(int fd, char *buffer, size_t N) -{ - size_t total=0; - ssize_t ret; - - while (total < N) { - ret = sys_write(fd,buffer + total,N - total); - - if (ret == -1) { - DEBUG(0,("write_data: write failure. Error = %s\n", strerror(errno) )); - return -1; - } - if (ret == 0) - return total; - - total += ret; - } - - return (ssize_t)total; -} - - -/* - Read data from the client, reading exactly N bytes -*/ -static ssize_t read_data(int fd, char *buffer, size_t N) -{ - ssize_t ret; - size_t total=0; - - while (total < N) { - - ret = sys_read(fd,buffer + total,N - total); - - if (ret == 0) { - DEBUG(10,("read_data: read of %d returned 0. Error = %s\n", - (int)(N - total), strerror(errno) )); - return 0; - } - - if (ret == -1) { - DEBUG(0,("read_data: read failure for %d. Error = %s\n", - (int)(N - total), strerror(errno) )); - return -1; - } - total += ret; - } - - return (ssize_t)total; -} - -BOOL ldap_sasl_send_msg(struct ldap_connection *conn, struct ldap_message *msg, - const struct timeval *endtime) -{ - NTSTATUS status; - DATA_BLOB request; - BOOL result; - DATA_BLOB wrapped; - int len; - char length[4]; - struct asn1_data asn1; - TALLOC_CTX *mem_ctx; - - msg->messageid = conn->next_msgid++; - - if (!ldap_encode(msg, &request)) - return False; - - status = gensec_wrap(conn->gensec, - msg->mem_ctx, - &request, - &wrapped); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("gensec_wrap: %s\n",nt_errstr(status))); - return False; - } - - RSIVAL(length, 0, wrapped.length); - - result = (write_data(conn->sock, length, 4) == 4); - if (!result) - return result; - - result = (write_data(conn->sock, wrapped.data, wrapped.length) == wrapped.length); - if (!result) - return result; - - wrapped = data_blob(NULL, 0x4000); - data_blob_clear(&wrapped); - - result = (read_data(conn->sock, length, 4) == 4); - if (!result) - return result; - - len = RIVAL(length,0); - - result = (read_data(conn->sock, wrapped.data, MIN(wrapped.length,len)) == len); - if (!result) - return result; - - wrapped.length = len; - - status = gensec_unwrap(conn->gensec, - msg->mem_ctx, - &wrapped, - &request); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("gensec_unwrap: %s\n",nt_errstr(status))); - return False; - } - - mem_ctx = msg->mem_ctx; - ZERO_STRUCTP(msg); - msg->mem_ctx = mem_ctx; - - asn1_load(&asn1, request); - if (!ldap_decode(&asn1, msg)) { - return False; - } - - result = True; - - return result; -} -- cgit