ctdb-tests: Update statd-callout tests to handle both modes
[samba4-gss.git] / source4 / cldap_server / cldap_server.c
blob69db574db2726565b6234b12e95f6279283aea46
1 /*
2 Unix SMB/CIFS implementation.
4 CLDAP server task
6 Copyright (C) Andrew Tridgell 2005
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include <talloc.h>
24 #include "lib/messaging/irpc.h"
25 #include "samba/service_task.h"
26 #include "samba/service.h"
27 #include "cldap_server/cldap_server.h"
28 #include "system/network.h"
29 #include "lib/socket/netif.h"
30 #include <ldb.h>
31 #include <ldb_errors.h>
32 #include "dsdb/samdb/samdb.h"
33 #include "ldb_wrap.h"
34 #include "auth/auth.h"
35 #include "param/param.h"
36 #include "../lib/tsocket/tsocket.h"
37 #include "libds/common/roles.h"
39 NTSTATUS server_service_cldapd_init(TALLOC_CTX *);
42 send an error reply (used on any error, so the client doesn't keep waiting
43 or send the bad request again)
45 static NTSTATUS cldap_error_reply(struct cldap_socket *cldap,
46 uint32_t message_id,
47 struct tsocket_address *dest,
48 int resultcode,
49 const char *errormessage)
51 NTSTATUS status;
52 struct cldap_reply reply;
53 struct ldap_Result result;
55 reply.messageid = message_id;
56 reply.dest = dest;
57 reply.response = NULL;
58 reply.result = &result;
60 ZERO_STRUCT(result);
61 result.resultcode = resultcode;
62 result.errormessage = errormessage;
64 status = cldap_reply_send(cldap, &reply);
66 return status;
70 handle incoming cldap requests
72 static void cldapd_request_handler(struct cldap_socket *cldap,
73 void *private_data,
74 struct cldap_incoming *in)
76 struct cldapd_server *cldapd = talloc_get_type(private_data,
77 struct cldapd_server);
78 struct ldap_SearchRequest *search;
80 if (in->ldap_msg->type == LDAP_TAG_AbandonRequest) {
81 DEBUG(10,("Got (and ignoring) CLDAP AbandonRequest from %s.\n",
82 tsocket_address_string(in->src, in)));
83 talloc_free(in);
84 return;
87 if (in->ldap_msg->type != LDAP_TAG_SearchRequest) {
88 DEBUG(0,("Invalid CLDAP request type %d from %s\n",
89 in->ldap_msg->type,
90 tsocket_address_string(in->src, in)));
91 cldap_error_reply(cldap, in->ldap_msg->messageid, in->src,
92 LDAP_OPERATIONS_ERROR, "Invalid CLDAP request");
93 talloc_free(in);
94 return;
97 search = &in->ldap_msg->r.SearchRequest;
99 if (strcmp("", search->basedn) != 0) {
100 DEBUG(0,("Invalid CLDAP basedn '%s' from %s\n",
101 search->basedn,
102 tsocket_address_string(in->src, in)));
103 cldap_error_reply(cldap, in->ldap_msg->messageid, in->src,
104 LDAP_OPERATIONS_ERROR, "Invalid CLDAP basedn");
105 talloc_free(in);
106 return;
109 if (search->scope != LDAP_SEARCH_SCOPE_BASE) {
110 DEBUG(0,("Invalid CLDAP scope %d from %s\n",
111 search->scope,
112 tsocket_address_string(in->src, in)));
113 cldap_error_reply(cldap, in->ldap_msg->messageid, in->src,
114 LDAP_OPERATIONS_ERROR, "Invalid CLDAP scope");
115 talloc_free(in);
116 return;
119 cldapd_rootdse_request(cldap, cldapd, in,
120 in->ldap_msg->messageid,
121 search, in->src);
122 talloc_free(in);
127 start listening on the given address
129 static NTSTATUS cldapd_add_socket(struct cldapd_server *cldapd, struct loadparm_context *lp_ctx,
130 const char *address)
132 struct cldap_socket *cldapsock;
133 struct tsocket_address *socket_address;
134 NTSTATUS status;
135 int ret;
137 ret = tsocket_address_inet_from_strings(
138 cldapd, "ip", address, 389, &socket_address);
139 if (ret != 0) {
140 status = map_nt_error_from_unix_common(errno);
141 DEBUG(0,("invalid address %s:%d - %s:%s\n",
142 address, 389,
143 gai_strerror(ret), nt_errstr(status)));
144 return status;
147 /* listen for unicasts on the CLDAP port (389) */
148 status = cldap_socket_init(cldapd,
149 socket_address,
150 NULL,
151 &cldapsock);
152 if (!NT_STATUS_IS_OK(status)) {
153 DEBUG(0,("Failed to bind to %s - %s\n",
154 tsocket_address_string(socket_address, socket_address),
155 nt_errstr(status)));
156 talloc_free(socket_address);
157 return status;
159 talloc_free(socket_address);
161 cldap_set_incoming_handler(cldapsock, cldapd->task->event_ctx,
162 cldapd_request_handler, cldapd);
164 return NT_STATUS_OK;
168 setup our listening sockets on the configured network interfaces
170 static NTSTATUS cldapd_startup_interfaces(struct cldapd_server *cldapd, struct loadparm_context *lp_ctx,
171 struct interface *ifaces)
173 int i, num_interfaces;
174 TALLOC_CTX *tmp_ctx = talloc_new(cldapd);
175 NTSTATUS status;
177 num_interfaces = iface_list_count(ifaces);
179 /* if we are allowing incoming packets from any address, then
180 we need to bind to the wildcard address */
181 if (!lpcfg_bind_interfaces_only(lp_ctx)) {
182 size_t num_binds = 0;
183 char **wcard = iface_list_wildcard(cldapd);
184 NT_STATUS_HAVE_NO_MEMORY(wcard);
185 for (i=0; wcard[i]; i++) {
186 status = cldapd_add_socket(cldapd, lp_ctx, wcard[i]);
187 if (NT_STATUS_IS_OK(status)) {
188 num_binds++;
191 talloc_free(wcard);
192 if (num_binds == 0) {
193 return NT_STATUS_INVALID_PARAMETER_MIX;
197 /* now we have to also listen on the specific interfaces,
198 so that replies always come from the right IP */
199 for (i=0; i<num_interfaces; i++) {
200 const char *address = talloc_strdup(tmp_ctx, iface_list_n_ip(ifaces, i));
201 status = cldapd_add_socket(cldapd, lp_ctx, address);
202 NT_STATUS_NOT_OK_RETURN(status);
205 talloc_free(tmp_ctx);
207 return NT_STATUS_OK;
211 startup the cldapd task
213 static NTSTATUS cldapd_task_init(struct task_server *task)
215 struct cldapd_server *cldapd;
216 NTSTATUS status;
217 struct interface *ifaces;
219 load_interface_list(task, task->lp_ctx, &ifaces);
221 if (iface_list_count(ifaces) == 0) {
222 task_server_terminate(task, "cldapd: no network interfaces configured", false);
223 return NT_STATUS_UNSUCCESSFUL;
226 switch (lpcfg_server_role(task->lp_ctx)) {
227 case ROLE_STANDALONE:
228 task_server_terminate(task, "cldap_server: no CLDAP server required in standalone configuration",
229 false);
230 return NT_STATUS_INVALID_DOMAIN_ROLE;
231 case ROLE_DOMAIN_MEMBER:
232 task_server_terminate(task, "cldap_server: no CLDAP server required in member server configuration",
233 false);
234 return NT_STATUS_INVALID_DOMAIN_ROLE;
235 case ROLE_ACTIVE_DIRECTORY_DC:
236 /* Yes, we want an CLDAP server */
237 break;
240 task_server_set_title(task, "task[cldapd]");
242 cldapd = talloc(task, struct cldapd_server);
243 if (cldapd == NULL) {
244 task_server_terminate(task, "cldapd: out of memory", true);
245 return NT_STATUS_NO_MEMORY;
248 cldapd->task = task;
249 cldapd->samctx = samdb_connect(cldapd,
250 task->event_ctx,
251 task->lp_ctx,
252 system_session(task->lp_ctx),
253 NULL,
255 if (cldapd->samctx == NULL) {
256 task_server_terminate(task, "cldapd failed to open samdb", true);
257 return NT_STATUS_UNSUCCESSFUL;
260 /* start listening on the configured network interfaces */
261 status = cldapd_startup_interfaces(cldapd, task->lp_ctx, ifaces);
262 if (!NT_STATUS_IS_OK(status)) {
263 task_server_terminate(task, "cldapd failed to setup interfaces", true);
264 return status;
267 irpc_add_name(task->msg_ctx, "cldap_server");
269 return NT_STATUS_OK;
274 register ourselves as a available server
276 NTSTATUS server_service_cldapd_init(TALLOC_CTX *ctx)
278 static const struct service_details details = {
279 .inhibit_fork_on_accept = true,
280 .inhibit_pre_fork = true,
281 .task_init = cldapd_task_init,
282 .post_fork = NULL
284 return register_server_service(ctx, "cldap", &details);