summaryrefslogtreecommitdiff
path: root/source3/rpc_server
diff options
context:
space:
mode:
Diffstat (limited to 'source3/rpc_server')
-rw-r--r--source3/rpc_server/srv_eventlog.c206
-rw-r--r--source3/rpc_server/srv_eventlog_nt.c923
-rw-r--r--source3/rpc_server/srv_lsa_ds_nt.c7
-rw-r--r--source3/rpc_server/srv_netlog.c2
-rw-r--r--source3/rpc_server/srv_pipe.c7
-rw-r--r--source3/rpc_server/srv_reg.c67
-rw-r--r--source3/rpc_server/srv_reg_nt.c141
-rw-r--r--source3/rpc_server/srv_spoolss_nt.c19
-rw-r--r--source3/rpc_server/srv_svcctl.c294
-rw-r--r--source3/rpc_server/srv_svcctl_nt.c291
10 files changed, 1875 insertions, 82 deletions
diff --git a/source3/rpc_server/srv_eventlog.c b/source3/rpc_server/srv_eventlog.c
new file mode 100644
index 0000000000..07aebcd2fa
--- /dev/null
+++ b/source3/rpc_server/srv_eventlog.c
@@ -0,0 +1,206 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * RPC Pipe client / server routines
+ * Copyright (C) Marcin Krzysztof Porwit 2005.
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
+static BOOL api_eventlog_open_eventlog(pipes_struct *p)
+{
+ EVENTLOG_Q_OPEN_EVENTLOG q_u;
+ EVENTLOG_R_OPEN_EVENTLOG r_u;
+
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!(eventlog_io_q_open_eventlog("", &q_u, data, 0))) {
+ DEBUG(0, ("eventlog_io_q_open_eventlog: unable to unmarshall EVENTLOG_Q_OPEN_EVENTLOG.\n"));
+ return False;
+ }
+
+ r_u.status = _eventlog_open_eventlog(p, &q_u, &r_u);
+
+ if (!(eventlog_io_r_open_eventlog("", &r_u, rdata, 0))) {
+ DEBUG(0, ("eventlog_io_r_open_eventlog: unable to marshall EVENTLOG_R_OPEN_EVENTLOG.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+static BOOL api_eventlog_close_eventlog(pipes_struct *p)
+{
+ EVENTLOG_Q_CLOSE_EVENTLOG q_u;
+ EVENTLOG_R_CLOSE_EVENTLOG r_u;
+
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!(eventlog_io_q_close_eventlog("", &q_u, data, 0))) {
+ DEBUG(0, ("eventlog_io_q_close_eventlog: unable to unmarshall EVENTLOG_Q_CLOSE_EVENTLOG.\n"));
+ return False;
+ }
+
+ r_u.status = _eventlog_close_eventlog(p, &q_u, &r_u);
+
+ if (!(eventlog_io_r_close_eventlog("", &r_u, rdata, 0))) {
+ DEBUG(0, ("eventlog_io_r_close_eventlog: unable to marshall EVENTLOG_R_CLOSE_EVENTLOG.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+static BOOL api_eventlog_get_num_records(pipes_struct *p)
+{
+ EVENTLOG_Q_GET_NUM_RECORDS q_u;
+ EVENTLOG_R_GET_NUM_RECORDS r_u;
+
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!(eventlog_io_q_get_num_records("", &q_u, data, 0))) {
+ DEBUG(0, ("eventlog_io_q_get_num_records: unable to unmarshall EVENTLOG_Q_GET_NUM_RECORDS.\n"));
+ return False;
+ }
+
+ r_u.status = _eventlog_get_num_records(p, &q_u, &r_u);
+
+ if (!(eventlog_io_r_get_num_records("", &r_u, rdata, 0))) {
+ DEBUG(0, ("eventlog_io_r_get_num_records: unable to marshall EVENTLOG_R_GET_NUM_RECORDS.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+static BOOL api_eventlog_get_oldest_entry(pipes_struct *p)
+{
+ EVENTLOG_Q_GET_OLDEST_ENTRY q_u;
+ EVENTLOG_R_GET_OLDEST_ENTRY r_u;
+
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!(eventlog_io_q_get_oldest_entry("", &q_u, data, 0))) {
+ DEBUG(0, ("eventlog_io_q_get_oldest_entry: unable to unmarshall EVENTLOG_Q_GET_OLDEST_ENTRY.\n"));
+ return False;
+ }
+
+ r_u.status = _eventlog_get_oldest_entry(p, &q_u, &r_u);
+
+ if (!(eventlog_io_r_get_oldest_entry("", &r_u, rdata, 0))) {
+ DEBUG(0, ("eventlog_io_r_get_oldest_entry: unable to marshall EVENTLOG_R_GET_OLDEST_ENTRY.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+static BOOL api_eventlog_read_eventlog(pipes_struct *p)
+{
+ EVENTLOG_Q_READ_EVENTLOG q_u;
+ EVENTLOG_R_READ_EVENTLOG r_u;
+
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!(eventlog_io_q_read_eventlog("", &q_u, data, 0))) {
+ DEBUG(0, ("eventlog_io_q_read_eventlog: unable to unmarshall EVENTLOG_Q_READ_EVENTLOG.\n"));
+ return False;
+ }
+
+ r_u.status = _eventlog_read_eventlog(p, &q_u, &r_u);
+
+ if (!(eventlog_io_r_read_eventlog("", &q_u, &r_u, rdata, 0))) {
+ DEBUG(0, ("eventlog_io_r_read_eventlog: unable to marshall EVENTLOG_R_READ_EVENTLOG.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+static BOOL api_eventlog_clear_eventlog(pipes_struct *p)
+{
+ EVENTLOG_Q_CLEAR_EVENTLOG q_u;
+ EVENTLOG_R_CLEAR_EVENTLOG r_u;
+
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!(eventlog_io_q_clear_eventlog("", &q_u, data, 0))) {
+ DEBUG(0, ("eventlog_io_q_clear_eventlog: unable to unmarshall EVENTLOG_Q_CLEAR_EVENTLOG.\n"));
+ return False;
+ }
+
+ r_u.status = _eventlog_clear_eventlog(p, &q_u, &r_u);
+
+ if (!(eventlog_io_r_clear_eventlog("", &r_u, rdata, 0))) {
+ DEBUG(0, ("eventlog_io_q_clear_eventlog: unable to marshall EVENTLOG_Q_CLEAR_EVENTLOG.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+/*
+ \pipe\eventlog commands
+*/
+struct api_struct api_eventlog_cmds[] =
+{
+ {"EVENTLOG_OPENEVENTLOG", EVENTLOG_OPENEVENTLOG, api_eventlog_open_eventlog },
+ {"EVENTLOG_CLOSEVENTLOG", EVENTLOG_CLOSEEVENTLOG, api_eventlog_close_eventlog },
+ {"EVENTLOG_GETNUMRECORDS", EVENTLOG_GETNUMRECORDS, api_eventlog_get_num_records },
+ {"EVENTLOG_GETOLDESTENTRY", EVENTLOG_GETOLDESTENTRY, api_eventlog_get_oldest_entry },
+ {"EVENTLOG_READEVENTLOG", EVENTLOG_READEVENTLOG, api_eventlog_read_eventlog },
+ {"EVENTLOG_CLEAREVENTLOG", EVENTLOG_CLEAREVENTLOG, api_eventlog_clear_eventlog }
+};
+
+NTSTATUS rpc_eventlog_init(void)
+{
+ return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION,
+ "eventlog", "eventlog", api_eventlog_cmds,
+ sizeof(api_eventlog_cmds)/sizeof(struct api_struct));
+}
+
+void eventlog_get_pipe_fns(struct api_struct **fns, int *n_fns)
+{
+ *fns = api_eventlog_cmds;
+ *n_fns = sizeof(api_eventlog_cmds) / sizeof(struct api_struct);
+}
diff --git a/source3/rpc_server/srv_eventlog_nt.c b/source3/rpc_server/srv_eventlog_nt.c
new file mode 100644
index 0000000000..7501434a13
--- /dev/null
+++ b/source3/rpc_server/srv_eventlog_nt.c
@@ -0,0 +1,923 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * RPC Pipe client / server routines
+ * Copyright (C) Marcin Krzysztof Porwit 2005.
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
+typedef struct eventlog_info
+{
+ /* for use by the \PIPE\eventlog policy */
+ fstring source_log_file_name;
+ fstring source_server_name;
+ fstring handle_string;
+ uint32 num_records;
+ uint32 oldest_entry;
+} Eventlog_info;
+
+static void free_eventlog_info(void *ptr)
+{
+ struct eventlog_info *info = (struct eventlog_info *)ptr;
+ memset(info->source_log_file_name, '0', sizeof(*(info->source_log_file_name)));
+ memset(info->source_server_name, '0', sizeof(*(info->source_server_name)));
+ memset(info->handle_string, '0', sizeof(*(info->handle_string)));
+ memset(info, 0, sizeof(*(info)));
+ SAFE_FREE(info);
+}
+
+static Eventlog_info *find_eventlog_info_by_hnd(pipes_struct *p,
+ POLICY_HND *handle)
+{
+ Eventlog_info *info = NULL;
+
+ if(!(find_policy_by_hnd(p,handle,(void **)&info)))
+ {
+ DEBUG(2,("find_eventlog_info_by_hnd: eventlog not found.\n"));
+ }
+
+ return info;
+}
+
+void policy_handle_to_string(POLICY_HND *handle, fstring *dest)
+{
+ memset(dest, 0, sizeof(*dest));
+ snprintf((char *)dest, sizeof(*dest), "%08X-%08X-%04X-%04X-%02X%02X%02X%02X%02X",
+ handle->data1,
+ handle->data2,
+ handle->data3,
+ handle->data4,
+ handle->data5[0],
+ handle->data5[1],
+ handle->data5[2],
+ handle->data5[3],
+ handle->data5[4]);
+}
+
+/**
+ * Callout to open the specified event log
+ *
+ * smbrun calling convention --
+ * INPUT: <open_cmd> <log name> <policy handle>
+ * OUTPUT: the string "SUCCESS" if the command succeeded
+ * no such string if there was a failure.
+ */
+static BOOL _eventlog_open_eventlog_hook(Eventlog_info *info)
+{
+ char *cmd = lp_eventlog_open_cmd();
+ char **qlines;
+ pstring command;
+ int numlines = 0;
+ int ret;
+ int fd = -1;
+
+ if(cmd == NULL || strlen(cmd) == 0)
+ {
+ DEBUG(0, ("Must define an \"eventlog open command\" entry in the config.\n"));
+ return False;
+ }
+
+ memset(command, 0, sizeof(command));
+ slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"",
+ cmd,
+ info->source_log_file_name,
+ info->handle_string);
+
+ DEBUG(10, ("Running [%s]\n", command));
+ ret = smbrun(command, &fd);
+ DEBUGADD(10, ("returned [%d]\n", ret));
+
+ if(ret != 0)
+ {
+ if(fd != -1)
+ close(fd);
+ return False;
+ }
+
+ qlines = fd_lines_load(fd, &numlines);
+ DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
+ close(fd);
+
+ if(numlines)
+ {
+ DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
+ if(0 == strncmp(qlines[0], "SUCCESS", strlen("SUCCESS")))
+ {
+ DEBUGADD(10, ("Able to open [%s].\n", info->source_log_file_name));
+ file_lines_free(qlines);
+ return True;
+ }
+ }
+
+ file_lines_free(qlines);
+ return False;
+}
+
+WERROR _eventlog_open_eventlog(pipes_struct *p,
+ EVENTLOG_Q_OPEN_EVENTLOG *q_u,
+ EVENTLOG_R_OPEN_EVENTLOG *r_u)
+{
+ Eventlog_info *info = NULL;
+
+ if(!q_u || !r_u)
+ return WERR_NOMEM;
+
+ if((info = SMB_MALLOC_P(Eventlog_info)) == NULL)
+ return WERR_NOMEM;
+
+ ZERO_STRUCTP(info);
+
+ if(q_u->servername_ptr != 0)
+ {
+ unistr2_to_ascii(info->source_server_name, &(q_u->servername), sizeof(info->source_server_name));
+ }
+ else
+ {
+ /* if servername == NULL, use the local computer */
+ fstrcpy(info->source_server_name, global_myname());
+ }
+ DEBUG(10, ("_eventlog_open_eventlog: Using [%s] as the server name.\n", info->source_server_name));
+
+ if(q_u->sourcename_ptr != 0)
+ {
+ unistr2_to_ascii(info->source_log_file_name, &(q_u->sourcename), sizeof(info->source_log_file_name));
+ }
+ else
+ {
+ /* if sourcename == NULL, default to "Application" log */
+ fstrcpy(info->source_log_file_name, "Application");
+ }
+ DEBUG(10, ("_eventlog_open_eventlog: Using [%s] as the source log file.\n", info->source_log_file_name));
+
+ if(!create_policy_hnd(p, &(r_u->handle), free_eventlog_info, (void *)info))
+ return WERR_NOMEM;
+
+ policy_handle_to_string(&r_u->handle, &info->handle_string);
+
+ if(!(_eventlog_open_eventlog_hook(info)))
+ return WERR_BADFILE;
+
+ return WERR_OK;
+}
+/**
+ * Callout to get the number of records in the specified event log
+ *
+ * smbrun calling convention --
+ * INPUT: <get_num_records_cmd> <log name> <policy handle>
+ * OUTPUT: A single line with a single integer containing the number of
+ * entries in the log. If there are no entries in the log, return 0.
+ */
+static BOOL _eventlog_get_num_records_hook(Eventlog_info *info)
+{
+ char *cmd = lp_eventlog_num_records_cmd();
+ char **qlines;
+ pstring command;
+ int numlines = 0;
+ int ret;
+ int fd = -1;
+
+ if(cmd == NULL || strlen(cmd) == 0)
+ {
+ DEBUG(0, ("Must define an \"eventlog num records command\" entry in the config.\n"));
+ return False;
+ }
+
+ memset(command, 0, sizeof(command));
+ slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"",
+ cmd,
+ info->source_log_file_name,
+ info->handle_string);
+
+ DEBUG(10, ("Running [%s]\n", command));
+ ret = smbrun(command, &fd);
+ DEBUGADD(10, ("returned [%d]\n", ret));
+
+ if(ret != 0)
+ {
+ if(fd != -1)
+ close(fd);
+ return False;
+ }
+
+ qlines = fd_lines_load(fd, &numlines);
+ DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
+ close(fd);
+
+ if(numlines)
+ {
+ DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
+ sscanf(qlines[0], "%d", &(info->num_records));
+ file_lines_free(qlines);
+ return True;
+ }
+
+ file_lines_free(qlines);
+ return False;
+}
+
+WERROR _eventlog_get_num_records(pipes_struct *p,
+ EVENTLOG_Q_GET_NUM_RECORDS *q_u,
+ EVENTLOG_R_GET_NUM_RECORDS *r_u)
+{
+ Eventlog_info *info = NULL;
+ POLICY_HND *handle = NULL;
+
+ if(!q_u || !r_u)
+ return WERR_NOMEM;
+
+ handle = &(q_u->handle);
+ info = find_eventlog_info_by_hnd(p, handle);
+
+ if(!(_eventlog_get_num_records_hook(info)))
+ return WERR_BADFILE;
+
+ r_u->num_records = info->num_records;
+
+ return WERR_OK;
+}
+/**
+ * Callout to find the oldest record in the log
+ *
+ * smbrun calling convention --
+ * INPUT: <oldest_entry_cmd> <log name> <policy handle>
+ * OUTPUT: If there are entries in the event log, the index of the
+ * oldest entry. Must be 1 or greater.
+ * If there are no entries in the log, returns a 0
+ */
+static BOOL _eventlog_get_oldest_entry_hook(Eventlog_info *info)
+{
+ char *cmd = lp_eventlog_oldest_record_cmd();
+ char **qlines;
+ pstring command;
+ int numlines = 0;
+ int ret;
+ int fd = -1;
+
+ if(cmd == NULL || strlen(cmd) == 0)
+ {
+ DEBUG(0, ("Must define an \"eventlog oldest record command\" entry in the config.\n"));
+ return False;
+ }
+
+ memset(command, 0, sizeof(command));
+ slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"",
+ cmd,
+ info->source_log_file_name,
+ info->handle_string);
+
+ DEBUG(10, ("Running [%s]\n", command));
+ ret = smbrun(command, &fd);
+ DEBUGADD(10, ("returned [%d]\n", ret));
+
+ if(ret != 0)
+ {
+ if(fd != -1)
+ close(fd);
+ return False;
+ }
+
+ qlines = fd_lines_load(fd, &numlines);
+ DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
+ close(fd);
+
+ if(numlines)
+ {
+ DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
+ sscanf(qlines[0], "%d", &(info->oldest_entry));
+ file_lines_free(qlines);
+ return True;
+ }
+
+ file_lines_free(qlines);
+ return False;
+}
+
+WERROR _eventlog_get_oldest_entry(pipes_struct *p,
+ EVENTLOG_Q_GET_OLDEST_ENTRY *q_u,
+ EVENTLOG_R_GET_OLDEST_ENTRY *r_u)
+{
+ Eventlog_info *info = NULL;
+ POLICY_HND *handle = NULL;
+
+ if(!q_u || !r_u)
+ return WERR_NOMEM;
+
+ handle = &(q_u->handle);
+ info = find_eventlog_info_by_hnd(p, handle);
+
+ if(!(_eventlog_get_oldest_entry_hook(info)))
+ return WERR_BADFILE;
+
+ r_u->oldest_entry = info->oldest_entry;
+
+ return WERR_OK;
+}
+
+/**
+ * Callout to close the specified event log
+ *
+ * smbrun calling convention --
+ * INPUT: <close_cmd> <log name> <policy handle>
+ * OUTPUT: the string "SUCCESS" if the command succeeded
+ * no such string if there was a failure.
+ */
+static BOOL _eventlog_close_eventlog_hook(Eventlog_info *info)
+{
+ char *cmd = lp_eventlog_close_cmd();
+ char **qlines;
+ pstring command;
+ int numlines = 0;
+ int ret;
+ int fd = -1;
+
+ if(cmd == NULL || strlen(cmd) == 0)
+ {
+ DEBUG(0, ("Must define an \"eventlog close command\" entry in the config.\n"));
+ return False;
+ }
+
+ memset(command, 0, sizeof(command));
+ slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"",
+ cmd,
+ info->source_log_file_name,
+ info->handle_string);
+
+ DEBUG(10, ("Running [%s]\n", command));
+ ret = smbrun(command, &fd);
+ DEBUGADD(10, ("returned [%d]\n", ret));
+
+ if(ret != 0)
+ {
+ if(fd != -1)
+ close(fd);
+ return False;
+ }
+
+ qlines = fd_lines_load(fd, &numlines);
+ DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
+ close(fd);
+
+ if(numlines)
+ {
+ DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
+ if(0 == strncmp(qlines[0], "SUCCESS", strlen("SUCCESS")))
+ {
+ DEBUGADD(10, ("Able to close [%s].\n", info->source_log_file_name));
+ file_lines_free(qlines);
+ return True;
+ }
+ }
+
+ file_lines_free(qlines);
+ return False;
+}
+
+WERROR _eventlog_close_eventlog(pipes_struct *p,
+ EVENTLOG_Q_CLOSE_EVENTLOG *q_u,
+ EVENTLOG_R_CLOSE_EVENTLOG *r_u)
+{
+ Eventlog_info *info = NULL;
+ POLICY_HND *handle;
+
+ if(!q_u || !r_u)
+ return WERR_NOMEM;
+
+ handle = &(q_u->handle);
+
+ info = find_eventlog_info_by_hnd(p, handle);
+ if(!(_eventlog_close_eventlog_hook(info)))
+ return WERR_BADFILE;
+
+ if(!(close_policy_hnd(p, handle)))
+ {
+ /* WERR_NOMEM is probably not the correct error, but until I figure out a better
+ one it will have to do */
+ return WERR_NOMEM;
+ }
+
+ return WERR_OK;
+}
+
+static BOOL _eventlog_read_parse_line(char *line, Eventlog_entry *entry)
+{
+ char *start = NULL, *stop = NULL;
+ pstring temp;
+ int temp_len = 0, i;
+
+ start = line;
+
+ if(start == NULL || strlen(start) == 0)
+ return False;
+ if(!(stop = strchr(line, ':')))
+ return False;
+
+ DEBUG(6, ("_eventlog_read_parse_line: trying to parse [%s].\n", line));
+
+ if(0 == strncmp(start, "LEN", stop - start))
+ {
+ /* This will get recomputed later anyway -- probably not necessary */
+ entry->record.length = atoi(stop + 1);
+ }
+ else if(0 == strncmp(start, "RS1", stop - start))
+ {
+ /* For now all these reserved entries seem to have the same value,
+ which can be hardcoded to int(1699505740) for now */
+ entry->record.reserved1 = atoi(stop + 1);
+ }
+ else if(0 == strncmp(start, "RCN", stop - start))
+ {
+ entry->record.record_number = atoi(stop + 1);
+ }
+ else if(0 == strncmp(start, "TMG", stop - start))
+ {
+ entry->record.time_generated = atoi(stop + 1);
+ }
+ else if(0 == strncmp(start, "TMW", stop - start))
+ {
+ entry->record.time_written = atoi(stop + 1);
+ }
+ else if(0 == strncmp(start, "EID", stop - start))
+ {
+ entry->record.event_id = atoi(stop + 1);
+ }
+ else if(0 == strncmp(start, "ETP", stop - start))
+ {
+ if(strstr(start, "ERROR"))
+ {
+ entry->record.event_type = EVENTLOG_ERROR_TYPE;
+ }
+ else if(strstr(start, "WARNING"))
+ {
+ entry->record.event_type = EVENTLOG_WARNING_TYPE;
+ }
+ else if(strstr(start, "INFO"))
+ {
+ entry->record.event_type = EVENTLOG_INFORMATION_TYPE;
+ }
+ else if(strstr(start, "AUDIT_SUCCESS"))
+ {
+ entry->record.event_type = EVENTLOG_AUDIT_SUCCESS;
+ }
+ else if(strstr(start, "AUDIT_FAILURE"))
+ {
+ entry->record.event_type = EVENTLOG_AUDIT_FAILURE;
+ }
+ else if(strstr(start, "SUCCESS"))
+ {
+ entry->record.event_type = EVENTLOG_SUCCESS;
+ }
+ else
+ {
+ /* some other eventlog type -- currently not defined in MSDN docs, so error out */
+ return False;
+ }
+ }
+/*
+ else if(0 == strncmp(start, "NST", stop - start))
+ {
+ entry->record.num_strings = atoi(stop + 1);
+ }
+*/
+ else if(0 == strncmp(start, "ECT", stop - start))
+ {
+ entry->record.event_category = atoi(stop + 1);
+ }
+ else if(0 == strncmp(start, "RS2", stop - start))
+ {
+ entry->record.reserved2 = atoi(stop + 1);
+ }
+ else if(0 == strncmp(start, "CRN", stop - start))
+ {
+ entry->record.closing_record_number = atoi(stop + 1);
+ }
+ else if(0 == strncmp(start, "USL", stop - start))
+ {
+ entry->record.user_sid_length = atoi(stop + 1);
+ }
+ else if(0 == strncmp(start, "SRC", stop - start))
+ {
+ memset(temp, 0, sizeof(temp));
+ sscanf(stop+1, "%s", temp);
+ temp_len = strlen(temp);
+ rpcstr_push((void *)(entry->data_record.source_name), temp,
+ sizeof(entry->data_record.source_name), STR_TERMINATE);
+ entry->data_record.source_name_len = (strlen_w(entry->data_record.source_name)* 2) + 2;
+ }
+ else if(0 == strncmp(start, "SRN", stop - start))
+ {
+ memset(temp, 0, sizeof(temp));
+ sscanf(stop+1, "%s", temp);
+ temp_len = strlen(temp);
+ rpcstr_push((void *)(entry->data_record.computer_name), temp,
+ sizeof(entry->data_record.computer_name), STR_TERMINATE);
+ entry->data_record.computer_name_len = (strlen_w(entry->data_record.computer_name)* 2) + 2;
+ }
+ else if(0 == strncmp(start, "SID", stop - start))
+ {
+ memset(temp, 0, sizeof(temp));
+ sscanf(stop+1, "%s", temp);
+ temp_len = strlen(temp);
+ rpcstr_push((void *)(entry->data_record.sid), temp,
+ sizeof(entry->data_record.sid), STR_TERMINATE);
+ entry->record.user_sid_length = (strlen_w(entry->data_record.sid) * 2) + 2;
+ }
+ else if(0 == strncmp(start, "STR", stop - start))
+ {
+ /* skip past initial ":" */
+ stop++;
+ /* now skip any other leading whitespace */
+ while(isspace(stop[0]))
+ stop++;
+ temp_len = strlen(stop);
+ memset(temp, 0, sizeof(temp));
+ strncpy(temp, stop, temp_len);
+ rpcstr_push((void *)(entry->data_record.strings + entry->data_record.strings_len),
+ temp,
+ sizeof(entry->data_record.strings) - entry->data_record.strings_len,
+ STR_TERMINATE);
+ entry->data_record.strings_len += temp_len + 1;
+ fprintf(stderr, "Dumping strings:\n");
+ for(i = 0; i < entry->data_record.strings_len; i++)
+ {
+ fputc((char)entry->data_record.strings[i], stderr);
+ }
+ fprintf(stderr, "\nDone\n");
+ entry->record.num_strings++;
+ }
+ else if(0 == strncmp(start, "DAT", stop - start))
+ {
+ /* Now that we're done processing the STR data, adjust the length to account for
+ unicode, then proceed with the DAT data. */
+ entry->data_record.strings_len *= 2;
+ /* skip past initial ":" */
+ stop++;
+ /* now skip any other leading whitespace */
+ while(isspace(stop[0]))
+ stop++;
+ memset(temp, 0, sizeof(temp));
+ temp_len = strlen(stop);
+ strncpy(temp, stop, temp_len);
+ rpcstr_push((void *)(entry->data_record.user_data), temp,
+ sizeof(entry->data_record.user_data), STR_TERMINATE);
+ entry->data_record.user_data_len = (strlen_w((const smb_ucs2_t *)entry->data_record.user_data) * 2) + 2;
+ }
+ else
+ {
+ /* some other eventlog entry -- not implemented, so dropping on the floor */
+ DEBUG(10, ("Unknown entry [%s]. Ignoring.\n", line));
+ /* For now return true so that we can keep on parsing this mess. Eventually
+ we will return False here. */
+ return True;
+ }
+ return True;
+}
+/**
+ * Callout to read entries from the specified event log
+ *
+ * smbrun calling convention --
+ * INPUT: <read_cmd> <log name> <direction> <starting record> <buffer size> <policy handle>
+ * where direction is either "forward" or "backward", the starting record is somewhere
+ * between the oldest_record and oldest_record+num_records, and the buffer size is the
+ * maximum size of the buffer that the client can accomodate.
+ * OUTPUT: A buffer containing a set of entries, one to a line, of the format:
+ * line type:line data
+ * These are the allowed line types:
+ * RS1:(uint32) - reserved. All M$ entries seem to have int(1699505740) for now
+ * RCN:(uint32) - record number of the record, however it may be calculated by the script
+ * TMG:(uint32) - time generated, seconds since January 1, 1970, 0000 UTC
+ * TMW:(uint32) - time written, seconds since January 1, 1970, 0000 UTC
+ * EID:(uint32) - eventlog source defined event identifier. If there's a stringfile for the event, it is an index into that
+ * ETP:(uint16) - eventlog type - one of ERROR, WARNING, INFO, AUDIT_SUCCESS, AUDIT_FAILURE
+ * ECT:(uint16) - event category - depends on the eventlog generator...
+ * RS2:(uint16) - reserved, make it 0000
+ * CRN:(uint32) - reserved, make it 00000000 for now
+ * USL:(uint32) - user SID length. No sid? Make this 0. Must match SID below
+ * SRC:[(uint8)] - Name of the source, for example ccPwdSvc, in hex bytes. Can not be multiline.
+ * SRN:[(uint8)] - Name of the computer on which this is generated, the short hostname usually.
+ * SID:[(uint8)] - User sid if one exists. Must be present even if there is no SID.
+ * STR:[(uint8)] - String data. One string per line. Multiple strings can be specified using consecutive "STR" lines,
+ * up to a total aggregate string length of 1024 characters.
+ * DAT:[(uint8)] - The user-defined data portion of the event log. Can not be multiple lines.
+ */
+static BOOL _eventlog_read_eventlog_hook(Eventlog_info *info, Eventlog_entry *entry, const char *direction, int starting_record, int buffer_size, BOOL *eof)
+{
+ char *cmd = lp_eventlog_read_cmd();
+ char **qlines;
+ pstring command;
+ int numlines = 0;
+ int ret;
+ int fd = -1;
+ int i;
+
+ if(info == NULL)
+ return False;
+
+ if(cmd == NULL || strlen(cmd) == 0)
+ {
+ DEBUG(0, ("Must define an \"eventlog read command\" entry in the config.\n"));
+ return False;
+ }
+
+ slprintf(command, sizeof(command)-1, "%s \"%s\" %s %d %d \"%s\"",
+ cmd,
+ info->source_log_file_name,
+ direction,
+ starting_record,
+ buffer_size,
+ info->handle_string);
+
+ DEBUG(10, ("Running [%s]\n", command));
+ ret = smbrun(command, &fd);
+ DEBUGADD(10, ("returned [%d]\n", ret));
+
+ if(ret != 0)
+ {
+ if(fd != -1)
+ close(fd);
+ return False;
+ }
+
+ qlines = fd_lines_load(fd, &numlines);
+ DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
+ close(fd);
+
+ if(numlines)
+ {
+ for(i = 0; i < numlines; i++)
+ {
+ DEBUGADD(10, ("Line[%d] = %s\n", i, qlines[i]));
+ _eventlog_read_parse_line(qlines[i], entry);
+ }
+ file_lines_free(qlines);
+ return True;
+ }
+ else
+ *eof = True;
+
+ file_lines_free(qlines);
+ return False;
+}
+
+static BOOL _eventlog_read_prepare_data_buffer(prs_struct *ps,
+ EVENTLOG_Q_READ_EVENTLOG *q_u,
+ EVENTLOG_R_READ_EVENTLOG *r_u,
+ Eventlog_entry *entry)
+{
+ uint8 *offset;
+ Eventlog_entry *new = NULL, *insert_point = NULL;
+
+ new = PRS_ALLOC_MEM(ps, Eventlog_entry, 1);
+ if(new == NULL)
+ return False;
+
+ entry->data_record.sid_padding = ((4 - ((entry->data_record.source_name_len
+ + entry->data_record.computer_name_len) % 4)) %4);
+ entry->data_record.data_padding = (4 - ((entry->data_record.strings_len
+ + entry->data_record.user_data_len) % 4)) % 4;
+ entry->record.length = sizeof(Eventlog_record);
+ entry->record.length += entry->data_record.source_name_len;
+ entry->record.length += entry->data_record.computer_name_len;
+ if(entry->record.user_sid_length == 0)
+ {
+ /* Should not pad to a DWORD boundary for writing out the sid if there is
+ no SID, so just propagate the padding to pad the data */
+ entry->data_record.data_padding += entry->data_record.sid_padding;
+ entry->data_record.sid_padding = 0;
+ }
+ DEBUG(10, ("sid_padding is [%d].\n", entry->data_record.sid_padding));
+ DEBUG(10, ("data_padding is [%d].\n", entry->data_record.data_padding));
+
+ entry->record.length += entry->data_record.sid_padding;
+ entry->record.length += entry->record.user_sid_length;
+ entry->record.length += entry->data_record.strings_len;
+ entry->record.length += entry->data_record.user_data_len;
+ entry->record.length += entry->data_record.data_padding;
+ /* need another copy of length at the end of the data */
+ entry->record.length += sizeof(entry->record.length);
+ DEBUG(10, ("entry->record.length is [%d].\n", entry->record.length));
+ entry->data = PRS_ALLOC_MEM(ps, uint8, entry->record.length - sizeof(Eventlog_record) - sizeof(entry->record.length));
+ if(entry->data == NULL)
+ return False;
+ offset = entry->data;
+ memcpy(offset, &(entry->data_record.source_name), entry->data_record.source_name_len);
+ offset += entry->data_record.source_name_len;
+ memcpy(offset, &(entry->data_record.computer_name), entry->data_record.computer_name_len);
+ offset += entry->data_record.computer_name_len;
+ /* SID needs to be DWORD-aligned */
+ offset += entry->data_record.sid_padding;
+ entry->record.user_sid_offset = sizeof(Eventlog_record) + (offset - entry->data);
+ memcpy(offset, &(entry->data_record.sid), entry->record.user_sid_length);
+ offset += entry->record.user_sid_length;
+ /* Now do the strings */
+ entry->record.string_offset = sizeof(Eventlog_record) + (offset - entry->data);
+ memcpy(offset, &(entry->data_record.strings), entry->data_record.strings_len);
+ offset += entry->data_record.strings_len;
+ /* Now do the data */
+ entry->record.data_length = entry->data_record.user_data_len;
+ entry->record.data_offset = sizeof(Eventlog_record) + (offset - entry->data);
+ memcpy(offset, &(entry->data_record.user_data), entry->data_record.user_data_len);
+ offset += entry->data_record.user_data_len;
+ /* Now that we've massaged the current entry, copy it into the new entry and add it
+ to end of the list */
+ insert_point=r_u->entry;
+
+ if (NULL == insert_point)
+ {
+ r_u->entry = new;
+ new->next = NULL;
+ }
+ else
+ {
+ while ((NULL != insert_point->next))
+ {
+ insert_point=insert_point->next;
+ }
+ new->next = NULL;
+ insert_point->next = new;
+ }
+
+ memcpy(&(new->record), &entry->record, sizeof(Eventlog_record));
+ memcpy(&(new->data_record), &entry->data_record, sizeof(Eventlog_data_record));
+ new->data = entry->data;
+
+ r_u->num_records++;
+ r_u->num_bytes_in_resp += entry->record.length;
+
+ return True;
+}
+
+WERROR _eventlog_read_eventlog(pipes_struct *p,
+ EVENTLOG_Q_READ_EVENTLOG *q_u,
+ EVENTLOG_R_READ_EVENTLOG *r_u)
+{
+ Eventlog_info *info = NULL;
+ POLICY_HND *handle;
+ Eventlog_entry entry;
+ BOOL eof = False;
+ const char *direction = "";
+ int starting_record;
+ prs_struct *ps;
+
+ if(!q_u || !r_u)
+ return WERR_NOMEM;
+
+ handle = &(q_u->handle);
+ info = find_eventlog_info_by_hnd(p, handle);
+ ps = &p->out_data.rdata;
+ /* Rather than checking the EVENTLOG_SEQUENTIAL_READ/EVENTLOG_SEEK_READ flags,
+ we'll just go to the offset specified in the request, or the oldest entry
+ if no offset is specified */
+ if(q_u->offset > 0)
+ starting_record = q_u->offset;
+ else
+ starting_record = info->oldest_entry;
+ if(q_u->flags & EVENTLOG_FORWARDS_READ)
+ direction = "forward";
+ else if(q_u->flags & EVENTLOG_BACKWARDS_READ)
+ direction = "backward";
+
+ do
+ {
+ ZERO_STRUCT(entry);
+ if(!(_eventlog_read_eventlog_hook(info, &entry, direction, starting_record, q_u->max_read_size, &eof)))
+ {
+ if(eof == False)
+ return WERR_NOMEM;
+ }
+ if(eof == False)
+ {
+ /* only if the read hook returned data */
+ if(!(_eventlog_read_prepare_data_buffer(ps, q_u, r_u, &entry)))
+ return WERR_NOMEM;
+ DEBUG(10, ("_eventlog_read_eventlog: read [%d] bytes out of a max of [%d].\n",
+ r_u->num_bytes_in_resp,
+ q_u->max_read_size));
+ }
+ } while((r_u->num_bytes_in_resp <= q_u->max_read_size) && (eof != True));
+
+ return WERR_OK;
+}
+/**
+ * Callout to clear (and optionally backup) a specified event log
+ *
+ * smbrun calling convention --
+ * INPUT: <clear_eventlog_cmd> <log name> <policy handle>
+ * OUTPUT: A single line with the string "SUCCESS" if the command succeeded.
+ * Otherwise it is assumed to have failed
+ *
+ * INPUT: <clear_eventlog_cmd> <log name> <backup file> <policy handle>
+ * OUTPUT: A single line with the string "SUCCESS" if the command succeeded.
+ * Otherwise it is assumed to have failed
+ * The given log is copied to that location on the server. See comments for
+ * eventlog_io_q_clear_eventlog for info about odd file name behavior
+ */
+static BOOL _eventlog_clear_eventlog_hook(Eventlog_info *info,
+ pstring backup_file_name)
+{
+ char *cmd = lp_eventlog_clear_cmd();
+ char **qlines;
+ pstring command;
+ int numlines = 0;
+ int ret;
+ int fd = -1;
+
+ if(cmd == NULL || strlen(cmd) == 0)
+ {
+ DEBUG(0, ("Must define an \"eventlog clear command\" entry in the config.\n"));
+ return False;
+ }
+
+ memset(command, 0, sizeof(command));
+ if(strlen(backup_file_name) > 0)
+ slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\"",
+ cmd,
+ info->source_log_file_name,
+ backup_file_name,
+ info->handle_string);
+ else
+ slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"",
+ cmd,
+ info->source_log_file_name,
+ info->handle_string);
+
+ DEBUG(10, ("Running [%s]\n", command));
+ ret = smbrun(command, &fd);
+ DEBUGADD(10, ("returned [%d]\n", ret));
+
+ if(ret != 0)
+ {
+ if(fd != -1)
+ close(fd);
+ return False;
+ }
+
+ qlines = fd_lines_load(fd, &numlines);
+ DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
+ close(fd);
+
+ if(numlines)
+ {
+ DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
+ if(0 == strncmp(qlines[0], "SUCCESS", strlen("SUCCESS")))
+ {
+ DEBUGADD(10, ("Able to clear [%s].\n", info->source_log_file_name));
+ file_lines_free(qlines);
+ return True;
+ }
+ }
+
+ file_lines_free(qlines);
+ return False;
+}
+
+WERROR _eventlog_clear_eventlog(pipes_struct *p,
+ EVENTLOG_Q_CLEAR_EVENTLOG *q_u,
+ EVENTLOG_R_CLEAR_EVENTLOG *r_u)
+{
+ Eventlog_info *info = NULL;
+ pstring backup_file_name;
+ POLICY_HND *handle = NULL;
+
+ if(!q_u || !r_u)
+ return WERR_NOMEM;
+
+ handle = &(q_u->handle);
+ info = find_eventlog_info_by_hnd(p, handle);
+ memset(backup_file_name, 0, sizeof(backup_file_name));
+
+ if(q_u->backup_file_ptr != 0)
+ {
+ unistr2_to_ascii(backup_file_name, &(q_u->backup_file), sizeof(backup_file_name));
+ DEBUG(10, ("_eventlog_clear_eventlog: Using [%s] as the backup file name for log [%s].",
+ backup_file_name,
+ info->source_log_file_name));
+ }
+ else
+ {
+ /* if backup_file == NULL, do not back up the log before clearing it */
+ DEBUG(10, ("_eventlog_clear_eventlog: clearing [%s] log without making a backup.",
+ info->source_log_file_name));
+ }
+
+ if(!(_eventlog_clear_eventlog_hook(info, backup_file_name)))
+ return WERR_BADFILE;
+
+ return WERR_OK;
+}
diff --git a/source3/rpc_server/srv_lsa_ds_nt.c b/source3/rpc_server/srv_lsa_ds_nt.c
index d0b7a299be..b410af8ded 100644
--- a/source3/rpc_server/srv_lsa_ds_nt.c
+++ b/source3/rpc_server/srv_lsa_ds_nt.c
@@ -46,6 +46,9 @@ static NTSTATUS fill_dsrole_dominfo_basic(TALLOC_CTX *ctx, DSROLE_PRIMARY_DOMAIN
return NT_STATUS_NO_MEMORY;
}
+ get_mydnsdomname(dnsdomain);
+ strlower_m(dnsdomain);
+
switch ( lp_server_role() ) {
case ROLE_STANDALONE:
basic->machine_role = DSROLE_STANDALONE_SRV;
@@ -58,16 +61,12 @@ static NTSTATUS fill_dsrole_dominfo_basic(TALLOC_CTX *ctx, DSROLE_PRIMARY_DOMAIN
basic->flags = DSROLE_PRIMARY_DS_RUNNING|DSROLE_PRIMARY_DS_MIXED_MODE;
if ( secrets_fetch_domain_guid( lp_workgroup(), &basic->domain_guid ) )
basic->flags |= DSROLE_PRIMARY_DOMAIN_GUID_PRESENT;
- get_mydnsdomname(dnsdomain);
- strlower_m(dnsdomain);
break;
case ROLE_DOMAIN_PDC:
basic->machine_role = DSROLE_PDC;
basic->flags = DSROLE_PRIMARY_DS_RUNNING|DSROLE_PRIMARY_DS_MIXED_MODE;
if ( secrets_fetch_domain_guid( lp_workgroup(), &basic->domain_guid ) )
basic->flags |= DSROLE_PRIMARY_DOMAIN_GUID_PRESENT;
- get_mydnsdomname(dnsdomain);
- strlower_m(dnsdomain);
break;
}
diff --git a/source3/rpc_server/srv_netlog.c b/source3/rpc_server/srv_netlog.c
index 705b629732..a45a7eebf6 100644
--- a/source3/rpc_server/srv_netlog.c
+++ b/source3/rpc_server/srv_netlog.c
@@ -299,7 +299,7 @@ static BOOL api_net_logon_ctrl(pipes_struct *p)
r_u.status = _net_logon_ctrl(p, &q_u, &r_u);
if(!net_io_r_logon_ctrl("", &r_u, rdata, 0)) {
- DEBUG(0,("net_reply_logon_ctrl2: Failed to marshall NET_R_LOGON_CTRL2.\n"));
+ DEBUG(0,("net_reply_logon_ctrl2: Failed to marshall NET_R_LOGON_CTRL.\n"));
return False;
}
diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c
index 01e91ce6c5..ab21f60902 100644
--- a/source3/rpc_server/srv_pipe.c
+++ b/source3/rpc_server/srv_pipe.c
@@ -765,6 +765,7 @@ BOOL check_bind_req(struct pipes_struct *p, RPC_IFACE* abstract,
for ( i=0; pipe_names[i].client_pipe; i++ )
{
+ DEBUG(10,("checking %s\n", pipe_names[i].client_pipe));
if ( strequal(pipe_names[i].client_pipe, pname)
&& (abstract->version == pipe_names[i].abstr_syntax.version)
&& (memcmp(&abstract->uuid, &pipe_names[i].abstr_syntax.uuid, sizeof(struct uuid)) == 0)
@@ -1631,6 +1632,12 @@ void get_pipe_fns( int idx, struct api_struct **fns, int *n_fns )
case PI_NETDFS:
netdfs_get_pipe_fns( &cmds, &n_cmds );
break;
+ case PI_SVCCTL:
+ svcctl_get_pipe_fns( &cmds, &n_cmds );
+ break;
+ case PI_EVENTLOG:
+ eventlog_get_pipe_fns( &cmds, &n_cmds );
+ break;
#ifdef DEVELOPER
case PI_ECHO:
echo_get_pipe_fns( &cmds, &n_cmds );
diff --git a/source3/rpc_server/srv_reg.c b/source3/rpc_server/srv_reg.c
index b780be0aff..b2b3920e9e 100644
--- a/source3/rpc_server/srv_reg.c
+++ b/source3/rpc_server/srv_reg.c
@@ -63,8 +63,8 @@ static BOOL api_reg_close(pipes_struct *p)
static BOOL api_reg_open_hklm(pipes_struct *p)
{
- REG_Q_OPEN_HKLM q_u;
- REG_R_OPEN_HKLM r_u;
+ REG_Q_OPEN_HIVE q_u;
+ REG_R_OPEN_HIVE r_u;
prs_struct *data = &p->in_data.data;
prs_struct *rdata = &p->out_data.rdata;
@@ -72,12 +72,12 @@ static BOOL api_reg_open_hklm(pipes_struct *p)
ZERO_STRUCT(r_u);
/* grab the reg open */
- if(!reg_io_q_open_hklm("", &q_u, data, 0))
+ if(!reg_io_q_open_hive("", &q_u, data, 0))
return False;
r_u.status = _reg_open_hklm(p, &q_u, &r_u);
- if(!reg_io_r_open_hklm("", &r_u, rdata, 0))
+ if(!reg_io_r_open_hive("", &r_u, rdata, 0))
return False;
return True;
@@ -89,8 +89,8 @@ static BOOL api_reg_open_hklm(pipes_struct *p)
static BOOL api_reg_open_hku(pipes_struct *p)
{
- REG_Q_OPEN_HKU q_u;
- REG_R_OPEN_HKU r_u;
+ REG_Q_OPEN_HIVE q_u;
+ REG_R_OPEN_HIVE r_u;
prs_struct *data = &p->in_data.data;
prs_struct *rdata = &p->out_data.rdata;
@@ -98,12 +98,12 @@ static BOOL api_reg_open_hku(pipes_struct *p)
ZERO_STRUCT(r_u);
/* grab the reg open */
- if(!reg_io_q_open_hku("", &q_u, data, 0))
+ if(!reg_io_q_open_hive("", &q_u, data, 0))
return False;
r_u.status = _reg_open_hku(p, &q_u, &r_u);
- if(!reg_io_r_open_hku("", &r_u, rdata, 0))
+ if(!reg_io_r_open_hive("", &r_u, rdata, 0))
return False;
return True;
@@ -115,8 +115,8 @@ static BOOL api_reg_open_hku(pipes_struct *p)
static BOOL api_reg_open_hkcr(pipes_struct *p)
{
- REG_Q_OPEN_HKCR q_u;
- REG_R_OPEN_HKCR r_u;
+ REG_Q_OPEN_HIVE q_u;
+ REG_R_OPEN_HIVE r_u;
prs_struct *data = &p->in_data.data;
prs_struct *rdata = &p->out_data.rdata;
@@ -124,12 +124,12 @@ static BOOL api_reg_open_hkcr(pipes_struct *p)
ZERO_STRUCT(r_u);
/* grab the reg open */
- if(!reg_io_q_open_hkcr("", &q_u, data, 0))
+ if(!reg_io_q_open_hive("", &q_u, data, 0))
return False;
r_u.status = _reg_open_hkcr(p, &q_u, &r_u);
- if(!reg_io_r_open_hkcr("", &r_u, rdata, 0))
+ if(!reg_io_r_open_hive("", &r_u, rdata, 0))
return False;
return True;
@@ -216,6 +216,32 @@ static BOOL api_reg_shutdown(pipes_struct *p)
}
/*******************************************************************
+ api_reg_shutdown_ex
+ ********************************************************************/
+
+static BOOL api_reg_shutdown_ex(pipes_struct *p)
+{
+ REG_Q_SHUTDOWN_EX q_u;
+ REG_R_SHUTDOWN_EX r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ /* grab the reg shutdown ex */
+ if(!reg_io_q_shutdown_ex("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _reg_shutdown_ex(p, &q_u, &r_u);
+
+ if(!reg_io_r_shutdown_ex("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
api_reg_abort_shutdown
********************************************************************/
@@ -268,25 +294,25 @@ static BOOL api_reg_query_key(pipes_struct *p)
}
/*******************************************************************
- api_reg_unknown_1a
+ api_reg_getversion
********************************************************************/
-static BOOL api_reg_unknown_1a(pipes_struct *p)
+static BOOL api_reg_getversion(pipes_struct *p)
{
- REG_Q_UNKNOWN_1A q_u;
- REG_R_UNKNOWN_1A r_u;
+ REG_Q_GETVERSION q_u;
+ REG_R_GETVERSION r_u;
prs_struct *data = &p->in_data.data;
prs_struct *rdata = &p->out_data.rdata;
ZERO_STRUCT(q_u);
ZERO_STRUCT(r_u);
- if(!reg_io_q_unknown_1a("", &q_u, data, 0))
+ if(!reg_io_q_getversion("", &q_u, data, 0))
return False;
- r_u.status = _reg_unknown_1a(p, &q_u, &r_u);
+ r_u.status = _reg_getversion(p, &q_u, &r_u);
- if(!reg_io_r_unknown_1a("", &r_u, rdata, 0))
+ if(!reg_io_r_getversion("", &r_u, rdata, 0))
return False;
return True;
@@ -383,8 +409,9 @@ static struct api_struct api_reg_cmds[] =
{ "REG_QUERY_KEY" , REG_QUERY_KEY , api_reg_query_key },
{ "REG_INFO" , REG_INFO , api_reg_info },
{ "REG_SHUTDOWN" , REG_SHUTDOWN , api_reg_shutdown },
+ { "REG_SHUTDOWN_EX" , REG_SHUTDOWN_EX , api_reg_shutdown_ex },
{ "REG_ABORT_SHUTDOWN" , REG_ABORT_SHUTDOWN , api_reg_abort_shutdown },
- { "REG_UNKNOWN_1A" , REG_UNKNOWN_1A , api_reg_unknown_1a },
+ { "REG_GETVERSION" , REG_GETVERSION , api_reg_getversion },
{ "REG_SAVE_KEY" , REG_SAVE_KEY , api_reg_save_key }
};
diff --git a/source3/rpc_server/srv_reg_nt.c b/source3/rpc_server/srv_reg_nt.c
index c11e0d59a0..f0d831cc6a 100644
--- a/source3/rpc_server/srv_reg_nt.c
+++ b/source3/rpc_server/srv_reg_nt.c
@@ -5,7 +5,7 @@
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997.
* Copyright (C) Paul Ashton 1997.
* Copyright (C) Jeremy Allison 2001.
- * Copyright (C) Gerald Carter 2002.
+ * Copyright (C) Gerald Carter 2002-2005.
*
* 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
@@ -291,7 +291,7 @@ WERROR _reg_close(pipes_struct *p, REG_Q_CLOSE *q_u, REG_R_CLOSE *r_u)
/*******************************************************************
********************************************************************/
-WERROR _reg_open_hklm(pipes_struct *p, REG_Q_OPEN_HKLM *q_u, REG_R_OPEN_HKLM *r_u)
+WERROR _reg_open_hklm(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
{
return open_registry_key( p, &r_u->pol, NULL, KEY_HKLM, 0x0 );
}
@@ -299,7 +299,7 @@ WERROR _reg_open_hklm(pipes_struct *p, REG_Q_OPEN_HKLM *q_u, REG_R_OPEN_HKLM *r_
/*******************************************************************
********************************************************************/
-WERROR _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HKCR *q_u, REG_R_OPEN_HKCR *r_u)
+WERROR _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
{
return open_registry_key( p, &r_u->pol, NULL, KEY_HKCR, 0x0 );
}
@@ -307,7 +307,7 @@ WERROR _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HKCR *q_u, REG_R_OPEN_HKCR *r_
/*******************************************************************
********************************************************************/
-WERROR _reg_open_hku(pipes_struct *p, REG_Q_OPEN_HKU *q_u, REG_R_OPEN_HKU *r_u)
+WERROR _reg_open_hku(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
{
return open_registry_key( p, &r_u->pol, NULL, KEY_HKU, 0x0 );
}
@@ -328,7 +328,7 @@ WERROR _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTRY
if ( !key )
return WERR_BADFID; /* This will be reported as an RPC fault anyway. */
- rpcstr_pull(name,q_u->uni_name.buffer,sizeof(name),q_u->uni_name.uni_str_len*2,0);
+ rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
result = open_registry_key( p, &pol, key, name, 0x0 );
@@ -362,7 +362,7 @@ WERROR _reg_info(pipes_struct *p, REG_Q_INFO *q_u, REG_R_INFO *r_u)
DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name));
- rpcstr_pull(name, q_u->uni_type.buffer, sizeof(name), q_u->uni_type.uni_str_len*2, 0);
+ rpcstr_pull(name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0);
DEBUG(5,("reg_info: looking up value: [%s]\n", name));
@@ -439,7 +439,7 @@ WERROR _reg_info(pipes_struct *p, REG_Q_INFO *q_u, REG_R_INFO *r_u)
out:
- new_init_reg_r_info(q_u->ptr_buf, r_u, val, status);
+ init_reg_r_info(q_u->ptr_buf, r_u, val, status);
regval_ctr_destroy( &regvals );
free_registry_value( val );
@@ -485,22 +485,22 @@ WERROR _reg_query_key(pipes_struct *p, REG_Q_QUERY_KEY *q_u, REG_R_QUERY_KEY *r_
/*****************************************************************************
- Implementation of REG_UNKNOWN_1A
+ Implementation of REG_GETVERSION
****************************************************************************/
-WERROR _reg_unknown_1a(pipes_struct *p, REG_Q_UNKNOWN_1A *q_u, REG_R_UNKNOWN_1A *r_u)
+WERROR _reg_getversion(pipes_struct *p, REG_Q_GETVERSION *q_u, REG_R_GETVERSION *r_u)
{
WERROR status = WERR_OK;
REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
- DEBUG(5,("_reg_unknown_1a: Enter\n"));
+ DEBUG(5,("_reg_getversion: Enter\n"));
if ( !regkey )
return WERR_BADFID; /* This will be reported as an RPC fault anyway. */
r_u->unknown = 0x00000005; /* seems to be consistent...no idea what it means */
- DEBUG(5,("_reg_unknown_1a: Exit\n"));
+ DEBUG(5,("_reg_getversion: Exit\n"));
return status;
}
@@ -593,82 +593,131 @@ done:
WERROR _reg_shutdown(pipes_struct *p, REG_Q_SHUTDOWN *q_u, REG_R_SHUTDOWN *r_u)
{
- WERROR status = WERR_OK;
+ REG_Q_SHUTDOWN_EX q_u_ex;
+ REG_R_SHUTDOWN_EX r_u_ex;
+
+ /* copy fields (including stealing memory) */
+
+ q_u_ex.server = q_u->server;
+ q_u_ex.message = q_u->message;
+ q_u_ex.timeout = q_u->timeout;
+ q_u_ex.force = q_u->force;
+ q_u_ex.reboot = q_u->reboot;
+ q_u_ex.reason = 0x0; /* don't care for now */
+
+ /* thunk down to _reg_shutdown_ex() (just returns a status) */
+
+ return _reg_shutdown_ex( p, &q_u_ex, &r_u_ex );
+}
+
+/*******************************************************************
+ reg_shutdown_ex
+ ********************************************************************/
+
+#define SHUTDOWN_R_STRING "-r"
+#define SHUTDOWN_F_STRING "-f"
+
+
+WERROR _reg_shutdown_ex(pipes_struct *p, REG_Q_SHUTDOWN_EX *q_u, REG_R_SHUTDOWN_EX *r_u)
+{
pstring shutdown_script;
- UNISTR2 unimsg = q_u->uni_msg;
pstring message;
pstring chkmsg;
fstring timeout;
+ fstring reason;
fstring r;
fstring f;
+ int ret;
+ BOOL can_shutdown;
- /* message */
- rpcstr_pull (message, unimsg.buffer, sizeof(message), unimsg.uni_str_len*2,0);
- /* security check */
+
+ pstrcpy(shutdown_script, lp_shutdown_script());
+
+ if ( !*shutdown_script )
+ return WERR_ACCESS_DENIED;
+
+ /* pull the message string and perform necessary sanity checks on it */
+
+ pstrcpy( message, "" );
+ if ( q_u->message ) {
+ UNISTR2 *msg_string = q_u->message->string;
+
+ rpcstr_pull( message, msg_string->buffer, sizeof(message), msg_string->uni_str_len*2, 0 );
+ }
alpha_strcpy (chkmsg, message, NULL, sizeof(message));
- /* timeout */
+
fstr_sprintf(timeout, "%d", q_u->timeout);
- /* reboot */
fstr_sprintf(r, (q_u->reboot) ? SHUTDOWN_R_STRING : "");
- /* force */
fstr_sprintf(f, (q_u->force) ? SHUTDOWN_F_STRING : "");
+ fstr_sprintf( reason, "%d", q_u->reason );
- pstrcpy(shutdown_script, lp_shutdown_script());
-
- if(*shutdown_script) {
- int shutdown_ret;
- SE_PRIV se_shutdown = SE_REMOTE_SHUTDOWN;
- BOOL can_shutdown;
+ all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) );
+ all_string_sub( shutdown_script, "%t", timeout, sizeof(shutdown_script) );
+ all_string_sub( shutdown_script, "%r", r, sizeof(shutdown_script) );
+ all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
+ all_string_sub( shutdown_script, "%x", reason, sizeof(shutdown_script) );
- can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_shutdown );
+ can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
/********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
- if ( can_shutdown )
+
+ /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
+ Take the error return from the script and provide it as the Windows return code. */
+
+ if ( can_shutdown ) {
+ DEBUG(3,("_reg_shutdown_ex: Privilege Check is OK for shutdown \n"));
become_root();
- all_string_sub(shutdown_script, "%m", chkmsg, sizeof(shutdown_script));
- all_string_sub(shutdown_script, "%t", timeout, sizeof(shutdown_script));
- all_string_sub(shutdown_script, "%r", r, sizeof(shutdown_script));
- all_string_sub(shutdown_script, "%f", f, sizeof(shutdown_script));
- shutdown_ret = smbrun(shutdown_script,NULL);
- DEBUG(3,("_reg_shutdown: Running the command `%s' gave %d\n",shutdown_script,shutdown_ret));
+ }
+
+ ret = smbrun( shutdown_script, NULL );
+
+ DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
+ shutdown_script, ret));
+
if ( can_shutdown )
unbecome_root();
+
/********** END SeRemoteShutdownPrivilege BLOCK **********/
- }
- return status;
+ return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
}
+
+
+
/*******************************************************************
reg_abort_shutdwon
********************************************************************/
WERROR _reg_abort_shutdown(pipes_struct *p, REG_Q_ABORT_SHUTDOWN *q_u, REG_R_ABORT_SHUTDOWN *r_u)
{
- WERROR status = WERR_OK;
pstring abort_shutdown_script;
+ int ret;
+ BOOL can_shutdown;
pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
- if(*abort_shutdown_script) {
- int abort_shutdown_ret;
- SE_PRIV se_shutdown = SE_REMOTE_SHUTDOWN;
- BOOL can_shutdown;
+ if ( !*abort_shutdown_script )
+ return WERR_ACCESS_DENIED;
- can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_shutdown );
+ can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
/********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
+
if ( can_shutdown )
become_root();
- abort_shutdown_ret = smbrun(abort_shutdown_script,NULL);
- DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",abort_shutdown_script,abort_shutdown_ret));
+
+ ret = smbrun( abort_shutdown_script, NULL );
+
+ DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
+ abort_shutdown_script, ret));
+
if ( can_shutdown )
unbecome_root();
- /********** END SeRemoteShutdownPrivilege BLOCK **********/
- }
+ /********** END SeRemoteShutdownPrivilege BLOCK **********/
- return status;
+ return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
}
/*******************************************************************
diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c
index 3c611be9ac..2e84a7b909 100644
--- a/source3/rpc_server/srv_spoolss_nt.c
+++ b/source3/rpc_server/srv_spoolss_nt.c
@@ -1491,10 +1491,10 @@ static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q
DEBUG(8,("convert_to_openprinterex\n"));
- q_u_ex->printername_ptr = q_u->printername_ptr;
-
- if (q_u->printername_ptr)
- copy_unistr2(&q_u_ex->printername, &q_u->printername);
+ if ( q_u->printername ) {
+ q_u_ex->printername = TALLOC_P( ctx, UNISTR2 );
+ copy_unistr2(q_u_ex->printername, q_u->printername);
+ }
copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
}
@@ -1588,7 +1588,6 @@ WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R
WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
{
- UNISTR2 *printername = NULL;
PRINTER_DEFAULT *printer_default = &q_u->printer_default;
POLICY_HND *handle = &r_u->handle;
@@ -1597,15 +1596,13 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
struct current_user user;
Printer_entry *Printer=NULL;
- if (q_u->printername_ptr != 0)
- printername = &q_u->printername;
-
- if (printername == NULL)
+ if ( !q_u->printername )
return WERR_INVALID_PRINTER_NAME;
/* some sanity check because you can open a printer or a print server */
/* aka: \\server\printer or \\server */
- unistr2_to_ascii(name, printername, sizeof(name)-1);
+
+ unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
DEBUGADD(3,("checking name: %s\n",name));
@@ -7595,7 +7592,7 @@ static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_
WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
{
- UNISTR2 *uni_srv_name = &q_u->server_name;
+ UNISTR2 *uni_srv_name = q_u->server_name;
uint32 level = q_u->level;
SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
diff --git a/source3/rpc_server/srv_svcctl.c b/source3/rpc_server/srv_svcctl.c
new file mode 100644
index 0000000000..85fb9f9ce3
--- /dev/null
+++ b/source3/rpc_server/srv_svcctl.c
@@ -0,0 +1,294 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * RPC Pipe client / server routines
+ * Copyright (C) Gerald Carter 2005.
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
+/*******************************************************************
+ ********************************************************************/
+
+static BOOL api_svcctl_close_service(pipes_struct *p)
+{
+ SVCCTL_Q_CLOSE_SERVICE q_u;
+ SVCCTL_R_CLOSE_SERVICE r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!svcctl_io_q_close_service("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _svcctl_close_service(p, &q_u, &r_u);
+
+ if(!svcctl_io_r_close_service("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+static BOOL api_svcctl_open_scmanager(pipes_struct *p)
+{
+ SVCCTL_Q_OPEN_SCMANAGER q_u;
+ SVCCTL_R_OPEN_SCMANAGER r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!svcctl_io_q_open_scmanager("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _svcctl_open_scmanager(p, &q_u, &r_u);
+
+ if(!svcctl_io_r_open_scmanager("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+static BOOL api_svcctl_open_service(pipes_struct *p)
+{
+ SVCCTL_Q_OPEN_SERVICE q_u;
+ SVCCTL_R_OPEN_SERVICE r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!svcctl_io_q_open_service("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _svcctl_open_service(p, &q_u, &r_u);
+
+ if(!svcctl_io_r_open_service("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+static BOOL api_svcctl_get_display_name(pipes_struct *p)
+{
+ SVCCTL_Q_GET_DISPLAY_NAME q_u;
+ SVCCTL_R_GET_DISPLAY_NAME r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!svcctl_io_q_get_display_name("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _svcctl_get_display_name(p, &q_u, &r_u);
+
+ if(!svcctl_io_r_get_display_name("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+static BOOL api_svcctl_query_status(pipes_struct *p)
+{
+ SVCCTL_Q_QUERY_STATUS q_u;
+ SVCCTL_R_QUERY_STATUS r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!svcctl_io_q_query_status("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _svcctl_query_status(p, &q_u, &r_u);
+
+ if(!svcctl_io_r_query_status("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+static BOOL api_svcctl_enum_services_status(pipes_struct *p)
+{
+ SVCCTL_Q_ENUM_SERVICES_STATUS q_u;
+ SVCCTL_R_ENUM_SERVICES_STATUS r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!svcctl_io_q_enum_services_status("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _svcctl_enum_services_status(p, &q_u, &r_u);
+
+ if(!svcctl_io_r_enum_services_status("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+static BOOL api_svcctl_enum_dependent_services(pipes_struct *p)
+{
+ SVCCTL_Q_ENUM_DEPENDENT_SERVICES q_u;
+ SVCCTL_R_ENUM_DEPENDENT_SERVICES r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!svcctl_io_q_enum_dependent_services("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _svcctl_enum_dependent_services(p, &q_u, &r_u);
+
+ if(!svcctl_io_r_enum_dependent_services("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+static BOOL api_svcctl_start_service(pipes_struct *p)
+{
+ SVCCTL_Q_START_SERVICE q_u;
+ SVCCTL_R_START_SERVICE r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!svcctl_io_q_start_service("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _svcctl_start_service(p, &q_u, &r_u);
+
+ if(!svcctl_io_r_start_service("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+static BOOL api_svcctl_control_service(pipes_struct *p)
+{
+ SVCCTL_Q_CONTROL_SERVICE q_u;
+ SVCCTL_R_CONTROL_SERVICE r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!svcctl_io_q_control_service("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _svcctl_control_service(p, &q_u, &r_u);
+
+ if(!svcctl_io_r_control_service("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+static BOOL api_svcctl_query_service_config(pipes_struct *p)
+{
+ SVCCTL_Q_QUERY_SERVICE_CONFIG q_u;
+ SVCCTL_R_QUERY_SERVICE_CONFIG r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!svcctl_io_q_query_service_config("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _svcctl_query_service_config(p, &q_u, &r_u);
+
+ if(!svcctl_io_r_query_service_config("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ \PIPE\svcctl commands
+ ********************************************************************/
+
+static struct api_struct api_svcctl_cmds[] =
+{
+ { "SVCCTL_CLOSE_SERVICE" , SVCCTL_CLOSE_SERVICE , api_svcctl_close_service },
+ { "SVCCTL_OPEN_SCMANAGER_W" , SVCCTL_OPEN_SCMANAGER_W , api_svcctl_open_scmanager },
+ { "SVCCTL_OPEN_SERVICE_W" , SVCCTL_OPEN_SERVICE_W , api_svcctl_open_service },
+ { "SVCCTL_GET_DISPLAY_NAME" , SVCCTL_GET_DISPLAY_NAME , api_svcctl_get_display_name },
+ { "SVCCTL_QUERY_STATUS" , SVCCTL_QUERY_STATUS , api_svcctl_query_status },
+ { "SVCCTL_QUERY_SERVICE_CONFIG_W", SVCCTL_QUERY_SERVICE_CONFIG_W, api_svcctl_query_service_config },
+ { "SVCCTL_ENUM_SERVICES_STATUS_W", SVCCTL_ENUM_SERVICES_STATUS_W, api_svcctl_enum_services_status },
+ { "SVCCTL_ENUM_DEPENDENT_SERVICES_W", SVCCTL_ENUM_DEPENDENT_SERVICES_W, api_svcctl_enum_dependent_services },
+ { "SVCCTL_START_SERVICE_W" , SVCCTL_START_SERVICE_W , api_svcctl_start_service },
+ { "SVCCTL_CONTROL_SERVICE" , SVCCTL_CONTROL_SERVICE , api_svcctl_control_service }
+};
+
+void svcctl_get_pipe_fns( struct api_struct **fns, int *n_fns )
+{
+ *fns = api_svcctl_cmds;
+ *n_fns = sizeof(api_svcctl_cmds) / sizeof(struct api_struct);
+}
+
+NTSTATUS rpc_svcctl_init(void)
+{
+ return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, "svcctl", "ntsvcs", api_svcctl_cmds,
+ sizeof(api_svcctl_cmds) / sizeof(struct api_struct));
+}
diff --git a/source3/rpc_server/srv_svcctl_nt.c b/source3/rpc_server/srv_svcctl_nt.c
new file mode 100644
index 0000000000..19244d2208
--- /dev/null
+++ b/source3/rpc_server/srv_svcctl_nt.c
@@ -0,0 +1,291 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * RPC Pipe client / server routines
+ * Copyright (C) Gerald (Jerry) Carter 2005
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
+/*
+ * sertup the \PIPE\svcctl db API
+ */
+
+static TDB_CONTEXT *svcctl_tdb; /* used for share security descriptors */
+
+#define SCVCTL_DATABASE_VERSION_V1 1
+
+/********************************************************************
+********************************************************************/
+
+static BOOL init_svcctl_db( void )
+{
+ static pid_t local_pid;
+ const char *vstring = "INFO/version";
+
+ /* see if we've already opened the tdb */
+
+ if (svcctl_tdb && local_pid == sys_getpid())
+ return True;
+
+ /* so open it */
+ if ( !(svcctl_tdb = tdb_open_log(lock_path("svcctl.tdb"), 0, TDB_DEFAULT,
+ O_RDWR|O_CREAT, 0600)))
+ {
+ DEBUG(0,("Failed to open svcctl database %s (%s)\n",
+ lock_path("svcctl.tdb"), strerror(errno) ));
+ return False;
+ }
+
+ local_pid = sys_getpid();
+
+ /***** BEGIN Check the tdb version ******/
+
+ tdb_lock_bystring(svcctl_tdb, vstring, 0);
+
+ if ( tdb_fetch_int32(svcctl_tdb, vstring) != SCVCTL_DATABASE_VERSION_V1 )
+ tdb_store_int32(svcctl_tdb, vstring, SCVCTL_DATABASE_VERSION_V1);
+
+ tdb_unlock_bystring(svcctl_tdb, vstring);
+
+ /***** END Check the tdb version ******/
+
+ return True;
+}
+
+/********************************************************************
+ TODO
+ (a) get and set security descriptors on services
+ (b) read and write QUERY_SERVICE_CONFIG structures
+ (c) create default secdesc objects for services and SCM
+ (d) check access control masks with se_access_check()
+ (e) implement SERVICE * for associating with open handles
+********************************************************************/
+
+/********************************************************************
+********************************************************************/
+
+WERROR _svcctl_open_scmanager(pipes_struct *p, SVCCTL_Q_OPEN_SCMANAGER *q_u, SVCCTL_R_OPEN_SCMANAGER *r_u)
+{
+ /* just fake it for now */
+
+ if ( !create_policy_hnd( p, &r_u->handle, NULL, NULL ) )
+ return WERR_ACCESS_DENIED;
+
+ return WERR_OK;
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR _svcctl_open_service(pipes_struct *p, SVCCTL_Q_OPEN_SERVICE *q_u, SVCCTL_R_OPEN_SERVICE *r_u)
+{
+ fstring service;
+
+ rpcstr_pull(service, q_u->servicename.buffer, sizeof(service), q_u->servicename.uni_str_len*2, 0);
+
+ /* can only be called on service name (not displayname) */
+
+ if ( !(strequal( service, "NETLOGON") || strequal(service, "Spooler")) )
+ return WERR_NO_SUCH_SERVICE;
+
+ if ( !create_policy_hnd( p, &r_u->handle, NULL, NULL ) )
+ return WERR_ACCESS_DENIED;
+
+ return WERR_OK;
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR _svcctl_close_service(pipes_struct *p, SVCCTL_Q_CLOSE_SERVICE *q_u, SVCCTL_R_CLOSE_SERVICE *r_u)
+{
+ if ( !close_policy_hnd( p, &q_u->handle ) )
+ return WERR_BADFID;
+
+ return WERR_OK;
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR _svcctl_get_display_name(pipes_struct *p, SVCCTL_Q_GET_DISPLAY_NAME *q_u, SVCCTL_R_GET_DISPLAY_NAME *r_u)
+{
+ fstring service;
+ fstring displayname;
+
+ rpcstr_pull(service, q_u->servicename.buffer, sizeof(service), q_u->servicename.uni_str_len*2, 0);
+
+ DEBUG(10,("_svcctl_get_display_name: service name [%s]\n", service));
+
+ if ( !strequal( service, "NETLOGON" ) )
+ return WERR_ACCESS_DENIED;
+
+ fstrcpy( displayname, "Net Logon");
+ init_svcctl_r_get_display_name( r_u, displayname );
+
+ return WERR_OK;
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR _svcctl_query_status(pipes_struct *p, SVCCTL_Q_QUERY_STATUS *q_u, SVCCTL_R_QUERY_STATUS *r_u)
+{
+
+ r_u->svc_status.type = 0x0110;
+ r_u->svc_status.state = 0x0004;
+ r_u->svc_status.controls_accepted = 0x0005;
+
+ return WERR_OK;
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR _svcctl_enum_services_status(pipes_struct *p, SVCCTL_Q_ENUM_SERVICES_STATUS *q_u, SVCCTL_R_ENUM_SERVICES_STATUS *r_u)
+{
+ ENUM_SERVICES_STATUS *services = NULL;
+ uint32 num_services = 0;
+ int i = 0;
+ size_t buffer_size;
+ WERROR result = WERR_OK;
+
+ /* num_services = str_list_count( lp_enable_svcctl() ); */
+ num_services = 2;
+
+ if ( !(services = TALLOC_ARRAY( p->mem_ctx, ENUM_SERVICES_STATUS, num_services )) )
+ return WERR_NOMEM;
+
+ DEBUG(8,("_svcctl_enum_services_status: Enumerating %d services\n", num_services));
+
+ init_unistr( &services[i].servicename, "Spooler" );
+ init_unistr( &services[i].displayname, "Spooler" );
+
+ services[i].status.type = 0x110;
+ services[i].status.controls_accepted = 0x0;
+ services[i].status.win32_exit_code = 0x0;
+ services[i].status.service_exit_code = 0x0;
+ services[i].status.check_point = 0x0;
+ services[i].status.wait_hint = 0x0;
+ if ( !lp_disable_spoolss() )
+ services[i].status.state = SVCCTL_RUNNING;
+ else
+ services[i].status.state = SVCCTL_STOPPED;
+
+ i++;
+
+ init_unistr( &services[i].servicename, "Netlogon" );
+ init_unistr( &services[i].displayname, "Net Logon" );
+
+ services[i].status.type = 0x20;
+ services[i].status.controls_accepted = 0x0;
+ services[i].status.win32_exit_code = 0x0;
+ services[i].status.service_exit_code = 0x0;
+ services[i].status.check_point = 0x0;
+ services[i].status.wait_hint = 0x0;
+ if ( lp_servicenumber("NETLOGON") != -1 )
+ services[i].status.state = SVCCTL_RUNNING;
+ else
+ services[i].status.state = SVCCTL_STOPPED;
+
+ buffer_size = 0;
+ for (i=0; i<num_services; i++ )
+ buffer_size += svcctl_sizeof_enum_services_status( &services[i] );
+
+ buffer_size += buffer_size % 4;
+
+ if ( buffer_size > q_u->buffer_size ) {
+ num_services = 0;
+ result = WERR_MORE_DATA;
+ }
+
+ /* we have to set the outgoing buffer size to the same as the
+ incoming buffer size (even in the case of failure */
+
+ rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx );
+
+ if ( W_ERROR_IS_OK(result) ) {
+ for ( i=0; i<num_services; i++ )
+ svcctl_io_enum_services_status( "", &services[i], &r_u->buffer, 0 );
+ }
+
+ r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size;
+ r_u->returned = num_services;
+
+ if ( !(r_u->resume = TALLOC_P( p->mem_ctx, uint32 )) )
+ return WERR_NOMEM;
+
+ *r_u->resume = 0x0;
+
+ return result;
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR _svcctl_start_service(pipes_struct *p, SVCCTL_Q_START_SERVICE *q_u, SVCCTL_R_START_SERVICE *r_u)
+{
+ return WERR_ACCESS_DENIED;
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR _svcctl_control_service(pipes_struct *p, SVCCTL_Q_CONTROL_SERVICE *q_u, SVCCTL_R_CONTROL_SERVICE *r_u)
+{
+ return WERR_ACCESS_DENIED;
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR _svcctl_enum_dependent_services( pipes_struct *p, SVCCTL_Q_ENUM_DEPENDENT_SERVICES *q_u, SVCCTL_R_ENUM_DEPENDENT_SERVICES *r_u )
+{
+
+ /* we have to set the outgoing buffer size to the same as the
+ incoming buffer size (even in the case of failure */
+
+ rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx );
+
+ r_u->needed = q_u->buffer_size;
+
+ /* no dependent services...basically a stub function */
+ r_u->returned = 0;
+
+ return WERR_OK;
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR _svcctl_query_service_config( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CONFIG *q_u, SVCCTL_R_QUERY_SERVICE_CONFIG *r_u )
+{
+
+ /* we have to set the outgoing buffer size to the same as the
+ incoming buffer size (even in the case of failure */
+
+ r_u->needed = q_u->buffer_size;
+
+ /* no dependent services...basically a stub function */
+
+ return WERR_ACCESS_DENIED;
+}
+
+