2 Unix SMB/CIFS implementation.
3 Main winbindd server routines
5 Copyright (C) Stefan Metzmacher 2005
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/>.
23 #include "smbd/process_model.h"
24 #include "winbind/wb_server.h"
25 #include "lib/stream/packet.h"
26 #include "lib/tsocket/tsocket.h"
27 #include "libcli/util/tstream.h"
28 #include "param/param.h"
30 void wbsrv_terminate_connection(struct wbsrv_connection
*wbconn
, const char *reason
)
32 stream_terminate_connection(wbconn
->conn
, reason
);
35 static void wbsrv_call_loop(struct tevent_req
*subreq
)
37 struct wbsrv_connection
*wbsrv_conn
= tevent_req_callback_data(subreq
,
38 struct wbsrv_connection
);
39 struct wbsrv_samba3_call
*call
;
42 call
= talloc_zero(wbsrv_conn
, struct wbsrv_samba3_call
);
44 wbsrv_terminate_connection(wbsrv_conn
, "wbsrv_call_loop: "
45 "no memory for wbsrv_samba3_call");
48 call
->wbconn
= wbsrv_conn
;
50 status
= tstream_read_pdu_blob_recv(subreq
,
54 if (!NT_STATUS_IS_OK(status
)) {
57 reason
= talloc_asprintf(call
, "wbsrv_call_loop: "
58 "tstream_read_pdu_blob_recv() - %s",
61 reason
= nt_errstr(status
);
64 wbsrv_terminate_connection(wbsrv_conn
, reason
);
68 DEBUG(10,("Received winbind TCP packet of length %lu from %s\n",
69 (long) call
->in
.length
,
70 tsocket_address_string(wbsrv_conn
->conn
->remote_address
, call
)));
72 status
= wbsrv_samba3_process(call
);
73 if (!NT_STATUS_IS_OK(status
)) {
76 reason
= talloc_asprintf(call
, "wbsrv_call_loop: "
77 "tstream_read_pdu_blob_recv() - %s",
80 reason
= nt_errstr(status
);
83 wbsrv_terminate_connection(wbsrv_conn
, reason
);
88 * The winbind pdu's has the length as 4 byte (initial_read_size),
89 * wbsrv_samba3_packet_full_request provides the pdu length then.
91 subreq
= tstream_read_pdu_blob_send(wbsrv_conn
,
92 wbsrv_conn
->conn
->event
.ctx
,
94 4, /* initial_read_size */
95 wbsrv_samba3_packet_full_request
,
98 wbsrv_terminate_connection(wbsrv_conn
, "wbsrv_call_loop: "
99 "no memory for tstream_read_pdu_blob_send");
102 tevent_req_set_callback(subreq
, wbsrv_call_loop
, wbsrv_conn
);
105 static void wbsrv_accept(struct stream_connection
*conn
)
107 struct wbsrv_listen_socket
*wbsrv_socket
= talloc_get_type(conn
->private_data
,
108 struct wbsrv_listen_socket
);
109 struct wbsrv_connection
*wbsrv_conn
;
110 struct tevent_req
*subreq
;
113 wbsrv_conn
= talloc_zero(conn
, struct wbsrv_connection
);
114 if (wbsrv_conn
== NULL
) {
115 stream_terminate_connection(conn
, "wbsrv_accept: out of memory");
119 wbsrv_conn
->send_queue
= tevent_queue_create(conn
, "wbsrv_accept");
120 if (wbsrv_conn
->send_queue
== NULL
) {
121 stream_terminate_connection(conn
,
122 "wbsrv_accept: out of memory");
126 TALLOC_FREE(conn
->event
.fde
);
128 rc
= tstream_bsd_existing_socket(wbsrv_conn
->tstream
,
129 socket_get_fd(conn
->socket
),
130 &wbsrv_conn
->tstream
);
132 stream_terminate_connection(conn
,
133 "wbsrv_accept: out of memory");
137 wbsrv_conn
->conn
= conn
;
138 wbsrv_conn
->listen_socket
= wbsrv_socket
;
139 wbsrv_conn
->lp_ctx
= wbsrv_socket
->service
->task
->lp_ctx
;
140 conn
->private_data
= wbsrv_conn
;
143 * The winbind pdu's has the length as 4 byte (initial_read_size),
144 * wbsrv_samba3_packet_full_request provides the pdu length then.
146 subreq
= tstream_read_pdu_blob_send(wbsrv_conn
,
147 wbsrv_conn
->conn
->event
.ctx
,
149 4, /* initial_read_size */
150 wbsrv_samba3_packet_full_request
,
152 if (subreq
== NULL
) {
153 wbsrv_terminate_connection(wbsrv_conn
, "wbsrv_accept: "
154 "no memory for tstream_read_pdu_blob_send");
157 tevent_req_set_callback(subreq
, wbsrv_call_loop
, wbsrv_conn
);
163 static void wbsrv_recv(struct stream_connection
*conn
, uint16_t flags
)
165 struct wbsrv_connection
*wbsrv_conn
= talloc_get_type(conn
->private_data
,
166 struct wbsrv_connection
);
167 wbsrv_terminate_connection(wbsrv_conn
, "wbsrv_recv: called");
171 called when we can write to a connection
173 static void wbsrv_send(struct stream_connection
*conn
, uint16_t flags
)
175 struct wbsrv_connection
*wbsrv_conn
= talloc_get_type(conn
->private_data
,
176 struct wbsrv_connection
);
177 /* this should never be triggered! */
178 wbsrv_terminate_connection(wbsrv_conn
, "wbsrv_send: called");
181 static const struct stream_server_ops wbsrv_ops
= {
182 .name
= "winbind samba3 protocol",
183 .accept_connection
= wbsrv_accept
,
184 .recv_handler
= wbsrv_recv
,
185 .send_handler
= wbsrv_send
189 startup the winbind task
191 static void winbind_task_init(struct task_server
*task
)
194 const struct model_ops
*model_ops
;
196 struct wbsrv_service
*service
;
197 struct wbsrv_listen_socket
*listen_socket
;
199 task_server_set_title(task
, "task[winbind]");
201 /* within the winbind task we want to be a single process, so
202 ask for the single process model ops and pass these to the
203 stream_setup_socket() call. */
204 model_ops
= process_model_startup(task
->event_ctx
, "single");
206 task_server_terminate(task
,
207 "Can't find 'single' process model_ops", true);
211 /* Make sure the directory for the Samba3 socket exists, and is of the correct permissions */
212 if (!directory_create_or_exist(lp_winbindd_socket_directory(task
->lp_ctx
), geteuid(), 0755)) {
213 task_server_terminate(task
,
214 "Cannot create winbindd pipe directory", true);
218 /* Make sure the directory for the Samba3 socket exists, and is of the correct permissions */
219 if (!directory_create_or_exist(lp_winbindd_privileged_socket_directory(task
->lp_ctx
), geteuid(), 0750)) {
220 task_server_terminate(task
,
221 "Cannot create winbindd privileged pipe directory", true);
225 service
= talloc_zero(task
, struct wbsrv_service
);
226 if (!service
) goto nomem
;
227 service
->task
= task
;
229 status
= wbsrv_setup_domains(service
);
230 if (!NT_STATUS_IS_OK(status
)) {
231 task_server_terminate(task
, nt_errstr(status
), true);
235 service
->idmap_ctx
= idmap_init(service
, task
->event_ctx
, task
->lp_ctx
);
236 if (service
->idmap_ctx
== NULL
) {
237 task_server_terminate(task
, "Failed to load idmap database", true);
241 /* setup the unprivileged samba3 socket */
242 listen_socket
= talloc(service
, struct wbsrv_listen_socket
);
243 if (!listen_socket
) goto nomem
;
244 listen_socket
->socket_path
= talloc_asprintf(listen_socket
, "%s/%s",
245 lp_winbindd_socket_directory(task
->lp_ctx
),
246 WINBINDD_SAMBA3_SOCKET
);
247 if (!listen_socket
->socket_path
) goto nomem
;
248 listen_socket
->service
= service
;
249 listen_socket
->privileged
= false;
250 status
= stream_setup_socket(task
->event_ctx
, task
->lp_ctx
, model_ops
,
252 listen_socket
->socket_path
, &port
,
253 lp_socket_options(task
->lp_ctx
),
255 if (!NT_STATUS_IS_OK(status
)) goto listen_failed
;
257 /* setup the privileged samba3 socket */
258 listen_socket
= talloc(service
, struct wbsrv_listen_socket
);
259 if (!listen_socket
) goto nomem
;
260 listen_socket
->socket_path
261 = service
->priv_socket_path
262 = talloc_asprintf(listen_socket
, "%s/%s",
263 lp_winbindd_privileged_socket_directory(task
->lp_ctx
),
264 WINBINDD_SAMBA3_SOCKET
);
265 if (!listen_socket
->socket_path
) goto nomem
;
266 if (!listen_socket
->socket_path
) goto nomem
;
267 listen_socket
->service
= service
;
268 listen_socket
->privileged
= true;
269 status
= stream_setup_socket(task
->event_ctx
, task
->lp_ctx
, model_ops
,
271 listen_socket
->socket_path
, &port
,
272 lp_socket_options(task
->lp_ctx
),
274 if (!NT_STATUS_IS_OK(status
)) goto listen_failed
;
276 status
= wbsrv_init_irpc(service
);
277 if (!NT_STATUS_IS_OK(status
)) goto irpc_failed
;
282 DEBUG(0,("stream_setup_socket(path=%s) failed - %s\n",
283 listen_socket
->socket_path
, nt_errstr(status
)));
284 task_server_terminate(task
, nt_errstr(status
), true);
287 DEBUG(0,("wbsrv_init_irpc() failed - %s\n",
289 task_server_terminate(task
, nt_errstr(status
), true);
292 task_server_terminate(task
, nt_errstr(NT_STATUS_NO_MEMORY
), true);
297 register ourselves as a available server
299 NTSTATUS
server_service_winbind_init(void)
301 return register_server_service("winbind", winbind_task_init
);