r4549: got rid of a lot more uses of plain talloc(), instead using
[Samba/gebeck_regimport.git] / source4 / libcli / ldap / ldap_client.c
blob84fd0f1d645dde4485c2e83d366b964158473dd3
1 /*
2 Unix SMB/CIFS mplementation.
3 LDAP protocol helper functions for SAMBA
5 Copyright (C) Andrew Tridgell 2004
6 Copyright (C) Volker Lendecke 2004
7 Copyright (C) Stefan Metzmacher 2004
8 Copyright (C) Simo Sorce 2004
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "includes.h"
27 #include "system/network.h"
28 #include "auth/auth.h"
29 #include "asn_1.h"
30 #include "dlinklist.h"
32 #if 0
33 static struct ldap_message *new_ldap_search_message(struct ldap_connection *conn,
34 const char *base,
35 enum ldap_scope scope,
36 char *filter,
37 int num_attributes,
38 const char **attributes)
40 struct ldap_message *res;
42 res = new_ldap_message(conn);
43 if (!res) {
44 return NULL;
47 res->type = LDAP_TAG_SearchRequest;
48 res->r.SearchRequest.basedn = base;
49 res->r.SearchRequest.scope = scope;
50 res->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
51 res->r.SearchRequest.timelimit = 0;
52 res->r.SearchRequest.sizelimit = 0;
53 res->r.SearchRequest.attributesonly = False;
54 res->r.SearchRequest.filter = filter;
55 res->r.SearchRequest.num_attributes = num_attributes;
56 res->r.SearchRequest.attributes = attributes;
58 return res;
60 #endif
62 static struct ldap_message *new_ldap_simple_bind_msg(struct ldap_connection *conn, const char *dn, const char *pw)
64 struct ldap_message *res;
66 res = new_ldap_message(conn);
67 if (!res) {
68 return NULL;
71 res->type = LDAP_TAG_BindRequest;
72 res->r.BindRequest.version = 3;
73 res->r.BindRequest.dn = talloc_strdup(res->mem_ctx, dn);
74 res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SIMPLE;
75 res->r.BindRequest.creds.password = talloc_strdup(res->mem_ctx, pw);
77 return res;
80 static struct ldap_message *new_ldap_sasl_bind_msg(struct ldap_connection *conn, const char *sasl_mechanism, DATA_BLOB *secblob)
82 struct ldap_message *res;
84 res = new_ldap_message(conn);
85 if (!res) {
86 return NULL;
89 res->type = LDAP_TAG_BindRequest;
90 res->r.BindRequest.version = 3;
91 res->r.BindRequest.dn = "";
92 res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SASL;
93 res->r.BindRequest.creds.SASL.mechanism = talloc_strdup(res->mem_ctx, sasl_mechanism);
94 res->r.BindRequest.creds.SASL.secblob = *secblob;
96 return res;
99 static struct ldap_connection *new_ldap_connection(TALLOC_CTX *mem_ctx)
101 struct ldap_connection *result;
103 result = talloc_p(mem_ctx, struct ldap_connection);
105 if (!result) {
106 return NULL;
109 result->mem_ctx = result;
110 result->next_msgid = 1;
111 result->outstanding = NULL;
112 result->searchid = 0;
113 result->search_entries = NULL;
114 result->auth_dn = NULL;
115 result->simple_pw = NULL;
116 result->gensec = NULL;
118 return result;
121 struct ldap_connection *ldap_connect(TALLOC_CTX *mem_ctx, const char *url)
123 struct hostent *hp;
124 struct ipv4_addr ip;
125 struct ldap_connection *conn;
126 BOOL ret;
128 conn = new_ldap_connection(mem_ctx);
129 if (!conn) {
130 return NULL;
133 ret = ldap_parse_basic_url(conn->mem_ctx, url, &conn->host,
134 &conn->port, &conn->ldaps);
135 if (!ret) {
136 talloc_free(conn);
137 return NULL;
140 hp = sys_gethostbyname(conn->host);
141 if (!hp || !hp->h_addr) {
142 talloc_free(conn);
143 return NULL;
146 putip((char *)&ip, (char *)hp->h_addr);
148 conn->sock = open_socket_out(SOCK_STREAM, &ip, conn->port, LDAP_CONNECTION_TIMEOUT);
149 if (conn->sock < 0) {
150 talloc_free(conn);
151 return NULL;
154 return conn;
157 struct ldap_message *new_ldap_message(TALLOC_CTX *mem_ctx)
159 struct ldap_message *result;
161 result = talloc_p(mem_ctx, struct ldap_message);
163 if (!result) {
164 return NULL;
167 result->mem_ctx = result;
169 return result;
172 BOOL ldap_send_msg(struct ldap_connection *conn, struct ldap_message *msg,
173 const struct timeval *endtime)
175 DATA_BLOB request;
176 BOOL result;
177 struct ldap_queue_entry *entry;
179 msg->messageid = conn->next_msgid++;
181 if (!ldap_encode(msg, &request))
182 return False;
184 result = (write_data_until(conn->sock, request.data, request.length,
185 endtime) == request.length);
187 data_blob_free(&request);
189 if (!result)
190 return result;
192 /* abandon and unbind don't expect results */
194 if ((msg->type == LDAP_TAG_AbandonRequest) ||
195 (msg->type == LDAP_TAG_UnbindRequest))
196 return True;
198 entry = malloc_p(struct ldap_queue_entry);
200 if (entry == NULL)
201 return False;
203 entry->msgid = msg->messageid;
204 entry->msg = NULL;
205 DLIST_ADD(conn->outstanding, entry);
207 return True;
210 BOOL ldap_receive_msg(struct ldap_connection *conn, struct ldap_message *msg,
211 const struct timeval *endtime)
213 struct asn1_data data;
214 BOOL result;
216 if (!asn1_read_sequence_until(conn->sock, &data, endtime))
217 return False;
219 result = ldap_decode(&data, msg);
221 asn1_free(&data);
222 return result;
225 static struct ldap_message *recv_from_queue(struct ldap_connection *conn,
226 int msgid)
228 struct ldap_queue_entry *e;
230 for (e = conn->outstanding; e != NULL; e = e->next) {
232 if (e->msgid == msgid) {
233 struct ldap_message *result = e->msg;
234 DLIST_REMOVE(conn->outstanding, e);
235 SAFE_FREE(e);
236 return result;
240 return NULL;
243 static void add_search_entry(struct ldap_connection *conn,
244 struct ldap_message *msg)
246 struct ldap_queue_entry *e = malloc_p(struct ldap_queue_entry);
248 if (e == NULL)
249 return;
251 e->msg = msg;
252 DLIST_ADD_END(conn->search_entries, e, struct ldap_queue_entry *);
253 return;
256 static void fill_outstanding_request(struct ldap_connection *conn,
257 struct ldap_message *msg)
259 struct ldap_queue_entry *e;
261 for (e = conn->outstanding; e != NULL; e = e->next) {
262 if (e->msgid == msg->messageid) {
263 e->msg = msg;
264 return;
268 /* This reply has not been expected, destroy the incoming msg */
269 talloc_free(msg);
270 return;
273 struct ldap_message *ldap_receive(struct ldap_connection *conn, int msgid,
274 const struct timeval *endtime)
276 struct ldap_message *result = recv_from_queue(conn, msgid);
278 if (result != NULL)
279 return result;
281 while (True) {
282 struct asn1_data data;
283 BOOL res;
285 result = new_ldap_message(conn);
287 if (!asn1_read_sequence_until(conn->sock, &data, endtime))
288 return NULL;
290 res = ldap_decode(&data, result);
291 asn1_free(&data);
293 if (!res)
294 return NULL;
296 if (result->messageid == msgid)
297 return result;
299 if (result->type == LDAP_TAG_SearchResultEntry) {
300 add_search_entry(conn, result);
301 } else {
302 fill_outstanding_request(conn, result);
306 return NULL;
309 struct ldap_message *ldap_transaction(struct ldap_connection *conn,
310 struct ldap_message *request)
312 if (!ldap_send_msg(conn, request, NULL))
313 return False;
315 return ldap_receive(conn, request->messageid, NULL);
318 int ldap_bind_simple(struct ldap_connection *conn, const char *userdn, const char *password)
320 struct ldap_message *response;
321 struct ldap_message *msg;
322 const char *dn, *pw;
323 int result = LDAP_OTHER;
325 if (conn == NULL)
326 return result;
328 if (userdn) {
329 dn = userdn;
330 } else {
331 if (conn->auth_dn) {
332 dn = conn->auth_dn;
333 } else {
334 dn = "";
338 if (password) {
339 pw = password;
340 } else {
341 if (conn->simple_pw) {
342 pw = conn->simple_pw;
343 } else {
344 pw = "";
348 msg = new_ldap_simple_bind_msg(conn, dn, pw);
349 if (!msg)
350 return result;
352 response = ldap_transaction(conn, msg);
353 if (!response) {
354 talloc_free(msg);
355 return result;
358 result = response->r.BindResponse.response.resultcode;
360 talloc_free(msg);
361 talloc_free(response);
363 return result;
366 int ldap_bind_sasl(struct ldap_connection *conn, const char *username, const char *domain, const char *password)
368 NTSTATUS status;
369 TALLOC_CTX *mem_ctx = NULL;
370 struct ldap_message *response;
371 struct ldap_message *msg;
372 DATA_BLOB input = data_blob(NULL, 0);
373 DATA_BLOB output = data_blob(NULL, 0);
374 int result = LDAP_OTHER;
376 if (conn == NULL)
377 return result;
379 status = gensec_client_start(conn, &conn->gensec);
380 if (!NT_STATUS_IS_OK(status)) {
381 DEBUG(0, ("Failed to start GENSEC engine (%s)\n", nt_errstr(status)));
382 return result;
385 gensec_want_feature(conn->gensec, GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL);
387 status = gensec_set_domain(conn->gensec, domain);
388 if (!NT_STATUS_IS_OK(status)) {
389 DEBUG(1, ("Failed to start set GENSEC client domain to %s: %s\n",
390 domain, nt_errstr(status)));
391 goto done;
394 status = gensec_set_username(conn->gensec, username);
395 if (!NT_STATUS_IS_OK(status)) {
396 DEBUG(1, ("Failed to start set GENSEC client username to %s: %s\n",
397 username, nt_errstr(status)));
398 goto done;
401 status = gensec_set_password(conn->gensec, password);
402 if (!NT_STATUS_IS_OK(status)) {
403 DEBUG(1, ("Failed to start set GENSEC client password: %s\n",
404 nt_errstr(status)));
405 goto done;
408 status = gensec_set_target_hostname(conn->gensec, conn->host);
409 if (!NT_STATUS_IS_OK(status)) {
410 DEBUG(1, ("Failed to start set GENSEC target hostname: %s\n",
411 nt_errstr(status)));
412 goto done;
415 status = gensec_set_target_service(conn->gensec, "ldap");
416 if (!NT_STATUS_IS_OK(status)) {
417 DEBUG(1, ("Failed to start set GENSEC target service: %s\n",
418 nt_errstr(status)));
419 goto done;
422 status = gensec_start_mech_by_sasl_name(conn->gensec, "GSS-SPNEGO");
423 if (!NT_STATUS_IS_OK(status)) {
424 DEBUG(1, ("Failed to start set GENSEC client SPNEGO mechanism: %s\n",
425 nt_errstr(status)));
426 goto done;
429 mem_ctx = talloc_init("ldap_bind_sasl");
430 if (!mem_ctx)
431 goto done;
433 status = gensec_update(conn->gensec, mem_ctx,
434 input,
435 &output);
437 while(1) {
438 if (NT_STATUS_IS_OK(status) && output.length == 0) {
439 break;
441 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
442 break;
445 msg = new_ldap_sasl_bind_msg(conn, "GSS-SPNEGO", &output);
446 if (!msg)
447 goto done;
449 response = ldap_transaction(conn, msg);
450 talloc_free(msg);
452 if (!response) {
453 goto done;
456 result = response->r.BindResponse.response.resultcode;
458 if (result != LDAP_SUCCESS && result != LDAP_SASL_BIND_IN_PROGRESS) {
459 break;
462 if (!NT_STATUS_IS_OK(status)) {
463 status = gensec_update(conn->gensec, mem_ctx,
464 response->r.BindResponse.SASL.secblob,
465 &output);
466 } else {
467 output.length = 0;
470 talloc_free(response);
473 done:
474 if (mem_ctx)
475 talloc_destroy(mem_ctx);
477 return result;
480 struct ldap_connection *ldap_setup_connection(TALLOC_CTX *mem_ctx, const char *url,
481 const char *userdn, const char *password)
483 struct ldap_connection *conn;
484 int result;
486 conn =ldap_connect(mem_ctx, url);
487 if (!conn) {
488 return NULL;
491 result = ldap_bind_simple(conn, userdn, password);
492 if (result != LDAP_SUCCESS) {
493 talloc_free(conn);
494 return NULL;
497 return conn;
500 struct ldap_connection *ldap_setup_connection_with_sasl(TALLOC_CTX *mem_ctx, const char *url,
501 const char *username, const char *domain, const char *password)
503 struct ldap_connection *conn;
504 int result;
506 conn =ldap_connect(mem_ctx, url);
507 if (!conn) {
508 return NULL;
511 result = ldap_bind_sasl(conn, username, domain, password);
512 if (result != LDAP_SUCCESS) {
513 talloc_free(conn);
514 return NULL;
517 return conn;
520 BOOL ldap_abandon_message(struct ldap_connection *conn, int msgid,
521 const struct timeval *endtime)
523 struct ldap_message *msg = new_ldap_message(conn);
524 BOOL result;
526 if (msg == NULL)
527 return False;
529 msg->type = LDAP_TAG_AbandonRequest;
530 msg->r.AbandonRequest.messageid = msgid;
532 result = ldap_send_msg(conn, msg, endtime);
533 talloc_free(msg);
534 return result;
537 BOOL ldap_setsearchent(struct ldap_connection *conn, struct ldap_message *msg,
538 const struct timeval *endtime)
540 if ((conn->searchid != 0) &&
541 (!ldap_abandon_message(conn, conn->searchid, endtime)))
542 return False;
544 conn->searchid = conn->next_msgid;
545 return ldap_send_msg(conn, msg, endtime);
548 struct ldap_message *ldap_getsearchent(struct ldap_connection *conn,
549 const struct timeval *endtime)
551 struct ldap_message *result;
553 if (conn->search_entries != NULL) {
554 struct ldap_queue_entry *e = conn->search_entries;
556 result = e->msg;
557 DLIST_REMOVE(conn->search_entries, e);
558 SAFE_FREE(e);
559 return result;
562 result = ldap_receive(conn, conn->searchid, endtime);
563 if (!result) {
564 return NULL;
567 if (result->type == LDAP_TAG_SearchResultEntry)
568 return result;
570 if (result->type == LDAP_TAG_SearchResultDone) {
571 /* TODO: Handle Paged Results */
572 talloc_free(result);
573 return NULL;
576 /* TODO: Handle Search References here */
577 return NULL;
580 void ldap_endsearchent(struct ldap_connection *conn,
581 const struct timeval *endtime)
583 struct ldap_queue_entry *e;
585 e = conn->search_entries;
587 while (e != NULL) {
588 struct ldap_queue_entry *next = e->next;
589 DLIST_REMOVE(conn->search_entries, e);
590 SAFE_FREE(e);
591 e = next;
595 struct ldap_message *ldap_searchone(struct ldap_connection *conn,
596 struct ldap_message *msg,
597 const struct timeval *endtime)
599 struct ldap_message *res1, *res2 = NULL;
600 if (!ldap_setsearchent(conn, msg, endtime))
601 return NULL;
603 res1 = ldap_getsearchent(conn, endtime);
605 if (res1 != NULL)
606 res2 = ldap_getsearchent(conn, endtime);
608 ldap_endsearchent(conn, endtime);
610 if (res1 == NULL)
611 return NULL;
613 if (res2 != NULL) {
614 /* More than one entry */
615 talloc_free(res1);
616 talloc_free(res2);
617 return NULL;
620 return res1;
623 BOOL ldap_find_single_value(struct ldap_message *msg, const char *attr,
624 DATA_BLOB *value)
626 int i;
627 struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
629 if (msg->type != LDAP_TAG_SearchResultEntry)
630 return False;
632 for (i=0; i<r->num_attributes; i++) {
633 if (strequal(attr, r->attributes[i].name)) {
634 if (r->attributes[i].num_values != 1)
635 return False;
637 *value = r->attributes[i].values[0];
638 return True;
641 return False;
644 BOOL ldap_find_single_string(struct ldap_message *msg, const char *attr,
645 TALLOC_CTX *mem_ctx, char **value)
647 DATA_BLOB blob;
649 if (!ldap_find_single_value(msg, attr, &blob))
650 return False;
652 *value = talloc_size(mem_ctx, blob.length+1);
654 if (*value == NULL)
655 return False;
657 memcpy(*value, blob.data, blob.length);
658 (*value)[blob.length] = '\0';
659 return True;
662 BOOL ldap_find_single_int(struct ldap_message *msg, const char *attr,
663 int *value)
665 DATA_BLOB blob;
666 char *val;
667 int errno_save;
668 BOOL res;
670 if (!ldap_find_single_value(msg, attr, &blob))
671 return False;
673 val = malloc(blob.length+1);
674 if (val == NULL)
675 return False;
677 memcpy(val, blob.data, blob.length);
678 val[blob.length] = '\0';
680 errno_save = errno;
681 errno = 0;
683 *value = strtol(val, NULL, 10);
685 res = (errno == 0);
687 free(val);
688 errno = errno_save;
690 return res;
693 int ldap_error(struct ldap_connection *conn)
695 return 0;
698 NTSTATUS ldap2nterror(int ldaperror)
700 return NT_STATUS_OK;