11815ddd6d465fa1aff6ec9493f12e203fcb6613
[bbaumbach/samba-autobuild/.git] / source4 / libcli / ldap / ldap_client.c
1 /* 
2    Unix SMB/CIFS mplementation.
3    LDAP protocol helper functions for SAMBA
4    
5    Copyright (C) Andrew Tridgell  2004
6    Copyright (C) Volker Lendecke 2004
7    Copyright (C) Stefan Metzmacher 2004
8    Copyright (C) Simo Sorce 2004
9     
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.
14    
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.
19    
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.
23    
24 */
25
26 #include "includes.h"
27 #include "system/network.h"
28 #include "system/filesys.h"
29 #include "auth/auth.h"
30 #include "asn_1.h"
31 #include "dlinklist.h"
32 #include "libcli/ldap/ldap.h"
33
34
35
36 /****************************************************************************
37  Check the timeout. 
38 ****************************************************************************/
39 static BOOL timeout_until(struct timeval *timeout,
40                           const struct timeval *endtime)
41 {
42         struct timeval now;
43
44         GetTimeOfDay(&now);
45
46         if ((now.tv_sec > endtime->tv_sec) ||
47             ((now.tv_sec == endtime->tv_sec) &&
48              (now.tv_usec > endtime->tv_usec)))
49                 return False;
50
51         timeout->tv_sec = endtime->tv_sec - now.tv_sec;
52         timeout->tv_usec = endtime->tv_usec - now.tv_usec;
53         return True;
54 }
55
56
57 /****************************************************************************
58  Read data from the client, reading exactly N bytes, with timeout. 
59 ****************************************************************************/
60 static ssize_t read_data_until(int fd,char *buffer,size_t N,
61                                const struct timeval *endtime)
62 {
63         ssize_t ret;
64         size_t total=0;  
65  
66         while (total < N) {
67
68                 if (endtime != NULL) {
69                         fd_set r_fds;
70                         struct timeval timeout;
71                         int res;
72
73                         FD_ZERO(&r_fds);
74                         FD_SET(fd, &r_fds);
75
76                         if (!timeout_until(&timeout, endtime))
77                                 return -1;
78
79                         res = sys_select(fd+1, &r_fds, NULL, NULL, &timeout);
80                         if (res <= 0)
81                                 return -1;
82                 }
83
84                 ret = sys_read(fd,buffer + total,N - total);
85
86                 if (ret == 0) {
87                         DEBUG(10,("read_data: read of %d returned 0. Error = %s\n", (int)(N - total), strerror(errno) ));
88                         return 0;
89                 }
90
91                 if (ret == -1) {
92                         DEBUG(0,("read_data: read failure for %d. Error = %s\n", (int)(N - total), strerror(errno) ));
93                         return -1;
94                 }
95                 total += ret;
96         }
97         return (ssize_t)total;
98 }
99
100
101 /****************************************************************************
102  Write data to a fd with timeout.
103 ****************************************************************************/
104 static ssize_t write_data_until(int fd,char *buffer,size_t N,
105                                 const struct timeval *endtime)
106 {
107         size_t total=0;
108         ssize_t ret;
109
110         while (total < N) {
111
112                 if (endtime != NULL) {
113                         fd_set w_fds;
114                         struct timeval timeout;
115                         int res;
116
117                         FD_ZERO(&w_fds);
118                         FD_SET(fd, &w_fds);
119
120                         if (!timeout_until(&timeout, endtime))
121                                 return -1;
122
123                         res = sys_select(fd+1, NULL, &w_fds, NULL, &timeout);
124                         if (res <= 0)
125                                 return -1;
126                 }
127
128                 ret = sys_write(fd,buffer + total,N - total);
129
130                 if (ret == -1) {
131                         DEBUG(0,("write_data: write failure. Error = %s\n", strerror(errno) ));
132                         return -1;
133                 }
134                 if (ret == 0)
135                         return total;
136
137                 total += ret;
138         }
139         return (ssize_t)total;
140 }
141
142
143
144 static BOOL read_one_uint8(int sock, uint8_t *result, struct asn1_data *data,
145                            const struct timeval *endtime)
146 {
147         if (read_data_until(sock, result, 1, endtime) != 1)
148                 return False;
149
150         return asn1_write(data, result, 1);
151 }
152
153 /* Read a complete ASN sequence (ie LDAP result) from a socket */
154 static BOOL asn1_read_sequence_until(int sock, struct asn1_data *data,
155                                      const struct timeval *endtime)
156 {
157         uint8_t b;
158         size_t len;
159         char *buf;
160
161         ZERO_STRUCTP(data);
162
163         if (!read_one_uint8(sock, &b, data, endtime))
164                 return False;
165
166         if (b != 0x30) {
167                 data->has_error = True;
168                 return False;
169         }
170
171         if (!read_one_uint8(sock, &b, data, endtime))
172                 return False;
173
174         if (b & 0x80) {
175                 int n = b & 0x7f;
176                 if (!read_one_uint8(sock, &b, data, endtime))
177                         return False;
178                 len = b;
179                 while (n > 1) {
180                         if (!read_one_uint8(sock, &b, data, endtime))
181                                 return False;
182                         len = (len<<8) | b;
183                         n--;
184                 }
185         } else {
186                 len = b;
187         }
188
189         buf = talloc_size(NULL, len);
190         if (buf == NULL)
191                 return False;
192
193         if (read_data_until(sock, buf, len, endtime) != len)
194                 return False;
195
196         if (!asn1_write(data, buf, len))
197                 return False;
198
199         talloc_free(buf);
200
201         data->ofs = 0;
202         
203         return True;
204 }
205
206
207
208 /****************************************************************************
209   create an outgoing socket. timeout is in milliseconds.
210   **************************************************************************/
211 static int open_socket_out(int type, struct ipv4_addr *addr, int port, int timeout)
212 {
213         struct sockaddr_in sock_out;
214         int res,ret;
215         int connect_loop = 250; /* 250 milliseconds */
216         int loops = (timeout) / connect_loop;
217
218         /* create a socket to write to */
219         res = socket(PF_INET, type, 0);
220         if (res == -1) 
221         { DEBUG(0,("socket error\n")); return -1; }
222         
223         if (type != SOCK_STREAM) return(res);
224         
225         memset((char *)&sock_out,'\0',sizeof(sock_out));
226         putip((char *)&sock_out.sin_addr,(char *)addr);
227         
228         sock_out.sin_port = htons( port );
229         sock_out.sin_family = PF_INET;
230         
231         /* set it non-blocking */
232         set_blocking(res,False);
233         
234         DEBUG(3,("Connecting to %s at port %d\n", sys_inet_ntoa(*addr),port));
235         
236         /* and connect it to the destination */
237 connect_again:
238         ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out));
239         
240         /* Some systems return EAGAIN when they mean EINPROGRESS */
241         if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY ||
242                         errno == EAGAIN) && loops--) {
243                 msleep(connect_loop);
244                 goto connect_again;
245         }
246         
247         if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY ||
248                         errno == EAGAIN)) {
249                 DEBUG(1,("timeout connecting to %s:%d\n", sys_inet_ntoa(*addr),port));
250                 close(res);
251                 return -1;
252         }
253         
254 #ifdef EISCONN
255         if (ret < 0 && errno == EISCONN) {
256                 errno = 0;
257                 ret = 0;
258         }
259 #endif
260         
261         if (ret < 0) {
262                 DEBUG(2,("error connecting to %s:%d (%s)\n",
263                          sys_inet_ntoa(*addr),port,strerror(errno)));
264                 close(res);
265                 return -1;
266         }
267         
268         /* set it blocking again */
269         set_blocking(res,True);
270         
271         return res;
272 }
273
274 #if 0
275 static struct ldap_message *new_ldap_search_message(struct ldap_connection *conn,
276                                              const char *base,
277                                              enum ldap_scope scope,
278                                              char *filter,
279                                              int num_attributes,
280                                              const char **attributes)
281 {
282         struct ldap_message *res;
283
284         res = new_ldap_message(conn);
285         if (!res) {
286                 return NULL;
287         }
288
289         res->type = LDAP_TAG_SearchRequest;
290         res->r.SearchRequest.basedn = base;
291         res->r.SearchRequest.scope = scope;
292         res->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
293         res->r.SearchRequest.timelimit = 0;
294         res->r.SearchRequest.sizelimit = 0;
295         res->r.SearchRequest.attributesonly = False;
296         res->r.SearchRequest.filter = filter;
297         res->r.SearchRequest.num_attributes = num_attributes;
298         res->r.SearchRequest.attributes = attributes;
299
300         return res;
301 }
302 #endif
303
304 static struct ldap_message *new_ldap_simple_bind_msg(struct ldap_connection *conn, const char *dn, const char *pw)
305 {
306         struct ldap_message *res;
307
308         res = new_ldap_message(conn);
309         if (!res) {
310                 return NULL;
311         }
312
313         res->type = LDAP_TAG_BindRequest;
314         res->r.BindRequest.version = 3;
315         res->r.BindRequest.dn = talloc_strdup(res->mem_ctx, dn);
316         res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SIMPLE;
317         res->r.BindRequest.creds.password = talloc_strdup(res->mem_ctx, pw);
318
319         return res;
320 }
321
322 static struct ldap_message *new_ldap_sasl_bind_msg(struct ldap_connection *conn, const char *sasl_mechanism, DATA_BLOB *secblob)
323 {
324         struct ldap_message *res;
325
326         res = new_ldap_message(conn);
327         if (!res) {
328                 return NULL;
329         }
330
331         res->type = LDAP_TAG_BindRequest;
332         res->r.BindRequest.version = 3;
333         res->r.BindRequest.dn = "";
334         res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SASL;
335         res->r.BindRequest.creds.SASL.mechanism = talloc_strdup(res->mem_ctx, sasl_mechanism);
336         res->r.BindRequest.creds.SASL.secblob = *secblob;
337
338         return res;
339 }
340
341 static struct ldap_connection *new_ldap_connection(TALLOC_CTX *mem_ctx)
342 {
343         struct ldap_connection *result;
344
345         result = talloc(mem_ctx, struct ldap_connection);
346
347         if (!result) {
348                 return NULL;
349         }
350
351         result->mem_ctx = result;
352         result->next_msgid = 1;
353         result->outstanding = NULL;
354         result->searchid = 0;
355         result->search_entries = NULL;
356         result->auth_dn = NULL;
357         result->simple_pw = NULL;
358         result->gensec = NULL;
359
360         return result;
361 }
362
363 struct ldap_connection *ldap_connect(TALLOC_CTX *mem_ctx, const char *url)
364 {
365         struct hostent *hp;
366         struct ipv4_addr ip;
367         struct ldap_connection *conn;
368         BOOL ret;
369
370         conn = new_ldap_connection(mem_ctx);
371         if (!conn) {
372                 return NULL;
373         }
374
375         ret = ldap_parse_basic_url(conn->mem_ctx, url, &conn->host,
376                                   &conn->port, &conn->ldaps);
377         if (!ret) {
378                 talloc_free(conn);
379                 return NULL;
380         }
381
382         hp = sys_gethostbyname(conn->host);
383         if (!hp || !hp->h_addr) {
384                 talloc_free(conn);
385                 return NULL;
386         }
387
388         putip((char *)&ip, (char *)hp->h_addr);
389
390         conn->sock = open_socket_out(SOCK_STREAM, &ip, conn->port, LDAP_CONNECTION_TIMEOUT);
391         if (conn->sock < 0) {
392                 talloc_free(conn);
393                 return NULL;
394         }
395
396         return conn;
397 }
398
399 struct ldap_message *new_ldap_message(TALLOC_CTX *mem_ctx)
400 {
401         struct ldap_message *result;
402
403         result = talloc(mem_ctx, struct ldap_message);
404
405         if (!result) {
406                 return NULL;
407         }
408
409         result->mem_ctx = result;
410
411         return result;
412 }
413
414 BOOL ldap_send_msg(struct ldap_connection *conn, struct ldap_message *msg,
415                    const struct timeval *endtime)
416 {
417         DATA_BLOB request;
418         BOOL result;
419         struct ldap_queue_entry *entry;
420
421         msg->messageid = conn->next_msgid++;
422
423         if (!ldap_encode(msg, &request))
424                 return False;
425
426         result = (write_data_until(conn->sock, request.data, request.length,
427                                    endtime) == request.length);
428
429         data_blob_free(&request);
430
431         if (!result)
432                 return result;
433
434         /* abandon and unbind don't expect results */
435
436         if ((msg->type == LDAP_TAG_AbandonRequest) ||
437             (msg->type == LDAP_TAG_UnbindRequest))
438                 return True;
439
440         entry = malloc_p(struct ldap_queue_entry);
441
442         if (entry == NULL)
443                 return False;
444
445         entry->msgid = msg->messageid;
446         entry->msg = NULL;
447         DLIST_ADD(conn->outstanding, entry);
448
449         return True;
450 }
451
452 BOOL ldap_receive_msg(struct ldap_connection *conn, struct ldap_message *msg,
453                       const struct timeval *endtime)
454 {
455         struct asn1_data data;
456         BOOL result;
457
458         if (!asn1_read_sequence_until(conn->sock, &data, endtime))
459                 return False;
460
461         result = ldap_decode(&data, msg);
462
463         asn1_free(&data);
464         return result;
465 }
466
467 static struct ldap_message *recv_from_queue(struct ldap_connection *conn,
468                                             int msgid)
469 {
470         struct ldap_queue_entry *e;
471
472         for (e = conn->outstanding; e != NULL; e = e->next) {
473
474                 if (e->msgid == msgid) {
475                         struct ldap_message *result = e->msg;
476                         DLIST_REMOVE(conn->outstanding, e);
477                         SAFE_FREE(e);
478                         return result;
479                 }
480         }
481
482         return NULL;
483 }
484
485 static void add_search_entry(struct ldap_connection *conn,
486                              struct ldap_message *msg)
487 {
488         struct ldap_queue_entry *e = malloc_p(struct ldap_queue_entry);
489
490         if (e == NULL)
491                 return;
492
493         e->msg = msg;
494         DLIST_ADD_END(conn->search_entries, e, struct ldap_queue_entry *);
495         return;
496 }
497
498 static void fill_outstanding_request(struct ldap_connection *conn,
499                                      struct ldap_message *msg)
500 {
501         struct ldap_queue_entry *e;
502
503         for (e = conn->outstanding; e != NULL; e = e->next) {
504                 if (e->msgid == msg->messageid) {
505                         e->msg = msg;
506                         return;
507                 }
508         }
509
510         /* This reply has not been expected, destroy the incoming msg */
511         talloc_free(msg);
512         return;
513 }
514
515 struct ldap_message *ldap_receive(struct ldap_connection *conn, int msgid,
516                                   const struct timeval *endtime)
517 {
518         struct ldap_message *result = recv_from_queue(conn, msgid);
519
520         if (result != NULL)
521                 return result;
522
523         while (True) {
524                 struct asn1_data data;
525                 BOOL res;
526
527                 result = new_ldap_message(conn);
528
529                 if (!asn1_read_sequence_until(conn->sock, &data, endtime))
530                         return NULL;
531
532                 res = ldap_decode(&data, result);
533                 asn1_free(&data);
534
535                 if (!res)
536                         return NULL;
537
538                 if (result->messageid == msgid)
539                         return result;
540
541                 if (result->type == LDAP_TAG_SearchResultEntry) {
542                         add_search_entry(conn, result);
543                 } else {
544                         fill_outstanding_request(conn, result);
545                 }
546         }
547
548         return NULL;
549 }
550
551 struct ldap_message *ldap_transaction(struct ldap_connection *conn,
552                                       struct ldap_message *request)
553 {
554         if (!ldap_send_msg(conn, request, NULL))
555                 return False;
556
557         return ldap_receive(conn, request->messageid, NULL);
558 }
559
560 int ldap_bind_simple(struct ldap_connection *conn, const char *userdn, const char *password)
561 {
562         struct ldap_message *response;
563         struct ldap_message *msg;
564         const char *dn, *pw;
565         int result = LDAP_OTHER;
566
567         if (conn == NULL)
568                 return result;
569
570         if (userdn) {
571                 dn = userdn;
572         } else {
573                 if (conn->auth_dn) {
574                         dn = conn->auth_dn;
575                 } else {
576                         dn = "";
577                 }
578         }
579
580         if (password) {
581                 pw = password;
582         } else {
583                 if (conn->simple_pw) {
584                         pw = conn->simple_pw;
585                 } else {
586                         pw = "";
587                 }
588         }
589
590         msg =  new_ldap_simple_bind_msg(conn, dn, pw);
591         if (!msg)
592                 return result;
593
594         response = ldap_transaction(conn, msg);
595         if (!response) {
596                 talloc_free(msg);
597                 return result;
598         }
599                 
600         result = response->r.BindResponse.response.resultcode;
601
602         talloc_free(msg);
603         talloc_free(response);
604
605         return result;
606 }
607
608 int ldap_bind_sasl(struct ldap_connection *conn, const char *username, const char *domain, const char *password)
609 {
610         NTSTATUS status;
611         TALLOC_CTX *mem_ctx = NULL;
612         struct ldap_message *response;
613         struct ldap_message *msg;
614         DATA_BLOB input = data_blob(NULL, 0);
615         DATA_BLOB output = data_blob(NULL, 0);
616         int result = LDAP_OTHER;
617
618         if (conn == NULL)
619                 return result;
620
621         status = gensec_client_start(conn, &conn->gensec);
622         if (!NT_STATUS_IS_OK(status)) {
623                 DEBUG(0, ("Failed to start GENSEC engine (%s)\n", nt_errstr(status)));
624                 return result;
625         }
626
627         gensec_want_feature(conn->gensec, GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL);
628
629         status = gensec_set_domain(conn->gensec, domain);
630         if (!NT_STATUS_IS_OK(status)) {
631                 DEBUG(1, ("Failed to start set GENSEC client domain to %s: %s\n", 
632                           domain, nt_errstr(status)));
633                 goto done;
634         }
635
636         status = gensec_set_username(conn->gensec, username);
637         if (!NT_STATUS_IS_OK(status)) {
638                 DEBUG(1, ("Failed to start set GENSEC client username to %s: %s\n", 
639                           username, nt_errstr(status)));
640                 goto done;
641         }
642
643         status = gensec_set_password(conn->gensec, password);
644         if (!NT_STATUS_IS_OK(status)) {
645                 DEBUG(1, ("Failed to start set GENSEC client password: %s\n", 
646                           nt_errstr(status)));
647                 goto done;
648         }
649
650         status = gensec_set_target_hostname(conn->gensec, conn->host);
651         if (!NT_STATUS_IS_OK(status)) {
652                 DEBUG(1, ("Failed to start set GENSEC target hostname: %s\n", 
653                           nt_errstr(status)));
654                 goto done;
655         }
656
657         status = gensec_set_target_service(conn->gensec, "ldap");
658         if (!NT_STATUS_IS_OK(status)) {
659                 DEBUG(1, ("Failed to start set GENSEC target service: %s\n", 
660                           nt_errstr(status)));
661                 goto done;
662         }
663
664         status = gensec_start_mech_by_sasl_name(conn->gensec, "GSS-SPNEGO");
665         if (!NT_STATUS_IS_OK(status)) {
666                 DEBUG(1, ("Failed to start set GENSEC client SPNEGO mechanism: %s\n",
667                           nt_errstr(status)));
668                 goto done;
669         }
670
671         mem_ctx = talloc_init("ldap_bind_sasl");
672         if (!mem_ctx)
673                 goto done;
674
675         status = gensec_update(conn->gensec, mem_ctx,
676                                input,
677                                &output);
678
679         while(1) {
680                 if (NT_STATUS_IS_OK(status) && output.length == 0) {
681                         break;
682                 }
683                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
684                         break;
685                 }
686
687                 msg =  new_ldap_sasl_bind_msg(conn, "GSS-SPNEGO", &output);
688                 if (!msg)
689                         goto done;
690
691                 response = ldap_transaction(conn, msg);
692                 talloc_free(msg);
693
694                 if (!response) {
695                         goto done;
696                 }
697
698                 result = response->r.BindResponse.response.resultcode;
699
700                 if (result != LDAP_SUCCESS && result != LDAP_SASL_BIND_IN_PROGRESS) {
701                         break;
702                 }
703
704                 if (!NT_STATUS_IS_OK(status)) {
705                         status = gensec_update(conn->gensec, mem_ctx,
706                                                response->r.BindResponse.SASL.secblob,
707                                                &output);
708                 } else {
709                         output.length = 0;
710                 }
711
712                 talloc_free(response);
713         }
714
715 done:
716         if (mem_ctx)
717                 talloc_free(mem_ctx);
718
719         return result;
720 }
721
722 struct ldap_connection *ldap_setup_connection(TALLOC_CTX *mem_ctx, const char *url, 
723                                                 const char *userdn, const char *password)
724 {
725         struct ldap_connection *conn;
726         int result;
727
728         conn =ldap_connect(mem_ctx, url);
729         if (!conn) {
730                 return NULL;
731         }
732
733         result = ldap_bind_simple(conn, userdn, password);
734         if (result != LDAP_SUCCESS) {
735                 talloc_free(conn);
736                 return NULL;
737         }
738
739         return conn;
740 }
741
742 struct ldap_connection *ldap_setup_connection_with_sasl(TALLOC_CTX *mem_ctx, const char *url,
743                                                         const char *username, const char *domain, const char *password)
744 {
745         struct ldap_connection *conn;
746         int result;
747
748         conn =ldap_connect(mem_ctx, url);
749         if (!conn) {
750                 return NULL;
751         }
752
753         result = ldap_bind_sasl(conn, username, domain, password);
754         if (result != LDAP_SUCCESS) {
755                 talloc_free(conn);
756                 return NULL;
757         }
758
759         return conn;
760 }
761
762 BOOL ldap_abandon_message(struct ldap_connection *conn, int msgid,
763                                  const struct timeval *endtime)
764 {
765         struct ldap_message *msg = new_ldap_message(conn);
766         BOOL result;
767
768         if (msg == NULL)
769                 return False;
770
771         msg->type = LDAP_TAG_AbandonRequest;
772         msg->r.AbandonRequest.messageid = msgid;
773
774         result = ldap_send_msg(conn, msg, endtime);
775         talloc_free(msg);
776         return result;
777 }
778
779 BOOL ldap_setsearchent(struct ldap_connection *conn, struct ldap_message *msg,
780                        const struct timeval *endtime)
781 {
782         if ((conn->searchid != 0) &&
783             (!ldap_abandon_message(conn, conn->searchid, endtime)))
784                 return False;
785
786         conn->searchid = conn->next_msgid;
787         return ldap_send_msg(conn, msg, endtime);
788 }
789
790 struct ldap_message *ldap_getsearchent(struct ldap_connection *conn,
791                                        const struct timeval *endtime)
792 {
793         struct ldap_message *result;
794
795         if (conn->search_entries != NULL) {
796                 struct ldap_queue_entry *e = conn->search_entries;
797
798                 result = e->msg;
799                 DLIST_REMOVE(conn->search_entries, e);
800                 SAFE_FREE(e);
801                 return result;
802         }
803
804         result = ldap_receive(conn, conn->searchid, endtime);
805         if (!result) {
806                 return NULL;
807         }
808
809         if (result->type == LDAP_TAG_SearchResultEntry)
810                 return result;
811
812         if (result->type == LDAP_TAG_SearchResultDone) {
813                 /* TODO: Handle Paged Results */
814                 talloc_free(result);
815                 return NULL;
816         }
817
818         /* TODO: Handle Search References here */
819         return NULL;
820 }
821
822 void ldap_endsearchent(struct ldap_connection *conn,
823                        const struct timeval *endtime)
824 {
825         struct ldap_queue_entry *e;
826
827         e = conn->search_entries;
828
829         while (e != NULL) {
830                 struct ldap_queue_entry *next = e->next;
831                 DLIST_REMOVE(conn->search_entries, e);
832                 SAFE_FREE(e);
833                 e = next;
834         }
835 }
836
837 struct ldap_message *ldap_searchone(struct ldap_connection *conn,
838                                     struct ldap_message *msg,
839                                     const struct timeval *endtime)
840 {
841         struct ldap_message *res1, *res2 = NULL;
842         if (!ldap_setsearchent(conn, msg, endtime))
843                 return NULL;
844
845         res1 = ldap_getsearchent(conn, endtime);
846
847         if (res1 != NULL)
848                 res2 = ldap_getsearchent(conn, endtime);
849
850         ldap_endsearchent(conn, endtime);
851
852         if (res1 == NULL)
853                 return NULL;
854
855         if (res2 != NULL) {
856                 /* More than one entry */
857                 talloc_free(res1);
858                 talloc_free(res2);
859                 return NULL;
860         }
861
862         return res1;
863 }
864
865 BOOL ldap_find_single_value(struct ldap_message *msg, const char *attr,
866                             DATA_BLOB *value)
867 {
868         int i;
869         struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
870
871         if (msg->type != LDAP_TAG_SearchResultEntry)
872                 return False;
873
874         for (i=0; i<r->num_attributes; i++) {
875                 if (strequal(attr, r->attributes[i].name)) {
876                         if (r->attributes[i].num_values != 1)
877                                 return False;
878
879                         *value = r->attributes[i].values[0];
880                         return True;
881                 }
882         }
883         return False;
884 }
885
886 BOOL ldap_find_single_string(struct ldap_message *msg, const char *attr,
887                              TALLOC_CTX *mem_ctx, char **value)
888 {
889         DATA_BLOB blob;
890
891         if (!ldap_find_single_value(msg, attr, &blob))
892                 return False;
893
894         *value = talloc_size(mem_ctx, blob.length+1);
895
896         if (*value == NULL)
897                 return False;
898
899         memcpy(*value, blob.data, blob.length);
900         (*value)[blob.length] = '\0';
901         return True;
902 }
903
904 BOOL ldap_find_single_int(struct ldap_message *msg, const char *attr,
905                           int *value)
906 {
907         DATA_BLOB blob;
908         char *val;
909         int errno_save;
910         BOOL res;
911
912         if (!ldap_find_single_value(msg, attr, &blob))
913                 return False;
914
915         val = malloc(blob.length+1);
916         if (val == NULL)
917                 return False;
918
919         memcpy(val, blob.data, blob.length);
920         val[blob.length] = '\0';
921
922         errno_save = errno;
923         errno = 0;
924
925         *value = strtol(val, NULL, 10);
926
927         res = (errno == 0);
928
929         free(val);
930         errno = errno_save;
931
932         return res;
933 }
934
935 int ldap_error(struct ldap_connection *conn)
936 {
937         return 0;
938 }
939
940 NTSTATUS ldap2nterror(int ldaperror)
941 {
942         return NT_STATUS_OK;
943 }