s4-winbind: Migrated winbind connection to tsocket.
[Samba/nascimento.git] / source4 / winbind / wb_server.c
blobfdf8deaa2c0e3c9542deec34a0ceba71dac99c6e
1 /*
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/>.
22 #include "includes.h"
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;
40 NTSTATUS status;
42 call = talloc_zero(wbsrv_conn, struct wbsrv_samba3_call);
43 if (call == NULL) {
44 wbsrv_terminate_connection(wbsrv_conn, "wbsrv_call_loop: "
45 "no memory for wbsrv_samba3_call");
46 return;
48 call->wbconn = wbsrv_conn;
50 status = tstream_read_pdu_blob_recv(subreq,
51 call,
52 &call->in);
53 TALLOC_FREE(subreq);
54 if (!NT_STATUS_IS_OK(status)) {
55 const char *reason;
57 reason = talloc_asprintf(call, "wbsrv_call_loop: "
58 "tstream_read_pdu_blob_recv() - %s",
59 nt_errstr(status));
60 if (!reason) {
61 reason = nt_errstr(status);
64 wbsrv_terminate_connection(wbsrv_conn, reason);
65 return;
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)) {
74 const char *reason;
76 reason = talloc_asprintf(call, "wbsrv_call_loop: "
77 "tstream_read_pdu_blob_recv() - %s",
78 nt_errstr(status));
79 if (!reason) {
80 reason = nt_errstr(status);
83 wbsrv_terminate_connection(wbsrv_conn, reason);
84 return;
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,
93 wbsrv_conn->tstream,
94 4, /* initial_read_size */
95 wbsrv_samba3_packet_full_request,
96 wbsrv_conn);
97 if (subreq == NULL) {
98 wbsrv_terminate_connection(wbsrv_conn, "wbsrv_call_loop: "
99 "no memory for tstream_read_pdu_blob_send");
100 return;
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;
111 int rc;
113 wbsrv_conn = talloc_zero(conn, struct wbsrv_connection);
114 if (wbsrv_conn == NULL) {
115 stream_terminate_connection(conn, "wbsrv_accept: out of memory");
116 return;
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");
123 return;
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);
131 if (rc < 0) {
132 stream_terminate_connection(conn,
133 "wbsrv_accept: out of memory");
134 return;
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,
148 wbsrv_conn->tstream,
149 4, /* initial_read_size */
150 wbsrv_samba3_packet_full_request,
151 wbsrv_conn);
152 if (subreq == NULL) {
153 wbsrv_terminate_connection(wbsrv_conn, "wbsrv_accept: "
154 "no memory for tstream_read_pdu_blob_send");
155 return;
157 tevent_req_set_callback(subreq, wbsrv_call_loop, wbsrv_conn);
161 called on a tcp recv
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)
193 uint16_t port = 1;
194 const struct model_ops *model_ops;
195 NTSTATUS status;
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");
205 if (!model_ops) {
206 task_server_terminate(task,
207 "Can't find 'single' process model_ops", true);
208 return;
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);
215 return;
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);
222 return;
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);
232 return;
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);
238 return;
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,
251 &wbsrv_ops, "unix",
252 listen_socket->socket_path, &port,
253 lp_socket_options(task->lp_ctx),
254 listen_socket);
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,
270 &wbsrv_ops, "unix",
271 listen_socket->socket_path, &port,
272 lp_socket_options(task->lp_ctx),
273 listen_socket);
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;
279 return;
281 listen_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);
285 return;
286 irpc_failed:
287 DEBUG(0,("wbsrv_init_irpc() failed - %s\n",
288 nt_errstr(status)));
289 task_server_terminate(task, nt_errstr(status), true);
290 return;
291 nomem:
292 task_server_terminate(task, nt_errstr(NT_STATUS_NO_MEMORY), true);
293 return;
297 register ourselves as a available server
299 NTSTATUS server_service_winbind_init(void)
301 return register_server_service("winbind", winbind_task_init);