torture: convert torture_comment() -> torture_result() so we can knownfail flapping...
[Samba/wip.git] / source4 / winbind / wb_server.c
blob29ed5a67161e70351cae555690629c3b74c09d42
1 /*
2 Unix SMB/CIFS implementation.
3 Main winbindd server routines
5 Copyright (C) Stefan Metzmacher 2005-2008
6 Copyright (C) Andrew Tridgell 2005
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2010
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "smbd/process_model.h"
25 #include "winbind/wb_server.h"
26 #include "lib/stream/packet.h"
27 #include "lib/tsocket/tsocket.h"
28 #include "libcli/util/tstream.h"
29 #include "param/param.h"
30 #include "param/secrets.h"
31 #include "lib/util/dlinklist.h"
33 void wbsrv_terminate_connection(struct wbsrv_connection *wbconn, const char *reason)
35 struct wbsrv_service *service = wbconn->listen_socket->service;
37 if (wbconn->pending_calls == 0) {
38 char *full_reason = talloc_asprintf(wbconn, "wbsrv: %s", reason);
40 DLIST_REMOVE(service->broken_connections, wbconn);
41 stream_terminate_connection(wbconn->conn, full_reason ? full_reason : reason);
42 return;
45 if (wbconn->terminate != NULL) {
46 return;
49 DEBUG(3,("wbsrv: terminating connection due to '%s' defered due to %d pending calls\n",
50 reason, wbconn->pending_calls));
51 wbconn->terminate = talloc_strdup(wbconn, reason);
52 if (wbconn->terminate == NULL) {
53 wbconn->terminate = "wbsrv: defered terminating connection - no memory";
55 DLIST_ADD_END(service->broken_connections, wbconn, NULL);
58 static void wbsrv_cleanup_broken_connections(struct wbsrv_service *s)
60 struct wbsrv_connection *cur, *next;
62 next = s->broken_connections;
63 while (next != NULL) {
64 cur = next;
65 next = cur->next;
67 wbsrv_terminate_connection(cur, cur->terminate);
71 static void wbsrv_call_loop(struct tevent_req *subreq)
73 struct wbsrv_connection *wbsrv_conn = tevent_req_callback_data(subreq,
74 struct wbsrv_connection);
75 struct wbsrv_service *service = wbsrv_conn->listen_socket->service;
76 struct wbsrv_samba3_call *call;
77 NTSTATUS status;
79 if (wbsrv_conn->terminate) {
81 * if the current connection is broken
82 * we need to clean it up before any other connection
84 wbsrv_terminate_connection(wbsrv_conn, wbsrv_conn->terminate);
85 wbsrv_cleanup_broken_connections(service);
86 return;
89 wbsrv_cleanup_broken_connections(service);
91 call = talloc_zero(wbsrv_conn, struct wbsrv_samba3_call);
92 if (call == NULL) {
93 wbsrv_terminate_connection(wbsrv_conn, "wbsrv_call_loop: "
94 "no memory for wbsrv_samba3_call");
95 return;
97 call->wbconn = wbsrv_conn;
99 status = tstream_read_pdu_blob_recv(subreq,
100 call,
101 &call->in);
102 TALLOC_FREE(subreq);
103 if (!NT_STATUS_IS_OK(status)) {
104 const char *reason;
106 reason = talloc_asprintf(wbsrv_conn, "wbsrv_call_loop: "
107 "tstream_read_pdu_blob_recv() - %s",
108 nt_errstr(status));
109 if (!reason) {
110 reason = nt_errstr(status);
113 wbsrv_terminate_connection(wbsrv_conn, reason);
114 return;
117 DEBUG(10,("Received winbind TCP packet of length %lu from %s\n",
118 (long) call->in.length,
119 tsocket_address_string(wbsrv_conn->conn->remote_address, call)));
121 status = wbsrv_samba3_process(call);
122 if (!NT_STATUS_IS_OK(status)) {
123 const char *reason;
125 reason = talloc_asprintf(wbsrv_conn, "wbsrv_call_loop: "
126 "tstream_read_pdu_blob_recv() - %s",
127 nt_errstr(status));
128 if (!reason) {
129 reason = nt_errstr(status);
132 wbsrv_terminate_connection(wbsrv_conn, reason);
133 return;
137 * The winbind pdu's has the length as 4 byte (initial_read_size),
138 * wbsrv_samba3_packet_full_request provides the pdu length then.
140 subreq = tstream_read_pdu_blob_send(wbsrv_conn,
141 wbsrv_conn->conn->event.ctx,
142 wbsrv_conn->tstream,
143 4, /* initial_read_size */
144 wbsrv_samba3_packet_full_request,
145 wbsrv_conn);
146 if (subreq == NULL) {
147 wbsrv_terminate_connection(wbsrv_conn, "wbsrv_call_loop: "
148 "no memory for tstream_read_pdu_blob_send");
149 return;
151 tevent_req_set_callback(subreq, wbsrv_call_loop, wbsrv_conn);
154 static void wbsrv_accept(struct stream_connection *conn)
156 struct wbsrv_listen_socket *wbsrv_socket = talloc_get_type(conn->private_data,
157 struct wbsrv_listen_socket);
158 struct wbsrv_connection *wbsrv_conn;
159 struct tevent_req *subreq;
160 int rc;
162 wbsrv_cleanup_broken_connections(wbsrv_socket->service);
164 wbsrv_conn = talloc_zero(conn, struct wbsrv_connection);
165 if (wbsrv_conn == NULL) {
166 stream_terminate_connection(conn, "wbsrv_accept: out of memory");
167 return;
170 wbsrv_conn->send_queue = tevent_queue_create(conn, "wbsrv_accept");
171 if (wbsrv_conn->send_queue == NULL) {
172 stream_terminate_connection(conn,
173 "wbsrv_accept: out of memory");
174 return;
177 TALLOC_FREE(conn->event.fde);
179 rc = tstream_bsd_existing_socket(wbsrv_conn,
180 socket_get_fd(conn->socket),
181 &wbsrv_conn->tstream);
182 if (rc < 0) {
183 stream_terminate_connection(conn,
184 "wbsrv_accept: out of memory");
185 return;
188 wbsrv_conn->conn = conn;
189 wbsrv_conn->listen_socket = wbsrv_socket;
190 wbsrv_conn->lp_ctx = wbsrv_socket->service->task->lp_ctx;
191 conn->private_data = wbsrv_conn;
194 * The winbind pdu's has the length as 4 byte (initial_read_size),
195 * wbsrv_samba3_packet_full_request provides the pdu length then.
197 subreq = tstream_read_pdu_blob_send(wbsrv_conn,
198 wbsrv_conn->conn->event.ctx,
199 wbsrv_conn->tstream,
200 4, /* initial_read_size */
201 wbsrv_samba3_packet_full_request,
202 wbsrv_conn);
203 if (subreq == NULL) {
204 wbsrv_terminate_connection(wbsrv_conn, "wbsrv_accept: "
205 "no memory for tstream_read_pdu_blob_send");
206 return;
208 tevent_req_set_callback(subreq, wbsrv_call_loop, wbsrv_conn);
212 called on a tcp recv
214 static void wbsrv_recv(struct stream_connection *conn, uint16_t flags)
216 struct wbsrv_connection *wbsrv_conn = talloc_get_type(conn->private_data,
217 struct wbsrv_connection);
218 wbsrv_terminate_connection(wbsrv_conn, "wbsrv_recv: called");
222 called when we can write to a connection
224 static void wbsrv_send(struct stream_connection *conn, uint16_t flags)
226 struct wbsrv_connection *wbsrv_conn = talloc_get_type(conn->private_data,
227 struct wbsrv_connection);
228 /* this should never be triggered! */
229 wbsrv_terminate_connection(wbsrv_conn, "wbsrv_send: called");
232 static const struct stream_server_ops wbsrv_ops = {
233 .name = "winbind samba3 protocol",
234 .accept_connection = wbsrv_accept,
235 .recv_handler = wbsrv_recv,
236 .send_handler = wbsrv_send
240 startup the winbind task
242 static void winbind_task_init(struct task_server *task)
244 uint16_t port = 1;
245 const struct model_ops *model_ops;
246 NTSTATUS status;
247 struct wbsrv_service *service;
248 struct wbsrv_listen_socket *listen_socket;
249 char *errstring;
250 struct dom_sid *primary_sid;
251 bool ok;
253 task_server_set_title(task, "task[winbind]");
255 /* within the winbind task we want to be a single process, so
256 ask for the single process model ops and pass these to the
257 stream_setup_socket() call. */
258 model_ops = process_model_startup("single");
259 if (!model_ops) {
260 task_server_terminate(task,
261 "Can't find 'single' process model_ops", true);
262 return;
265 /* Make sure the directory for the Samba3 socket exists, and is of the correct permissions */
266 ok = directory_create_or_exist_strict(lpcfg_winbindd_socket_directory(task->lp_ctx),
267 geteuid(), 0755);
268 if (!ok) {
269 task_server_terminate(task,
270 "Cannot create winbindd pipe directory", true);
271 return;
274 /* Make sure the directory for the Samba3 socket exists, and is of the correct permissions */
275 ok = directory_create_or_exist_strict(lpcfg_winbindd_privileged_socket_directory(task->lp_ctx),
276 geteuid(), 0750);
277 if (!ok) {
278 task_server_terminate(task,
279 "Cannot create winbindd privileged pipe directory", true);
280 return;
283 service = talloc_zero(task, struct wbsrv_service);
284 if (!service) goto nomem;
285 service->task = task;
288 /* Find the primary SID, depending if we are a standalone
289 * server (what good is winbind in this case, but anyway...),
290 * or are in a domain as a member or a DC */
291 switch (lpcfg_server_role(service->task->lp_ctx)) {
292 case ROLE_STANDALONE:
293 primary_sid = secrets_get_domain_sid(service,
294 service->task->lp_ctx,
295 lpcfg_netbios_name(service->task->lp_ctx),
296 &service->sec_channel_type,
297 &errstring);
298 if (!primary_sid) {
299 char *message = talloc_asprintf(task,
300 "Cannot start Winbind (standalone configuration): %s: "
301 "Have you provisioned this server (%s) or changed it's name?",
302 errstring, lpcfg_netbios_name(service->task->lp_ctx));
303 task_server_terminate(task, message, true);
304 return;
306 break;
307 case ROLE_DOMAIN_MEMBER:
308 primary_sid = secrets_get_domain_sid(service,
309 service->task->lp_ctx,
310 lpcfg_workgroup(service->task->lp_ctx),
311 &service->sec_channel_type,
312 &errstring);
313 if (!primary_sid) {
314 char *message = talloc_asprintf(task, "Cannot start Winbind (domain member): %s: "
315 "Have you joined the %s domain?",
316 errstring, lpcfg_workgroup(service->task->lp_ctx));
317 task_server_terminate(task, message, true);
318 return;
320 break;
321 case ROLE_ACTIVE_DIRECTORY_DC:
322 primary_sid = secrets_get_domain_sid(service,
323 service->task->lp_ctx,
324 lpcfg_workgroup(service->task->lp_ctx),
325 &service->sec_channel_type,
326 &errstring);
327 if (!primary_sid) {
328 char *message = talloc_asprintf(task, "Cannot start Winbind (domain controller): %s: "
329 "Have you provisioned the %s domain?",
330 errstring, lpcfg_workgroup(service->task->lp_ctx));
331 task_server_terminate(task, message, true);
332 return;
334 break;
335 case ROLE_DOMAIN_PDC:
336 case ROLE_DOMAIN_BDC:
337 task_server_terminate(task, "Cannot start 'samba' winbindd as a 'classic samba' DC: use winbindd instead", true);
338 return;
340 service->primary_sid = primary_sid;
342 service->idmap_ctx = idmap_init(service, task->event_ctx, task->lp_ctx);
343 if (service->idmap_ctx == NULL) {
344 task_server_terminate(task, "Failed to load idmap database", true);
345 return;
348 service->priv_pipe_dir = lpcfg_winbindd_privileged_socket_directory(task->lp_ctx);
349 service->pipe_dir = lpcfg_winbindd_socket_directory(task->lp_ctx);
351 /* setup the unprivileged samba3 socket */
352 listen_socket = talloc(service, struct wbsrv_listen_socket);
353 if (!listen_socket) goto nomem;
354 listen_socket->socket_path = talloc_asprintf(listen_socket, "%s/%s",
355 service->pipe_dir,
356 WINBINDD_SOCKET_NAME);
357 if (!listen_socket->socket_path) goto nomem;
358 listen_socket->service = service;
359 listen_socket->privileged = false;
360 status = stream_setup_socket(task, task->event_ctx, task->lp_ctx, model_ops,
361 &wbsrv_ops, "unix",
362 listen_socket->socket_path, &port,
363 lpcfg_socket_options(task->lp_ctx),
364 listen_socket);
365 if (!NT_STATUS_IS_OK(status)) goto listen_failed;
367 /* setup the privileged samba3 socket */
368 listen_socket = talloc(service, struct wbsrv_listen_socket);
369 if (!listen_socket) goto nomem;
370 listen_socket->socket_path
371 = talloc_asprintf(listen_socket, "%s/%s",
372 service->priv_pipe_dir,
373 WINBINDD_SOCKET_NAME);
374 if (!listen_socket->socket_path) goto nomem;
375 listen_socket->service = service;
376 listen_socket->privileged = true;
377 status = stream_setup_socket(task, task->event_ctx, task->lp_ctx, model_ops,
378 &wbsrv_ops, "unix",
379 listen_socket->socket_path, &port,
380 lpcfg_socket_options(task->lp_ctx),
381 listen_socket);
382 if (!NT_STATUS_IS_OK(status)) goto listen_failed;
384 status = wbsrv_init_irpc(service);
385 if (!NT_STATUS_IS_OK(status)) goto irpc_failed;
387 return;
389 listen_failed:
390 DEBUG(0,("stream_setup_socket(path=%s) failed - %s\n",
391 listen_socket->socket_path, nt_errstr(status)));
392 task_server_terminate(task, nt_errstr(status), true);
393 return;
394 irpc_failed:
395 DEBUG(0,("wbsrv_init_irpc() failed - %s\n",
396 nt_errstr(status)));
397 task_server_terminate(task, nt_errstr(status), true);
398 return;
399 nomem:
400 task_server_terminate(task, nt_errstr(NT_STATUS_NO_MEMORY), true);
401 return;
405 register ourselves as a available server
407 NTSTATUS server_service_winbind_init(void)
409 return register_server_service("winbind", winbind_task_init);