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,
40 char *ip_str = talloc_strdup(service->mem_ctx, inet_ntoa(*ifip));
42 service_setup_socket(service, model_ops, ip_str, &port);
47 /****************************************************************************
48 Open the socket communication.
49 ****************************************************************************/
50 static void ldapsrv_init(struct server_service *service,
51 const struct model_ops *model_ops)
53 DEBUG(1,("ldapsrv_init\n"));
55 if (lp_interfaces() && lp_bind_interfaces_only()) {
56 int num_interfaces = iface_count();
59 /* We have been given an interfaces line, and been
60 told to only bind to those interfaces. Create a
61 socket per interface and bind to only these.
63 for(i = 0; i < num_interfaces; i++) {
64 struct in_addr *ifip = iface_n_ip(i);
67 DEBUG(0,("ldapsrv_init: interface %d has NULL "
68 "IP address !\n", i));
72 add_socket(service, model_ops, ifip);
76 TALLOC_CTX *mem_ctx = talloc_init("ldapsrv_init");
79 smb_panic("No memory");
82 /* Just bind to lp_socket_address() (usually 0.0.0.0) */
83 ifip = interpret_addr2(mem_ctx, lp_socket_address());
84 add_socket(service, model_ops, ifip);
86 talloc_destroy(mem_ctx);
90 /* This rw-buf api is made to avoid memcpy. For now do that like mad... The
91 idea is to write into a circular list of buffers where the ideal case is
92 that a read(2) holds a complete request that is then thrown away
95 static BOOL append_to_buf(struct rw_buffer *buf, uint8_t *data, size_t length)
97 buf->data = realloc(buf->data, buf->length+length);
99 if (buf->data == NULL)
102 memcpy(buf->data+buf->length, data, length);
104 buf->length += length;
108 static BOOL read_into_buf(struct socket_context *sock, struct rw_buffer *buf)
114 status = socket_recv(sock, sock, &tmp_blob, 1024, 0);
115 if (!NT_STATUS_IS_OK(status)) {
116 DEBUG(0,("socket_recv: %s\n",nt_errstr(status)));
120 ret = append_to_buf(buf, tmp_blob.data, tmp_blob.length);
122 talloc_free(tmp_blob.data);
127 static BOOL write_from_buf(struct socket_context *sock, struct rw_buffer *buf)
133 tmp_blob.data = buf->data;
134 tmp_blob.length = buf->length;
136 status = socket_send(sock, sock, &tmp_blob, &sendlen, 0);
137 if (!NT_STATUS_IS_OK(status)) {
141 if (buf->length != sendlen) {
148 static void peek_into_read_buf(struct rw_buffer *buf, uint8_t **out,
152 *out_length = buf->length;
155 static void consumed_from_read_buf(struct rw_buffer *buf,
158 memcpy(buf->data, buf->data+length, buf->length-length);
159 buf->length -= length;
162 static BOOL ldap_append_to_buf(struct ldap_message *msg, struct rw_buffer *buf)
167 if (!ldap_encode(msg, &blob))
170 res = append_to_buf(buf, blob.data, blob.length);
172 data_blob_free(&blob);
176 static void reply_unwilling(struct ldapsrv_connection *ldap_conn, int error)
178 struct ldap_message *msg;
179 struct ldap_ExtendedResponse *r;
181 msg = new_ldap_message();
184 ldapsrv_terminate_connection(ldap_conn, "new_ldap_message() failed");
189 r = &msg->r.ExtendedResponse;
191 /* When completely freaking out, OpenLDAP responds with an ExtResp */
192 msg->type = LDAP_TAG_ExtendedResponse;
193 r->response.resultcode = error;
194 r->response.dn = NULL;
195 r->response.errormessage = NULL;
196 r->response.referral = NULL;
198 r->value.data = NULL;
201 ldap_append_to_buf(msg, &ldap_conn->out_buffer);
203 talloc_destroy(msg->mem_ctx);
206 static void ldap_reply_BindRequest(struct ldapsrv_connection *conn,
207 struct ldap_message *request)
209 struct ldap_BindRequest *req = &request->r.BindRequest;
211 struct ldap_message *msg;
212 struct ldap_BindResponse *resp;
214 DEBUG(5, ("Binding as %s with pw %s\n",
215 req->dn, req->creds.password));
217 msg = new_ldap_message();
220 ldapsrv_terminate_connection(conn, "new_ldap_message() failed");
224 resp = &msg->r.BindResponse;
226 msg->messageid = request->messageid;
227 msg->type = LDAP_TAG_BindResponse;
228 resp->response.resultcode = 0;
229 resp->response.dn = NULL;
230 resp->response.errormessage = NULL;
231 resp->response.referral = NULL;
232 resp->SASL.secblob = data_blob(NULL, 0);
234 ldap_append_to_buf(msg, &conn->out_buffer);
235 talloc_destroy(msg->mem_ctx);
238 static void ldap_reply_SearchRequest(struct ldapsrv_connection *conn,
239 struct ldap_message *request)
241 struct ldap_SearchRequest *req = &request->r.SearchRequest;
243 struct ldap_message *msg;
244 struct ldap_Result *resp;
246 DEBUG(10, ("Search filter: %s\n", req->filter));
248 msg = new_ldap_message();
251 ldapsrv_terminate_connection(conn, "new_ldap_message() failed");
255 msg->messageid = request->messageid;
256 resp = &msg->r.SearchResultDone;
258 /* Is this a rootdse request? */
259 if ((strlen(req->basedn) == 0) &&
260 (req->scope == LDAP_SEARCH_SCOPE_BASE) &&
261 strequal(req->filter, "(objectclass=*)")) {
263 #define ATTR_BLOB_CONST(val) data_blob(val, sizeof(val)-1)
264 #define ATTR_CONST_SINGLE(attr, blob, nam, val) do { \
266 attr.num_values = ARRAY_SIZE(blob); \
267 attr.values = blob; \
268 blob[0] = ATTR_BLOB_CONST(val); \
270 #define ATTR_CONST_SINGLE_NOVAL(attr, blob, nam) do { \
272 attr.num_values = ARRAY_SIZE(blob); \
276 struct ldap_attribute attrs[3];
277 DATA_BLOB currentTime[1];
278 DATA_BLOB supportedLDAPVersion[2];
279 DATA_BLOB dnsHostName[1];
281 mem_ctx = talloc_init("rootDSE");
283 ldapsrv_terminate_connection(conn, "no memory");
291 ATTR_CONST_SINGLE_NOVAL(attrs[0], currentTime, "currentTime");
293 char *str = ldap_timestring(mem_ctx, time(NULL));
295 ldapsrv_terminate_connection(conn, "no memory");
298 currentTime[0] = data_blob(str, strlen(str));
304 * CN=Aggregate,CN=Schema,CN=Configuration,DC=DOM,DC=TLD
309 * CN=NTDS Settings,CN=NETBIOSNAME,CN=Servers,CN=Default-First-Site,CN=Sites,CN=Configuration,DC=DOM,DC=TLD
315 * CN=Configuration,DC=DOM,DC=TLD
316 * CN=Schema,CN=Configuration,DC=DOM,DC=TLD
317 * DC=DomainDnsZones,DC=DOM,DC=TLD
318 * DC=ForestDnsZones,DC=DOM,DC=TLD
322 * defaultNamingContext
327 * schemaNamingContext
328 * CN=Schema,CN=Configuration,DC=DOM,DC=TLD
332 * configurationNamingContext
333 * CN=Configuration,DC=DOM,DC=TLD
337 * rootDomainNamingContext
343 * 1.2.840.113556.1.4.319
344 * 1.2.840.113556.1.4.801
345 * 1.2.840.113556.1.4.473
346 * 1.2.840.113556.1.4.528
347 * 1.2.840.113556.1.4.417
348 * 1.2.840.113556.1.4.619
349 * 1.2.840.113556.1.4.841
350 * 1.2.840.113556.1.4.529
351 * 1.2.840.113556.1.4.805
352 * 1.2.840.113556.1.4.521
353 * 1.2.840.113556.1.4.970
354 * 1.2.840.113556.1.4.1338
355 * 1.2.840.113556.1.4.474
356 * 1.2.840.113556.1.4.1339
357 * 1.2.840.113556.1.4.1340
358 * 1.2.840.113556.1.4.1413
359 * 2.16.840.1.113730.3.4.9
360 * 2.16.840.1.113730.3.4.10
361 * 1.2.840.113556.1.4.1504
362 * 1.2.840.113556.1.4.1852
363 * 1.2.840.113556.1.4.802
367 * supportedLDAPVersion
371 ATTR_CONST_SINGLE_NOVAL(attrs[1], supportedLDAPVersion, "supportedLDAPVersion");
372 supportedLDAPVersion[0] = ATTR_BLOB_CONST("3");
373 supportedLDAPVersion[1] = ATTR_BLOB_CONST("2");
376 * supportedLDAPPolicies
387 * MaxNotificationPerConn
392 * highestCommittedUSN
397 * supportedSASLMechanisms
406 * netbiosname.dom.tld
408 ATTR_CONST_SINGLE_NOVAL(attrs[2], dnsHostName, "dnsHostName");
409 dnsHostName[0] = data_blob(lp_netbios_name(),strlen(lp_netbios_name()));
413 * dom.tld:netbiosname$@DOM.TLD
418 * CN=NETBIOSNAME,CN=Servers,CN=Default-First-Site,CN=Sites,CN=Configuration,DC=DOM,DC=TLD
422 * supportedCapabilities
423 * 1.2.840.113556.1.4.800
424 * 1.2.840.113556.1.4.1670
425 * 1.2.840.113556.1.4.1791
434 * isGlobalCatalogReady
439 * domainFunctionality
444 * forestFunctionality
449 * domainControllerFunctionality
453 msg->type = LDAP_TAG_SearchResultEntry;
454 msg->r.SearchResultEntry.dn = "";
455 msg->r.SearchResultEntry.num_attributes = ARRAY_SIZE(attrs);
456 msg->r.SearchResultEntry.attributes = attrs;
458 ldap_append_to_buf(msg, &conn->out_buffer);
459 talloc_free(mem_ctx);
462 msg->type = LDAP_TAG_SearchResultDone;
463 resp->resultcode = 0;
465 resp->errormessage = NULL;
466 resp->referral = NULL;
468 ldap_append_to_buf(msg, &conn->out_buffer);
469 talloc_destroy(msg->mem_ctx);
472 static void switch_ldap_message(struct ldapsrv_connection *conn,
473 struct ldap_message *msg)
476 case LDAP_TAG_BindRequest:
477 ldap_reply_BindRequest(conn, msg);
479 case LDAP_TAG_SearchRequest:
480 ldap_reply_SearchRequest(conn, msg);
483 reply_unwilling(conn, 2);
488 static void ldap_queue_run(struct server_connection *conn)
490 struct ldapsrv_connection *ldap_conn = conn->private_data;
492 while (ldap_conn->in_queue) {
493 struct ldap_message_queue *req = ldap_conn->in_queue;
494 DLIST_REMOVE(ldap_conn->in_queue, req);
496 switch_ldap_message(ldap_conn, req->msg);
497 talloc_destroy(req->msg->mem_ctx);
502 called when a LDAP socket becomes readable
504 static void ldapsrv_recv(struct server_connection *conn, time_t t,
507 struct ldapsrv_connection *ldap_conn = conn->private_data;
509 int buf_length, msg_length;
512 struct ldap_message *msg;
513 struct ldap_message_queue *queue_entry;
515 DEBUG(10,("ldapsrv_recv\n"));
517 if (!read_into_buf(conn->socket, &ldap_conn->in_buffer)) {
518 ldapsrv_terminate_connection(ldap_conn, "read_into_buf() failed");
522 peek_into_read_buf(&ldap_conn->in_buffer, &buf, &buf_length);
524 while (buf_length > 0) {
526 /* LDAP Messages are always SEQUENCES */
528 if (!asn1_object_length(buf, buf_length, ASN1_SEQUENCE(0),
530 ldapsrv_terminate_connection(ldap_conn, "asn1_object_length() failed");
534 if (buf_length < msg_length) {
539 /* We've got a complete LDAP request in the in-buffer, convert
540 * that to a ldap_message and put it into the incoming
544 blob.length = msg_length;
546 if (!asn1_load(&data, blob)) {
547 ldapsrv_terminate_connection(ldap_conn, "asn1_load() failed");
551 msg = new_ldap_message();
553 if ((msg == NULL) || !ldap_decode(&data, msg)) {
554 ldapsrv_terminate_connection(ldap_conn, "ldap_decode() failed");
558 queue_entry = talloc_p(msg->mem_ctx, struct ldap_message_queue);
560 if (queue_entry == NULL) {
561 ldapsrv_terminate_connection(ldap_conn, "alloc_p(msg->mem_ctx, struct ldap_message_queue) failed");
565 queue_entry->msg = msg;
567 DLIST_ADD_END(ldap_conn->in_queue, queue_entry,
568 struct ldap_message_queue *);
570 consumed_from_read_buf(&ldap_conn->in_buffer, msg_length);
572 peek_into_read_buf(&ldap_conn->in_buffer, &buf, &buf_length);
575 ldap_queue_run(conn);
577 conn->event.fde->flags |= EVENT_FD_WRITE;
583 called when a LDAP socket becomes writable
585 static void ldapsrv_send(struct server_connection *conn, time_t t,
588 struct ldapsrv_connection *ldap_conn = conn->private_data;
590 DEBUG(10,("ldapsrv_send\n"));
592 if (!write_from_buf(conn->socket, &ldap_conn->out_buffer)) {
593 ldapsrv_terminate_connection(ldap_conn, "write_from_buf() failed");
597 conn->event.fde->flags &= ~EVENT_FD_WRITE;
603 called when connection is idle
605 static void ldapsrv_idle(struct server_connection *conn, time_t t)
607 DEBUG(10,("ldapsrv_idle: not implemented!\n"));
611 static void ldapsrv_close(struct server_connection *conn, const char *reason)
613 struct ldapsrv_connection *ldap_conn = conn->private_data;
615 talloc_free(ldap_conn);
621 initialise a server_context from a open socket and register a event handler
622 for reading from that socket
624 static void ldapsrv_accept(struct server_connection *conn)
626 struct ldapsrv_connection *ldap_conn;
628 DEBUG(5, ("ldapsrv_accept\n"));
630 ldap_conn = talloc_p(NULL, struct ldapsrv_connection);
632 if (ldap_conn == NULL)
635 ZERO_STRUCTP(ldap_conn);
636 ldap_conn->connection = conn;
638 conn->private_data = ldap_conn;
644 called on a fatal error that should cause this server to terminate
646 static void ldapsrv_exit(struct server_service *service, const char *reason)
648 DEBUG(1,("ldapsrv_exit\n"));
652 static const struct server_service_ops ldap_server_ops = {
654 .service_init = ldapsrv_init,
655 .accept_connection = ldapsrv_accept,
656 .recv_handler = ldapsrv_recv,
657 .send_handler = ldapsrv_send,
658 .idle_handler = ldapsrv_idle,
659 .close_connection = ldapsrv_close,
660 .service_exit = ldapsrv_exit,
663 const struct server_service_ops *ldapsrv_get_ops(void)
665 return &ldap_server_ops;
668 NTSTATUS server_service_ldap_init(void)