mirror of
https://github.com/samba-team/samba.git
synced 2025-03-09 08:58:35 +03:00
r3583: - seperate the ldap client code and the ldap parsing code
(vl: we should only sync the parsing code with trunk) - use hierachical talloc in the ldap client code metze
This commit is contained in:
parent
07405f1c67
commit
1e9c0b68ca
@ -2,6 +2,7 @@
|
||||
# Start SUBSYSTEM LIBCLI_LDAP
|
||||
[SUBSYSTEM::LIBCLI_LDAP]
|
||||
ADD_OBJ_FILES = libcli/ldap/ldap.o \
|
||||
libcli/ldap/ldap_client.o \
|
||||
libcli/ldap/ldap_ldif.o
|
||||
# End SUBSYSTEM LIBCLI_LDAP
|
||||
#################################
|
||||
|
@ -24,11 +24,8 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "system/network.h"
|
||||
#include "system/iconv.h"
|
||||
#include "auth/auth.h"
|
||||
#include "asn_1.h"
|
||||
#include "dlinklist.h"
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
@ -1218,8 +1215,8 @@ BOOL ldap_parse_basic_url(TALLOC_CTX *mem_ctx, const char *url,
|
||||
char **host, uint16 *port, BOOL *ldaps)
|
||||
{
|
||||
int tmp_port = 0;
|
||||
fstring protocol;
|
||||
fstring tmp_host;
|
||||
char protocol[11];
|
||||
char tmp_host[255];
|
||||
const char *p = url;
|
||||
|
||||
/* skip leading "URL:" (if any) */
|
||||
@ -1245,654 +1242,8 @@ BOOL ldap_parse_basic_url(TALLOC_CTX *mem_ctx, const char *url,
|
||||
|
||||
if (tmp_port != 0)
|
||||
*port = tmp_port;
|
||||
|
||||
|
||||
*host = talloc_strdup(mem_ctx, tmp_host);
|
||||
|
||||
return (*host != NULL);
|
||||
}
|
||||
|
||||
struct ldap_connection *new_ldap_connection(void)
|
||||
{
|
||||
TALLOC_CTX *mem_ctx = talloc_init("ldap_connection");
|
||||
struct ldap_connection *result;
|
||||
|
||||
if (mem_ctx == NULL)
|
||||
return NULL;
|
||||
|
||||
result = talloc(mem_ctx, sizeof(*result));
|
||||
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
|
||||
result->mem_ctx = mem_ctx;
|
||||
result->next_msgid = 1;
|
||||
result->outstanding = NULL;
|
||||
result->searchid = 0;
|
||||
result->search_entries = NULL;
|
||||
result->auth_dn = NULL;
|
||||
result->simple_pw = NULL;
|
||||
result->gensec = NULL;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOL ldap_connect(struct ldap_connection *conn, const char *url)
|
||||
{
|
||||
struct hostent *hp;
|
||||
struct ipv4_addr ip;
|
||||
|
||||
if (!ldap_parse_basic_url(conn->mem_ctx, url, &conn->host,
|
||||
&conn->port, &conn->ldaps))
|
||||
return False;
|
||||
|
||||
hp = sys_gethostbyname(conn->host);
|
||||
|
||||
if ((hp == NULL) || (hp->h_addr == NULL))
|
||||
return False;
|
||||
|
||||
putip((char *)&ip, (char *)hp->h_addr);
|
||||
|
||||
conn->sock = open_socket_out(SOCK_STREAM, &ip, conn->port, LDAP_CONNECTION_TIMEOUT);
|
||||
|
||||
return (conn->sock >= 0);
|
||||
}
|
||||
|
||||
BOOL ldap_set_simple_creds(struct ldap_connection *conn,
|
||||
const char *dn, const char *password)
|
||||
{
|
||||
conn->auth_dn = talloc_strdup(conn->mem_ctx, dn);
|
||||
conn->simple_pw = talloc_strdup(conn->mem_ctx, password);
|
||||
|
||||
return ((conn->auth_dn != NULL) && (conn->simple_pw != NULL));
|
||||
}
|
||||
|
||||
struct ldap_message *new_ldap_message(void)
|
||||
{
|
||||
TALLOC_CTX *mem_ctx = talloc_init("ldap_message");
|
||||
struct ldap_message *result;
|
||||
|
||||
if (mem_ctx == NULL)
|
||||
return NULL;
|
||||
|
||||
result = talloc(mem_ctx, sizeof(*result));
|
||||
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
|
||||
result->mem_ctx = mem_ctx;
|
||||
return result;
|
||||
}
|
||||
|
||||
void destroy_ldap_message(struct ldap_message *msg)
|
||||
{
|
||||
if (msg != NULL)
|
||||
talloc_destroy(msg->mem_ctx);
|
||||
}
|
||||
|
||||
BOOL ldap_send_msg(struct ldap_connection *conn, struct ldap_message *msg,
|
||||
const struct timeval *endtime)
|
||||
{
|
||||
DATA_BLOB request;
|
||||
BOOL result;
|
||||
struct ldap_queue_entry *entry;
|
||||
|
||||
msg->messageid = conn->next_msgid++;
|
||||
|
||||
if (!ldap_encode(msg, &request))
|
||||
return False;
|
||||
|
||||
result = (write_data_until(conn->sock, request.data, request.length,
|
||||
endtime) == request.length);
|
||||
|
||||
data_blob_free(&request);
|
||||
|
||||
if (!result)
|
||||
return result;
|
||||
|
||||
/* abandon and unbind don't expect results */
|
||||
|
||||
if ((msg->type == LDAP_TAG_AbandonRequest) ||
|
||||
(msg->type == LDAP_TAG_UnbindRequest))
|
||||
return True;
|
||||
|
||||
entry = malloc(sizeof(*entry));
|
||||
|
||||
if (entry == NULL)
|
||||
return False;
|
||||
|
||||
entry->msgid = msg->messageid;
|
||||
entry->msg = NULL;
|
||||
DLIST_ADD(conn->outstanding, entry);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
BOOL ldap_receive_msg(struct ldap_connection *conn, struct ldap_message *msg,
|
||||
const struct timeval *endtime)
|
||||
{
|
||||
struct asn1_data data;
|
||||
BOOL result;
|
||||
|
||||
if (!asn1_read_sequence_until(conn->sock, &data, endtime))
|
||||
return False;
|
||||
|
||||
result = ldap_decode(&data, msg);
|
||||
|
||||
asn1_free(&data);
|
||||
return result;
|
||||
}
|
||||
|
||||
static struct ldap_message *recv_from_queue(struct ldap_connection *conn,
|
||||
int msgid)
|
||||
{
|
||||
struct ldap_queue_entry *e;
|
||||
|
||||
for (e = conn->outstanding; e != NULL; e = e->next) {
|
||||
|
||||
if (e->msgid == msgid) {
|
||||
struct ldap_message *result = e->msg;
|
||||
DLIST_REMOVE(conn->outstanding, e);
|
||||
SAFE_FREE(e);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void add_search_entry(struct ldap_connection *conn,
|
||||
struct ldap_message *msg)
|
||||
{
|
||||
struct ldap_queue_entry *e = malloc(sizeof *e);
|
||||
|
||||
if (e == NULL)
|
||||
return;
|
||||
|
||||
e->msg = msg;
|
||||
DLIST_ADD_END(conn->search_entries, e, struct ldap_queue_entry *);
|
||||
return;
|
||||
}
|
||||
|
||||
static void fill_outstanding_request(struct ldap_connection *conn,
|
||||
struct ldap_message *msg)
|
||||
{
|
||||
struct ldap_queue_entry *e;
|
||||
|
||||
for (e = conn->outstanding; e != NULL; e = e->next) {
|
||||
if (e->msgid == msg->messageid) {
|
||||
e->msg = msg;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* This reply has not been expected, destroy the incoming msg */
|
||||
destroy_ldap_message(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
struct ldap_message *ldap_receive(struct ldap_connection *conn, int msgid,
|
||||
const struct timeval *endtime)
|
||||
{
|
||||
struct ldap_message *result = recv_from_queue(conn, msgid);
|
||||
|
||||
if (result != NULL)
|
||||
return result;
|
||||
|
||||
while (True) {
|
||||
struct asn1_data data;
|
||||
BOOL res;
|
||||
|
||||
result = new_ldap_message();
|
||||
|
||||
if (!asn1_read_sequence_until(conn->sock, &data, endtime))
|
||||
return NULL;
|
||||
|
||||
res = ldap_decode(&data, result);
|
||||
asn1_free(&data);
|
||||
|
||||
if (!res)
|
||||
return NULL;
|
||||
|
||||
if (result->messageid == msgid)
|
||||
return result;
|
||||
|
||||
if (result->type == LDAP_TAG_SearchResultEntry) {
|
||||
add_search_entry(conn, result);
|
||||
} else {
|
||||
fill_outstanding_request(conn, result);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct ldap_message *ldap_transaction(struct ldap_connection *conn,
|
||||
struct ldap_message *request)
|
||||
{
|
||||
if (!ldap_send_msg(conn, request, NULL))
|
||||
return False;
|
||||
|
||||
return ldap_receive(conn, request->messageid, NULL);
|
||||
}
|
||||
|
||||
int ldap_bind_simple(struct ldap_connection *conn, const char *userdn, const char *password)
|
||||
{
|
||||
struct ldap_message *response;
|
||||
struct ldap_message *msg;
|
||||
const char *dn, *pw;
|
||||
int result = LDAP_OTHER;
|
||||
|
||||
if (conn == NULL)
|
||||
return result;
|
||||
|
||||
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(dn, pw);
|
||||
if (!msg)
|
||||
return result;
|
||||
|
||||
response = ldap_transaction(conn, msg);
|
||||
if (!response) {
|
||||
destroy_ldap_message(msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = response->r.BindResponse.response.resultcode;
|
||||
|
||||
destroy_ldap_message(msg);
|
||||
destroy_ldap_message(response);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int ldap_bind_sasl(struct ldap_connection *conn, const char *username, const char *domain, const char *password)
|
||||
{
|
||||
NTSTATUS status;
|
||||
TALLOC_CTX *mem_ctx = NULL;
|
||||
struct ldap_message *response;
|
||||
struct ldap_message *msg;
|
||||
DATA_BLOB input = data_blob(NULL, 0);
|
||||
DATA_BLOB output = data_blob(NULL, 0);
|
||||
int result = LDAP_OTHER;
|
||||
|
||||
if (conn == NULL)
|
||||
return result;
|
||||
|
||||
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)));
|
||||
return result;
|
||||
}
|
||||
|
||||
gensec_want_feature(conn->gensec, GENSEC_WANT_SIGN | GENSEC_WANT_SEAL);
|
||||
|
||||
status = gensec_set_domain(conn->gensec, domain);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(1, ("Failed to start set GENSEC client domain to %s: %s\n",
|
||||
domain, nt_errstr(status)));
|
||||
goto done;
|
||||
}
|
||||
|
||||
status = gensec_set_username(conn->gensec, username);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(1, ("Failed to start set GENSEC client username to %s: %s\n",
|
||||
username, nt_errstr(status)));
|
||||
goto done;
|
||||
}
|
||||
|
||||
status = gensec_set_password(conn->gensec, password);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(1, ("Failed to start set GENSEC client password: %s\n",
|
||||
nt_errstr(status)));
|
||||
goto done;
|
||||
}
|
||||
|
||||
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 done;
|
||||
}
|
||||
|
||||
status = gensec_start_mech_by_sasl_name(conn->gensec, "GSS-SPNEGO");
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(1, ("Failed to start set GENSEC client SPNEGO mechanism: %s\n",
|
||||
nt_errstr(status)));
|
||||
goto done;
|
||||
}
|
||||
|
||||
mem_ctx = talloc_init("ldap_bind_sasl");
|
||||
if (!mem_ctx)
|
||||
goto done;
|
||||
|
||||
status = gensec_update(conn->gensec, mem_ctx,
|
||||
input,
|
||||
&output);
|
||||
|
||||
while(1) {
|
||||
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("GSS-SPNEGO", &output);
|
||||
if (!msg)
|
||||
goto done;
|
||||
|
||||
response = ldap_transaction(conn, msg);
|
||||
destroy_ldap_message(msg);
|
||||
|
||||
if (!response) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
result = response->r.BindResponse.response.resultcode;
|
||||
|
||||
if (result != LDAP_SUCCESS && result != LDAP_SASL_BIND_IN_PROGRESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
status = gensec_update(conn->gensec, mem_ctx,
|
||||
response->r.BindResponse.SASL.secblob,
|
||||
&output);
|
||||
|
||||
destroy_ldap_message(response);
|
||||
}
|
||||
|
||||
done:
|
||||
if (mem_ctx)
|
||||
talloc_destroy(mem_ctx);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOL ldap_setup_connection(struct ldap_connection *conn,
|
||||
const char *url, const char *userdn, const char *password)
|
||||
{
|
||||
int result;
|
||||
|
||||
if (!ldap_connect(conn, url)) {
|
||||
return False;
|
||||
}
|
||||
|
||||
result = ldap_bind_simple(conn, userdn, password);
|
||||
if (result == LDAP_SUCCESS) {
|
||||
return True;
|
||||
}
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
BOOL ldap_setup_connection_with_sasl(struct ldap_connection *conn, const char *url, const char *username, const char *domain, const char *password)
|
||||
{
|
||||
int result;
|
||||
|
||||
if (!ldap_connect(conn, url)) {
|
||||
return False;
|
||||
}
|
||||
|
||||
result = ldap_bind_sasl(conn, username, domain, password);
|
||||
if (result == LDAP_SUCCESS) {
|
||||
return True;
|
||||
}
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
static BOOL ldap_abandon_message(struct ldap_connection *conn, int msgid,
|
||||
const struct timeval *endtime)
|
||||
{
|
||||
struct ldap_message *msg = new_ldap_message();
|
||||
BOOL result;
|
||||
|
||||
if (msg == NULL)
|
||||
return False;
|
||||
|
||||
msg->type = LDAP_TAG_AbandonRequest;
|
||||
msg->r.AbandonRequest.messageid = msgid;
|
||||
|
||||
result = ldap_send_msg(conn, msg, endtime);
|
||||
destroy_ldap_message(msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
struct ldap_message *new_ldap_search_message(const char *base,
|
||||
enum ldap_scope scope,
|
||||
char *filter,
|
||||
int num_attributes,
|
||||
const char **attributes)
|
||||
{
|
||||
struct ldap_message *res = new_ldap_message();
|
||||
|
||||
if (res == NULL)
|
||||
return NULL;
|
||||
|
||||
res->type = LDAP_TAG_SearchRequest;
|
||||
res->r.SearchRequest.basedn = base;
|
||||
res->r.SearchRequest.scope = scope;
|
||||
res->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
|
||||
res->r.SearchRequest.timelimit = 0;
|
||||
res->r.SearchRequest.sizelimit = 0;
|
||||
res->r.SearchRequest.attributesonly = False;
|
||||
res->r.SearchRequest.filter = filter;
|
||||
res->r.SearchRequest.num_attributes = num_attributes;
|
||||
res->r.SearchRequest.attributes = attributes;
|
||||
return res;
|
||||
}
|
||||
|
||||
struct ldap_message *new_ldap_simple_bind_msg(const char *dn, const char *pw)
|
||||
{
|
||||
struct ldap_message *res = new_ldap_message();
|
||||
|
||||
if (res == NULL)
|
||||
return NULL;
|
||||
|
||||
res->type = LDAP_TAG_BindRequest;
|
||||
res->r.BindRequest.version = 3;
|
||||
res->r.BindRequest.dn = talloc_strdup(res->mem_ctx, dn);
|
||||
res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SIMPLE;
|
||||
res->r.BindRequest.creds.password = talloc_strdup(res->mem_ctx, pw);
|
||||
return res;
|
||||
}
|
||||
|
||||
struct ldap_message *new_ldap_sasl_bind_msg(const char *sasl_mechanism, DATA_BLOB *secblob)
|
||||
{
|
||||
struct ldap_message *res = new_ldap_message();
|
||||
|
||||
if (res == NULL)
|
||||
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->mem_ctx, sasl_mechanism);
|
||||
res->r.BindRequest.creds.SASL.secblob = *secblob;
|
||||
return res;
|
||||
}
|
||||
|
||||
BOOL ldap_setsearchent(struct ldap_connection *conn, struct ldap_message *msg,
|
||||
const struct timeval *endtime)
|
||||
{
|
||||
if ((conn->searchid != 0) &&
|
||||
(!ldap_abandon_message(conn, conn->searchid, endtime)))
|
||||
return False;
|
||||
|
||||
conn->searchid = conn->next_msgid;
|
||||
return ldap_send_msg(conn, msg, endtime);
|
||||
}
|
||||
|
||||
struct ldap_message *ldap_getsearchent(struct ldap_connection *conn,
|
||||
const struct timeval *endtime)
|
||||
{
|
||||
struct ldap_message *result;
|
||||
|
||||
if (conn->search_entries != NULL) {
|
||||
struct ldap_queue_entry *e = conn->search_entries;
|
||||
|
||||
result = e->msg;
|
||||
DLIST_REMOVE(conn->search_entries, e);
|
||||
SAFE_FREE(e);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = ldap_receive(conn, conn->searchid, endtime);
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (result->type == LDAP_TAG_SearchResultEntry)
|
||||
return result;
|
||||
|
||||
if (result->type == LDAP_TAG_SearchResultDone) {
|
||||
/* TODO: Handle Paged Results */
|
||||
destroy_ldap_message(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* TODO: Handle Search References here */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ldap_endsearchent(struct ldap_connection *conn,
|
||||
const struct timeval *endtime)
|
||||
{
|
||||
struct ldap_queue_entry *e;
|
||||
|
||||
e = conn->search_entries;
|
||||
|
||||
while (e != NULL) {
|
||||
struct ldap_queue_entry *next = e->next;
|
||||
DLIST_REMOVE(conn->search_entries, e);
|
||||
SAFE_FREE(e);
|
||||
e = next;
|
||||
}
|
||||
}
|
||||
|
||||
struct ldap_message *ldap_searchone(struct ldap_connection *conn,
|
||||
struct ldap_message *msg,
|
||||
const struct timeval *endtime)
|
||||
{
|
||||
struct ldap_message *res1, *res2 = NULL;
|
||||
if (!ldap_setsearchent(conn, msg, endtime))
|
||||
return NULL;
|
||||
|
||||
res1 = ldap_getsearchent(conn, endtime);
|
||||
|
||||
if (res1 != NULL)
|
||||
res2 = ldap_getsearchent(conn, endtime);
|
||||
|
||||
ldap_endsearchent(conn, endtime);
|
||||
|
||||
if (res1 == NULL)
|
||||
return NULL;
|
||||
|
||||
if (res2 != NULL) {
|
||||
/* More than one entry */
|
||||
destroy_ldap_message(res1);
|
||||
destroy_ldap_message(res2);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return res1;
|
||||
}
|
||||
|
||||
BOOL ldap_find_single_value(struct ldap_message *msg, const char *attr,
|
||||
DATA_BLOB *value)
|
||||
{
|
||||
int i;
|
||||
struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
|
||||
|
||||
if (msg->type != LDAP_TAG_SearchResultEntry)
|
||||
return False;
|
||||
|
||||
for (i=0; i<r->num_attributes; i++) {
|
||||
if (strequal(attr, r->attributes[i].name)) {
|
||||
if (r->attributes[i].num_values != 1)
|
||||
return False;
|
||||
|
||||
*value = r->attributes[i].values[0];
|
||||
return True;
|
||||
}
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
BOOL ldap_find_single_string(struct ldap_message *msg, const char *attr,
|
||||
TALLOC_CTX *mem_ctx, char **value)
|
||||
{
|
||||
DATA_BLOB blob;
|
||||
|
||||
if (!ldap_find_single_value(msg, attr, &blob))
|
||||
return False;
|
||||
|
||||
*value = talloc(mem_ctx, blob.length+1);
|
||||
|
||||
if (*value == NULL)
|
||||
return False;
|
||||
|
||||
memcpy(*value, blob.data, blob.length);
|
||||
(*value)[blob.length] = '\0';
|
||||
return True;
|
||||
}
|
||||
|
||||
BOOL ldap_find_single_int(struct ldap_message *msg, const char *attr,
|
||||
int *value)
|
||||
{
|
||||
DATA_BLOB blob;
|
||||
char *val;
|
||||
int errno_save;
|
||||
BOOL res;
|
||||
|
||||
if (!ldap_find_single_value(msg, attr, &blob))
|
||||
return False;
|
||||
|
||||
val = malloc(blob.length+1);
|
||||
if (val == NULL)
|
||||
return False;
|
||||
|
||||
memcpy(val, blob.data, blob.length);
|
||||
val[blob.length] = '\0';
|
||||
|
||||
errno_save = errno;
|
||||
errno = 0;
|
||||
|
||||
*value = strtol(val, NULL, 10);
|
||||
|
||||
res = (errno == 0);
|
||||
|
||||
free(val);
|
||||
errno = errno_save;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int ldap_error(struct ldap_connection *conn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
NTSTATUS ldap2nterror(int ldaperror)
|
||||
{
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
690
source/libcli/ldap/ldap_client.c
Normal file
690
source/libcli/ldap/ldap_client.c
Normal file
@ -0,0 +1,690 @@
|
||||
/*
|
||||
Unix SMB/CIFS mplementation.
|
||||
LDAP protocol helper functions for SAMBA
|
||||
|
||||
Copyright (C) Andrew Tridgell 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
|
||||
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 "system/network.h"
|
||||
#include "auth/auth.h"
|
||||
#include "asn_1.h"
|
||||
#include "dlinklist.h"
|
||||
|
||||
#if 0
|
||||
static struct ldap_message *new_ldap_search_message(struct ldap_connection *conn,
|
||||
const char *base,
|
||||
enum ldap_scope scope,
|
||||
char *filter,
|
||||
int num_attributes,
|
||||
const char **attributes)
|
||||
{
|
||||
struct ldap_message *res;
|
||||
|
||||
res = new_ldap_message(conn);
|
||||
if (!res) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res->type = LDAP_TAG_SearchRequest;
|
||||
res->r.SearchRequest.basedn = base;
|
||||
res->r.SearchRequest.scope = scope;
|
||||
res->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
|
||||
res->r.SearchRequest.timelimit = 0;
|
||||
res->r.SearchRequest.sizelimit = 0;
|
||||
res->r.SearchRequest.attributesonly = False;
|
||||
res->r.SearchRequest.filter = filter;
|
||||
res->r.SearchRequest.num_attributes = num_attributes;
|
||||
res->r.SearchRequest.attributes = attributes;
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
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->mem_ctx, dn);
|
||||
res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SIMPLE;
|
||||
res->r.BindRequest.creds.password = talloc_strdup(res->mem_ctx, pw);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
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->mem_ctx, sasl_mechanism);
|
||||
res->r.BindRequest.creds.SASL.secblob = *secblob;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct ldap_connection *new_ldap_connection(TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
struct ldap_connection *result;
|
||||
|
||||
result = talloc_p(mem_ctx, struct ldap_connection);
|
||||
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result->mem_ctx = result;
|
||||
result->next_msgid = 1;
|
||||
result->outstanding = NULL;
|
||||
result->searchid = 0;
|
||||
result->search_entries = NULL;
|
||||
result->auth_dn = NULL;
|
||||
result->simple_pw = NULL;
|
||||
result->gensec = NULL;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct ldap_connection *ldap_connect(TALLOC_CTX *mem_ctx, const char *url)
|
||||
{
|
||||
struct hostent *hp;
|
||||
struct ipv4_addr ip;
|
||||
struct ldap_connection *conn;
|
||||
BOOL ret;
|
||||
|
||||
conn = new_ldap_connection(mem_ctx);
|
||||
if (!conn) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = ldap_parse_basic_url(conn->mem_ctx, url, &conn->host,
|
||||
&conn->port, &conn->ldaps);
|
||||
if (!ret) {
|
||||
talloc_free(conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hp = sys_gethostbyname(conn->host);
|
||||
if (!hp || !hp->h_addr) {
|
||||
talloc_free(conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
putip((char *)&ip, (char *)hp->h_addr);
|
||||
|
||||
conn->sock = open_socket_out(SOCK_STREAM, &ip, conn->port, LDAP_CONNECTION_TIMEOUT);
|
||||
if (conn->sock < 0) {
|
||||
talloc_free(conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
struct ldap_message *new_ldap_message(TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
struct ldap_message *result;
|
||||
|
||||
result = talloc_p(mem_ctx, struct ldap_message);
|
||||
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result->mem_ctx = result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOL ldap_send_msg(struct ldap_connection *conn, struct ldap_message *msg,
|
||||
const struct timeval *endtime)
|
||||
{
|
||||
DATA_BLOB request;
|
||||
BOOL result;
|
||||
struct ldap_queue_entry *entry;
|
||||
|
||||
msg->messageid = conn->next_msgid++;
|
||||
|
||||
if (!ldap_encode(msg, &request))
|
||||
return False;
|
||||
|
||||
result = (write_data_until(conn->sock, request.data, request.length,
|
||||
endtime) == request.length);
|
||||
|
||||
data_blob_free(&request);
|
||||
|
||||
if (!result)
|
||||
return result;
|
||||
|
||||
/* abandon and unbind don't expect results */
|
||||
|
||||
if ((msg->type == LDAP_TAG_AbandonRequest) ||
|
||||
(msg->type == LDAP_TAG_UnbindRequest))
|
||||
return True;
|
||||
|
||||
entry = malloc(sizeof(*entry));
|
||||
|
||||
if (entry == NULL)
|
||||
return False;
|
||||
|
||||
entry->msgid = msg->messageid;
|
||||
entry->msg = NULL;
|
||||
DLIST_ADD(conn->outstanding, entry);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
BOOL ldap_receive_msg(struct ldap_connection *conn, struct ldap_message *msg,
|
||||
const struct timeval *endtime)
|
||||
{
|
||||
struct asn1_data data;
|
||||
BOOL result;
|
||||
|
||||
if (!asn1_read_sequence_until(conn->sock, &data, endtime))
|
||||
return False;
|
||||
|
||||
result = ldap_decode(&data, msg);
|
||||
|
||||
asn1_free(&data);
|
||||
return result;
|
||||
}
|
||||
|
||||
static struct ldap_message *recv_from_queue(struct ldap_connection *conn,
|
||||
int msgid)
|
||||
{
|
||||
struct ldap_queue_entry *e;
|
||||
|
||||
for (e = conn->outstanding; e != NULL; e = e->next) {
|
||||
|
||||
if (e->msgid == msgid) {
|
||||
struct ldap_message *result = e->msg;
|
||||
DLIST_REMOVE(conn->outstanding, e);
|
||||
SAFE_FREE(e);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void add_search_entry(struct ldap_connection *conn,
|
||||
struct ldap_message *msg)
|
||||
{
|
||||
struct ldap_queue_entry *e = malloc(sizeof *e);
|
||||
|
||||
if (e == NULL)
|
||||
return;
|
||||
|
||||
e->msg = msg;
|
||||
DLIST_ADD_END(conn->search_entries, e, struct ldap_queue_entry *);
|
||||
return;
|
||||
}
|
||||
|
||||
static void fill_outstanding_request(struct ldap_connection *conn,
|
||||
struct ldap_message *msg)
|
||||
{
|
||||
struct ldap_queue_entry *e;
|
||||
|
||||
for (e = conn->outstanding; e != NULL; e = e->next) {
|
||||
if (e->msgid == msg->messageid) {
|
||||
e->msg = msg;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* This reply has not been expected, destroy the incoming msg */
|
||||
talloc_free(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
struct ldap_message *ldap_receive(struct ldap_connection *conn, int msgid,
|
||||
const struct timeval *endtime)
|
||||
{
|
||||
struct ldap_message *result = recv_from_queue(conn, msgid);
|
||||
|
||||
if (result != NULL)
|
||||
return result;
|
||||
|
||||
while (True) {
|
||||
struct asn1_data data;
|
||||
BOOL res;
|
||||
|
||||
result = new_ldap_message(conn);
|
||||
|
||||
if (!asn1_read_sequence_until(conn->sock, &data, endtime))
|
||||
return NULL;
|
||||
|
||||
res = ldap_decode(&data, result);
|
||||
asn1_free(&data);
|
||||
|
||||
if (!res)
|
||||
return NULL;
|
||||
|
||||
if (result->messageid == msgid)
|
||||
return result;
|
||||
|
||||
if (result->type == LDAP_TAG_SearchResultEntry) {
|
||||
add_search_entry(conn, result);
|
||||
} else {
|
||||
fill_outstanding_request(conn, result);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct ldap_message *ldap_transaction(struct ldap_connection *conn,
|
||||
struct ldap_message *request)
|
||||
{
|
||||
if (!ldap_send_msg(conn, request, NULL))
|
||||
return False;
|
||||
|
||||
return ldap_receive(conn, request->messageid, NULL);
|
||||
}
|
||||
|
||||
int ldap_bind_simple(struct ldap_connection *conn, const char *userdn, const char *password)
|
||||
{
|
||||
struct ldap_message *response;
|
||||
struct ldap_message *msg;
|
||||
const char *dn, *pw;
|
||||
int result = LDAP_OTHER;
|
||||
|
||||
if (conn == NULL)
|
||||
return result;
|
||||
|
||||
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);
|
||||
if (!msg)
|
||||
return result;
|
||||
|
||||
response = ldap_transaction(conn, msg);
|
||||
if (!response) {
|
||||
talloc_free(msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = response->r.BindResponse.response.resultcode;
|
||||
|
||||
talloc_free(msg);
|
||||
talloc_free(response);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int ldap_bind_sasl(struct ldap_connection *conn, const char *username, const char *domain, const char *password)
|
||||
{
|
||||
NTSTATUS status;
|
||||
TALLOC_CTX *mem_ctx = NULL;
|
||||
struct ldap_message *response;
|
||||
struct ldap_message *msg;
|
||||
DATA_BLOB input = data_blob(NULL, 0);
|
||||
DATA_BLOB output = data_blob(NULL, 0);
|
||||
int result = LDAP_OTHER;
|
||||
|
||||
if (conn == NULL)
|
||||
return result;
|
||||
|
||||
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)));
|
||||
return result;
|
||||
}
|
||||
|
||||
gensec_want_feature(conn->gensec, GENSEC_WANT_SIGN | GENSEC_WANT_SEAL);
|
||||
|
||||
status = gensec_set_domain(conn->gensec, domain);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(1, ("Failed to start set GENSEC client domain to %s: %s\n",
|
||||
domain, nt_errstr(status)));
|
||||
goto done;
|
||||
}
|
||||
|
||||
status = gensec_set_username(conn->gensec, username);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(1, ("Failed to start set GENSEC client username to %s: %s\n",
|
||||
username, nt_errstr(status)));
|
||||
goto done;
|
||||
}
|
||||
|
||||
status = gensec_set_password(conn->gensec, password);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(1, ("Failed to start set GENSEC client password: %s\n",
|
||||
nt_errstr(status)));
|
||||
goto done;
|
||||
}
|
||||
|
||||
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 done;
|
||||
}
|
||||
|
||||
status = gensec_start_mech_by_sasl_name(conn->gensec, "GSS-SPNEGO");
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(1, ("Failed to start set GENSEC client SPNEGO mechanism: %s\n",
|
||||
nt_errstr(status)));
|
||||
goto done;
|
||||
}
|
||||
|
||||
mem_ctx = talloc_init("ldap_bind_sasl");
|
||||
if (!mem_ctx)
|
||||
goto done;
|
||||
|
||||
status = gensec_update(conn->gensec, mem_ctx,
|
||||
input,
|
||||
&output);
|
||||
|
||||
while(1) {
|
||||
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(conn, "GSS-SPNEGO", &output);
|
||||
if (!msg)
|
||||
goto done;
|
||||
|
||||
response = ldap_transaction(conn, msg);
|
||||
talloc_free(msg);
|
||||
|
||||
if (!response) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
result = response->r.BindResponse.response.resultcode;
|
||||
|
||||
if (result != LDAP_SUCCESS && result != LDAP_SASL_BIND_IN_PROGRESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
status = gensec_update(conn->gensec, mem_ctx,
|
||||
response->r.BindResponse.SASL.secblob,
|
||||
&output);
|
||||
|
||||
talloc_free(response);
|
||||
}
|
||||
|
||||
done:
|
||||
if (mem_ctx)
|
||||
talloc_destroy(mem_ctx);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct ldap_connection *ldap_setup_connection(TALLOC_CTX *mem_ctx, const char *url,
|
||||
const char *userdn, const char *password)
|
||||
{
|
||||
struct ldap_connection *conn;
|
||||
int result;
|
||||
|
||||
conn =ldap_connect(mem_ctx, url);
|
||||
if (!conn) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = ldap_bind_simple(conn, userdn, password);
|
||||
if (result != LDAP_SUCCESS) {
|
||||
talloc_free(conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
struct ldap_connection *ldap_setup_connection_with_sasl(TALLOC_CTX *mem_ctx, const char *url,
|
||||
const char *username, const char *domain, const char *password)
|
||||
{
|
||||
struct ldap_connection *conn;
|
||||
int result;
|
||||
|
||||
conn =ldap_connect(mem_ctx, url);
|
||||
if (!conn) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = ldap_bind_sasl(conn, username, domain, password);
|
||||
if (result != LDAP_SUCCESS) {
|
||||
talloc_free(conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
BOOL ldap_abandon_message(struct ldap_connection *conn, int msgid,
|
||||
const struct timeval *endtime)
|
||||
{
|
||||
struct ldap_message *msg = new_ldap_message(conn);
|
||||
BOOL result;
|
||||
|
||||
if (msg == NULL)
|
||||
return False;
|
||||
|
||||
msg->type = LDAP_TAG_AbandonRequest;
|
||||
msg->r.AbandonRequest.messageid = msgid;
|
||||
|
||||
result = ldap_send_msg(conn, msg, endtime);
|
||||
talloc_free(msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOL ldap_setsearchent(struct ldap_connection *conn, struct ldap_message *msg,
|
||||
const struct timeval *endtime)
|
||||
{
|
||||
if ((conn->searchid != 0) &&
|
||||
(!ldap_abandon_message(conn, conn->searchid, endtime)))
|
||||
return False;
|
||||
|
||||
conn->searchid = conn->next_msgid;
|
||||
return ldap_send_msg(conn, msg, endtime);
|
||||
}
|
||||
|
||||
struct ldap_message *ldap_getsearchent(struct ldap_connection *conn,
|
||||
const struct timeval *endtime)
|
||||
{
|
||||
struct ldap_message *result;
|
||||
|
||||
if (conn->search_entries != NULL) {
|
||||
struct ldap_queue_entry *e = conn->search_entries;
|
||||
|
||||
result = e->msg;
|
||||
DLIST_REMOVE(conn->search_entries, e);
|
||||
SAFE_FREE(e);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = ldap_receive(conn, conn->searchid, endtime);
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (result->type == LDAP_TAG_SearchResultEntry)
|
||||
return result;
|
||||
|
||||
if (result->type == LDAP_TAG_SearchResultDone) {
|
||||
/* TODO: Handle Paged Results */
|
||||
talloc_free(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* TODO: Handle Search References here */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ldap_endsearchent(struct ldap_connection *conn,
|
||||
const struct timeval *endtime)
|
||||
{
|
||||
struct ldap_queue_entry *e;
|
||||
|
||||
e = conn->search_entries;
|
||||
|
||||
while (e != NULL) {
|
||||
struct ldap_queue_entry *next = e->next;
|
||||
DLIST_REMOVE(conn->search_entries, e);
|
||||
SAFE_FREE(e);
|
||||
e = next;
|
||||
}
|
||||
}
|
||||
|
||||
struct ldap_message *ldap_searchone(struct ldap_connection *conn,
|
||||
struct ldap_message *msg,
|
||||
const struct timeval *endtime)
|
||||
{
|
||||
struct ldap_message *res1, *res2 = NULL;
|
||||
if (!ldap_setsearchent(conn, msg, endtime))
|
||||
return NULL;
|
||||
|
||||
res1 = ldap_getsearchent(conn, endtime);
|
||||
|
||||
if (res1 != NULL)
|
||||
res2 = ldap_getsearchent(conn, endtime);
|
||||
|
||||
ldap_endsearchent(conn, endtime);
|
||||
|
||||
if (res1 == NULL)
|
||||
return NULL;
|
||||
|
||||
if (res2 != NULL) {
|
||||
/* More than one entry */
|
||||
talloc_free(res1);
|
||||
talloc_free(res2);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return res1;
|
||||
}
|
||||
|
||||
BOOL ldap_find_single_value(struct ldap_message *msg, const char *attr,
|
||||
DATA_BLOB *value)
|
||||
{
|
||||
int i;
|
||||
struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
|
||||
|
||||
if (msg->type != LDAP_TAG_SearchResultEntry)
|
||||
return False;
|
||||
|
||||
for (i=0; i<r->num_attributes; i++) {
|
||||
if (strequal(attr, r->attributes[i].name)) {
|
||||
if (r->attributes[i].num_values != 1)
|
||||
return False;
|
||||
|
||||
*value = r->attributes[i].values[0];
|
||||
return True;
|
||||
}
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
BOOL ldap_find_single_string(struct ldap_message *msg, const char *attr,
|
||||
TALLOC_CTX *mem_ctx, char **value)
|
||||
{
|
||||
DATA_BLOB blob;
|
||||
|
||||
if (!ldap_find_single_value(msg, attr, &blob))
|
||||
return False;
|
||||
|
||||
*value = talloc(mem_ctx, blob.length+1);
|
||||
|
||||
if (*value == NULL)
|
||||
return False;
|
||||
|
||||
memcpy(*value, blob.data, blob.length);
|
||||
(*value)[blob.length] = '\0';
|
||||
return True;
|
||||
}
|
||||
|
||||
BOOL ldap_find_single_int(struct ldap_message *msg, const char *attr,
|
||||
int *value)
|
||||
{
|
||||
DATA_BLOB blob;
|
||||
char *val;
|
||||
int errno_save;
|
||||
BOOL res;
|
||||
|
||||
if (!ldap_find_single_value(msg, attr, &blob))
|
||||
return False;
|
||||
|
||||
val = malloc(blob.length+1);
|
||||
if (val == NULL)
|
||||
return False;
|
||||
|
||||
memcpy(val, blob.data, blob.length);
|
||||
val[blob.length] = '\0';
|
||||
|
||||
errno_save = errno;
|
||||
errno = 0;
|
||||
|
||||
*value = strtol(val, NULL, 10);
|
||||
|
||||
res = (errno == 0);
|
||||
|
||||
free(val);
|
||||
errno = errno_save;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int ldap_error(struct ldap_connection *conn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
NTSTATUS ldap2nterror(int ldaperror)
|
||||
{
|
||||
return NT_STATUS_OK;
|
||||
}
|
@ -307,7 +307,7 @@ static BOOL fill_mods(struct ldap_message *msg, char **chunk)
|
||||
/*
|
||||
read from a LDIF source, creating a ldap_message
|
||||
*/
|
||||
static struct ldap_message *ldif_read(int (*fgetc_fn)(void *),
|
||||
static struct ldap_message *ldif_read(TALLOC_CTX *mem_ctx, int (*fgetc_fn)(void *),
|
||||
void *private_data)
|
||||
{
|
||||
struct ldap_message *msg;
|
||||
@ -318,7 +318,7 @@ static struct ldap_message *ldif_read(int (*fgetc_fn)(void *),
|
||||
|
||||
value.data = NULL;
|
||||
|
||||
msg = new_ldap_message();
|
||||
msg = new_ldap_message(mem_ctx);
|
||||
if (msg == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -383,7 +383,7 @@ static struct ldap_message *ldif_read(int (*fgetc_fn)(void *),
|
||||
DEBUG(3, ("changetype %s not supported\n", (char *)value.data));
|
||||
|
||||
failed:
|
||||
destroy_ldap_message(msg);
|
||||
talloc_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -403,10 +403,10 @@ static int fgetc_string(void *private_data)
|
||||
return EOF;
|
||||
}
|
||||
|
||||
struct ldap_message *ldap_ldif2msg(const char *s)
|
||||
struct ldap_message *ldap_ldif2msg(TALLOC_CTX *mem_ctx, const char *s)
|
||||
{
|
||||
struct ldif_read_string_state state;
|
||||
state.s = s;
|
||||
return ldif_read(fgetc_string, &state);
|
||||
return ldif_read(mem_ctx, fgetc_string, &state);
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ static BOOL test_search_rootDSE(struct ldap_connection *conn, char **basedn)
|
||||
conn->searchid = 0;
|
||||
conn->next_msgid = 30;
|
||||
|
||||
msg = new_ldap_message();
|
||||
msg = new_ldap_message(conn);
|
||||
if (!msg) {
|
||||
return False;
|
||||
}
|
||||
@ -147,7 +147,7 @@ static BOOL test_compare_sasl(struct ldap_connection *conn, const char *basedn)
|
||||
|
||||
conn->next_msgid = 55;
|
||||
|
||||
msg = new_ldap_message();
|
||||
msg = new_ldap_message(conn);
|
||||
if (!msg) {
|
||||
return False;
|
||||
}
|
||||
@ -200,7 +200,7 @@ BOOL torture_ldap_basic(void)
|
||||
|
||||
url = talloc_asprintf(mem_ctx, "ldap://%s/", host);
|
||||
|
||||
status = torture_ldap_connection(&conn, url, userdn, secret);
|
||||
status = torture_ldap_connection(mem_ctx, &conn, url, userdn, secret);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return False;
|
||||
}
|
||||
|
@ -67,25 +67,25 @@ NTSTATUS torture_ldap_bind_sasl(struct ldap_connection *conn, const char *userna
|
||||
}
|
||||
|
||||
/* open a ldap connection to a server */
|
||||
NTSTATUS torture_ldap_connection(struct ldap_connection **conn,
|
||||
NTSTATUS torture_ldap_connection(TALLOC_CTX *mem_ctx, struct ldap_connection **conn,
|
||||
const char *url, const char *userdn, const char *password)
|
||||
{
|
||||
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
|
||||
BOOL ret;
|
||||
int ret;
|
||||
|
||||
if (!url) {
|
||||
printf("You must specify a url string\n");
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*conn = new_ldap_connection();
|
||||
*conn = ldap_connect(mem_ctx, url);
|
||||
if (!*conn) {
|
||||
printf("Failed to initialize ldap_connection structure\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
ret = ldap_setup_connection(*conn, url, userdn, password);
|
||||
if (!ret) {
|
||||
ret = ldap_bind_simple(*conn, userdn, password);
|
||||
if (ret != LDAP_SUCCESS) {
|
||||
printf("Failed to connect with url [%s]\n", url);
|
||||
/* FIXME: what abut actually implementing an ldap_connection_free() function ?
|
||||
:-) sss */
|
||||
|
Loading…
x
Reference in New Issue
Block a user