1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-11 05:18:09 +03:00

r7626: a new ldap client library. Main features are:

- hooked into events system, so requests can be truly async and won't
   interfere with other processing happening at the same time

 - uses NTSTATUS codes for errors (previously errors were mostly
   ignored). In a similar fashion to the DOS error handling, I have
   reserved a range of the NTSTATUS code 32 bit space for LDAP error
   codes, so a function can return a LDAP error code in a NTSTATUS

 - much cleaner packet handling
This commit is contained in:
Andrew Tridgell 2005-06-16 05:39:40 +00:00 committed by Gerald (Jerry) Carter
parent da78ed1a4d
commit 2e3c660b2f
16 changed files with 1038 additions and 1190 deletions

View File

@ -117,4 +117,9 @@ typedef uint32_t WERROR;
#define NT_STATUS_DOS_CLASS(status) ((NT_STATUS_V(status) >> 16) & 0xFF) #define NT_STATUS_DOS_CLASS(status) ((NT_STATUS_V(status) >> 16) & 0xFF)
#define NT_STATUS_DOS_CODE(status) (NT_STATUS_V(status) & 0xFFFF) #define NT_STATUS_DOS_CODE(status) (NT_STATUS_V(status) & 0xFFFF)
/* define ldap error codes as NTSTATUS codes */
#define NT_STATUS_LDAP(code) NT_STATUS(0xF2000000 | code)
#define NT_STATUS_IS_LDAP(status) ((NT_STATUS_V(status) & 0xFF000000) == 0xF2000000)
#define NT_STATUS_LDAP_CODE(status) (NT_STATUS_V(status) & ~0xFF000000)
#endif #endif

View File

@ -92,6 +92,7 @@ struct ldapsrv_call;
struct ldapsrv_connection; struct ldapsrv_connection;
struct ldap_connection; struct ldap_connection;
struct ldap_message; struct ldap_message;
struct ldap_Result;
struct rw_buffer; struct rw_buffer;
struct registry_context; struct registry_context;
struct registry_key; struct registry_key;
@ -158,6 +159,8 @@ struct ldb_val;
struct ldb_message; struct ldb_message;
struct ldb_context; struct ldb_context;
struct ldb_parse_tree; struct ldb_parse_tree;
struct ldb_message_element;
struct ldap_mod;
struct dom_sid; struct dom_sid;
struct security_token; struct security_token;

View File

@ -35,7 +35,8 @@ NOPROTO=YES
INIT_OBJ_FILES = \ INIT_OBJ_FILES = \
lib/socket/socket.o lib/socket/socket.o
ADD_OBJ_FILES = \ ADD_OBJ_FILES = \
lib/socket/access.o lib/socket/access.o \
lib/socket/connect.o
NOPROTO=YES NOPROTO=YES
# End SUBSYSTEM SOCKET # End SUBSYSTEM SOCKET
################################################ ################################################

View File

@ -0,0 +1,74 @@
/*
Unix SMB/CIFS implementation.
implements a non-blocking connect operation that is aware of the samba4 events
system
Copyright (C) Andrew Tridgell 2005
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
#include "lib/socket/socket.h"
#include "lib/events/events.h"
/*
handle write events on connect completion
*/
static void socket_connect_handler(struct event_context *ev, struct fd_event *fde,
uint16_t flags, void *private)
{
NTSTATUS *status = (NTSTATUS *)private;
*status = NT_STATUS_OK;
}
/*
just like socket_connect() but other events can happen while the
connect is ongoing. This isn't as good as making the calling code
fully async during its connect phase, but at least it means that any
calling code that uses this won't interfere with code that is
properly async
*/
NTSTATUS socket_connect_ev(struct socket_context *sock,
const char *my_address, int my_port,
const char *server_address, int server_port,
uint32_t flags, struct event_context *ev)
{
TALLOC_CTX *tmp_ctx = talloc_new(sock);
NTSTATUS status;
set_blocking(socket_get_fd(sock), False);
status = socket_connect(sock, my_address, my_port,
server_address, server_port, flags);
event_add_fd(ev, tmp_ctx, socket_get_fd(sock), EVENT_FD_WRITE,
socket_connect_handler, &status);
while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
if (event_loop_once(ev) != 0) {
talloc_free(tmp_ctx);
return NT_STATUS_INTERNAL_ERROR;
}
}
status = socket_connect_complete(sock, flags);
talloc_free(tmp_ctx);
return status;
}

View File

@ -243,13 +243,10 @@ NTSTATUS socket_sendto(struct socket_context *sock,
/* /*
ask for the number of bytes in a pending incoming datagram ask for the number of bytes in a pending incoming packet
*/ */
NTSTATUS socket_pending(struct socket_context *sock, size_t *npending) NTSTATUS socket_pending(struct socket_context *sock, size_t *npending)
{ {
if (sock->type != SOCKET_TYPE_DGRAM) {
return NT_STATUS_INVALID_PARAMETER;
}
if (!sock->ops->fn_pending) { if (!sock->ops->fn_pending) {
return NT_STATUS_NOT_IMPLEMENTED; return NT_STATUS_NOT_IMPLEMENTED;
} }

View File

@ -139,4 +139,9 @@ BOOL socket_check_access(struct socket_context *sock,
const char *service_name, const char *service_name,
const char **allow_list, const char **deny_list); const char **allow_list, const char **deny_list);
NTSTATUS socket_connect_ev(struct socket_context *sock,
const char *my_address, int my_port,
const char *server_address, int server_port,
uint32_t flags, struct event_context *ev);
#endif /* _SAMBA_SOCKET_H */ #endif /* _SAMBA_SOCKET_H */

View File

@ -3,8 +3,8 @@
[SUBSYSTEM::LIBCLI_LDAP] [SUBSYSTEM::LIBCLI_LDAP]
ADD_OBJ_FILES = libcli/ldap/ldap.o \ ADD_OBJ_FILES = libcli/ldap/ldap.o \
libcli/ldap/ldap_client.o \ libcli/ldap/ldap_client.o \
libcli/ldap/ldap_ldif.o \ libcli/ldap/ldap_bind.o \
libcli/ldap/ldap_msg.o \
libcli/ldap/ldap_ndr.o libcli/ldap/ldap_ndr.o
NOPROTO=YES
# End SUBSYSTEM LIBCLI_LDAP # End SUBSYSTEM LIBCLI_LDAP
################################# #################################

View File

@ -1013,44 +1013,4 @@ BOOL ldap_decode(struct asn1_data *data, struct ldap_message *msg)
return ((!data->has_error) && (data->nesting == NULL)); return ((!data->has_error) && (data->nesting == NULL));
} }
BOOL ldap_parse_basic_url(TALLOC_CTX *mem_ctx, const char *url,
char **host, uint16_t *port, BOOL *ldaps)
{
int tmp_port = 0;
char protocol[11];
char tmp_host[255];
const char *p = url;
int ret;
/* skip leading "URL:" (if any) */
if (strncasecmp( p, "URL:", 4) == 0) {
p += 4;
}
/* Paranoia check */
SMB_ASSERT(sizeof(protocol)>10 && sizeof(tmp_host)>254);
ret = sscanf(p, "%10[^:]://%254[^:/]:%d", protocol, tmp_host, &tmp_port);
if (ret < 2) {
return False;
}
if (strequal(protocol, "ldap")) {
*port = 389;
*ldaps = False;
} else if (strequal(protocol, "ldaps")) {
*port = 636;
*ldaps = True;
} else {
DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
return False;
}
if (tmp_port != 0)
*port = tmp_port;
*host = talloc_strdup(mem_ctx, tmp_host);
return (*host != NULL);
}

View File

@ -253,101 +253,4 @@ struct ldap_message {
struct ldap_Control *controls; struct ldap_Control *controls;
}; };
struct ldap_queue_entry {
struct ldap_queue_entry *next, *prev;
int msgid;
struct ldap_message *msg;
};
struct ldap_connection {
int sock;
int next_msgid;
char *host;
uint16_t port;
BOOL ldaps;
const char *auth_dn;
const char *simple_pw;
/* Current outstanding search entry */
int searchid;
/* List for incoming search entries */
struct ldap_queue_entry *search_entries;
/* Outstanding LDAP requests that have not yet been replied to */
struct ldap_queue_entry *outstanding;
/* Let's support SASL */
struct gensec_security *gensec;
};
#define LDAP_CONNECTION_TIMEOUT 10000
/* The following definitions come from libcli/ldap/ldap.c */
BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result);
BOOL ldap_decode(struct asn1_data *data, struct ldap_message *msg);
BOOL ldap_parse_basic_url(TALLOC_CTX *mem_ctx, const char *url,
char **host, uint16_t *port, BOOL *ldaps);
/* The following definitions come from libcli/ldap/ldap_client.c */
struct ldap_connection *ldap_connect(TALLOC_CTX *mem_ctx, const char *url);
struct ldap_message *new_ldap_message(TALLOC_CTX *mem_ctx);
BOOL ldap_send_msg(struct ldap_connection *conn, struct ldap_message *msg,
const struct timeval *endtime);
BOOL ldap_receive_msg(struct ldap_connection *conn, struct ldap_message *msg,
const struct timeval *endtime);
struct ldap_message *ldap_receive(struct ldap_connection *conn, int msgid,
const struct timeval *endtime);
struct ldap_message *ldap_transaction(struct ldap_connection *conn,
struct ldap_message *request);
int ldap_bind_simple(struct ldap_connection *conn, const char *userdn, const char *password);
int ldap_bind_sasl(struct ldap_connection *conn, struct cli_credentials *creds);
struct ldap_connection *ldap_setup_connection(TALLOC_CTX *mem_ctx, const char *url,
const char *userdn, const char *password);
struct ldap_connection *ldap_setup_connection_with_sasl(TALLOC_CTX *mem_ctx, const char *url,
struct cli_credentials *creds);
BOOL ldap_abandon_message(struct ldap_connection *conn, int msgid,
const struct timeval *endtime);
BOOL ldap_setsearchent(struct ldap_connection *conn, struct ldap_message *msg,
const struct timeval *endtime);
struct ldap_message *ldap_getsearchent(struct ldap_connection *conn,
const struct timeval *endtime);
void ldap_endsearchent(struct ldap_connection *conn,
const struct timeval *endtime);
struct ldap_message *ldap_searchone(struct ldap_connection *conn,
struct ldap_message *msg,
const struct timeval *endtime);
BOOL ldap_find_single_value(struct ldap_message *msg, const char *attr,
DATA_BLOB *value);
BOOL ldap_find_single_string(struct ldap_message *msg, const char *attr,
TALLOC_CTX *mem_ctx, char **value);
BOOL ldap_find_single_int(struct ldap_message *msg, const char *attr,
int *value);
int ldap_error(struct ldap_connection *conn);
NTSTATUS ldap2nterror(int ldaperror);
/* The following definitions come from libcli/ldap/ldap_ldif.c */
BOOL add_value_to_attrib(TALLOC_CTX *mem_ctx, struct ldb_val *value,
struct ldb_message_element *attrib);
BOOL add_attrib_to_array_talloc(TALLOC_CTX *mem_ctx,
const struct ldb_message_element *attrib,
struct ldb_message_element **attribs,
int *num_attribs);
BOOL add_mod_to_array_talloc(TALLOC_CTX *mem_ctx,
struct ldap_mod *mod,
struct ldap_mod **mods,
int *num_mods);
struct ldap_message *ldap_ldif2msg(TALLOC_CTX *mem_ctx, const char *s);
/* The following definitions come from libcli/ldap/ldap_ndr.c */
const char *ldap_encode_ndr_uint32(TALLOC_CTX *mem_ctx, uint32_t value);
const char *ldap_encode_ndr_dom_sid(TALLOC_CTX *mem_ctx, struct dom_sid *sid);
const char *ldap_encode_ndr_GUID(TALLOC_CTX *mem_ctx, struct GUID *guid);
NTSTATUS ldap_decode_ndr_GUID(TALLOC_CTX *mem_ctx, struct ldb_val val, struct GUID *guid);
#endif #endif

View File

@ -0,0 +1,250 @@
/*
Unix SMB/CIFS mplementation.
LDAP bind calls
Copyright (C) Andrew Tridgell 2005
Copyright (C) Volker Lendecke 2004
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
#include "libcli/ldap/ldap.h"
#include "libcli/ldap/ldap_client.h"
#include "auth/auth.h"
static struct ldap_message *new_ldap_simple_bind_msg(struct ldap_connection *conn,
const char *dn, const char *pw)
{
struct ldap_message *res;
res = new_ldap_message(conn);
if (!res) {
return NULL;
}
res->type = LDAP_TAG_BindRequest;
res->r.BindRequest.version = 3;
res->r.BindRequest.dn = talloc_strdup(res, dn);
res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SIMPLE;
res->r.BindRequest.creds.password = talloc_strdup(res, pw);
return res;
}
/*
perform a simple username/password bind
*/
NTSTATUS ldap_bind_simple(struct ldap_connection *conn,
const char *userdn, const char *password)
{
struct ldap_request *req;
struct ldap_message *msg;
const char *dn, *pw;
NTSTATUS status;
if (conn == NULL) {
return NT_STATUS_INVALID_CONNECTION;
}
if (userdn) {
dn = userdn;
} else {
if (conn->auth_dn) {
dn = conn->auth_dn;
} else {
dn = "";
}
}
if (password) {
pw = password;
} else {
if (conn->simple_pw) {
pw = conn->simple_pw;
} else {
pw = "";
}
}
msg = new_ldap_simple_bind_msg(conn, dn, pw);
NT_STATUS_HAVE_NO_MEMORY(msg);
/* send the request */
req = ldap_request_send(conn, msg);
talloc_free(msg);
NT_STATUS_HAVE_NO_MEMORY(req);
/* wait for replies */
status = ldap_request_wait(req);
if (!NT_STATUS_IS_OK(status)) {
talloc_free(req);
return status;
}
/* check its a valid reply */
msg = req->replies[0];
if (msg->type != LDAP_TAG_BindResponse) {
talloc_free(req);
return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
}
status = ldap_check_response(conn, &msg->r.BindResponse.response);
talloc_free(req);
return status;
}
static struct ldap_message *new_ldap_sasl_bind_msg(struct ldap_connection *conn,
const char *sasl_mechanism,
DATA_BLOB *secblob)
{
struct ldap_message *res;
res = new_ldap_message(conn);
if (!res) {
return NULL;
}
res->type = LDAP_TAG_BindRequest;
res->r.BindRequest.version = 3;
res->r.BindRequest.dn = "";
res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SASL;
res->r.BindRequest.creds.SASL.mechanism = talloc_strdup(res, sasl_mechanism);
res->r.BindRequest.creds.SASL.secblob = *secblob;
return res;
}
/*
perform a sasl bind using the given credentials
*/
NTSTATUS ldap_bind_sasl(struct ldap_connection *conn, struct cli_credentials *creds)
{
NTSTATUS status;
TALLOC_CTX *tmp_ctx = NULL;
DATA_BLOB input = data_blob(NULL, 0);
DATA_BLOB output = data_blob(NULL, 0);
status = gensec_client_start(conn, &conn->gensec);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("Failed to start GENSEC engine (%s)\n", nt_errstr(status)));
goto failed;
}
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)) {
DEBUG(1, ("Failed to start set GENSEC creds: %s\n",
nt_errstr(status)));
goto failed;
}
status = gensec_set_target_hostname(conn->gensec, conn->host);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to start set GENSEC target hostname: %s\n",
nt_errstr(status)));
goto failed;
}
status = gensec_set_target_service(conn->gensec, "ldap");
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to start set GENSEC target service: %s\n",
nt_errstr(status)));
goto failed;
}
status = gensec_start_mech_by_sasl_name(conn->gensec, "NTLM");
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to start set GENSEC client SPNEGO mechanism: %s\n",
nt_errstr(status)));
goto failed;
}
tmp_ctx = talloc_new(conn);
if (tmp_ctx == NULL) goto failed;
status = gensec_update(conn->gensec, tmp_ctx, input, &output);
while (1) {
struct ldap_message *response;
struct ldap_message *msg;
struct ldap_request *req;
int result = LDAP_OTHER;
if (NT_STATUS_IS_OK(status) && output.length == 0) {
break;
}
if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
!NT_STATUS_IS_OK(status)) {
break;
}
msg = new_ldap_sasl_bind_msg(tmp_ctx, "GSS-SPNEGO", &output);
if (msg == NULL) {
status = NT_STATUS_NO_MEMORY;
goto failed;
}
req = ldap_request_send(conn, msg);
if (req == NULL) {
status = NT_STATUS_NO_MEMORY;
goto failed;
}
talloc_steal(tmp_ctx, req);
status = ldap_result_n(req, 0, &response);
if (!NT_STATUS_IS_OK(status)) {
goto failed;
}
if (response->type != LDAP_TAG_BindResponse) {
status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
goto failed;
}
result = response->r.BindResponse.response.resultcode;
if (result != LDAP_SUCCESS && result != LDAP_SASL_BIND_IN_PROGRESS) {
break;
}
status = gensec_update(conn->gensec, tmp_ctx,
response->r.BindResponse.SASL.secblob,
&output);
}
if (NT_STATUS_IS_OK(status) &&
(gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) ||
gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN))) {
conn->enable_wrap = True;
}
talloc_free(tmp_ctx);
return status;
failed:
talloc_free(tmp_ctx);
talloc_free(conn->gensec);
conn->gensec = NULL;
return status;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,86 @@
/*
Unix SMB/CIFS Implementation.
ldap client side header
Copyright (C) Andrew Tridgell 2005
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
enum ldap_request_state {LDAP_REQUEST_SEND, LDAP_REQUEST_PENDING, LDAP_REQUEST_DONE};
/* this is the handle that the caller gets when an async ldap message
is sent */
struct ldap_request {
struct ldap_request *next, *prev;
struct ldap_connection *conn;
enum ldap_request_tag type;
int messageid;
enum ldap_request_state state;
int num_replies;
struct ldap_message **replies;
NTSTATUS status;
DATA_BLOB data;
struct {
void (*fn)(struct ldap_request *);
void *private;
} async;
};
/* main context for a ldap client connection */
struct ldap_connection {
struct socket_context *sock;
char *host;
uint16_t port;
BOOL ldaps;
const char *auth_dn;
const char *simple_pw;
/* next message id to assign */
unsigned next_messageid;
/* outgoing send queue */
struct ldap_request *send_queue;
/* Outstanding LDAP requests that have not yet been replied to */
struct ldap_request *pending;
/* Let's support SASL */
struct gensec_security *gensec;
/* set if we are wrapping requests */
BOOL enable_wrap;
/* partially received packet */
DATA_BLOB partial;
/* the default timeout for messages */
int timeout;
/* last error message */
char *last_error;
struct {
struct event_context *event_ctx;
struct fd_event *fde;
} event;
};

View File

@ -1,11 +1,10 @@
/* /*
Unix SMB/CIFS mplementation. Unix SMB/CIFS mplementation.
LDAP protocol helper functions for SAMBA LDAP protocol helper functions for SAMBA
Copyright (C) Andrew Tridgell 2004 Copyright (C) Andrew Tridgell 2005
Copyright (C) Volker Lendecke 2004 Copyright (C) Volker Lendecke 2004
Copyright (C) Stefan Metzmacher 2004
Copyright (C) Simo Sorce 2004
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -24,8 +23,15 @@
*/ */
#include "includes.h" #include "includes.h"
#include "system/iconv.h"
#include "libcli/ldap/ldap.h" #include "libcli/ldap/ldap.h"
#include "libcli/ldap/ldap_client.h"
struct ldap_message *new_ldap_message(TALLOC_CTX *mem_ctx)
{
return talloc(mem_ctx, struct ldap_message);
}
BOOL add_value_to_attrib(TALLOC_CTX *mem_ctx, struct ldb_val *value, BOOL add_value_to_attrib(TALLOC_CTX *mem_ctx, struct ldb_val *value,
struct ldb_message_element *attrib) struct ldb_message_element *attrib)

View File

@ -648,7 +648,7 @@ static const nt_err_code_struct nt_err_desc[] =
*****************************************************************************/ *****************************************************************************/
const char *nt_errstr(NTSTATUS nt_code) const char *nt_errstr(NTSTATUS nt_code)
{ {
static pstring msg; static fstring msg;
int idx = 0; int idx = 0;
while (nt_errs[idx].nt_errstr != NULL) { while (nt_errs[idx].nt_errstr != NULL) {
@ -659,7 +659,14 @@ const char *nt_errstr(NTSTATUS nt_code)
idx++; idx++;
} }
slprintf(msg, sizeof(msg), "NT code 0x%08x", NT_STATUS_V(nt_code)); if (NT_STATUS_IS_DOS(nt_code)) {
slprintf(msg, sizeof(msg), "DOS code %u:%u",
NT_STATUS_DOS_CLASS(nt_code), NT_STATUS_DOS_CODE(nt_code));
} else if (NT_STATUS_IS_LDAP(nt_code)) {
slprintf(msg, sizeof(msg), "LDAP code %u", NT_STATUS_LDAP_CODE(nt_code));
} else {
slprintf(msg, sizeof(msg), "NT code 0x%08x", NT_STATUS_V(nt_code));
}
return msg; return msg;
} }

View File

@ -24,6 +24,7 @@
#include "includes.h" #include "includes.h"
#include "lib/ldb/include/ldb.h" #include "lib/ldb/include/ldb.h"
#include "libcli/ldap/ldap.h" #include "libcli/ldap/ldap.h"
#include "libcli/ldap/ldap_client.h"
#include "lib/cmdline/popt_common.h" #include "lib/cmdline/popt_common.h"
static BOOL test_bind_simple(struct ldap_connection *conn, const char *userdn, const char *password) static BOOL test_bind_simple(struct ldap_connection *conn, const char *userdn, const char *password)
@ -78,12 +79,14 @@ static BOOL test_search_rootDSE(struct ldap_connection *conn, char **basedn)
{ {
BOOL ret = True; BOOL ret = True;
struct ldap_message *msg, *result; struct ldap_message *msg, *result;
struct ldap_request *req;
int i;
struct ldap_SearchResEntry *r;
NTSTATUS status;
printf("Testing RootDSE Search\n"); printf("Testing RootDSE Search\n");
*basedn = NULL; *basedn = NULL;
conn->searchid = 0;
conn->next_msgid = 30;
msg = new_ldap_message(conn); msg = new_ldap_message(conn);
if (!msg) { if (!msg) {
@ -101,45 +104,50 @@ static BOOL test_search_rootDSE(struct ldap_connection *conn, char **basedn)
msg->r.SearchRequest.num_attributes = 0; msg->r.SearchRequest.num_attributes = 0;
msg->r.SearchRequest.attributes = NULL; msg->r.SearchRequest.attributes = NULL;
if (!ldap_setsearchent(conn, msg, NULL)) { req = ldap_request_send(conn, msg);
printf("Could not setsearchent\n"); if (req == NULL) {
printf("Could not setup ldap search\n");
return False; return False;
} }
result = ldap_getsearchent(conn, NULL); status = ldap_result_one(req, &result, LDAP_TAG_SearchResultEntry);
if (result) { if (!NT_STATUS_IS_OK(status)) {
int i; printf("search failed - %s\n", nt_errstr(status));
struct ldap_SearchResEntry *r = &result->r.SearchResultEntry; return False;
DEBUG(1,("\tdn: %s\n", r->dn));
for (i=0; i<r->num_attributes; i++) {
int j;
for (j=0; j<r->attributes[i].num_values; j++) {
DEBUG(1,("\t%s: %d %.*s\n", r->attributes[i].name,
r->attributes[i].values[j].length,
r->attributes[i].values[j].length,
(char *)r->attributes[i].values[j].data));
if (!(*basedn) &&
strcasecmp("defaultNamingContext",r->attributes[i].name)==0) {
*basedn = talloc_asprintf(conn, "%.*s",
r->attributes[i].values[j].length,
(char *)r->attributes[i].values[j].data);
}
}
}
} else {
ret = False;
} }
ldap_endsearchent(conn, NULL); printf("received %d replies\n", req->num_replies);
r = &result->r.SearchResultEntry;
DEBUG(1,("\tdn: %s\n", r->dn));
for (i=0; i<r->num_attributes; i++) {
int j;
for (j=0; j<r->attributes[i].num_values; j++) {
DEBUG(1,("\t%s: %d %.*s\n", r->attributes[i].name,
r->attributes[i].values[j].length,
r->attributes[i].values[j].length,
(char *)r->attributes[i].values[j].data));
if (!(*basedn) &&
strcasecmp("defaultNamingContext",r->attributes[i].name)==0) {
*basedn = talloc_asprintf(conn, "%.*s",
r->attributes[i].values[j].length,
(char *)r->attributes[i].values[j].data);
}
}
}
talloc_free(req);
return ret; return ret;
} }
static BOOL test_compare_sasl(struct ldap_connection *conn, const char *basedn) static BOOL test_compare_sasl(struct ldap_connection *conn, const char *basedn)
{ {
struct ldap_message *req, *rep; struct ldap_message *msg, *rep;
struct ldap_request *req;
const char *val; const char *val;
NTSTATUS status;
printf("Testing SASL Compare: %s\n", basedn); printf("Testing SASL Compare: %s\n", basedn);
@ -147,21 +155,25 @@ static BOOL test_compare_sasl(struct ldap_connection *conn, const char *basedn)
return False; return False;
} }
conn->next_msgid = 55; msg = new_ldap_message(conn);
if (!msg) {
return False;
}
req = new_ldap_message(conn); msg->type = LDAP_TAG_CompareRequest;
msg->r.CompareRequest.dn = basedn;
msg->r.CompareRequest.attribute = talloc_strdup(msg, "objectClass");
val = "domain";
msg->r.CompareRequest.value = data_blob_talloc(msg, val, strlen(val));
req = ldap_request_send(conn, msg);
if (!req) { if (!req) {
return False; return False;
} }
req->type = LDAP_TAG_CompareRequest; status = ldap_result_one(req, &rep, LDAP_TAG_CompareResponse);
req->r.CompareRequest.dn = basedn; if (!NT_STATUS_IS_OK(status)) {
req->r.CompareRequest.attribute = talloc_strdup(req, "objectClass"); printf("error in ldap compare request - %s\n", nt_errstr(status));
val = "domain";
req->r.CompareRequest.value = data_blob_talloc(req, val, strlen(val));
rep = ldap_transaction(conn, req);
if (!rep) {
return False; return False;
} }
@ -171,13 +183,10 @@ static BOOL test_compare_sasl(struct ldap_connection *conn, const char *basedn)
rep->r.CompareResponse.errormessage, rep->r.CompareResponse.errormessage,
rep->r.CompareResponse.referral)); rep->r.CompareResponse.referral));
if (rep->type != LDAP_TAG_CompareResponse) {
return False;
}
return True; return True;
} }
BOOL torture_ldap_basic(void) BOOL torture_ldap_basic(void)
{ {
NTSTATUS status; NTSTATUS status;
@ -186,7 +195,6 @@ BOOL torture_ldap_basic(void)
BOOL ret = True; BOOL ret = True;
const char *host = lp_parm_string(-1, "torture", "host"); const char *host = lp_parm_string(-1, "torture", "host");
const char *userdn = lp_parm_string(-1, "torture", "ldap_userdn"); const char *userdn = lp_parm_string(-1, "torture", "ldap_userdn");
/*const char *basedn = lp_parm_string(-1, "torture", "ldap_basedn");*/
const char *secret = lp_parm_string(-1, "torture", "ldap_secret"); const char *secret = lp_parm_string(-1, "torture", "ldap_secret");
char *url; char *url;
char *basedn; char *basedn;
@ -195,21 +203,21 @@ BOOL torture_ldap_basic(void)
url = talloc_asprintf(mem_ctx, "ldap://%s/", host); url = talloc_asprintf(mem_ctx, "ldap://%s/", host);
status = torture_ldap_connection2(mem_ctx, &conn, url, userdn, secret); status = torture_ldap_connection(mem_ctx, &conn, url);
if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_IS_OK(status)) {
return False; return False;
} }
if (!test_search_rootDSE(conn, &basedn)) {
ret = False;
}
/* other basic tests here */ /* other basic tests here */
if (!test_multibind(conn, userdn, secret)) { if (!test_multibind(conn, userdn, secret)) {
ret = False; ret = False;
} }
if (!test_search_rootDSE(conn, &basedn)) {
ret = False;
}
if (!test_bind_sasl(conn, cmdline_credentials)) { if (!test_bind_sasl(conn, cmdline_credentials)) {
ret = False; ret = False;
} }
@ -219,10 +227,9 @@ BOOL torture_ldap_basic(void)
} }
/* no more test we are closing */ /* no more test we are closing */
torture_ldap_close(conn);
talloc_free(mem_ctx); talloc_free(mem_ctx);
torture_ldap_close(conn);
return ret; return ret;
} }

View File

@ -28,92 +28,73 @@
NTSTATUS torture_ldap_bind(struct ldap_connection *conn, const char *userdn, const char *password) NTSTATUS torture_ldap_bind(struct ldap_connection *conn, const char *userdn, const char *password)
{ {
NTSTATUS status = NT_STATUS_UNSUCCESSFUL; NTSTATUS status;
int result;
if (!conn) { status = ldap_bind_simple(conn, userdn, password);
printf("We need a valid ldap_connection structure and be connected\n"); if (!NT_STATUS_IS_OK(status)) {
return status; printf("Failed to bind with provided credentials - %s\n",
nt_errstr(status));
} }
result = ldap_bind_simple(conn, userdn, password); return status;
if (result != LDAP_SUCCESS) {
printf("Failed to bind with provided credentials\n");
/* FIXME: what abut actually implementing an ldap_connection_free() function ?
:-) sss */
return status;
}
return NT_STATUS_OK;
} }
NTSTATUS torture_ldap_bind_sasl(struct ldap_connection *conn, NTSTATUS torture_ldap_bind_sasl(struct ldap_connection *conn,
struct cli_credentials *creds) struct cli_credentials *creds)
{ {
NTSTATUS status = NT_STATUS_UNSUCCESSFUL; NTSTATUS status;
int result;
if (!conn) { status = ldap_bind_sasl(conn, creds);
printf("We need a valid ldap_connection structure and be connected\n"); if (!NT_STATUS_IS_OK(status)) {
return status; printf("Failed sasl bind with provided credentials - %s\n",
} nt_errstr(status));
result = ldap_bind_sasl(conn, creds);
if (result != LDAP_SUCCESS) {
printf("Failed to bind with provided credentials and SASL mechanism\n");
/* FIXME: what abut actually implementing an ldap_connection_free() function ?
:-) sss */
return status;
} }
return NT_STATUS_OK; return status;
} }
/* open a ldap connection to a server */ /* open a ldap connection to a server */
NTSTATUS torture_ldap_connection(TALLOC_CTX *mem_ctx, struct ldap_connection **conn, NTSTATUS torture_ldap_connection(TALLOC_CTX *mem_ctx, struct ldap_connection **conn,
const char *url) const char *url)
{ {
NTSTATUS status = NT_STATUS_UNSUCCESSFUL; NTSTATUS status;
if (!url) { if (!url) {
printf("You must specify a url string\n"); printf("You must specify a url string\n");
return NT_STATUS_INVALID_PARAMETER; return NT_STATUS_INVALID_PARAMETER;
} }
*conn = ldap_connect(mem_ctx, url); *conn = ldap_new_connection(mem_ctx, NULL);
if (!*conn) {
printf("Failed to initialize ldap_connection structure\n"); status = ldap_connect(*conn, url);
return status; if (!NT_STATUS_IS_OK(status)) {
printf("Failed to connect to ldap server '%s' - %s\n",
url, nt_errstr(status));
} }
return NT_STATUS_OK; return status;
} }
/* open a ldap connection to a server */ /* open a ldap connection to a server */
NTSTATUS torture_ldap_connection2(TALLOC_CTX *mem_ctx, struct ldap_connection **conn, NTSTATUS torture_ldap_connection2(TALLOC_CTX *mem_ctx, struct ldap_connection **conn,
const char *url, const char *userdn, const char *password) const char *url, const char *userdn, const char *password)
{ {
NTSTATUS status = NT_STATUS_UNSUCCESSFUL; NTSTATUS status;
int ret;
status = torture_ldap_connection(mem_ctx, conn, url); status = torture_ldap_connection(mem_ctx, conn, url);
NT_STATUS_NOT_OK_RETURN(status); NT_STATUS_NOT_OK_RETURN(status);
ret = ldap_bind_simple(*conn, userdn, password); status = ldap_bind_simple(*conn, userdn, password);
if (ret != LDAP_SUCCESS) { if (!NT_STATUS_IS_OK(status)) {
printf("Failed to connect with url [%s]\n", url); printf("Failed a simple ldap bind - %s\n", ldap_errstr(*conn, status));
/* FIXME: what abut actually implementing an ldap_connection_free() function ?
:-) sss */
return status;
} }
return NT_STATUS_OK; return status;
} }
/* close an ldap connection to a server */ /* close an ldap connection to a server */
NTSTATUS torture_ldap_close(struct ldap_connection *conn) NTSTATUS torture_ldap_close(struct ldap_connection *conn)
{ {
/* FIXME: what about actually implementing ldap_close() ? talloc_free(conn);
:-) sss */
return NT_STATUS_OK; return NT_STATUS_OK;
} }