r2401: make our LDAP server useable:
[jelmer/samba4-debian.git] / source / ldap_server / ldap_server.c
1 /* 
2    Unix SMB/CIFS implementation.
3    LDAP server
4    Copyright (C) Volker Lendecke 2004
5    Copyright (C) Stefan Metzmacher 2004
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 /*
25   close the socket and shutdown a server_context
26 */
27 static void ldapsrv_terminate_connection(struct ldapsrv_connection *ldap_conn, const char *reason)
28 {
29         server_terminate_connection(ldap_conn->connection, reason);
30 }
31
32 /*
33   add a socket address to the list of events, one event per port
34 */
35 static void add_socket(struct server_service *service, 
36                        const struct model_ops *model_ops,
37                        struct socket_context *socket_ctx, 
38                        struct in_addr *ifip)
39 {
40         uint16_t port = 389;
41
42         service_setup_socket(service, model_ops, socket_ctx, ifip, &port);
43 }
44
45 /****************************************************************************
46  Open the socket communication.
47 ****************************************************************************/
48 static void ldapsrv_init(struct server_service *service,
49                          const struct model_ops *model_ops)
50 {       
51         DEBUG(1,("ldapsrv_init\n"));
52
53         if (lp_interfaces() && lp_bind_interfaces_only()) {
54                 int num_interfaces = iface_count();
55                 int i;
56
57                 /* We have been given an interfaces line, and been 
58                    told to only bind to those interfaces. Create a
59                    socket per interface and bind to only these.
60                 */
61                 for(i = 0; i < num_interfaces; i++) {
62                         struct in_addr *ifip = iface_n_ip(i);
63
64                         if (ifip == NULL) {
65                                 DEBUG(0,("ldapsrv_init: interface %d has NULL "
66                                          "IP address !\n", i));
67                                 continue;
68                         }
69
70                         add_socket(service, model_ops, NULL, ifip);
71                 }
72         } else {
73                 struct in_addr *ifip;
74                 TALLOC_CTX *mem_ctx = talloc_init("ldapsrv_init");
75
76                 if (!mem_ctx) {
77                         smb_panic("No memory");
78                 }       
79
80                 /* Just bind to lp_socket_address() (usually 0.0.0.0) */
81                 ifip = interpret_addr2(mem_ctx, lp_socket_address());
82                 add_socket(service, model_ops, NULL, ifip);
83
84                 talloc_destroy(mem_ctx);
85         }
86 }
87
88 /* This rw-buf api is made to avoid memcpy. For now do that like mad...  The
89    idea is to write into a circular list of buffers where the ideal case is
90    that a read(2) holds a complete request that is then thrown away
91    completely. */
92
93 static BOOL append_to_buf(struct rw_buffer *buf, uint8_t *data, size_t length)
94 {
95         buf->data = realloc(buf->data, buf->length+length);
96
97         if (buf->data == NULL)
98                 return False;
99
100         memcpy(buf->data+buf->length, data, length);
101
102         buf->length += length;
103         return True;
104 }
105
106 static BOOL read_into_buf(int fd, struct rw_buffer *buf)
107 {
108         char tmp_buf[1024];
109         int len;
110
111         len = read(fd, tmp_buf, sizeof(tmp_buf));
112         if (len == 0)
113                 return False;
114
115         return append_to_buf(buf, tmp_buf, len);
116 }
117
118 static BOOL write_from_buf(int fd, struct rw_buffer *buf)
119 {
120         int len;
121
122         len = write(fd, buf->data, buf->length);
123         if (len != buf->length)
124                 return False;
125
126         return True;
127 }
128
129 static void peek_into_read_buf(struct rw_buffer *buf, uint8_t **out,
130                                size_t *out_length)
131 {
132         *out = buf->data;
133         *out_length = buf->length;
134 }
135
136 static void consumed_from_read_buf(struct rw_buffer *buf,
137                                    size_t length)
138 {
139         memcpy(buf->data, buf->data+length, buf->length-length);
140         buf->length -= length;
141 }
142
143 static BOOL ldap_append_to_buf(struct ldap_message *msg, struct rw_buffer *buf)
144 {
145         DATA_BLOB blob;
146         BOOL res;
147
148         if (!ldap_encode(msg, &blob))
149                 return False;
150
151         res = append_to_buf(buf, blob.data, blob.length);
152
153         data_blob_free(&blob);
154         return res;
155 }
156
157 static void reply_unwilling(struct ldapsrv_connection *ldap_conn, int error)
158 {
159         struct ldap_message *msg;
160         struct ldap_ExtendedResponse *r;
161
162         msg = new_ldap_message();
163
164         if (msg == NULL) {
165                 ldapsrv_terminate_connection(ldap_conn, "new_ldap_message() failed");
166                 return;
167         }
168
169         msg->messageid = 0;
170         r = &msg->r.ExtendedResponse;   
171
172         /* When completely freaking out, OpenLDAP responds with an ExtResp */
173         msg->type = LDAP_TAG_ExtendedResponse;
174         r->response.resultcode = error;
175         r->response.dn = NULL;
176         r->response.errormessage = NULL;
177         r->response.referral = NULL;
178         r->name = NULL;
179         r->value.data = NULL;
180         r->value.length = 0;
181
182         ldap_append_to_buf(msg, &ldap_conn->out_buffer);
183
184         talloc_destroy(msg->mem_ctx);
185 }
186
187 static void ldap_reply_BindRequest(struct ldapsrv_connection *conn, 
188                                    struct ldap_message *request)
189 {
190         struct ldap_BindRequest *req = &request->r.BindRequest;
191
192         struct ldap_message *msg;
193         struct ldap_BindResponse *resp;
194
195         DEBUG(5, ("Binding as %s with pw %s\n",
196                   req->dn, req->creds.password));
197
198         msg = new_ldap_message();
199
200         if (msg == NULL) {
201                 ldapsrv_terminate_connection(conn, "new_ldap_message() failed");
202                 return;
203         }
204
205         resp = &msg->r.BindResponse;
206
207         msg->messageid = request->messageid;
208         msg->type = LDAP_TAG_BindResponse;
209         resp->response.resultcode = 0;
210         resp->response.dn = NULL;
211         resp->response.errormessage = NULL;
212         resp->response.referral = NULL;
213         resp->SASL.secblob = data_blob(NULL, 0);
214
215         ldap_append_to_buf(msg, &conn->out_buffer);
216         talloc_destroy(msg->mem_ctx);
217 }
218
219 static void ldap_reply_SearchRequest(struct ldapsrv_connection *conn,
220                                      struct ldap_message *request)
221 {
222         struct ldap_SearchRequest *req = &request->r.SearchRequest;
223
224         struct ldap_message *msg;
225         struct ldap_Result *resp;
226
227         DEBUG(10, ("Search filter: %s\n", req->filter));
228
229         msg = new_ldap_message();
230
231         if (msg == NULL) {
232                 ldapsrv_terminate_connection(conn, "new_ldap_message() failed");
233                 return;
234         }
235
236         msg->messageid = request->messageid;
237         resp = &msg->r.SearchResultDone;
238
239         /* Is this a rootdse request? */
240         if ((strlen(req->basedn) == 0) &&
241             (req->scope == LDAP_SEARCH_SCOPE_BASE) &&
242             strequal(req->filter, "(objectclass=*)")) {
243
244 #define ATTR_BLOB_CONST(val) data_blob(val, sizeof(val)-1)
245 #define ATTR_CONST_SINGLE(attr, blob, nam, val) do { \
246         attr.name = nam; \
247         attr.num_values = ARRAY_SIZE(blob); \
248         attr.values = blob; \
249         blob[0] = ATTR_BLOB_CONST(val); \
250 } while(0)
251 #define ATTR_CONST_SINGLE_NOVAL(attr, blob, nam) do { \
252         attr.name = nam;\
253         attr.num_values = ARRAY_SIZE(blob); \
254         attr.values = blob;\
255 } while(0)
256                 TALLOC_CTX *mem_ctx;
257                 struct ldap_attribute attrs[3];
258                 DATA_BLOB currentTime[1];
259                 DATA_BLOB supportedLDAPVersion[2];
260                 DATA_BLOB dnsHostName[1];
261
262                 mem_ctx = talloc_init("rootDSE");
263                 if (!mem_ctx) {
264                         ldapsrv_terminate_connection(conn, "no memory");
265                         return;
266                 }
267
268                 /* 
269                  * currentTime
270                  * 20040918090350.0Z
271                  */
272                 ATTR_CONST_SINGLE_NOVAL(attrs[0], currentTime, "currentTime");
273                 {
274                         char *str = ldap_timestring(mem_ctx, time(NULL));
275                         if (!str) {
276                                 ldapsrv_terminate_connection(conn, "no memory");
277                                 return;
278                         }
279                         currentTime[0] = data_blob(str, strlen(str));
280                         talloc_free(str);
281                 }
282
283                 /* 
284                  * subschemaSubentry 
285                  * CN=Aggregate,CN=Schema,CN=Configuration,DC=DOM,DC=TLD
286                  */
287
288                 /* 
289                  * dsServiceName
290                  * CN=NTDS Settings,CN=NETBIOSNAME,CN=Servers,CN=Default-First-Site,CN=Sites,CN=Configuration,DC=DOM,DC=TLD
291                  */
292
293                 /* 
294                  * namingContexts
295                  * DC=DOM,DC=TLD
296                  * CN=Configuration,DC=DOM,DC=TLD
297                  * CN=Schema,CN=Configuration,DC=DOM,DC=TLD
298                  * DC=DomainDnsZones,DC=DOM,DC=TLD
299                  * DC=ForestDnsZones,DC=DOM,DC=TLD
300                  */
301
302                 /* 
303                  * defaultNamingContext
304                  * DC=DOM,DC=TLD
305                  */
306
307                 /* 
308                  * schemaNamingContext
309                  * CN=Schema,CN=Configuration,DC=DOM,DC=TLD
310                  */
311
312                 /* 
313                  * configurationNamingContext
314                  * CN=Configuration,DC=DOM,DC=TLD
315                  */
316
317                 /* 
318                  * rootDomainNamingContext
319                  * DC=DOM,DC=TLD
320                  */
321
322                 /* 
323                  * supportedControl
324                  * 1.2.840.113556.1.4.319
325                  * 1.2.840.113556.1.4.801
326                  * 1.2.840.113556.1.4.473
327                  * 1.2.840.113556.1.4.528
328                  * 1.2.840.113556.1.4.417
329                  * 1.2.840.113556.1.4.619
330                  * 1.2.840.113556.1.4.841
331                  * 1.2.840.113556.1.4.529
332                  * 1.2.840.113556.1.4.805
333                  * 1.2.840.113556.1.4.521
334                  * 1.2.840.113556.1.4.970
335                  * 1.2.840.113556.1.4.1338
336                  * 1.2.840.113556.1.4.474
337                  * 1.2.840.113556.1.4.1339
338                  * 1.2.840.113556.1.4.1340
339                  * 1.2.840.113556.1.4.1413
340                  * 2.16.840.1.113730.3.4.9
341                  * 2.16.840.1.113730.3.4.10
342                  * 1.2.840.113556.1.4.1504
343                  * 1.2.840.113556.1.4.1852
344                  * 1.2.840.113556.1.4.802
345                  */
346
347                 /* 
348                  * supportedLDAPVersion 
349                  * 3
350                  * 2
351                  */
352                 ATTR_CONST_SINGLE_NOVAL(attrs[1], supportedLDAPVersion, "supportedLDAPVersion");
353                 supportedLDAPVersion[0] = ATTR_BLOB_CONST("3");
354                 supportedLDAPVersion[1] = ATTR_BLOB_CONST("2");
355
356                 /* 
357                  * supportedLDAPPolicies
358                  * MaxPoolThreads
359                  * MaxDatagramRecv
360                  * MaxReceiveBuffer
361                  * InitRecvTimeout
362                  * MaxConnections
363                  * MaxConnIdleTime
364                  * MaxPageSize
365                  * MaxQueryDuration
366                  * MaxTempTableSize
367                  * MaxResultSetSize
368                  * MaxNotificationPerConn
369                  * MaxValRange
370                  */
371
372                 /* 
373                  * highestCommittedUSN 
374                  * 4555
375                  */
376
377                 /* 
378                  * supportedSASLMechanisms
379                  * GSSAPI
380                  * GSS-SPNEGO
381                  * EXTERNAL
382                  * DIGEST-MD5
383                  */
384
385                 /* 
386                  * dnsHostName
387                  * netbiosname.dom.tld
388                  */
389                 ATTR_CONST_SINGLE_NOVAL(attrs[2], dnsHostName, "dnsHostName");
390                 dnsHostName[0] = data_blob(lp_netbios_name(),strlen(lp_netbios_name()));
391
392                 /* 
393                  * ldapServiceName
394                  * dom.tld:netbiosname$@DOM.TLD
395                  */
396
397                 /* 
398                  * serverName:
399                  * CN=NETBIOSNAME,CN=Servers,CN=Default-First-Site,CN=Sites,CN=Configuration,DC=DOM,DC=TLD
400                  */
401
402                 /* 
403                  * supportedCapabilities
404                  * 1.2.840.113556.1.4.800
405                  * 1.2.840.113556.1.4.1670
406                  * 1.2.840.113556.1.4.1791
407                  */
408
409                 /* 
410                  * isSynchronized:
411                  * TRUE/FALSE
412                  */
413
414                 /* 
415                  * isGlobalCatalogReady
416                  * TRUE/FALSE
417                  */
418
419                 /* 
420                  * domainFunctionality
421                  * 0
422                  */
423
424                 /* 
425                  * forestFunctionality
426                  * 0
427                  */
428
429                 /* 
430                  * domainControllerFunctionality
431                  * 2
432                  */
433
434                 msg->type = LDAP_TAG_SearchResultEntry;
435                 msg->r.SearchResultEntry.dn = "";
436                 msg->r.SearchResultEntry.num_attributes = ARRAY_SIZE(attrs);
437                 msg->r.SearchResultEntry.attributes = attrs;
438
439                 ldap_append_to_buf(msg, &conn->out_buffer);
440                 talloc_free(mem_ctx);
441         }
442
443         msg->type = LDAP_TAG_SearchResultDone;
444         resp->resultcode = 0;
445         resp->dn = NULL;
446         resp->errormessage = NULL;
447         resp->referral = NULL;
448
449         ldap_append_to_buf(msg, &conn->out_buffer);
450         talloc_destroy(msg->mem_ctx);
451 }
452
453 static void switch_ldap_message(struct ldapsrv_connection *conn,
454                          struct ldap_message *msg)
455 {
456         switch(msg->type) {
457         case LDAP_TAG_BindRequest:
458                 ldap_reply_BindRequest(conn, msg);
459                 break;
460         case LDAP_TAG_SearchRequest:
461                 ldap_reply_SearchRequest(conn, msg);
462                 break;
463         default:
464                 reply_unwilling(conn, 2);
465                 break;
466         }
467 }
468
469 static void ldap_queue_run(struct server_connection *conn)
470 {
471         struct ldapsrv_connection *ldap_conn = conn->private_data;
472         
473         while (ldap_conn->in_queue) {
474                 struct ldap_message_queue *req = ldap_conn->in_queue;
475                 DLIST_REMOVE(ldap_conn->in_queue, req);
476
477                 switch_ldap_message(ldap_conn, req->msg);
478                 talloc_destroy(req->msg->mem_ctx);
479         }
480 }
481
482 /*
483   called when a LDAP socket becomes readable
484 */
485 static void ldapsrv_recv(struct server_connection *conn, time_t t,
486                          uint16_t flags)
487 {
488         struct ldapsrv_connection *ldap_conn = conn->private_data;
489         uint8_t *buf;
490         int buf_length, msg_length;
491         DATA_BLOB blob;
492         ASN1_DATA data;
493         struct ldap_message *msg;
494         struct ldap_message_queue *queue_entry;
495
496         DEBUG(10,("ldapsrv_recv\n"));
497
498         if (!read_into_buf(conn->event.fde->fd, &ldap_conn->in_buffer)) {
499                 ldapsrv_terminate_connection(ldap_conn, "read_into_buf() failed");
500                 return;
501         }
502
503         peek_into_read_buf(&ldap_conn->in_buffer, &buf, &buf_length);
504
505         while (buf_length > 0) {
506
507                 /* LDAP Messages are always SEQUENCES */
508
509                 if (!asn1_object_length(buf, buf_length, ASN1_SEQUENCE(0),
510                                         &msg_length)) {
511                         ldapsrv_terminate_connection(ldap_conn, "asn1_object_length() failed");
512                         return;
513                 }
514
515                 if (buf_length < msg_length) {
516                         /* Not enough yet */
517                         break;
518                 }
519
520                 /* We've got a complete LDAP request in the in-buffer, convert
521                  * that to a ldap_message and put it into the incoming
522                  * queue. */
523
524                 blob.data = buf;
525                 blob.length = msg_length;
526
527                 if (!asn1_load(&data, blob)) {
528                         ldapsrv_terminate_connection(ldap_conn, "asn1_load() failed");
529                         return;
530                 }
531
532                 msg = new_ldap_message();
533
534                 if ((msg == NULL) || !ldap_decode(&data, msg)) {
535                         ldapsrv_terminate_connection(ldap_conn, "ldap_decode() failed");
536                         return;
537                 }
538
539                 queue_entry = talloc_p(msg->mem_ctx, struct ldap_message_queue);
540
541                 if (queue_entry == NULL) {
542                         ldapsrv_terminate_connection(ldap_conn, "alloc_p(msg->mem_ctx, struct ldap_message_queue) failed");
543                         return;
544                 }
545
546                 queue_entry->msg = msg;
547
548                 DLIST_ADD_END(ldap_conn->in_queue, queue_entry,
549                               struct ldap_message_queue *);
550
551                 consumed_from_read_buf(&ldap_conn->in_buffer, msg_length);
552
553                 peek_into_read_buf(&ldap_conn->in_buffer, &buf, &buf_length);
554         }
555
556         ldap_queue_run(conn);
557
558         conn->event.fde->flags |= EVENT_FD_WRITE;
559
560         return;
561 }
562         
563 /*
564   called when a LDAP socket becomes writable
565 */
566 static void ldapsrv_send(struct server_connection *conn, time_t t,
567                          uint16_t flags)
568 {
569         struct ldapsrv_connection *ldap_conn = conn->private_data;
570
571         DEBUG(10,("ldapsrv_send\n"));
572
573         if (!write_from_buf(conn->event.fde->fd, &ldap_conn->out_buffer)) {
574                 ldapsrv_terminate_connection(ldap_conn, "write_from_buf() failed");
575                 return;
576         }
577
578         conn->event.fde->flags &= ~EVENT_FD_WRITE;
579
580         return;
581 }
582
583 /*
584   called when connection is idle
585 */
586 static void ldapsrv_idle(struct server_connection *conn, time_t t)
587 {
588         DEBUG(10,("ldapsrv_idle: not implemented!\n"));
589         return;
590 }
591
592 static void ldapsrv_close(struct server_connection *conn, const char *reason)
593 {
594         struct ldapsrv_connection *ldap_conn = conn->private_data;
595
596         talloc_free(ldap_conn);
597
598         return;
599 }
600
601 /*
602   initialise a server_context from a open socket and register a event handler
603   for reading from that socket
604 */
605 static void ldapsrv_accept(struct server_connection *conn)
606 {
607         struct ldapsrv_connection *ldap_conn;
608
609         DEBUG(5, ("ldapsrv_accept\n"));
610
611         ldap_conn = talloc_p(NULL, struct ldapsrv_connection);
612
613         if (ldap_conn == NULL)
614                 return;
615
616         ZERO_STRUCTP(ldap_conn);
617         ldap_conn->connection = conn;
618
619         conn->private_data = ldap_conn;
620         
621         return;
622 }
623
624 /*
625   called on a fatal error that should cause this server to terminate
626 */
627 static void ldapsrv_exit(struct server_service *service, const char *reason)
628 {
629         DEBUG(1,("ldapsrv_exit\n"));
630         return;
631 }
632
633 static const struct server_service_ops ldap_server_ops = {
634         .name                   = "ldap",
635         .service_init           = ldapsrv_init,
636         .accept_connection      = ldapsrv_accept,
637         .recv_handler           = ldapsrv_recv,
638         .send_handler           = ldapsrv_send,
639         .idle_handler           = ldapsrv_idle,
640         .close_connection       = ldapsrv_close,
641         .service_exit           = ldapsrv_exit, 
642 };
643
644 const struct server_service_ops *ldapsrv_get_ops(void)
645 {
646         return &ldap_server_ops;
647 }
648
649 NTSTATUS server_service_ldap_init(void)
650 {
651         return NT_STATUS_OK;    
652 }