s4: ran minimal_includes.pl on source4/winbind
[kai/samba.git] / source4 / winbind / wb_server.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Main winbindd server routines
4
5    Copyright (C) Stefan Metzmacher      2005
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 "smbd/process_model.h"
24 #include "winbind/wb_server.h"
25 #include "lib/stream/packet.h"
26 #include "param/param.h"
27
28 void wbsrv_terminate_connection(struct wbsrv_connection *wbconn, const char *reason)
29 {
30         stream_terminate_connection(wbconn->conn, reason);
31 }
32
33 /*
34   called on a tcp recv error
35 */
36 static void wbsrv_recv_error(void *private_data, NTSTATUS status)
37 {
38         struct wbsrv_connection *wbconn = talloc_get_type(private_data, struct wbsrv_connection);
39         wbsrv_terminate_connection(wbconn, nt_errstr(status));
40 }
41
42 static void wbsrv_accept(struct stream_connection *conn)
43 {
44         struct wbsrv_listen_socket *listen_socket = talloc_get_type(conn->private_data,
45                                                                     struct wbsrv_listen_socket);
46         struct wbsrv_connection *wbconn;
47
48         wbconn = talloc_zero(conn, struct wbsrv_connection);
49         if (!wbconn) {
50                 stream_terminate_connection(conn, "wbsrv_accept: out of memory");
51                 return;
52         }
53         wbconn->conn          = conn;
54         wbconn->listen_socket = listen_socket;
55         wbconn->lp_ctx        = listen_socket->service->task->lp_ctx;
56         conn->private_data    = wbconn;
57
58         wbconn->packet = packet_init(wbconn);
59         if (wbconn->packet == NULL) {
60                 wbsrv_terminate_connection(wbconn, "wbsrv_accept: out of memory");
61                 return;
62         }
63         packet_set_private(wbconn->packet, wbconn);
64         packet_set_socket(wbconn->packet, conn->socket);
65         packet_set_callback(wbconn->packet, wbsrv_samba3_process);
66         packet_set_full_request(wbconn->packet, wbsrv_samba3_packet_full_request);
67         packet_set_error_handler(wbconn->packet, wbsrv_recv_error);
68         packet_set_event_context(wbconn->packet, conn->event.ctx);
69         packet_set_fde(wbconn->packet, conn->event.fde);
70         packet_set_serialise(wbconn->packet);
71 }
72
73 /*
74   receive some data on a winbind connection
75 */
76 static void wbsrv_recv(struct stream_connection *conn, uint16_t flags)
77 {
78         struct wbsrv_connection *wbconn = talloc_get_type(conn->private_data,
79                                                           struct wbsrv_connection);
80         packet_recv(wbconn->packet);
81
82 }
83
84 /*
85   called when we can write to a connection
86 */
87 static void wbsrv_send(struct stream_connection *conn, uint16_t flags)
88 {
89         struct wbsrv_connection *wbconn = talloc_get_type(conn->private_data,
90                                                           struct wbsrv_connection);
91         packet_queue_run(wbconn->packet);
92 }
93
94 static const struct stream_server_ops wbsrv_ops = {
95         .name                   = "winbind samba3 protocol",
96         .accept_connection      = wbsrv_accept,
97         .recv_handler           = wbsrv_recv,
98         .send_handler           = wbsrv_send
99 };
100
101 /*
102   startup the winbind task
103 */
104 static void winbind_task_init(struct task_server *task)
105 {
106         uint16_t port = 1;
107         const struct model_ops *model_ops;
108         NTSTATUS status;
109         struct wbsrv_service *service;
110         struct wbsrv_listen_socket *listen_socket;
111
112         task_server_set_title(task, "task[winbind]");
113
114         /* within the winbind task we want to be a single process, so
115            ask for the single process model ops and pass these to the
116            stream_setup_socket() call. */
117         model_ops = process_model_startup(task->event_ctx, "single");
118         if (!model_ops) {
119                 task_server_terminate(task,
120                                       "Can't find 'single' process model_ops", true);
121                 return;
122         }
123
124         /* Make sure the directory for the Samba3 socket exists, and is of the correct permissions */
125         if (!directory_create_or_exist(lp_winbindd_socket_directory(task->lp_ctx), geteuid(), 0755)) {
126                 task_server_terminate(task,
127                                       "Cannot create winbindd pipe directory", true);
128                 return;
129         }
130
131         /* Make sure the directory for the Samba3 socket exists, and is of the correct permissions */
132         if (!directory_create_or_exist(lp_winbindd_privileged_socket_directory(task->lp_ctx), geteuid(), 0750)) {
133                 task_server_terminate(task,
134                                       "Cannot create winbindd privileged pipe directory", true);
135                 return;
136         }
137
138         service = talloc_zero(task, struct wbsrv_service);
139         if (!service) goto nomem;
140         service->task   = task;
141
142         status = wbsrv_setup_domains(service);
143         if (!NT_STATUS_IS_OK(status)) {
144                 task_server_terminate(task, nt_errstr(status), true);
145                 return;
146         }
147
148         service->idmap_ctx = idmap_init(service, task->event_ctx, task->lp_ctx);
149         if (service->idmap_ctx == NULL) {
150                 task_server_terminate(task, "Failed to load idmap database", true);
151                 return;
152         }
153
154         /* setup the unprivileged samba3 socket */
155         listen_socket = talloc(service, struct wbsrv_listen_socket);
156         if (!listen_socket) goto nomem;
157         listen_socket->socket_path      = talloc_asprintf(listen_socket, "%s/%s", 
158                                                           lp_winbindd_socket_directory(task->lp_ctx), 
159                                                           WINBINDD_SAMBA3_SOCKET);
160         if (!listen_socket->socket_path) goto nomem;
161         listen_socket->service          = service;
162         listen_socket->privileged       = false;
163         status = stream_setup_socket(task->event_ctx, task->lp_ctx, model_ops,
164                                      &wbsrv_ops, "unix",
165                                      listen_socket->socket_path, &port,
166                                      lp_socket_options(task->lp_ctx), 
167                                      listen_socket);
168         if (!NT_STATUS_IS_OK(status)) goto listen_failed;
169
170         /* setup the privileged samba3 socket */
171         listen_socket = talloc(service, struct wbsrv_listen_socket);
172         if (!listen_socket) goto nomem;
173         listen_socket->socket_path 
174                 = service->priv_socket_path 
175                 = talloc_asprintf(listen_socket, "%s/%s", 
176                                                           lp_winbindd_privileged_socket_directory(task->lp_ctx), 
177                                                           WINBINDD_SAMBA3_SOCKET);
178         if (!listen_socket->socket_path) goto nomem;
179         if (!listen_socket->socket_path) goto nomem;
180         listen_socket->service          = service;
181         listen_socket->privileged       = true;
182         status = stream_setup_socket(task->event_ctx, task->lp_ctx, model_ops,
183                                      &wbsrv_ops, "unix",
184                                      listen_socket->socket_path, &port,
185                                      lp_socket_options(task->lp_ctx), 
186                                      listen_socket);
187         if (!NT_STATUS_IS_OK(status)) goto listen_failed;
188
189         status = wbsrv_init_irpc(service);
190         if (!NT_STATUS_IS_OK(status)) goto irpc_failed;
191
192         return;
193
194 listen_failed:
195         DEBUG(0,("stream_setup_socket(path=%s) failed - %s\n",
196                  listen_socket->socket_path, nt_errstr(status)));
197         task_server_terminate(task, nt_errstr(status), true);
198         return;
199 irpc_failed:
200         DEBUG(0,("wbsrv_init_irpc() failed - %s\n",
201                  nt_errstr(status)));
202         task_server_terminate(task, nt_errstr(status), true);
203         return;
204 nomem:
205         task_server_terminate(task, nt_errstr(NT_STATUS_NO_MEMORY), true);
206         return;
207 }
208
209 /*
210   register ourselves as a available server
211 */
212 NTSTATUS server_service_winbind_init(void)
213 {
214         return register_server_service("winbind", winbind_task_init);
215 }