diff options
Diffstat (limited to 'source3/lib')
-rw-r--r-- | source3/lib/doscalls.c | 2 | ||||
-rw-r--r-- | source3/lib/msrpc-client.c | 400 | ||||
-rw-r--r-- | source3/lib/msrpc_use.c | 328 | ||||
-rw-r--r-- | source3/lib/util.c | 15 | ||||
-rw-r--r-- | source3/lib/util_array.c | 194 | ||||
-rw-r--r-- | source3/lib/util_sid.c | 290 | ||||
-rw-r--r-- | source3/lib/util_sock.c | 100 |
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; +} |