r10213: fixed a memory leak in the ldap client and server code spotted by Karl
[ira/wip.git] / source / 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 "asn_1.h"
28 #include "dlinklist.h"
29 #include "lib/events/events.h"
30 #include "lib/socket/socket.h"
31 #include "lib/tls/tls.h"
32 #include "libcli/ldap/ldap.h"
33 #include "libcli/ldap/ldap_client.h"
34
35
36 /*
37   create a new ldap_connection stucture. The event context is optional
38 */
39 struct ldap_connection *ldap_new_connection(TALLOC_CTX *mem_ctx, 
40                                             struct event_context *ev)
41 {
42         struct ldap_connection *conn;
43
44         conn = talloc_zero(mem_ctx, struct ldap_connection);
45         if (conn == NULL) {
46                 return NULL;
47         }
48
49         if (ev == NULL) {
50                 ev = event_context_init(conn);
51                 if (ev == NULL) {
52                         talloc_free(conn);
53                         return NULL;
54                 }
55         }
56
57         conn->next_messageid  = 1;
58         conn->event.event_ctx = ev;
59
60         /* set a reasonable request timeout */
61         conn->timeout = 60;
62
63         return conn;
64 }
65
66
67 /*
68   the connection is dead
69 */
70 static void ldap_connection_dead(struct ldap_connection *conn)
71 {
72         struct ldap_request *req;
73
74         while (conn->pending) {
75                 req = conn->pending;
76                 DLIST_REMOVE(req->conn->pending, req);
77                 req->state = LDAP_REQUEST_DONE;
78                 req->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
79                 if (req->async.fn) {
80                         req->async.fn(req);
81                 }
82         }       
83
84         while (conn->send_queue) {
85                 req = conn->send_queue;
86                 DLIST_REMOVE(req->conn->send_queue, req);
87                 req->state = LDAP_REQUEST_DONE;
88                 req->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
89                 if (req->async.fn) {
90                         req->async.fn(req);
91                 }
92         }
93
94         talloc_free(conn->tls);
95         conn->tls = NULL;
96 }
97
98
99 /*
100   match up with a pending message, adding to the replies list
101 */
102 static void ldap_match_message(struct ldap_connection *conn, struct ldap_message *msg)
103 {
104         struct ldap_request *req;
105
106         for (req=conn->pending; req; req=req->next) {
107                 if (req->messageid == msg->messageid) break;
108         }
109         /* match a zero message id to the last request sent.
110            It seems that servers send 0 if unable to parse */
111         if (req == NULL && msg->messageid == 0) {
112                 req = conn->pending;
113         }
114         if (req == NULL) {
115                 DEBUG(0,("ldap: no matching message id for %u\n",
116                          msg->messageid));
117                 talloc_free(msg);
118                 return;
119         }
120
121         /* add to the list of replies received */
122         talloc_steal(req, msg);
123         req->replies = talloc_realloc(req, req->replies, 
124                                       struct ldap_message *, req->num_replies+1);
125         if (req->replies == NULL) {
126                 req->status = NT_STATUS_NO_MEMORY;
127                 req->state = LDAP_REQUEST_DONE;
128                 DLIST_REMOVE(conn->pending, req);
129                 if (req->async.fn) {
130                         req->async.fn(req);
131                 }
132                 return;
133         }
134
135         req->replies[req->num_replies] = talloc_steal(req->replies, msg);
136         req->num_replies++;
137
138         if (msg->type != LDAP_TAG_SearchResultEntry &&
139             msg->type != LDAP_TAG_SearchResultReference) {
140                 /* currently only search results expect multiple
141                    replies */
142                 req->state = LDAP_REQUEST_DONE;
143                 DLIST_REMOVE(conn->pending, req);
144         }
145
146         if (req->async.fn) {
147                 req->async.fn(req);
148         }
149 }
150
151 /*
152   try and decode/process plain data
153 */
154 static void ldap_try_decode_plain(struct ldap_connection *conn)
155 {
156         struct asn1_data asn1;
157
158         if (!asn1_load(&asn1, conn->partial)) {
159                 ldap_connection_dead(conn);
160                 return;
161         }
162
163         /* try and decode - this will fail if we don't have a full packet yet */
164         while (asn1.ofs < asn1.length) {
165                 struct ldap_message *msg = talloc(conn, struct ldap_message);
166                 off_t saved_ofs = asn1.ofs;
167                         
168                 if (msg == NULL) {
169                         ldap_connection_dead(conn);
170                         return;
171                 }
172
173                 if (ldap_decode(&asn1, msg)) {
174                         ldap_match_message(conn, msg);
175                 } else {
176                         asn1.ofs = saved_ofs;
177                         talloc_free(msg);
178                         break;
179                 }
180         }
181
182         /* keep any remaining data in conn->partial */
183         data_blob_free(&conn->partial);
184         if (asn1.ofs != asn1.length) {
185                 conn->partial = data_blob_talloc(conn, 
186                                                  asn1.data + asn1.ofs, 
187                                                  asn1.length - asn1.ofs);
188         }
189         asn1_free(&asn1);
190 }
191
192 /*
193   try and decode/process wrapped data
194 */
195 static void ldap_try_decode_wrapped(struct ldap_connection *conn)
196 {
197         uint32_t len;
198
199         /* keep decoding while we have a full wrapped packet */
200         while (conn->partial.length >= 4 &&
201                (len=RIVAL(conn->partial.data, 0)) <= conn->partial.length-4) {
202                 DATA_BLOB wrapped, unwrapped;
203                 struct asn1_data asn1;
204                 struct ldap_message *msg = talloc(conn, struct ldap_message);
205                 NTSTATUS status;
206
207                 if (msg == NULL) {
208                         ldap_connection_dead(conn);
209                         return;
210                 }
211
212                 wrapped.data   = conn->partial.data+4;
213                 wrapped.length = len;
214
215                 status = gensec_unwrap(conn->gensec, msg, &wrapped, &unwrapped);
216                 if (!NT_STATUS_IS_OK(status)) {
217                         ldap_connection_dead(conn);
218                         return;
219                 }
220
221                 if (!asn1_load(&asn1, unwrapped)) {
222                         ldap_connection_dead(conn);
223                         return;
224                 }
225
226                 while (ldap_decode(&asn1, msg)) {
227                         ldap_match_message(conn, msg);
228                         msg = talloc(conn, struct ldap_message);
229                 }
230                 
231                 talloc_free(msg);
232                 asn1_free(&asn1);
233
234                 if (conn->partial.length == len + 4) {
235                         data_blob_free(&conn->partial);
236                 } else {
237                         memmove(conn->partial.data, conn->partial.data+len+4,
238                                 conn->partial.length - (len+4));
239                         conn->partial.length -= len + 4;
240                 }
241         }
242 }
243
244
245 /*
246   handle ldap recv events
247 */
248 static void ldap_recv_handler(struct ldap_connection *conn)
249 {
250         NTSTATUS status;
251         size_t npending=0, nread;
252
253         /* work out how much data is pending */
254         status = tls_socket_pending(conn->tls, &npending);
255         if (!NT_STATUS_IS_OK(status) || npending == 0) {
256                 ldap_connection_dead(conn);
257                 return;
258         }
259
260         conn->partial.data = talloc_realloc_size(conn, conn->partial.data, 
261                                                  conn->partial.length + npending);
262         if (conn->partial.data == NULL) {
263                 ldap_connection_dead(conn);
264                 return;
265         }
266
267         /* receive the pending data */
268         status = tls_socket_recv(conn->tls, conn->partial.data + conn->partial.length,
269                                  npending, &nread);
270         if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
271                 return;
272         }
273         if (!NT_STATUS_IS_OK(status)) {
274                 ldap_connection_dead(conn);
275                 return;
276         }
277         conn->partial.length += nread;
278
279         /* see if we can decode what we have */
280         if (conn->enable_wrap) {
281                 ldap_try_decode_wrapped(conn);
282         } else {
283                 ldap_try_decode_plain(conn);
284         }
285 }
286
287
288 /*
289   handle ldap send events
290 */
291 static void ldap_send_handler(struct ldap_connection *conn)
292 {
293         while (conn->send_queue) {
294                 struct ldap_request *req = conn->send_queue;
295                 size_t nsent;
296                 NTSTATUS status;
297
298                 status = tls_socket_send(conn->tls, &req->data, &nsent);
299                 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
300                         break;
301                 }
302                 if (!NT_STATUS_IS_OK(status)) {
303                         ldap_connection_dead(conn);
304                         return;
305                 }
306
307                 req->data.data += nsent;
308                 req->data.length -= nsent;
309                 if (req->data.length == 0) {
310                         req->state = LDAP_REQUEST_PENDING;
311                         DLIST_REMOVE(conn->send_queue, req);
312
313                         /* some types of requests don't expect a reply */
314                         if (req->type == LDAP_TAG_AbandonRequest ||
315                             req->type == LDAP_TAG_UnbindRequest) {
316                                 req->status = NT_STATUS_OK;
317                                 req->state = LDAP_REQUEST_DONE;
318                                 if (req->async.fn) {
319                                         req->async.fn(req);
320                                 }
321                         } else {
322                                 DLIST_ADD(conn->pending, req);
323                         }
324                 }
325         }
326         if (conn->send_queue == NULL) {
327                 EVENT_FD_NOT_WRITEABLE(conn->event.fde);
328         }
329 }
330
331
332 /*
333   handle ldap socket events
334 */
335 static void ldap_io_handler(struct event_context *ev, struct fd_event *fde, 
336                             uint16_t flags, void *private)
337 {
338         struct ldap_connection *conn = talloc_get_type(private, struct ldap_connection);
339         if (flags & EVENT_FD_WRITE) {
340                 ldap_send_handler(conn);
341                 if (conn->tls == NULL) return;
342         }
343         if (flags & EVENT_FD_READ) {
344                 ldap_recv_handler(conn);
345         }
346 }
347
348 /*
349   parse a ldap URL
350 */
351 static NTSTATUS ldap_parse_basic_url(TALLOC_CTX *mem_ctx, const char *url,
352                                      char **host, uint16_t *port, BOOL *ldaps)
353 {
354         int tmp_port = 0;
355         char protocol[11];
356         char tmp_host[255];
357         const char *p = url;
358         int ret;
359
360         /* skip leading "URL:" (if any) */
361         if (strncasecmp(p, "URL:", 4) == 0) {
362                 p += 4;
363         }
364
365         /* Paranoia check */
366         SMB_ASSERT(sizeof(protocol)>10 && sizeof(tmp_host)>254);
367                 
368         ret = sscanf(p, "%10[^:]://%254[^:/]:%d", protocol, tmp_host, &tmp_port);
369         if (ret < 2) {
370                 return NT_STATUS_INVALID_PARAMETER;
371         }
372
373         if (strequal(protocol, "ldap")) {
374                 *port = 389;
375                 *ldaps = False;
376         } else if (strequal(protocol, "ldaps")) {
377                 *port = 636;
378                 *ldaps = True;
379         } else {
380                 DEBUG(0, ("unrecognised ldap protocol (%s)!\n", protocol));
381                 return NT_STATUS_PROTOCOL_UNREACHABLE;
382         }
383
384         if (tmp_port != 0)
385                 *port = tmp_port;
386
387         *host = talloc_strdup(mem_ctx, tmp_host);
388         NT_STATUS_HAVE_NO_MEMORY(*host);
389
390         return NT_STATUS_OK;
391 }
392
393 /*
394   connect to a ldap server
395 */
396 NTSTATUS ldap_connect(struct ldap_connection *conn, const char *url)
397 {
398         NTSTATUS status;
399
400         status = ldap_parse_basic_url(conn, url, &conn->host,
401                                       &conn->port, &conn->ldaps);
402         NT_STATUS_NOT_OK_RETURN(status);
403
404         status = socket_create("ipv4", SOCKET_TYPE_STREAM, &conn->sock, 0);
405         NT_STATUS_NOT_OK_RETURN(status);
406
407         talloc_steal(conn, conn->sock);
408
409         /* connect in a event friendly way */
410         status = socket_connect_ev(conn->sock, NULL, 0, conn->host, conn->port, 0, 
411                                    conn->event.event_ctx);
412         if (!NT_STATUS_IS_OK(status)) {
413                 talloc_free(conn->sock);
414                 return status;
415         }
416
417         /* setup a handler for events on this socket */
418         conn->event.fde = event_add_fd(conn->event.event_ctx, conn->sock, 
419                                        socket_get_fd(conn->sock), 
420                                        EVENT_FD_READ, ldap_io_handler, conn);
421         if (conn->event.fde == NULL) {
422                 talloc_free(conn->sock);
423                 return NT_STATUS_INTERNAL_ERROR;
424         }
425
426         conn->tls = tls_init_client(conn->sock, conn->event.fde, conn->ldaps);
427         if (conn->tls == NULL) {
428                 talloc_free(conn->sock);
429                 return NT_STATUS_INTERNAL_ERROR;
430         }
431         talloc_steal(conn, conn->tls);
432         talloc_steal(conn->tls, conn->sock);
433
434         return NT_STATUS_OK;
435 }
436
437 /* destroy an open ldap request */
438 static int ldap_request_destructor(void *ptr)
439 {
440         struct ldap_request *req = talloc_get_type(ptr, struct ldap_request);
441         if (req->state == LDAP_REQUEST_SEND) {
442                 DLIST_REMOVE(req->conn->send_queue, req);
443         }
444         if (req->state == LDAP_REQUEST_PENDING) {
445                 DLIST_REMOVE(req->conn->pending, req);
446         }
447         return 0;
448 }
449
450 /*
451   called on timeout of a ldap request
452 */
453 static void ldap_request_timeout(struct event_context *ev, struct timed_event *te, 
454                                       struct timeval t, void *private)
455 {
456         struct ldap_request *req = talloc_get_type(private, struct ldap_request);
457         req->status = NT_STATUS_IO_TIMEOUT;
458         if (req->state == LDAP_REQUEST_SEND) {
459                 DLIST_REMOVE(req->conn->send_queue, req);
460         }
461         if (req->state == LDAP_REQUEST_PENDING) {
462                 DLIST_REMOVE(req->conn->pending, req);
463         }
464         req->state = LDAP_REQUEST_DONE;
465         if (req->async.fn) {
466                 req->async.fn(req);
467         }
468 }
469
470 /*
471   send a ldap message - async interface
472 */
473 struct ldap_request *ldap_request_send(struct ldap_connection *conn,
474                                        struct ldap_message *msg)
475 {
476         struct ldap_request *req;
477
478         if (conn->tls == NULL) {
479                 return NULL;
480         }
481
482         req = talloc_zero(conn, struct ldap_request);
483         if (req == NULL) goto failed;
484
485         req->state       = LDAP_REQUEST_SEND;
486         req->conn        = conn;
487         req->messageid   = conn->next_messageid++;
488         if (conn->next_messageid == 0) {
489                 conn->next_messageid = 1;
490         }
491         req->type        = msg->type;
492         if (req->messageid == -1) {
493                 goto failed;
494         }
495
496         talloc_set_destructor(req, ldap_request_destructor);
497
498         msg->messageid = req->messageid;
499
500         if (!ldap_encode(msg, &req->data, req)) {
501                 goto failed;            
502         }
503
504         /* possibly encrypt/sign the request */
505         if (conn->enable_wrap) {
506                 DATA_BLOB wrapped;
507                 NTSTATUS status;
508
509                 status = gensec_wrap(conn->gensec, req, &req->data, &wrapped);
510                 if (!NT_STATUS_IS_OK(status)) {
511                         goto failed;
512                 }
513                 data_blob_free(&req->data);
514                 req->data = data_blob_talloc(req, NULL, wrapped.length + 4);
515                 if (req->data.data == NULL) {
516                         goto failed;
517                 }
518                 RSIVAL(req->data.data, 0, wrapped.length);
519                 memcpy(req->data.data+4, wrapped.data, wrapped.length);
520                 data_blob_free(&wrapped);
521         }
522
523
524         if (conn->send_queue == NULL) {
525                 EVENT_FD_WRITEABLE(conn->event.fde);
526         }
527         DLIST_ADD_END(conn->send_queue, req, struct ldap_request *);
528
529         /* put a timeout on the request */
530         event_add_timed(conn->event.event_ctx, req, 
531                         timeval_current_ofs(conn->timeout, 0),
532                         ldap_request_timeout, req);
533
534         return req;
535
536 failed:
537         talloc_free(req);
538         return NULL;
539 }
540
541
542 /*
543   wait for a request to complete
544   note that this does not destroy the request
545 */
546 NTSTATUS ldap_request_wait(struct ldap_request *req)
547 {
548         while (req->state != LDAP_REQUEST_DONE) {
549                 if (event_loop_once(req->conn->event.event_ctx) != 0) {
550                         req->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
551                         break;
552                 }
553         }
554         return req->status;
555 }
556
557
558 /*
559   used to setup the status code from a ldap response
560 */
561 NTSTATUS ldap_check_response(struct ldap_connection *conn, struct ldap_Result *r)
562 {
563         if (r->resultcode == LDAP_SUCCESS) {
564                 return NT_STATUS_OK;
565         }
566
567         if (conn->last_error) {
568                 talloc_free(conn->last_error);
569         }
570         conn->last_error = talloc_asprintf(conn, "LDAP error %u - %s <%s> <%s>", 
571                                            r->resultcode,
572                                            r->dn?r->dn:"(NULL)", 
573                                            r->errormessage?r->errormessage:"", 
574                                            r->referral?r->referral:"");
575         
576         return NT_STATUS_LDAP(r->resultcode);
577 }
578
579 /*
580   return error string representing the last error
581 */
582 const char *ldap_errstr(struct ldap_connection *conn, NTSTATUS status)
583 {
584         if (NT_STATUS_IS_LDAP(status) && conn->last_error != NULL) {
585                 return conn->last_error;
586         }
587         return nt_errstr(status);
588 }
589
590
591 /*
592   return the Nth result message, waiting if necessary
593 */
594 NTSTATUS ldap_result_n(struct ldap_request *req, int n, struct ldap_message **msg)
595 {
596         *msg = NULL;
597
598         NT_STATUS_HAVE_NO_MEMORY(req);
599
600         while (req->state != LDAP_REQUEST_DONE && n >= req->num_replies) {
601                 if (event_loop_once(req->conn->event.event_ctx) != 0) {
602                         return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
603                 }
604         }
605
606         if (n < req->num_replies) {
607                 *msg = req->replies[n];
608                 return NT_STATUS_OK;
609         }
610
611         if (!NT_STATUS_IS_OK(req->status)) {
612                 return req->status;
613         }
614
615         return NT_STATUS_NO_MORE_ENTRIES;
616 }
617
618
619 /*
620   return a single result message, checking if it is of the expected LDAP type
621 */
622 NTSTATUS ldap_result_one(struct ldap_request *req, struct ldap_message **msg, int type)
623 {
624         NTSTATUS status;
625         status = ldap_result_n(req, 0, msg);
626         if (!NT_STATUS_IS_OK(status)) {
627                 return status;
628         }
629         if ((*msg)->type != type) {
630                 *msg = NULL;
631                 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
632         }
633         return status;
634 }
635
636 /*
637   a simple ldap transaction, for single result requests that only need a status code
638   this relies on single valued requests having the response type == request type + 1
639 */
640 NTSTATUS ldap_transaction(struct ldap_connection *conn, struct ldap_message *msg)
641 {
642         struct ldap_request *req = ldap_request_send(conn, msg);
643         struct ldap_message *res;
644         NTSTATUS status;
645         status = ldap_result_n(req, 0, &res);
646         if (!NT_STATUS_IS_OK(status)) {
647                 talloc_free(req);
648                 return status;
649         }
650         if (res->type != msg->type + 1) {
651                 talloc_free(req);
652                 return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
653         }
654         status = ldap_check_response(conn, &res->r.GeneralResult);
655         talloc_free(req);
656         return status;
657 }