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 +++++++++++++++++++++++++++++++++++++- 1 file changed, 130 insertions(+), 1 deletion(-) (limited to 'source4/libcli/ldap/ldap_client.c') 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)) { -- cgit