2 Unix SMB/CIFS implementation.
4 Copyright (C) Volker Lendecke 2004
5 Copyright (C) Stefan Metzmacher 2004
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.
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.
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.
25 close the socket and shutdown a server_context
27 static void ldapsrv_terminate_connection(struct ldapsrv_connection *ldap_conn, const char *reason)
29 server_terminate_connection(ldap_conn->connection, reason);
33 add a socket address to the list of events, one event per port
35 static void add_socket(struct server_service *service,
36 const struct model_ops *model_ops,
37 struct socket_context *socket_ctx,
42 service_setup_socket(service, model_ops, socket_ctx, ifip, &port);
45 /****************************************************************************
46 Open the socket communication.
47 ****************************************************************************/
48 static void ldapsrv_init(struct server_service *service,
49 const struct model_ops *model_ops)
51 DEBUG(1,("ldapsrv_init\n"));
53 if (lp_interfaces() && lp_bind_interfaces_only()) {
54 int num_interfaces = iface_count();
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.
61 for(i = 0; i < num_interfaces; i++) {
62 struct in_addr *ifip = iface_n_ip(i);
65 DEBUG(0,("ldapsrv_init: interface %d has NULL "
66 "IP address !\n", i));
70 add_socket(service, model_ops, NULL, ifip);
74 TALLOC_CTX *mem_ctx = talloc_init("ldapsrv_init");
77 smb_panic("No memory");
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);
84 talloc_destroy(mem_ctx);
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
93 static BOOL append_to_buf(struct rw_buffer *buf, uint8_t *data, size_t length)
95 buf->data = realloc(buf->data, buf->length+length);
97 if (buf->data == NULL)
100 memcpy(buf->data+buf->length, data, length);
102 buf->length += length;
106 static BOOL read_into_buf(int fd, struct rw_buffer *buf)
111 len = read(fd, tmp_buf, sizeof(tmp_buf));
115 return append_to_buf(buf, tmp_buf, len);
118 static BOOL write_from_buf(int fd, struct rw_buffer *buf)
122 len = write(fd, buf->data, buf->length);
123 if (len != buf->length)
129 static void peek_into_read_buf(struct rw_buffer *buf, uint8_t **out,
133 *out_length = buf->length;
136 static void consumed_from_read_buf(struct rw_buffer *buf,
139 memcpy(buf->data, buf->data+length, buf->length-length);
140 buf->length -= length;
143 static BOOL ldap_append_to_buf(struct ldap_message *msg, struct rw_buffer *buf)
148 if (!ldap_encode(msg, &blob))
151 res = append_to_buf(buf, blob.data, blob.length);
153 data_blob_free(&blob);
157 static void reply_unwilling(struct ldapsrv_connection *ldap_conn, int error)
159 struct ldap_message *msg;
160 struct ldap_ExtendedResponse *r;
162 msg = new_ldap_message();
165 ldapsrv_terminate_connection(ldap_conn, "new_ldap_message() failed");
170 r = &msg->r.ExtendedResponse;
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;
179 r->value.data = NULL;
182 ldap_append_to_buf(msg, &ldap_conn->out_buffer);
184 talloc_destroy(msg->mem_ctx);
187 static void ldap_reply_BindRequest(struct ldapsrv_connection *conn,
188 struct ldap_message *request)
190 struct ldap_BindRequest *req = &request->r.BindRequest;
192 struct ldap_message *msg;
193 struct ldap_BindResponse *resp;
195 DEBUG(5, ("Binding as %s with pw %s\n",
196 req->dn, req->creds.password));
198 msg = new_ldap_message();
201 ldapsrv_terminate_connection(conn, "new_ldap_message() failed");
205 resp = &msg->r.BindResponse;
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);
215 ldap_append_to_buf(msg, &conn->out_buffer);
216 talloc_destroy(msg->mem_ctx);
219 static void ldap_reply_SearchRequest(struct ldapsrv_connection *conn,
220 struct ldap_message *request)
222 struct ldap_SearchRequest *req = &request->r.SearchRequest;
224 struct ldap_message *msg;
225 struct ldap_Result *resp;
227 DEBUG(10, ("Search filter: %s\n", req->filter));
229 msg = new_ldap_message();
232 ldapsrv_terminate_connection(conn, "new_ldap_message() failed");
236 msg->messageid = request->messageid;
237 resp = &msg->r.SearchResultDone;
239 /* Is this a rootdse request? */
240 if ((strlen(req->basedn) == 0) &&
241 (req->scope == LDAP_SEARCH_SCOPE_BASE) &&
242 strequal(req->filter, "(objectclass=*)")) {
244 #define ATTR_BLOB_CONST(val) data_blob(val, sizeof(val)-1)
245 #define ATTR_CONST_SINGLE(attr, blob, nam, val) do { \
247 attr.num_values = ARRAY_SIZE(blob); \
248 attr.values = blob; \
249 blob[0] = ATTR_BLOB_CONST(val); \
251 #define ATTR_CONST_SINGLE_NOVAL(attr, blob, nam) do { \
253 attr.num_values = ARRAY_SIZE(blob); \
257 struct ldap_attribute attrs[3];
258 DATA_BLOB currentTime[1];
259 DATA_BLOB supportedLDAPVersion[2];
260 DATA_BLOB dnsHostName[1];
262 mem_ctx = talloc_init("rootDSE");
264 ldapsrv_terminate_connection(conn, "no memory");
272 ATTR_CONST_SINGLE_NOVAL(attrs[0], currentTime, "currentTime");
274 char *str = ldap_timestring(mem_ctx, time(NULL));
276 ldapsrv_terminate_connection(conn, "no memory");
279 currentTime[0] = data_blob(str, strlen(str));
285 * CN=Aggregate,CN=Schema,CN=Configuration,DC=DOM,DC=TLD
290 * CN=NTDS Settings,CN=NETBIOSNAME,CN=Servers,CN=Default-First-Site,CN=Sites,CN=Configuration,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
303 * defaultNamingContext
308 * schemaNamingContext
309 * CN=Schema,CN=Configuration,DC=DOM,DC=TLD
313 * configurationNamingContext
314 * CN=Configuration,DC=DOM,DC=TLD
318 * rootDomainNamingContext
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
348 * supportedLDAPVersion
352 ATTR_CONST_SINGLE_NOVAL(attrs[1], supportedLDAPVersion, "supportedLDAPVersion");
353 supportedLDAPVersion[0] = ATTR_BLOB_CONST("3");
354 supportedLDAPVersion[1] = ATTR_BLOB_CONST("2");
357 * supportedLDAPPolicies
368 * MaxNotificationPerConn
373 * highestCommittedUSN
378 * supportedSASLMechanisms
387 * netbiosname.dom.tld
389 ATTR_CONST_SINGLE_NOVAL(attrs[2], dnsHostName, "dnsHostName");
390 dnsHostName[0] = data_blob(lp_netbios_name(),strlen(lp_netbios_name()));
394 * dom.tld:netbiosname$@DOM.TLD
399 * CN=NETBIOSNAME,CN=Servers,CN=Default-First-Site,CN=Sites,CN=Configuration,DC=DOM,DC=TLD
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
415 * isGlobalCatalogReady
420 * domainFunctionality
425 * forestFunctionality
430 * domainControllerFunctionality
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;
439 ldap_append_to_buf(msg, &conn->out_buffer);
440 talloc_free(mem_ctx);
443 msg->type = LDAP_TAG_SearchResultDone;
444 resp->resultcode = 0;
446 resp->errormessage = NULL;
447 resp->referral = NULL;
449 ldap_append_to_buf(msg, &conn->out_buffer);
450 talloc_destroy(msg->mem_ctx);
453 static void switch_ldap_message(struct ldapsrv_connection *conn,
454 struct ldap_message *msg)
457 case LDAP_TAG_BindRequest:
458 ldap_reply_BindRequest(conn, msg);
460 case LDAP_TAG_SearchRequest:
461 ldap_reply_SearchRequest(conn, msg);
464 reply_unwilling(conn, 2);
469 static void ldap_queue_run(struct server_connection *conn)
471 struct ldapsrv_connection *ldap_conn = conn->private_data;
473 while (ldap_conn->in_queue) {
474 struct ldap_message_queue *req = ldap_conn->in_queue;
475 DLIST_REMOVE(ldap_conn->in_queue, req);
477 switch_ldap_message(ldap_conn, req->msg);
478 talloc_destroy(req->msg->mem_ctx);
483 called when a LDAP socket becomes readable
485 static void ldapsrv_recv(struct server_connection *conn, time_t t,
488 struct ldapsrv_connection *ldap_conn = conn->private_data;
490 int buf_length, msg_length;
493 struct ldap_message *msg;
494 struct ldap_message_queue *queue_entry;
496 DEBUG(10,("ldapsrv_recv\n"));
498 if (!read_into_buf(conn->event.fde->fd, &ldap_conn->in_buffer)) {
499 ldapsrv_terminate_connection(ldap_conn, "read_into_buf() failed");
503 peek_into_read_buf(&ldap_conn->in_buffer, &buf, &buf_length);
505 while (buf_length > 0) {
507 /* LDAP Messages are always SEQUENCES */
509 if (!asn1_object_length(buf, buf_length, ASN1_SEQUENCE(0),
511 ldapsrv_terminate_connection(ldap_conn, "asn1_object_length() failed");
515 if (buf_length < msg_length) {
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
525 blob.length = msg_length;
527 if (!asn1_load(&data, blob)) {
528 ldapsrv_terminate_connection(ldap_conn, "asn1_load() failed");
532 msg = new_ldap_message();
534 if ((msg == NULL) || !ldap_decode(&data, msg)) {
535 ldapsrv_terminate_connection(ldap_conn, "ldap_decode() failed");
539 queue_entry = talloc_p(msg->mem_ctx, struct ldap_message_queue);
541 if (queue_entry == NULL) {
542 ldapsrv_terminate_connection(ldap_conn, "alloc_p(msg->mem_ctx, struct ldap_message_queue) failed");
546 queue_entry->msg = msg;
548 DLIST_ADD_END(ldap_conn->in_queue, queue_entry,
549 struct ldap_message_queue *);
551 consumed_from_read_buf(&ldap_conn->in_buffer, msg_length);
553 peek_into_read_buf(&ldap_conn->in_buffer, &buf, &buf_length);
556 ldap_queue_run(conn);
558 conn->event.fde->flags |= EVENT_FD_WRITE;
564 called when a LDAP socket becomes writable
566 static void ldapsrv_send(struct server_connection *conn, time_t t,
569 struct ldapsrv_connection *ldap_conn = conn->private_data;
571 DEBUG(10,("ldapsrv_send\n"));
573 if (!write_from_buf(conn->event.fde->fd, &ldap_conn->out_buffer)) {
574 ldapsrv_terminate_connection(ldap_conn, "write_from_buf() failed");
578 conn->event.fde->flags &= ~EVENT_FD_WRITE;
584 called when connection is idle
586 static void ldapsrv_idle(struct server_connection *conn, time_t t)
588 DEBUG(10,("ldapsrv_idle: not implemented!\n"));
592 static void ldapsrv_close(struct server_connection *conn, const char *reason)
594 struct ldapsrv_connection *ldap_conn = conn->private_data;
596 talloc_free(ldap_conn);
602 initialise a server_context from a open socket and register a event handler
603 for reading from that socket
605 static void ldapsrv_accept(struct server_connection *conn)
607 struct ldapsrv_connection *ldap_conn;
609 DEBUG(5, ("ldapsrv_accept\n"));
611 ldap_conn = talloc_p(NULL, struct ldapsrv_connection);
613 if (ldap_conn == NULL)
616 ZERO_STRUCTP(ldap_conn);
617 ldap_conn->connection = conn;
619 conn->private_data = ldap_conn;
625 called on a fatal error that should cause this server to terminate
627 static void ldapsrv_exit(struct server_service *service, const char *reason)
629 DEBUG(1,("ldapsrv_exit\n"));
633 static const struct server_service_ops ldap_server_ops = {
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,
644 const struct server_service_ops *ldapsrv_get_ops(void)
646 return &ldap_server_ops;
649 NTSTATUS server_service_ldap_init(void)