TODO witnessd
authorStefan Metzmacher <metze@samba.org>
Sun, 4 Nov 2012 16:16:21 +0000 (17:16 +0100)
committerStefan Metzmacher <metze@samba.org>
Mon, 19 Jan 2015 23:33:16 +0000 (00:33 +0100)
source3/rpc_server/mgmt/srv_mgmt.c [new file with mode: 0644]
source3/rpc_server/witness/srv_witness.c [new file with mode: 0644]
source3/rpc_server/witness/srv_witness.h [new file with mode: 0644]
source3/rpc_server/witnessd.c [new file with mode: 0644]
source3/rpc_server/wscript_build
source3/smbd/server.c
source3/wscript_build

diff --git a/source3/rpc_server/mgmt/srv_mgmt.c b/source3/rpc_server/mgmt/srv_mgmt.c
new file mode 100644 (file)
index 0000000..3f87e6e
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Copyright (C) 2012 Stefan Metzmacher
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "ntdomain.h"
+#include "../libcli/security/security.h"
+#include "../lib/tsocket/tsocket.h"
+#include "librpc/gen_ndr/srv_mgmt.h"
+#include "auth.h"
+
+bool srv_mgmt_delete_endpoints(struct pipes_struct *p)
+{
+       return true;
+}
+
+void srv_mgmt_cleanup(void)
+{
+}
+
+WERROR _mgmt_inq_if_ids(struct pipes_struct *p,
+                      struct mgmt_inq_if_ids *r)
+{
+       //const struct dcesrv_endpoint *ep = dce_call->conn->endpoint;
+       //struct dcesrv_if_list *l;
+       struct rpc_if_id_vector_t *vector;
+
+       vector = *r->out.if_id_vector = talloc(p->mem_ctx, struct rpc_if_id_vector_t);
+       vector->count = 0;
+       vector->if_id = NULL;
+#if 0
+       for (l = ep->interface_list; l; l = l->next) {
+               vector->count++;
+               vector->if_id = talloc_realloc(mem_ctx, vector->if_id, struct ndr_syntax_id_p, vector->count);
+               vector->if_id[vector->count-1].id = &l->iface.syntax_id;
+       }
+#endif
+       return WERR_OK;
+}
+
+
+/*
+  mgmt_inq_stats
+*/
+WERROR _mgmt_inq_stats(struct pipes_struct *p,
+                      struct mgmt_inq_stats *r)
+{
+       if (r->in.max_count != MGMT_STATS_ARRAY_MAX_SIZE)
+               return WERR_NOT_SUPPORTED;
+
+       r->out.statistics->count = r->in.max_count;
+       r->out.statistics->statistics = talloc_array(p->mem_ctx, uint32_t, r->in.max_count);
+       /* FIXME */
+       r->out.statistics->statistics[MGMT_STATS_CALLS_IN] = 0;
+       r->out.statistics->statistics[MGMT_STATS_CALLS_OUT] = 0;
+       r->out.statistics->statistics[MGMT_STATS_PKTS_IN] = 0;
+       r->out.statistics->statistics[MGMT_STATS_PKTS_OUT] = 0;
+
+       return WERR_OK;
+}
+
+
+/*
+  mgmt_is_server_listening
+*/
+uint32_t _mgmt_is_server_listening(struct pipes_struct *p,
+                      struct mgmt_is_server_listening *r)
+{
+       *r->out.status = 0;
+       return 1;
+}
+
+/*
+  mgmt_stop_server_listening
+*/
+WERROR _mgmt_stop_server_listening(struct pipes_struct *p,
+                      struct mgmt_stop_server_listening *r)
+{
+       return WERR_ACCESS_DENIED;
+}
+
+
+/*
+  mgmt_inq_princ_name
+*/
+WERROR _mgmt_inq_princ_name(struct pipes_struct *p,
+                      struct mgmt_inq_princ_name *r)
+{
+       snprintf(r->out.princ_name, r->in.princ_name_size, "cifs/%s",
+                lp_netbios_name());
+       DEBUG(0,("_mgmt_inq_princ_name[%s]\n", r->out.princ_name));
+       return WERR_OK;
+}
diff --git a/source3/rpc_server/witness/srv_witness.c b/source3/rpc_server/witness/srv_witness.c
new file mode 100644 (file)
index 0000000..0e47118
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Copyright (C) 2012 Stefan Metzmacher
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "ntdomain.h"
+#include "../libcli/security/security.h"
+#include "../lib/tsocket/tsocket.h"
+#include "librpc/gen_ndr/srv_witness.h"
+#include "srv_witness.h"
+#include "auth.h"
+
+bool srv_witness_delete_endpoints(struct pipes_struct *p)
+{
+       return true;
+}
+
+void srv_witness_cleanup(void)
+{
+}
+/*
+       typedef struct {
+               [charset(UTF16),to_null] uint16 group_name[260];
+               uint32 version;
+               uint16 state;
+               ipv4address ipv4;
+               ipv6address ipv6;
+               uint32 flags;
+       } witness_interfaceInfo;
+
+       typedef struct {
+               uint32 num_interfaces;
+               [size_is(num_interfaces)] witness_interfaceInfo *interfaces;
+       } witness_interfaceList;
+*/
+static const char * const ifaces[] = {
+       "172.31.91.173",
+       "172.31.91.174",
+       "172.31.91.175",
+};
+static uint32_t ifaces_idx;
+
+WERROR _witness_GetInterfaceList(struct pipes_struct *p,
+                                struct witness_GetInterfaceList *r)
+{
+       struct witness_interfaceList *list;
+       struct witness_interfaceInfo *infos;
+       uint32_t i;
+       uint32_t n = ARRAY_SIZE(ifaces);
+
+       list = talloc_zero(p->mem_ctx, struct witness_interfaceList);
+       if (list == NULL) {
+               return WERR_NOMEM;
+       }
+
+       infos = talloc_zero_array(list, struct witness_interfaceInfo, n);
+       if (infos == NULL) {
+               return WERR_NOMEM;
+       }
+
+       list->num_interfaces = n;
+       list->interfaces = infos;
+
+       for (i=0; i < n; i++) {
+               struct witness_interfaceInfo *info = &infos[i];
+
+               info->group_name = talloc_strdup(infos, "\\\\fedora14.vm.base");
+               info->version = 0x00010001;
+               info->state = 0x0001;
+               info->ipv4 = ifaces[i];
+               info->flags |= 0x00000001;
+               info->ipv6 = "::";
+               info->flags |= 0x00000004;
+       }
+
+       *r->out.interface_list = list;
+       return WERR_OK;
+}
+
+WERROR _witness_Register(struct pipes_struct *p,
+                        struct witness_Register *r)
+{
+       bool ok;
+
+       if (r->in.version != 0x00010001) {
+               return WERR_REVISION_MISMATCH;
+       }
+
+       ok = create_policy_hnd(p, r->out.context_handle, NULL);
+       if (!ok) {
+               return WERR_NO_SYSTEM_RESOURCES;
+       }
+
+       return WERR_OK;
+}
+
+WERROR _witness_RegisterEx(struct pipes_struct *p,
+                          struct witness_RegisterEx *r)
+{
+       return WERR_NOT_SUPPORTED; //???
+}
+
+WERROR _witness_UnRegister(struct pipes_struct *p,
+                          struct witness_UnRegister *r)
+{
+       bool ok;
+
+       ok = close_policy_hnd(p, &r->in.context_handle);
+       if (!ok) {
+               return WERR_NOT_FOUND;
+       }
+
+       return WERR_OK;
+}
+
+WERROR _witness_AsyncNotify(struct pipes_struct *p,
+                           struct witness_AsyncNotify *r)
+{
+       bool ok;
+       struct witness_notifyResponse *response = NULL;
+       DATA_BLOB blob = data_blob_null;
+       uint8_t msg[0x24];
+       uint32_t addr;
+
+       ok = find_policy_by_hnd(p, &r->in.context_handle, NULL);
+       if (!ok) {
+               return WERR_NOT_FOUND;
+       }
+
+       // HACK to avoid client loop...
+       // TODO => async response...
+       smb_msleep(15000);
+
+       addr = inet_addr(ifaces[ifaces_idx]);
+       ifaces_idx += 1;
+       if (ifaces_idx == ARRAY_SIZE(ifaces)) {
+               ifaces_idx = 0;
+       }
+
+       response = talloc_zero(p->mem_ctx, struct witness_notifyResponse);
+       if (response == NULL) {
+               return WERR_NOMEM;
+       }
+
+       SIVAL(msg, 0x00, sizeof(msg));
+       SIVAL(msg, 0x04, 0);
+       SIVAL(msg, 0x08, 1);
+
+       SIVAL(msg, 0x0C, 0x00000001);
+       RSIVAL(msg,0x10, htonl(addr));
+       SBVAL(msg, 0x14, 0);
+       SBVAL(msg, 0x1C, 0);
+
+       blob = data_blob_talloc(response, msg, sizeof(msg));
+       if (blob.data == NULL) {
+               return WERR_NOMEM;
+       }
+
+       response->message_type = 0x00000002;
+       response->num_messages = 1;
+       response->message_buffer = blob.data;
+       response->length = blob.length;
+
+       *r->out.response = response;
+       return WERR_OK;
+}
diff --git a/source3/rpc_server/witness/srv_witness.h b/source3/rpc_server/witness/srv_witness.h
new file mode 100644 (file)
index 0000000..dddb27f
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Unix SMB/CIFS implementation.
+ *
+ * Copyright (C) 2012 Stefan Metzmacher
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _SRV_WITNESS_H_
+#define _SRV_WITNESS_H_
+
+/**
+ * @brief Cleanup memory and other stuff.
+ */
+void srv_witness_cleanup(void);
+
+bool srv_witness_delete_endpoints(struct pipes_struct *p);
+
+#endif /*_SRV_WITNESS_H_ */
diff --git a/source3/rpc_server/witnessd.c b/source3/rpc_server/witnessd.c
new file mode 100644 (file)
index 0000000..0b2a67c
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ *  Unix SMB/CIFS implementation.
+ *
+ *  SMBD RPC service callbacks
+ *
+ *  Copyright (c) 2011      Andreas Schneider <asn@samba.org>
+ *  Copyright (c) 2012      Stefan Metzmacher <metze@samba.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+
+#include "serverid.h"
+#include "ntdomain.h"
+#include "messages.h"
+
+#include "librpc/rpc/dcerpc_ep.h"
+#include "../librpc/gen_ndr/srv_mgmt.h"
+#include "../librpc/gen_ndr/srv_witness.h"
+#include "rpc_server/rpc_server.h"
+#include "rpc_server/rpc_sock_helper.h"
+#include "rpc_server/rpc_ep_register.h"
+#include "rpc_server/witness/srv_witness.h"
+
+#define DAEMON_NAME "witnessd"
+
+void start_witnessd(struct tevent_context *ev_ctx,
+                   struct messaging_context *msg_ctx);
+
+static void witnessd_reopen_logs(void)
+{
+       char *lfile = lp_logfile(talloc_tos());
+       int rc;
+
+       if (lfile == NULL || lfile[0] == '\0') {
+               rc = asprintf(&lfile, "%s/log.%s", get_dyn_LOGFILEBASE(), DAEMON_NAME);
+               if (rc > 0) {
+                       lp_set_logfile(lfile);
+                       SAFE_FREE(lfile);
+               }
+       } else {
+               if (strstr(lfile, DAEMON_NAME) == NULL) {
+                       rc = asprintf(&lfile, "%s.%s",
+                                     lp_logfile(talloc_tos()), DAEMON_NAME);
+                       if (rc > 0) {
+                               lp_set_logfile(lfile);
+                               SAFE_FREE(lfile);
+                       }
+               }
+       }
+
+       reopen_logs();
+}
+
+static void witnessd_smb_conf_updated(struct messaging_context *msg,
+                                 void *private_data,
+                                 uint32_t msg_type,
+                                 struct server_id server_id,
+                                 DATA_BLOB *data)
+{
+       DEBUG(10, ("Got message saying smb.conf was updated. Reloading.\n"));
+       change_to_root_user();
+       witnessd_reopen_logs();
+}
+
+static void witnessd_sig_term_handler(struct tevent_context *ev,
+                                 struct tevent_signal *se,
+                                 int signum,
+                                 int count,
+                                 void *siginfo,
+                                 void *private_data)
+{
+       rpc_witness_shutdown();
+
+       exit_server_cleanly("termination signal");
+}
+
+static void witnessd_setup_sig_term_handler(struct tevent_context *ev_ctx)
+{
+       struct tevent_signal *se;
+
+       se = tevent_add_signal(ev_ctx,
+                              ev_ctx,
+                              SIGTERM, 0,
+                              witnessd_sig_term_handler,
+                              NULL);
+       if (se == NULL) {
+               exit_server("failed to setup SIGTERM handler");
+       }
+}
+
+static void witnessd_sig_hup_handler(struct tevent_context *ev,
+                                   struct tevent_signal *se,
+                                   int signum,
+                                   int count,
+                                   void *siginfo,
+                                   void *private_data)
+{
+       change_to_root_user();
+
+       DEBUG(1,("Reloading printers after SIGHUP\n"));
+       witnessd_reopen_logs();
+}
+
+static void witnessd_setup_sig_hup_handler(struct tevent_context *ev_ctx,
+                                      struct messaging_context *msg_ctx)
+{
+       struct tevent_signal *se;
+
+       se = tevent_add_signal(ev_ctx,
+                              ev_ctx,
+                              SIGHUP, 0,
+                              witnessd_sig_hup_handler,
+                              msg_ctx);
+       if (se == NULL) {
+               exit_server("failed to setup SIGHUP handler");
+       }
+}
+
+static bool witness_shutdown_cb(void *ptr) {
+       srv_witness_cleanup();
+
+       return true;
+}
+
+void start_witnessd(struct tevent_context *ev_ctx,
+                   struct messaging_context *msg_ctx)
+{
+       struct rpc_srv_callbacks mgmt_cb;
+       struct rpc_srv_callbacks witness_cb;
+       NTSTATUS status;
+       pid_t pid;
+       bool ok;
+       int rc;
+       struct dcerpc_binding_vector *bvec = NULL;
+
+       ZERO_STRUCT(mgmt_cb);
+       ZERO_STRUCT(witness_cb);
+
+       witness_cb.init = NULL;
+       witness_cb.shutdown = witness_shutdown_cb;
+       witness_cb.private_data = NULL;
+
+       DEBUG(1, ("Forking SMB Witness Daemon\n"));
+
+       pid = fork();
+
+       if (pid == -1) {
+               DEBUG(0, ("Failed to fork Endpoint Mapper [%s], aborting ...\n",
+                         strerror(errno)));
+               exit(1);
+       }
+
+       if (pid) {
+               /* parent */
+               return;
+       }
+
+       status = reinit_after_fork(msg_ctx,
+                                  ev_ctx,
+                                  true);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("reinit_after_fork() failed\n"));
+               smb_panic("reinit_after_fork() failed");
+       }
+
+       witnessd_reopen_logs();
+
+       witnessd_setup_sig_term_handler(ev_ctx);
+       witnessd_setup_sig_hup_handler(ev_ctx, msg_ctx);
+
+       ok = serverid_register(messaging_server_id(msg_ctx),
+                              FLAG_MSG_GENERAL |
+                              FLAG_MSG_PRINT_GENERAL);
+       if (!ok) {
+               DEBUG(0, ("Failed to register serverid in witnessd!\n"));
+               exit(1);
+       }
+
+       messaging_register(msg_ctx,
+                          ev_ctx,
+                          MSG_SMB_CONF_UPDATED,
+                          witnessd_smb_conf_updated);
+
+       status = rpc_mgmt_init(&mgmt_cb);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("Failed to register mgmt rpc inteface! (%s)\n",
+                         nt_errstr(status)));
+               exit(1);
+       }
+
+       status = rpc_witness_init(&witness_cb);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("Failed to register witnessd rpc inteface! (%s)\n",
+                         nt_errstr(status)));
+               exit(1);
+       }
+
+       status = dcerpc_binding_vector_new(ev_ctx, &bvec);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("Failed to create binding vector (%s)\n",
+                         nt_errstr(status)));
+               exit(1);
+       }
+
+       status = rpc_setup_tcpip_sockets(ev_ctx,
+                                        msg_ctx,
+                                        &ndr_table_witness,
+                                        bvec,
+                                        0);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("Failed to open witnessd tcpip sockets!\n"));
+               exit(1);
+       }
+
+       status = rpc_ep_register(ev_ctx,
+                                msg_ctx,
+                                &ndr_table_witness,
+                                bvec);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("Failed to register with endpoint mapper!\n"));
+               exit(1);
+       }
+
+       DEBUG(1, ("SMB Witness Daemon Started (%d)\n", getpid()));
+
+       /* loop forever */
+       rc = tevent_loop_wait(ev_ctx);
+
+       /* should not be reached */
+       DEBUG(0,(": tevent_loop_wait() exited with %d - %s\n",
+                rc, (rc == 0) ? "out of events" : strerror(errno)));
+
+       exit(1);
+}
+
+/* vim: set ts=8 sw=8 noet cindent ft=c.doxygen: */
index 481d39c36871d1a1b98d89c3d3673c27b43c5550..b660feb069f96fb0f23952dc6f39d1e5900c4aed 100755 (executable)
@@ -37,6 +37,7 @@ bld.SAMBA3_SUBSYSTEM('RPC_SERVER',
                     RPC_SERVER_LOOP
                     RPC_CRYPTO
                     NDR_NAMED_PIPE_AUTH
+                    RPC_WITNESS RPC_MGMT
                     ''')
 
 ### RPC_SERVICES
@@ -56,6 +57,22 @@ bld.SAMBA3_SUBSYSTEM('RPC_EVENTLOG',
                     ../../librpc/gen_ndr/srv_eventlog.c''',
                     deps='LIBEVENTLOG LIBCLI_WINREG_INTERNAL')
 
+bld.SAMBA3_SUBSYSTEM('WITNESSD',
+                    source='witnessd.c',
+                    deps='samba-util')
+
+bld.SAMBA3_SUBSYSTEM('RPC_WITNESS',
+                    source='''witness/srv_witness.c
+                    ../../librpc/gen_ndr/srv_witness.c''',
+                    deps='samba-util',
+                    vars=locals())
+
+bld.SAMBA3_SUBSYSTEM('RPC_MGMT',
+                    source='''mgmt/srv_mgmt.c
+                    ../../librpc/gen_ndr/srv_mgmt.c''',
+                    deps='samba-util',
+                    vars=locals())
+
 bld.SAMBA3_SUBSYSTEM('RPC_INITSHUTDOWN',
                     source='''initshutdown/srv_initshutdown_nt.c
                     ../../librpc/gen_ndr/srv_initshutdown.c''',
index 8207bf1676f822c8649f5882351c81e7c860be45..673aeb0200dccbef2318247704e56ced9a81e9da 100644 (file)
@@ -86,6 +86,9 @@ extern void start_epmd(struct tevent_context *ev_ctx,
 extern void start_lsasd(struct tevent_context *ev_ctx,
                        struct messaging_context *msg_ctx);
 
+extern void start_witnessd(struct tevent_context *ev_ctx,
+                          struct messaging_context *msg_ctx);
+
 #ifdef WITH_DFS
 extern int dcelogin_atmost_once;
 #endif /* WITH_DFS */
@@ -1527,7 +1530,7 @@ extern void build_options(bool screen);
        }
 
        if (is_daemon && !interactive) {
-               if (rpc_epmapper_daemon() == RPC_DAEMON_FORK) {
+               if (1 || rpc_epmapper_daemon() == RPC_DAEMON_FORK) {
                        start_epmd(ev_ctx, msg_ctx);
                }
        }
@@ -1557,6 +1560,10 @@ extern void build_options(bool screen);
                                exit_daemon("Samba failed to init printing subsystem", EACCES);
                        }
                }
+
+               if (1|| rpc_daemon_type("witnessd") == RPC_DAEMON_FORK) {
+                       start_witnessd(ev_ctx, msg_ctx);
+               }
        } else if (!lp__disable_spoolss() &&
                   (rpc_spoolss_daemon() != RPC_DAEMON_DISABLED)) {
                if (!printing_subsystem_init(ev_ctx, msg_ctx, false, false)) {
index a6ef5849a447009907c254476c697f94b0ce6799..d80ecc115cb71ac78ec70b783cef2f086b94d764 100755 (executable)
@@ -850,7 +850,7 @@ bld.SAMBA3_SUBSYSTEM('LIBLSA',
 
 bld.SAMBA3_BINARY('smbd/smbd',
                  source='smbd/server.c',
-                 deps='smbd_base EPMD LSASD',
+                 deps='smbd_base EPMD LSASD WITNESSD',
                  install_path='${SBINDIR}')
 
 bld.SAMBA3_BINARY('nmbd/nmbd',