5dd26f708122e1f4cb34435e001170f5d62a5436
[tridge/samba.git] / file_server / file_server.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    run s3 file server within Samba4
5
6    Copyright (C) Andrew Tridgell        2011
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 "source3/include/includes.h"
23
24 /* we use the full source3/source4 prefixes as this code mixes the two
25    sets of header pathsx */
26 #include "source3/smbd/globals.h"
27 #include "source3/smbd/proto.h"
28 #include "source3/include/memcache.h"
29 #include "source3/include/passdb.h"
30 #include "source3/include/secrets.h"
31 #include "source3/locking/proto.h"
32 #include "source3/include/messages.h"
33 #include "source3/include/serverid.h"
34 #include "source3/printing/printer_list.h"
35 #include "source3/registry/reg_init_full.h"
36 #include "source3/include/printing.h"
37 #include "source3/include/auth.h"
38 #include "rpc_server/rpc_service_setup.h"
39 #include "source4/smbd/service_stream.h"
40 #include "lib/param/param.h"
41 #include "source4/lib/socket/socket.h"
42 #include "source4/smbd/service.h"
43 #include "source4/smbd/process_model.h"
44 #include "source4/lib/socket/netif.h"
45 #include "libcli/auth/schannel.h"
46 #include "file_server/file_server.h"
47
48
49 /*
50   this runs through the initialisation that the samba3 file server
51   normally does. It is derived from main() in source3/smbd/server.c
52  */
53 static int s3fs_server_init(struct loadparm_context *lp_ctx)
54 {
55         uint64_t unique_id;
56         NTSTATUS status;
57         struct tevent_context *ev_ctx;
58         struct messaging_context *msg_ctx;
59
60         /* create a stackframe for the file server child */
61         talloc_stackframe();
62
63         smbd_init_globals();
64
65         TimeInit();
66
67         set_remote_machine_name("smbd", False);
68
69         /* get initial effective uid and gid */
70         sec_init();
71
72         lp_set_cmdline("config file", lpcfg_configfile(lp_ctx));
73         lp_set_cmdline("auth methods", "guest samba4");
74         lp_set_cmdline("passdb backend", "samba4");
75         lp_set_cmdline("rpc_server:lsarpc", "external");
76         lp_set_cmdline("rpc_server:netlogon", "external");
77         lp_set_cmdline("rpc_server:samr", "external");
78
79         if (!lp_load_initial_only(lpcfg_configfile(lp_ctx))) {
80                 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
81                 return -1;
82         }
83
84         /* Init the security context and global current_user */
85         init_sec_ctx();
86
87         /*
88          * Initialize the event context. The event context needs to be
89          * initialized before the messaging context, cause the messaging
90          * context holds an event context.
91          * FIXME: This should be s3_tevent_context_init()
92          */
93         ev_ctx = server_event_context();
94         if (ev_ctx == NULL) {
95                 DEBUG(0, ("Failed to get server event context"));
96                 return -1;
97         }
98
99         /*
100          * Init the messaging context
101          * FIXME: This should only call messaging_init()
102          */
103         msg_ctx = server_messaging_context();
104         if (msg_ctx == NULL) {
105                 DEBUG(0, ("Failed to get server messaging context"));
106                 return -1;
107         }
108
109         /*
110          * Reloading of the printers will not work here as we don't have a
111          * server info and rpc services set up. It will be called later.
112          */
113         if (!reload_services(NULL, -1, False)) {
114                 DEBUG(0, ("Failed to reload smb.conf"));
115                 return -1;
116         }
117
118         /* ...NOTE... Log files are working from this point! */
119
120         generate_random_buffer((uint8_t *)&unique_id, sizeof(unique_id));
121         set_my_unique_id(unique_id);
122
123         status = reinit_after_fork(msg_ctx,
124                                    ev_ctx,
125                                    procid_self(), false);
126         if (!NT_STATUS_IS_OK(status)) {
127                 DEBUG(0,("reinit_after_fork() failed\n"));
128                 return -1;
129         }
130
131         smbd_server_conn->msg_ctx = msg_ctx;
132
133         smbd_setup_sig_term_handler();
134         smbd_setup_sig_hup_handler(ev_ctx,
135                                    msg_ctx);
136
137         /* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */
138
139         if (smbd_memcache() == NULL) {
140                 DEBUG(0, ("Failed to init smbd memcache"));
141                 return -1;
142         }
143
144         memcache_set_global(smbd_memcache());
145
146         /* Initialise the password backed before the global_sam_sid
147            to ensure that we fetch from ldap before we make a domain sid up */
148
149         if(!initialize_password_db(false, ev_ctx)) {
150                 DEBUG(0, ("Failed to init passdb backends"));
151                 return -1;
152         }
153
154         if (!secrets_init()) {
155                 DEBUG(0, ("ERROR: smbd can not open secrets.tdb\n"));
156                 return -1;
157         }
158
159         if (lp_server_role() == ROLE_DOMAIN_BDC || lp_server_role() == ROLE_DOMAIN_PDC) {
160                 if (!open_schannel_session_store(NULL, lp_ctx)) {
161                         DEBUG(0,("ERROR: Samba cannot open schannel store for secured NETLOGON operations.\n"));
162                         return -1;
163                 }
164         }
165
166         if(!get_global_sam_sid()) {
167                 DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n"));
168                 return -1;
169         }
170
171         if (!sessionid_init()) {
172                 DEBUG(0, ("Failed to init sessionid database"));
173                 return -1;
174         }
175
176         if (!connections_init(True)) {
177                 DEBUG(0, ("Failed to init connections database"));
178                 return -1;
179         }
180
181         if (!locking_init()) {
182                 DEBUG(0, ("Failed to init locking database"));
183                 return -1;
184         }
185         if (!messaging_tdb_parent_init(ev_ctx)) {
186                 DEBUG(0, ("Failed to init messaging tdb as parent task"));
187                 return -1;
188         }
189
190         if (!notify_internal_parent_init(ev_ctx)) {
191                 DEBUG(0, ("Failed to init notify db as parent task"));
192                 return -1;
193         }
194
195         if (!serverid_parent_init(ev_ctx)) {
196                 return -1;
197         }
198
199         if (!W_ERROR_IS_OK(registry_init_full())) {
200                 DEBUG(0, ("Failed to init registry"));
201                 return -1;
202         }
203
204         /* Open the share_info.tdb here, so we don't have to open
205            after the fork on every single connection.  This is a small
206            performance improvment and reduces the total number of system
207            fds used. */
208         if (!share_info_db_init()) {
209                 DEBUG(0,("ERROR: failed to load share info db.\n"));
210                 return -1;
211         }
212
213         status = init_system_info();
214         if (!NT_STATUS_IS_OK(status)) {
215                 DEBUG(1, ("ERROR: failed to setup system user info: %s.\n",
216                           nt_errstr(status)));
217                 return -1;
218         }
219
220         if (!init_guest_info()) {
221                 DEBUG(0,("ERROR: failed to setup guest info.\n"));
222                 return -1;
223         }
224
225         if (!file_init(smbd_server_conn)) {
226                 DEBUG(0, ("ERROR: file_init failed\n"));
227                 return -1;
228         }
229
230         if (!dcesrv_ep_setup(ev_ctx, msg_ctx)) {
231                 DEBUG(0, ("Failed to init dcerpc endpoints"));
232                 return -1;
233         }
234
235         init_names();
236
237
238         return 0;
239 }
240
241 /*
242   initialise a server_context from a open socket and register a event handler
243   for reading from that socket
244 */
245 static void s3fs_smb_accept(struct stream_connection *conn)
246 {
247         if (lpcfg_parm_bool(conn->lp_ctx, NULL, "s3fs", "gdb", false)) {
248                 samba_start_debugger();
249                 sleep(2);
250         }
251         DEBUG(0,(__location__ ": new s3fs smbd connection\n"));
252
253         if (s3fs_server_init(conn->lp_ctx) != 0) {
254                 DEBUG(0,("Failed to initialise s3fs backend\n"));
255                 exit(1);
256         }
257
258         smbd_server_conn->sock = socket_get_fd(conn->socket);
259
260         if (!serverid_register(procid_self(),
261                                FLAG_MSG_GENERAL|FLAG_MSG_SMBD
262                                |FLAG_MSG_DBWRAP
263                                |FLAG_MSG_PRINT_GENERAL)) {
264                 exit_server_cleanly("Could not register myself in "
265                                     "serverid.tdb");
266         }
267
268         smbd_process(server_event_context(), smbd_server_conn);
269         exit(1);
270 }
271
272 static const struct stream_server_ops s3fs_smb_stream_ops = {
273         .name                   = "s3fs",
274         .accept_connection      = s3fs_smb_accept,
275 };
276
277 /*
278   setup a listening socket on all the SMB ports for a particular address
279 */
280 static NTSTATUS s3fs_add_socket(struct task_server *task,
281                                   struct tevent_context *event_context,
282                                   struct loadparm_context *lp_ctx,
283                                   const struct model_ops *model_ops,
284                                   const char *address)
285 {
286         const char **ports = lpcfg_smb_ports(lp_ctx);
287         int i;
288         NTSTATUS status;
289
290         for (i=0;ports[i];i++) {
291                 uint16_t port = atoi(ports[i]);
292                 if (port == 0) continue;
293                 status = stream_setup_socket(task, event_context, lp_ctx,
294                                              model_ops, &s3fs_smb_stream_ops,
295                                              "ip", address, &port,
296                                              lpcfg_socket_options(lp_ctx),
297                                              NULL);
298                 NT_STATUS_NOT_OK_RETURN(status);
299         }
300
301         return NT_STATUS_OK;
302 }
303
304 /*
305   open the s3 smb server sockets
306 */
307 static void s3fs_task_init(struct task_server *task)
308 {
309         NTSTATUS status;
310         const struct model_ops *model_ops;
311
312         model_ops = process_model_startup("standard");
313
314         if (model_ops == NULL) {
315                 goto failed;
316         }
317
318         task_server_set_title(task, "task[s3fs_parent]");
319
320         if (lpcfg_interfaces(task->lp_ctx) && lpcfg_bind_interfaces_only(task->lp_ctx)) {
321                 int num_interfaces;
322                 int i;
323                 struct interface *ifaces;
324
325                 load_interface_list(task, task->lp_ctx, &ifaces);
326
327                 num_interfaces = iface_list_count(ifaces);
328
329                 /* We have been given an interfaces line, and been
330                    told to only bind to those interfaces. Create a
331                    socket per interface and bind to only these.
332                 */
333                 for(i = 0; i < num_interfaces; i++) {
334                         const char *address = iface_list_n_ip(ifaces, i);
335                         status = s3fs_add_socket(task, task->event_ctx, task->lp_ctx, model_ops, address);
336                         if (!NT_STATUS_IS_OK(status)) goto failed;
337                 }
338         } else {
339                 const char **wcard;
340                 int i;
341                 wcard = iface_list_wildcard(task, task->lp_ctx);
342                 if (wcard == NULL) {
343                         DEBUG(0,("No wildcard addresses available\n"));
344                         goto failed;
345                 }
346                 for (i=0; wcard[i]; i++) {
347                         status = s3fs_add_socket(task, task->event_ctx, task->lp_ctx, model_ops, wcard[i]);
348                         if (!NT_STATUS_IS_OK(status)) goto failed;
349                 }
350                 talloc_free(wcard);
351         }
352
353         return;
354 failed:
355         task_server_terminate(task, "Failed to startup s3fs smb task", true);
356 }
357
358 /* called at smbd startup - register ourselves as a server service */
359 NTSTATUS server_service_s3fs_init(void);
360
361 NTSTATUS server_service_s3fs_init(void)
362 {
363         return register_server_service("s3fs", s3fs_task_init);
364 }