summaryrefslogtreecommitdiff
path: root/source3/lib
diff options
context:
space:
mode:
Diffstat (limited to 'source3/lib')
-rw-r--r--source3/lib/doscalls.c2
-rw-r--r--source3/lib/msrpc-client.c400
-rw-r--r--source3/lib/msrpc_use.c328
-rw-r--r--source3/lib/util.c15
-rw-r--r--source3/lib/util_array.c194
-rw-r--r--source3/lib/util_sid.c290
-rw-r--r--source3/lib/util_sock.c100
7 files changed, 1327 insertions, 2 deletions
diff --git a/source3/lib/doscalls.c b/source3/lib/doscalls.c
index e6f9d19879..1d459898b5 100644
--- a/source3/lib/doscalls.c
+++ b/source3/lib/doscalls.c
@@ -158,7 +158,7 @@ int dos_utime(char *fname,struct utimbuf *times)
<warrenb@hpcvscdp.cv.hp.com>
**********************************************************/
-static int copy_reg(char *source, const char *dest)
+int copy_reg(char *source, const char *dest)
{
SMB_STRUCT_STAT source_stats;
int ifd;
diff --git a/source3/lib/msrpc-client.c b/source3/lib/msrpc-client.c
new file mode 100644
index 0000000000..051a051093
--- /dev/null
+++ b/source3/lib/msrpc-client.c
@@ -0,0 +1,400 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ SMB msrpcent generic functions
+ Copyright (C) Andrew Tridgell 1994-1999
+ Copyright (C) Luke Kenneth Casson Leighton 1996-1999
+
+ 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.
+*/
+
+#define NO_SYSLOG
+
+#include "includes.h"
+
+extern int DEBUGLEVEL;
+
+/****************************************************************************
+ read an msrpc pdu from a fd.
+ The timeout is in milliseconds.
+****************************************************************************/
+BOOL receive_msrpc(int fd, prs_struct *data, unsigned int timeout)
+{
+ BOOL ok;
+ size_t len;
+ RPC_HDR hdr;
+
+ prs_init(data, 0, 4, True);
+
+ ok = prs_read(data, fd, 16, timeout);
+
+ if (!ok)
+ {
+ prs_mem_free(data);
+ return False;
+ }
+
+ if (!smb_io_rpc_hdr("hdr", &hdr, data, 0))
+ {
+ prs_mem_free(data);
+ return False;
+ }
+
+ len = hdr.frag_len - 16;
+ if (len > 0)
+ {
+ ok = prs_read(data, fd, hdr.frag_len, 0);
+ if (!ok)
+ {
+ prs_mem_free(data);
+ return False;
+ }
+ data->data_offset = hdr.frag_len;
+ return True;
+ }
+
+ prs_mem_free(data);
+ return False;
+}
+
+/****************************************************************************
+ send an smb to a fd and re-establish if necessary
+****************************************************************************/
+BOOL msrpc_send(int fd, prs_struct *ps)
+{
+ size_t len = ps != NULL ? ps->buffer_size : 0;
+ size_t nwritten=0;
+ ssize_t ret;
+ char *outbuf = ps->data_p;
+
+ DEBUG(10,("msrpc_send_prs: data: %p len %d\n", outbuf, len));
+ dbgflush();
+
+ dump_data(10, outbuf, len);
+
+ while (nwritten < len)
+ {
+ ret = write_socket(fd,outbuf+nwritten,len - nwritten);
+ if (ret <= 0)
+ {
+ DEBUG(0,("Error writing %d msrpc bytes. %d.\n",
+ len,ret));
+ prs_mem_free(ps);
+ return False;
+ }
+ nwritten += ret;
+ }
+
+ prs_mem_free(ps);
+ return True;
+}
+
+/****************************************************************************
+ receive msrpc packet
+****************************************************************************/
+BOOL msrpc_receive(int fd, prs_struct *ps)
+{
+ int len;
+
+ DEBUG(10,("msrpc_receive: %d\n", __LINE__));
+
+ if (!receive_msrpc(fd, ps, 0))
+ {
+ return False;
+ }
+
+ len = ps->buffer_size;
+
+ if (ps->data_p == NULL || len <= 0)
+ {
+ return False;
+ }
+
+ dump_data(10, ps->data_p, len);
+
+ DEBUG(10,("msrpc_receive: len %d\n", len));
+
+ return True;
+}
+
+/****************************************************************************
+open the msrpcent sockets
+****************************************************************************/
+BOOL msrpc_connect(struct msrpc_state *msrpc, const char *pipe_name)
+{
+ fstring path;
+ slprintf(path, sizeof(path)-1, "%s/.msrpc/%s", LOCKDIR, pipe_name);
+
+ fstrcpy(msrpc->pipe_name, pipe_name);
+
+ msrpc->fd = open_pipe_sock(path);
+
+ if (msrpc->fd == -1)
+ {
+ return False;
+ }
+
+ return True;
+}
+
+
+/****************************************************************************
+initialise a msrpcent structure
+****************************************************************************/
+void msrpc_init_creds(struct msrpc_state *msrpc, const struct user_creds *usr)
+{
+ copy_user_creds(&msrpc->usr, usr);
+}
+
+/****************************************************************************
+close the socket descriptor
+****************************************************************************/
+void msrpc_close_socket(struct msrpc_state *msrpc)
+{
+ if (msrpc->fd != -1)
+ {
+ close(msrpc->fd);
+ }
+ msrpc->fd = -1;
+}
+
+
+/****************************************************************************
+set socket options on a open connection
+****************************************************************************/
+void msrpc_sockopt(struct msrpc_state *msrpc, char *options)
+{
+ set_socket_options(msrpc->fd, options);
+}
+
+
+static BOOL msrpc_authenticate(struct msrpc_state *msrpc,
+ const struct user_creds *usr)
+{
+ struct msrpc_state msrpc_redir;
+
+ int sock = msrpc->fd;
+ char *data;
+ prs_struct ps;
+ uint32 len;
+ char *in = msrpc->inbuf;
+ char *out = msrpc->outbuf;
+ uint16 command;
+
+ command = usr != NULL ? AGENT_CMD_CON : AGENT_CMD_CON_ANON;
+
+ if (!create_user_creds(&ps, msrpc->pipe_name, 0x0, command, usr))
+ {
+ DEBUG(0,("could not parse credentials\n"));
+ close(sock);
+ return False;
+ }
+
+ len = ps.data_offset;
+ data = ps.data_p;
+
+ SIVAL(data, 0, len);
+
+#ifdef DEBUG_PASSWORD
+ DEBUG(100,("data len: %d\n", len));
+ dump_data(100, data, len);
+#endif
+
+ if (write(sock, data, len) <= 0)
+ {
+ DEBUG(0,("write failed\n"));
+ return False;
+ }
+
+ if (msrpc->redirect)
+ {
+ len = read(sock, &msrpc_redir, sizeof(msrpc_redir));
+
+ if (len != sizeof(msrpc_redir))
+ {
+ DEBUG(0,("read failed\n"));
+ return False;
+ }
+
+ memcpy(msrpc, &msrpc_redir, sizeof(msrpc_redir));
+ msrpc->inbuf = in;
+ msrpc->outbuf = out;
+ msrpc->fd = sock;
+ msrpc->usr.reuse = False;
+ }
+ else
+ {
+ uint32 status;
+ len = read(sock, &status, sizeof(status));
+
+ return len == sizeof(status) && status == 0x0;
+ }
+ return True;
+}
+
+static BOOL msrpc_init_redirect(struct msrpc_state *msrpc,
+ const char* pipe_name,
+ const struct user_creds *usr)
+{
+ int sock;
+ fstring path;
+
+ slprintf(path, sizeof(path)-1, "/tmp/.msrpc/.%s/agent", pipe_name);
+
+ sock = open_pipe_sock(path);
+
+ if (sock < 0)
+ {
+ return False;
+ }
+
+ msrpc->fd = sock;
+
+ if (!msrpc_authenticate(msrpc, usr))
+ {
+ DEBUG(0,("authenticate failed\n"));
+ close(msrpc->fd);
+ msrpc->fd = -1;
+ return False;
+ }
+
+ return True;
+}
+
+BOOL msrpc_connect_auth(struct msrpc_state *msrpc,
+ const char* pipename,
+ const struct user_creds *usr)
+{
+ ZERO_STRUCTP(msrpc);
+ if (!msrpc_initialise(msrpc))
+ {
+ DEBUG(0,("unable to initialise msrpcent connection.\n"));
+ return False;
+ }
+
+ msrpc_init_creds(msrpc, usr);
+
+ if (!msrpc_establish_connection(msrpc, pipename))
+ {
+ msrpc_shutdown(msrpc);
+ return False;
+ }
+
+ return True;
+}
+
+/****************************************************************************
+initialise a msrpcent structure
+****************************************************************************/
+struct msrpc_state *msrpc_initialise(struct msrpc_state *msrpc)
+{
+ if (!msrpc) {
+ msrpc = (struct msrpc_state *)malloc(sizeof(*msrpc));
+ if (!msrpc)
+ return NULL;
+ ZERO_STRUCTP(msrpc);
+ }
+
+ if (msrpc->initialised) {
+ msrpc_shutdown(msrpc);
+ }
+
+ ZERO_STRUCTP(msrpc);
+
+ msrpc->fd = -1;
+ msrpc->outbuf = (char *)malloc(CLI_BUFFER_SIZE+4);
+ msrpc->inbuf = (char *)malloc(CLI_BUFFER_SIZE+4);
+ if (!msrpc->outbuf || !msrpc->inbuf)
+ {
+ return False;
+ }
+
+ msrpc->initialised = 1;
+ msrpc_init_creds(msrpc, NULL);
+
+ return msrpc;
+}
+
+
+/****************************************************************************
+shutdown a msrpcent structure
+****************************************************************************/
+void msrpc_shutdown(struct msrpc_state *msrpc)
+{
+ DEBUG(10,("msrpc_shutdown\n"));
+ if (msrpc->outbuf)
+ {
+ free(msrpc->outbuf);
+ }
+ if (msrpc->inbuf)
+ {
+ free(msrpc->inbuf);
+ }
+ msrpc_close_socket(msrpc);
+ memset(msrpc, 0, sizeof(*msrpc));
+}
+
+/****************************************************************************
+establishes a connection right up to doing tconX, reading in a password.
+****************************************************************************/
+BOOL msrpc_establish_connection(struct msrpc_state *msrpc,
+ const char *pipe_name)
+{
+ DEBUG(5,("msrpc_establish_connection: connecting to %s (%s) - %s\n",
+ pipe_name,
+ msrpc->usr.ntc.user_name, msrpc->usr.ntc.domain));
+
+ /* establish connection */
+
+ if ((!msrpc->initialised))
+ {
+ return False;
+ }
+
+ if (msrpc->fd == -1 && msrpc->redirect)
+ {
+ if (msrpc_init_redirect(msrpc, pipe_name, &msrpc->usr))
+ {
+ DEBUG(10,("msrpc_establish_connection: redirected OK\n"));
+ return True;
+ }
+ else
+ {
+ DEBUG(10,("redirect FAILED\n"));
+ return False;
+ }
+ }
+ if (msrpc->fd == -1)
+ {
+ if (!msrpc_connect(msrpc, pipe_name))
+ {
+ DEBUG(1,("msrpc_establish_connection: failed %s)\n",
+ pipe_name));
+
+ return False;
+ }
+ }
+
+ if (!msrpc_authenticate(msrpc, &msrpc->usr))
+ {
+ DEBUG(0,("authenticate failed\n"));
+ close(msrpc->fd);
+ msrpc->fd = -1;
+ return False;
+ }
+
+ return True;
+}
+
diff --git a/source3/lib/msrpc_use.c b/source3/lib/msrpc_use.c
new file mode 100644
index 0000000000..c755a35fb4
--- /dev/null
+++ b/source3/lib/msrpc_use.c
@@ -0,0 +1,328 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ SMB client generic functions
+ Copyright (C) Andrew Tridgell 1994-1999
+ Copyright (C) Luke Kenneth Casson Leighton 1996-1999
+
+ 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.
+*/
+
+#define NO_SYSLOG
+
+#include "includes.h"
+#include "trans2.h"
+
+extern int DEBUGLEVEL;
+extern pstring scope;
+extern pstring global_myname;
+
+struct msrpc_use
+{
+ struct msrpc_state *cli;
+ uint32 num_users;
+};
+
+static struct msrpc_use **msrpcs = NULL;
+uint32 num_msrpcs = 0;
+
+/****************************************************************************
+terminate client connection
+****************************************************************************/
+static void msrpc_use_free(struct msrpc_use *cli)
+{
+ if (cli->cli != NULL)
+ {
+ if (cli->cli->initialised)
+ {
+ msrpc_shutdown(cli->cli);
+ }
+ free(cli->cli);
+ }
+
+ free(cli);
+}
+
+/****************************************************************************
+free a client array
+****************************************************************************/
+static void free_msrpc_array(uint32 num_entries, struct msrpc_use **entries)
+{
+ void(*fn)(void*) = (void(*)(void*))&msrpc_use_free;
+ free_void_array(num_entries, (void**)entries, *fn);
+}
+
+/****************************************************************************
+add a client state to the array
+****************************************************************************/
+static struct msrpc_use* add_msrpc_to_array(uint32 *len,
+ struct msrpc_use ***array,
+ struct msrpc_use *cli)
+{
+ int i;
+ for (i = 0; i < num_msrpcs; i++)
+ {
+ if (msrpcs[i] == NULL)
+ {
+ msrpcs[i] = cli;
+ return cli;
+ }
+ }
+
+ return (struct msrpc_use*)add_item_to_array(len,
+ (void***)array, (void*)cli);
+
+}
+
+/****************************************************************************
+initiate client array
+****************************************************************************/
+void init_msrpc_use(void)
+{
+ msrpcs = NULL;
+ num_msrpcs = 0;
+}
+
+/****************************************************************************
+terminate client array
+****************************************************************************/
+void free_msrpc_use(void)
+{
+ free_msrpc_array(num_msrpcs, msrpcs);
+ init_msrpc_use();
+}
+
+/****************************************************************************
+find client state. server name, user name, domain name and password must all
+match.
+****************************************************************************/
+static struct msrpc_use *msrpc_find(const char* pipe_name,
+ const struct user_creds *usr_creds)
+{
+ int i;
+ struct user_creds null_usr;
+
+ if (usr_creds == NULL)
+ {
+ copy_user_creds(&null_usr, usr_creds);
+ usr_creds = &null_usr;
+ }
+
+ DEBUG(10,("msrpc_find: %s %s %s\n",
+ pipe_name,
+ usr_creds->ntc.user_name,
+ usr_creds->ntc.domain));
+
+ for (i = 0; i < num_msrpcs; i++)
+ {
+ char *msrpc_name = NULL;
+ struct msrpc_use *c = msrpcs[i];
+
+ if (c == NULL) continue;
+
+ msrpc_name = c->cli->pipe_name;
+
+ DEBUG(10,("msrpc_find[%d]: %s %s %s\n",
+ i, msrpc_name,
+ c->cli->usr.ntc.user_name,
+ c->cli->usr.ntc.domain));
+
+ if (!strequal(msrpc_name, pipe_name))
+ {
+ continue;
+ }
+ if (!strequal(usr_creds->ntc.user_name, c->cli->usr.ntc.user_name))
+ {
+ continue;
+ }
+ if (!usr_creds->reuse &&
+ !pwd_compare(&usr_creds->ntc.pwd, &c->cli->usr.ntc.pwd))
+ {
+ DEBUG(100,("password doesn't match\n"));
+ continue;
+ }
+ if (usr_creds->ntc.domain[0] == 0)
+ {
+ return c;
+ }
+ if (strequal(usr_creds->ntc.domain, c->cli->usr.ntc.domain))
+ {
+ return c;
+ }
+ }
+
+ return NULL;
+}
+
+/****************************************************************************
+create a new client state from user credentials
+****************************************************************************/
+static struct msrpc_use *msrpc_use_get(const char* pipe_name,
+ const struct user_creds *usr_creds)
+{
+ struct msrpc_use *cli = (struct msrpc_use*)malloc(sizeof(*cli));
+
+ if (cli == NULL)
+ {
+ return NULL;
+ }
+
+ memset(cli, 0, sizeof(*cli));
+
+ cli->cli = msrpc_initialise(NULL);
+
+ if (cli->cli == NULL)
+ {
+ return NULL;
+ }
+
+ msrpc_init_creds(cli->cli, usr_creds);
+
+ return cli;
+}
+
+/****************************************************************************
+init client state
+****************************************************************************/
+struct msrpc_state *msrpc_use_add(const char* pipe_name,
+ const struct user_creds *usr_creds,
+ BOOL redir)
+{
+ struct msrpc_use *cli;
+ DEBUG(10,("msrpc_use_add: %s redir: %s\n", pipe_name, BOOLSTR(redir)));
+
+ cli = msrpc_find(pipe_name, usr_creds);
+
+ if (cli != NULL)
+ {
+ cli->num_users++;
+ return cli->cli;
+ }
+
+ /* reuse an existing connection requested, and one was not found */
+ if (usr_creds != NULL && usr_creds->reuse && !redir)
+ {
+ DEBUG(0,("msrpc_use_add: reuse requested, but one not found\n"));
+ return False;
+ }
+
+ /*
+ * allocate
+ */
+
+ cli = msrpc_use_get(pipe_name, usr_creds);
+ cli->cli->redirect = redir;
+
+ if (!msrpc_establish_connection(cli->cli, pipe_name))
+ {
+ DEBUG(0,("msrpc_use_add: connection failed\n"));
+ cli->cli = NULL;
+ msrpc_use_free(cli);
+ return NULL;
+ }
+
+ add_msrpc_to_array(&num_msrpcs, &msrpcs, cli);
+ cli->num_users++;
+
+ return cli->cli;
+}
+
+/****************************************************************************
+delete a client state
+****************************************************************************/
+BOOL msrpc_use_del(const char* pipe_name,
+ const struct user_creds *usr_creds,
+ BOOL force_close,
+ BOOL *connection_closed)
+{
+ int i;
+
+ DEBUG(10,("msrpc_net_use_del: %s. force close: %s\n",
+ pipe_name, BOOLSTR(force_close)));
+
+ if (connection_closed != NULL)
+ {
+ *connection_closed = False;
+ }
+
+ for (i = 0; i < num_msrpcs; i++)
+ {
+ char *msrpc_name = NULL;
+
+ if (msrpcs[i] == NULL) continue;
+ if (msrpcs[i]->cli == NULL) continue;
+
+ msrpc_name = msrpcs[i]->cli->pipe_name;
+
+ if (!strequal(msrpc_name, pipe_name)) continue;
+
+ if (strequal(usr_creds->ntc.user_name,
+ msrpcs[i]->cli->usr.ntc.user_name) &&
+ strequal(usr_creds->ntc.domain,
+ msrpcs[i]->cli->usr.ntc.domain))
+ {
+ /* decrement number of users */
+ msrpcs[i]->num_users--;
+
+ DEBUG(10,("idx: %i num_users now: %d\n",
+ i, msrpcs[i]->num_users));
+
+ if (force_close || msrpcs[i]->num_users == 0)
+ {
+ msrpc_use_free(msrpcs[i]);
+ msrpcs[i] = NULL;
+ if (connection_closed != NULL)
+ {
+ *connection_closed = True;
+ }
+ }
+ return True;
+ }
+ }
+
+ return False;
+}
+
+/****************************************************************************
+enumerate client states
+****************************************************************************/
+void msrpc_net_use_enum(uint32 *num_cons, struct use_info ***use)
+{
+ int i;
+
+ *num_cons = 0;
+ *use = NULL;
+
+ for (i = 0; i < num_msrpcs; i++)
+ {
+ struct use_info item;
+
+ ZERO_STRUCT(item);
+
+ if (msrpcs[i] == NULL) continue;
+
+ item.connected = msrpcs[i]->cli != NULL ? True : False;
+
+ if (item.connected)
+ {
+ item.srv_name = msrpcs[i]->cli->pipe_name;
+ item.user_name = msrpcs[i]->cli->usr.ntc.user_name;
+ item.domain = msrpcs[i]->cli->usr.ntc.domain;
+ }
+
+ add_use_info_to_array(num_cons, use, &item);
+ }
+}
+
diff --git a/source3/lib/util.c b/source3/lib/util.c
index 0ad14ad3ae..1a893c52ce 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -358,6 +358,21 @@ BOOL file_exist(char *fname,SMB_STRUCT_STAT *sbuf)
}
/*******************************************************************
+ rename a unix file
+********************************************************************/
+int file_rename(char *from, char *to)
+{
+ int rcode = rename (from, to);
+
+ if (errno == EXDEV)
+ {
+ /* Rename across filesystems needed. */
+ rcode = copy_reg (from, to);
+ }
+ return rcode;
+}
+
+/*******************************************************************
check a files mod time
********************************************************************/
time_t file_modtime(char *fname)
diff --git a/source3/lib/util_array.c b/source3/lib/util_array.c
new file mode 100644
index 0000000000..567c170834
--- /dev/null
+++ b/source3/lib/util_array.c
@@ -0,0 +1,194 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ Samba utility functions
+ Copyright (C) Andrew Tridgell 1992-1999
+ Copyright (C) Luke Kenneth Casson Leighton 1996-1999
+
+ 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"
+
+void free_void_array(uint32 num_entries, void **entries,
+ void(free_item)(void*))
+{
+ uint32 i;
+ if (entries != NULL)
+ {
+ for (i = 0; i < num_entries; i++)
+ {
+ if (entries[i] != NULL)
+ {
+ free_item(entries[i]);
+ }
+ }
+ free(entries);
+ }
+}
+
+void* add_copy_to_array(uint32 *len, void ***array, const void *item,
+ void*(item_dup)(const void*), BOOL alloc_anyway)
+{
+ void* copy = NULL;
+ if (len == NULL || array == NULL)
+ {
+ return NULL;
+ }
+
+ if (item != NULL || alloc_anyway)
+ {
+ copy = item_dup(item);
+ return add_item_to_array(len, array, copy);
+ }
+ return copy;
+}
+
+void* add_item_to_array(uint32 *len, void ***array, void *item)
+{
+ if (len == NULL || array == NULL)
+ {
+ return NULL;
+ }
+
+ (*array) = (void**)Realloc((*array), ((*len)+1)*sizeof((*array)[0]));
+
+ if ((*array) != NULL)
+ {
+ (*array)[(*len)] = item;
+ (*len)++;
+ return item;
+ }
+ return NULL;
+}
+
+static void use_info_free(struct use_info *item)
+{
+ if (item != NULL)
+ {
+ if (item->srv_name != NULL)
+ {
+ free(item->srv_name);
+ }
+ if (item->user_name != NULL)
+ {
+ free(item->user_name);
+ }
+ if (item->domain != NULL)
+ {
+ free(item->domain);
+ }
+ free(item);
+ }
+}
+
+static struct use_info *use_info_dup(const struct use_info *from)
+{
+ if (from != NULL)
+ {
+ struct use_info *copy = (struct use_info *)
+ malloc(sizeof(struct use_info));
+ if (copy != NULL)
+ {
+ ZERO_STRUCTP(copy);
+ copy->connected = from->connected;
+ if (from->srv_name != NULL)
+ {
+ copy->srv_name = strdup(from->srv_name );
+ }
+ if (from->user_name != NULL)
+ {
+ copy->user_name = strdup(from->user_name);
+ }
+ if (from->domain != NULL)
+ {
+ copy->domain = strdup(from->domain );
+ }
+ }
+ return copy;
+ }
+ return NULL;
+}
+
+void free_use_info_array(uint32 num_entries, struct use_info **entries)
+{
+ void(*fn)(void*) = (void(*)(void*))&use_info_free;
+ free_void_array(num_entries, (void**)entries, *fn);
+}
+
+struct use_info* add_use_info_to_array(uint32 *len, struct use_info ***array,
+ const struct use_info *name)
+{
+ void*(*fn)(const void*) = (void*(*)(const void*))&use_info_dup;
+ return (struct use_info*)add_copy_to_array(len,
+ (void***)array, (const void*)name, *fn, False);
+
+}
+
+void free_char_array(uint32 num_entries, char **entries)
+{
+ void(*fn)(void*) = (void(*)(void*))&free;
+ free_void_array(num_entries, (void**)entries, *fn);
+}
+
+char* add_chars_to_array(uint32 *len, char ***array, const char *name)
+{
+ void*(*fn)(const void*) = (void*(*)(const void*))&strdup;
+ return (char*)add_copy_to_array(len,
+ (void***)array, (const void*)name, *fn, False);
+
+}
+
+static uint32 *uint32_dup(const uint32* from)
+{
+ if (from != NULL)
+ {
+ uint32 *copy = (uint32 *)malloc(sizeof(uint32));
+ if (copy != NULL)
+ {
+ memcpy(copy, from, sizeof(*copy));
+ }
+ return copy;
+ }
+ return NULL;
+}
+
+void free_uint32_array(uint32 num_entries, uint32 **entries)
+{
+ void(*fn)(void*) = (void(*)(void*))&free;
+ free_void_array(num_entries, (void**)entries, *fn);
+}
+
+uint32* add_uint32s_to_array(uint32 *len, uint32 ***array, const uint32 *name)
+{
+ void*(*fn)(const void*) = (void*(*)(const void*))&uint32_dup;
+ return (uint32*)add_copy_to_array(len,
+ (void***)array, (const void*)name, *fn, False);
+
+}
+
+void free_sid_array(uint32 num_entries, DOM_SID **entries)
+{
+ void(*fn)(void*) = (void(*)(void*))&free;
+ free_void_array(num_entries, (void**)entries, *fn);
+}
+
+DOM_SID* add_sid_to_array(uint32 *len, DOM_SID ***array, const DOM_SID *sid)
+{
+ void*(*fn)(const void*) = (void*(*)(const void*))&sid_dup;
+ return (DOM_SID*)add_copy_to_array(len,
+ (void***)array, (const void*)sid, *fn, False);
+}
+
diff --git a/source3/lib/util_sid.c b/source3/lib/util_sid.c
index 9e5154d259..f2f7b3c8ae 100644
--- a/source3/lib/util_sid.c
+++ b/source3/lib/util_sid.c
@@ -335,7 +335,7 @@ BOOL sid_split_rid(DOM_SID *sid, uint32 *rid)
Copies a sid
*****************************************************************/
-void sid_copy(DOM_SID *dst, DOM_SID *src)
+void sid_copy(DOM_SID *dst, const DOM_SID *src)
{
int i;
@@ -424,3 +424,291 @@ size_t sid_size(DOM_SID *sid)
return sid->num_auths * sizeof(uint32) + 8;
}
+
+static BOOL read_sid_from_file(int fd, char *sid_file, DOM_SID *sid)
+{
+ fstring fline;
+ fstring sid_str;
+
+ memset(fline, '\0', sizeof(fline));
+
+ if (read(fd, fline, sizeof(fline) -1 ) < 0) {
+ DEBUG(0,("unable to read file %s. Error was %s\n",
+ sid_file, strerror(errno) ));
+ return False;
+ }
+
+ /*
+ * Convert to the machine SID.
+ */
+
+ fline[sizeof(fline)-1] = '\0';
+ if (!string_to_sid(sid, fline)) {
+ DEBUG(0,("unable to read sid.\n"));
+ return False;
+ }
+
+ sid_to_string(sid_str, sid);
+ DEBUG(5,("read_sid_from_file: sid %s\n", sid_str));
+
+ return True;
+}
+
+/****************************************************************************
+ Generate the global machine sid. Look for the DOMAINNAME.SID file first, if
+ not found then look in smb.conf and use it to create the DOMAINNAME.SID file.
+****************************************************************************/
+BOOL read_sid(char *sam_name, DOM_SID *sid)
+{
+ int fd;
+ char *p;
+ pstring sid_file;
+ fstring file_name;
+ SMB_STRUCT_STAT st;
+
+ pstrcpy(sid_file, lp_smb_passwd_file());
+
+ DEBUG(10,("read_sid: Domain: %s\n", sam_name));
+
+ if (sid_file[0] == 0)
+ {
+ DEBUG(0,("cannot find smb passwd file\n"));
+ return False;
+ }
+
+ p = strrchr(sid_file, '/');
+ if (p != NULL)
+ {
+ *++p = '\0';
+ }
+
+ if (!directory_exist(sid_file, NULL))
+ {
+ if (mkdir(sid_file, 0700) != 0)
+ {
+ DEBUG(0,("can't create private directory %s : %s\n",
+ sid_file, strerror(errno)));
+ return False;
+ }
+ }
+
+ slprintf(file_name, sizeof(file_name)-1, "%s.SID", sam_name);
+ strupper(file_name);
+ pstrcat(sid_file, file_name);
+
+ if ((fd = sys_open(sid_file, O_RDWR | O_CREAT, 0644)) == -1) {
+ DEBUG(0,("unable to open or create file %s. Error was %s\n",
+ sid_file, strerror(errno) ));
+ return False;
+ }
+
+ /*
+ * Check if the file contains data.
+ */
+
+ if (sys_fstat(fd, &st) < 0) {
+ DEBUG(0,("unable to stat file %s. Error was %s\n",
+ sid_file, strerror(errno) ));
+ close(fd);
+ return False;
+ }
+
+ if (st.st_size == 0)
+ {
+ close(fd);
+ return False;
+ }
+
+ /*
+ * We have a valid SID - read it.
+ */
+
+ if (!read_sid_from_file(fd, sid_file, sid))
+ {
+ DEBUG(0,("unable to read file %s. Error was %s\n",
+ sid_file, strerror(errno) ));
+ close(fd);
+ return False;
+ }
+ close(fd);
+ return True;
+}
+
+
+/****************************************************************************
+ Generate the global machine sid. Look for the DOMAINNAME.SID file first, if
+ not found then look in smb.conf and use it to create the DOMAINNAME.SID file.
+****************************************************************************/
+BOOL write_sid(char *sam_name, DOM_SID *sid)
+{
+ int fd;
+ char *p;
+ pstring sid_file;
+ fstring sid_string;
+ fstring file_name;
+ SMB_STRUCT_STAT st;
+
+ pstrcpy(sid_file, lp_smb_passwd_file());
+ sid_to_string(sid_string, sid);
+
+ DEBUG(10,("write_sid: Domain: %s SID: %s\n", sam_name, sid_string));
+ fstrcat(sid_string, "\n");
+
+ if (sid_file[0] == 0)
+ {
+ DEBUG(0,("cannot find smb passwd file\n"));
+ return False;
+ }
+
+ p = strrchr(sid_file, '/');
+ if (p != NULL)
+ {
+ *++p = '\0';
+ }
+
+ if (!directory_exist(sid_file, NULL)) {
+ if (mkdir(sid_file, 0700) != 0) {
+ DEBUG(0,("can't create private directory %s : %s\n",
+ sid_file, strerror(errno)));
+ return False;
+ }
+ }
+
+ slprintf(file_name, sizeof(file_name)-1, "%s.SID", sam_name);
+ strupper(file_name);
+ pstrcat(sid_file, file_name);
+
+ if ((fd = sys_open(sid_file, O_RDWR | O_CREAT, 0644)) == -1) {
+ DEBUG(0,("unable to open or create file %s. Error was %s\n",
+ sid_file, strerror(errno) ));
+ return False;
+ }
+
+ /*
+ * Check if the file contains data.
+ */
+
+ if (sys_fstat(fd, &st) < 0) {
+ DEBUG(0,("unable to stat file %s. Error was %s\n",
+ sid_file, strerror(errno) ));
+ close(fd);
+ return False;
+ }
+
+ if (st.st_size > 0)
+ {
+ /*
+ * We have a valid SID already.
+ */
+ close(fd);
+ DEBUG(0,("SID file %s already exists\n", sid_file));
+ return False;
+ }
+
+ if (!do_file_lock(fd, 60, F_WRLCK))
+ {
+ DEBUG(0,("unable to lock file %s. Error was %s\n",
+ sid_file, strerror(errno) ));
+ close(fd);
+ return False;
+ }
+
+ /*
+ * At this point we have a blocking lock on the SID
+ * file - check if in the meantime someone else wrote
+ * SID data into the file. If so - they were here first,
+ * use their data.
+ */
+
+ if (sys_fstat(fd, &st) < 0)
+ {
+ DEBUG(0,("unable to stat file %s. Error was %s\n",
+ sid_file, strerror(errno) ));
+ close(fd);
+ return False;
+ }
+
+ if (st.st_size > 0)
+ {
+ /*
+ * Unlock as soon as possible to reduce
+ * contention on the exclusive lock.
+ */
+ do_file_lock(fd, 60, F_UNLCK);
+
+ /*
+ * We have a valid SID already.
+ */
+
+ DEBUG(0,("SID file %s already exists\n", sid_file));
+ close(fd);
+ return False;
+ }
+
+ /*
+ * The file is still empty and we have an exlusive lock on it.
+ * Write out out SID data into the file.
+ */
+
+ if (fchmod(fd, 0644) < 0)
+ {
+ DEBUG(0,("unable to set correct permissions on file %s. \
+Error was %s\n", sid_file, strerror(errno) ));
+ close(fd);
+ return False;
+ }
+
+ if (write(fd, sid_string, strlen(sid_string)) != strlen(sid_string))
+ {
+ DEBUG(0,("unable to write file %s. Error was %s\n",
+ sid_file, strerror(errno) ));
+ close(fd);
+ return False;
+ }
+
+ /*
+ * Unlock & exit.
+ */
+
+ do_file_lock(fd, 60, F_UNLCK);
+ close(fd);
+ return True;
+}
+
+/****************************************************************************
+create a random SID.
+****************************************************************************/
+BOOL create_new_sid(DOM_SID *sid)
+{
+ uchar raw_sid_data[12];
+ fstring sid_string;
+ int i;
+
+ /*
+ * Generate the new sid data & turn it into a string.
+ */
+ generate_random_buffer(raw_sid_data, 12, True);
+
+ fstrcpy(sid_string, "S-1-5-21");
+ for(i = 0; i < 3; i++)
+ {
+ fstring tmp_string;
+ slprintf(tmp_string, sizeof(tmp_string) - 1, "-%u", IVAL(raw_sid_data, i*4));
+ fstrcat(sid_string, tmp_string);
+ }
+
+ fstrcat(sid_string, "\n");
+
+ /*
+ * Ensure our new SID is valid.
+ */
+
+ if (!string_to_sid(sid, sid_string))
+ {
+ DEBUG(0,("unable to generate machine SID.\n"));
+ return False;
+ }
+
+ return True;
+}
+
diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c
index 77ba4a7f4c..3a09c52a7a 100644
--- a/source3/lib/util_sock.c
+++ b/source3/lib/util_sock.c
@@ -1041,3 +1041,103 @@ char *client_addr(int fd)
global_client_addr_done = True;
return addr_buf;
}
+
+/*******************************************************************
+ opens and connects to a unix pipe socket
+ ******************************************************************/
+int open_pipe_sock(char *path)
+{
+ int sock;
+ struct sockaddr_un sa;
+
+ sock = socket(AF_UNIX, SOCK_STREAM, 0);
+
+ if (sock < 0)
+ {
+ DEBUG(0, ("unix socket open failed\n"));
+ return sock;
+ }
+
+ ZERO_STRUCT(sa);
+ sa.sun_family = AF_UNIX;
+ safe_strcpy(sa.sun_path, path, sizeof(sa.sun_path)-1);
+
+ DEBUG(10, ("socket open succeeded. file name: %s\n", sa.sun_path));
+
+ if (connect(sock, (struct sockaddr*) &sa, sizeof(sa)) < 0)
+ {
+ DEBUG(0,("socket connect to %s failed\n", sa.sun_path));
+ close(sock);
+ return -1;
+ }
+
+ return sock;
+}
+
+int create_pipe_socket(char *dir, int dir_perms,
+ char *path, int path_perms)
+{
+ int s;
+ struct sockaddr_un sa;
+
+ DEBUG(0,("create_pipe_socket: %s %d %s %d\n",
+ dir, dir_perms, path, path_perms));
+
+ DEBUG(0,("*** RACE CONDITION. PLEASE SOMEONE EXAMINE create_pipe_Socket AND FIX IT ***\n"));
+
+ mkdir(dir, dir_perms);
+
+ if (chmod(dir, dir_perms) < 0)
+ {
+ DEBUG(0, ("chmod on %s failed\n", dir));
+ return -1;
+ }
+
+ if (!remove(path))
+ {
+ DEBUG(0, ("remove on %s failed\n", path));
+ }
+
+ /* start listening on unix socket */
+ s = socket(AF_UNIX, SOCK_STREAM, 0);
+
+ if (s < 0)
+ {
+ DEBUG(0, ("socket open failed\n"));
+ return -1;
+ }
+
+ ZERO_STRUCT(sa);
+ sa.sun_family = AF_UNIX;
+ safe_strcpy(sa.sun_path, path, sizeof(sa.sun_path)-1);
+
+ if (bind(s, (struct sockaddr*) &sa, sizeof(sa)) < 0)
+ {
+ DEBUG(0, ("socket bind to %s failed\n", sa.sun_path));
+ close(s);
+ remove(path);
+ return -1;
+ }
+
+ if (s == -1)
+ {
+ DEBUG(0,("bind failed\n"));
+ remove(path);
+ return -1;
+ }
+
+ if (path_perms != 0)
+ {
+ chmod(path, path_perms);
+ }
+
+ if (listen(s, 5) == -1)
+ {
+ DEBUG(0,("listen failed\n"));
+ return -1;
+ }
+
+ DEBUG(5,("unix socket opened: %s\n", path));
+
+ return s;
+}