Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : CLDAP server task
5 :
6 : Copyright (C) Andrew Tridgell 2005
7 :
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.
12 :
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.
17 :
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/>.
20 : */
21 :
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"
38 :
39 : NTSTATUS server_service_cldapd_init(TALLOC_CTX *);
40 :
41 : /*
42 : handle incoming cldap requests
43 : */
44 2503 : static void cldapd_request_handler(struct cldap_socket *cldap,
45 : void *private_data,
46 : struct cldap_incoming *in)
47 : {
48 2503 : struct cldapd_server *cldapd = talloc_get_type(private_data,
49 : struct cldapd_server);
50 36 : struct ldap_SearchRequest *search;
51 :
52 2503 : if (in->ldap_msg->type == LDAP_TAG_AbandonRequest) {
53 0 : DEBUG(10,("Got (and ignoring) CLDAP AbandonRequest from %s.\n",
54 : tsocket_address_string(in->src, in)));
55 0 : talloc_free(in);
56 0 : return;
57 : }
58 :
59 2503 : if (in->ldap_msg->type != LDAP_TAG_SearchRequest) {
60 0 : DEBUG(0,("Invalid CLDAP request type %d from %s\n",
61 : in->ldap_msg->type,
62 : tsocket_address_string(in->src, in)));
63 0 : cldap_error_reply(cldap, in->ldap_msg->messageid, in->src,
64 : LDAP_OPERATIONS_ERROR, "Invalid CLDAP request");
65 0 : talloc_free(in);
66 0 : return;
67 : }
68 :
69 2503 : search = &in->ldap_msg->r.SearchRequest;
70 :
71 2503 : if (strcmp("", search->basedn) != 0) {
72 0 : DEBUG(0,("Invalid CLDAP basedn '%s' from %s\n",
73 : search->basedn,
74 : tsocket_address_string(in->src, in)));
75 0 : cldap_error_reply(cldap, in->ldap_msg->messageid, in->src,
76 : LDAP_OPERATIONS_ERROR, "Invalid CLDAP basedn");
77 0 : talloc_free(in);
78 0 : return;
79 : }
80 :
81 2503 : if (search->scope != LDAP_SEARCH_SCOPE_BASE) {
82 0 : DEBUG(0,("Invalid CLDAP scope %d from %s\n",
83 : search->scope,
84 : tsocket_address_string(in->src, in)));
85 0 : cldap_error_reply(cldap, in->ldap_msg->messageid, in->src,
86 : LDAP_OPERATIONS_ERROR, "Invalid CLDAP scope");
87 0 : talloc_free(in);
88 0 : return;
89 : }
90 :
91 2503 : cldapd_rootdse_request(cldap, cldapd, in,
92 2503 : in->ldap_msg->messageid,
93 : search, in->src);
94 2503 : talloc_free(in);
95 : }
96 :
97 :
98 : /*
99 : start listening on the given address
100 : */
101 236 : static NTSTATUS cldapd_add_socket(struct cldapd_server *cldapd, struct loadparm_context *lp_ctx,
102 : const char *address)
103 : {
104 8 : struct cldap_socket *cldapsock;
105 8 : struct tsocket_address *socket_address;
106 8 : NTSTATUS status;
107 8 : int ret;
108 :
109 236 : ret = tsocket_address_inet_from_strings(cldapd,
110 : "ip",
111 : address,
112 : lpcfg_cldap_port(lp_ctx),
113 : &socket_address);
114 236 : if (ret != 0) {
115 0 : status = map_nt_error_from_unix_common(errno);
116 0 : DEBUG(0,("invalid address %s:%d - %s:%s\n",
117 : address, lpcfg_cldap_port(lp_ctx),
118 : gai_strerror(ret), nt_errstr(status)));
119 0 : return status;
120 : }
121 :
122 : /* listen for unicasts on the CLDAP port (389) */
123 236 : status = cldap_socket_init(cldapd,
124 : socket_address,
125 : NULL,
126 : &cldapsock);
127 236 : if (!NT_STATUS_IS_OK(status)) {
128 0 : DEBUG(0,("Failed to bind to %s - %s\n",
129 : tsocket_address_string(socket_address, socket_address),
130 : nt_errstr(status)));
131 0 : talloc_free(socket_address);
132 0 : return status;
133 : }
134 236 : talloc_free(socket_address);
135 :
136 236 : cldap_set_incoming_handler(cldapsock, cldapd->task->event_ctx,
137 : cldapd_request_handler, cldapd);
138 :
139 236 : return NT_STATUS_OK;
140 : }
141 :
142 : /*
143 : setup our listening sockets on the configured network interfaces
144 : */
145 59 : static NTSTATUS cldapd_startup_interfaces(struct cldapd_server *cldapd, struct loadparm_context *lp_ctx,
146 : struct interface *ifaces)
147 : {
148 2 : int i, num_interfaces;
149 59 : TALLOC_CTX *tmp_ctx = talloc_new(cldapd);
150 2 : NTSTATUS status;
151 :
152 59 : num_interfaces = iface_list_count(ifaces);
153 :
154 : /* if we are allowing incoming packets from any address, then
155 : we need to bind to the wildcard address */
156 59 : if (!lpcfg_bind_interfaces_only(lp_ctx)) {
157 59 : size_t num_binds = 0;
158 59 : char **wcard = iface_list_wildcard(cldapd);
159 59 : NT_STATUS_HAVE_NO_MEMORY(wcard);
160 177 : for (i=0; wcard[i]; i++) {
161 118 : status = cldapd_add_socket(cldapd, lp_ctx, wcard[i]);
162 118 : if (NT_STATUS_IS_OK(status)) {
163 118 : num_binds++;
164 : }
165 : }
166 59 : talloc_free(wcard);
167 59 : if (num_binds == 0) {
168 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
169 : }
170 : }
171 :
172 : /* now we have to also listen on the specific interfaces,
173 : so that replies always come from the right IP */
174 177 : for (i=0; i<num_interfaces; i++) {
175 118 : const char *address = talloc_strdup(tmp_ctx, iface_list_n_ip(ifaces, i));
176 118 : status = cldapd_add_socket(cldapd, lp_ctx, address);
177 118 : NT_STATUS_NOT_OK_RETURN(status);
178 : }
179 :
180 59 : talloc_free(tmp_ctx);
181 :
182 59 : return NT_STATUS_OK;
183 : }
184 :
185 : /*
186 : startup the cldapd task
187 : */
188 65 : static NTSTATUS cldapd_task_init(struct task_server *task)
189 : {
190 2 : struct cldapd_server *cldapd;
191 2 : NTSTATUS status;
192 2 : struct interface *ifaces;
193 :
194 65 : load_interface_list(task, task->lp_ctx, &ifaces);
195 :
196 65 : if (iface_list_count(ifaces) == 0) {
197 0 : task_server_terminate(task, "cldapd: no network interfaces configured", false);
198 0 : return NT_STATUS_UNSUCCESSFUL;
199 : }
200 :
201 65 : switch (lpcfg_server_role(task->lp_ctx)) {
202 0 : case ROLE_STANDALONE:
203 0 : task_server_terminate(task, "cldap_server: no CLDAP server required in standalone configuration",
204 : false);
205 0 : return NT_STATUS_INVALID_DOMAIN_ROLE;
206 6 : case ROLE_DOMAIN_MEMBER:
207 6 : task_server_terminate(task, "cldap_server: no CLDAP server required in member server configuration",
208 : false);
209 0 : return NT_STATUS_INVALID_DOMAIN_ROLE;
210 57 : case ROLE_ACTIVE_DIRECTORY_DC:
211 : /* Yes, we want an CLDAP server */
212 57 : break;
213 : }
214 :
215 59 : task_server_set_title(task, "task[cldapd]");
216 :
217 59 : cldapd = talloc(task, struct cldapd_server);
218 59 : if (cldapd == NULL) {
219 0 : task_server_terminate(task, "cldapd: out of memory", true);
220 0 : return NT_STATUS_NO_MEMORY;
221 : }
222 :
223 59 : cldapd->task = task;
224 59 : cldapd->samctx = samdb_connect(cldapd,
225 : task->event_ctx,
226 : task->lp_ctx,
227 : system_session(task->lp_ctx),
228 : NULL,
229 : 0);
230 59 : if (cldapd->samctx == NULL) {
231 0 : task_server_terminate(task, "cldapd failed to open samdb", true);
232 0 : return NT_STATUS_UNSUCCESSFUL;
233 : }
234 :
235 : /* start listening on the configured network interfaces */
236 59 : status = cldapd_startup_interfaces(cldapd, task->lp_ctx, ifaces);
237 59 : if (!NT_STATUS_IS_OK(status)) {
238 0 : task_server_terminate(task, "cldapd failed to setup interfaces", true);
239 0 : return status;
240 : }
241 :
242 59 : irpc_add_name(task->msg_ctx, "cldap_server");
243 :
244 59 : return NT_STATUS_OK;
245 : }
246 :
247 :
248 : /*
249 : register ourselves as a available server
250 : */
251 66 : NTSTATUS server_service_cldapd_init(TALLOC_CTX *ctx)
252 : {
253 3 : static const struct service_details details = {
254 : .inhibit_fork_on_accept = true,
255 : .inhibit_pre_fork = true,
256 : .task_init = cldapd_task_init,
257 : .post_fork = NULL
258 : };
259 66 : return register_server_service(ctx, "cldap", &details);
260 : }
|