diff options
Diffstat (limited to 'source3/lib/util.c')
-rw-r--r-- | source3/lib/util.c | 652 |
1 files changed, 109 insertions, 543 deletions
diff --git a/source3/lib/util.c b/source3/lib/util.c index 0bb46db05f..b8fc319a6f 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -24,9 +24,11 @@ #include "includes.h" #include "system/passwd.h" #include "system/filesys.h" +#include "util_tdb.h" #include "ctdbd_conn.h" #include "../lib/util/util_pw.h" #include "messages.h" +#include <ccan/hash/hash.h> /* Max allowable allococation - 256mb - 0x10000000 */ #define MAX_ALLOC_SIZE (1024*1024*256) @@ -71,87 +73,6 @@ void set_Protocol(enum protocol_types p) static enum remote_arch_types ra_type = RA_UNKNOWN; -/*********************************************************************** - Definitions for all names. -***********************************************************************/ - -static char *smb_scope; -static int smb_num_netbios_names; -static char **smb_my_netbios_names; - -/*********************************************************************** - Allocate and set scope. Ensure upper case. -***********************************************************************/ - -bool set_global_scope(const char *scope) -{ - SAFE_FREE(smb_scope); - smb_scope = SMB_STRDUP(scope); - if (!smb_scope) - return False; - strupper_m(smb_scope); - return True; -} - -/********************************************************************* - Ensure scope is never null string. -*********************************************************************/ - -const char *global_scope(void) -{ - if (!smb_scope) - set_global_scope(""); - return smb_scope; -} - -static void free_netbios_names_array(void) -{ - int i; - - for (i = 0; i < smb_num_netbios_names; i++) - SAFE_FREE(smb_my_netbios_names[i]); - - SAFE_FREE(smb_my_netbios_names); - smb_num_netbios_names = 0; -} - -static bool allocate_my_netbios_names_array(size_t number) -{ - free_netbios_names_array(); - - smb_num_netbios_names = number + 1; - smb_my_netbios_names = SMB_MALLOC_ARRAY( char *, smb_num_netbios_names ); - - if (!smb_my_netbios_names) - return False; - - memset(smb_my_netbios_names, '\0', sizeof(char *) * smb_num_netbios_names); - return True; -} - -static bool set_my_netbios_names(const char *name, int i) -{ - SAFE_FREE(smb_my_netbios_names[i]); - - smb_my_netbios_names[i] = SMB_STRDUP(name); - if (!smb_my_netbios_names[i]) - return False; - strupper_m(smb_my_netbios_names[i]); - return True; -} - -/*********************************************************************** - Free memory allocated to global objects -***********************************************************************/ - -void gfree_names(void) -{ - gfree_netbios_names(); - SAFE_FREE( smb_scope ); - free_netbios_names_array(); - free_local_machine_name(); -} - void gfree_all( void ) { gfree_names(); @@ -161,87 +82,6 @@ void gfree_all( void ) gfree_debugsyms(); } -const char *my_netbios_names(int i) -{ - return smb_my_netbios_names[i]; -} - -bool set_netbios_aliases(const char **str_array) -{ - size_t namecount; - - /* Work out the max number of netbios aliases that we have */ - for( namecount=0; str_array && (str_array[namecount] != NULL); namecount++ ) - ; - - if ( global_myname() && *global_myname()) - namecount++; - - /* Allocate space for the netbios aliases */ - if (!allocate_my_netbios_names_array(namecount)) - return False; - - /* Use the global_myname string first */ - namecount=0; - if ( global_myname() && *global_myname()) { - set_my_netbios_names( global_myname(), namecount ); - namecount++; - } - - if (str_array) { - size_t i; - for ( i = 0; str_array[i] != NULL; i++) { - size_t n; - bool duplicate = False; - - /* Look for duplicates */ - for( n=0; n<namecount; n++ ) { - if( strequal( str_array[i], my_netbios_names(n) ) ) { - duplicate = True; - break; - } - } - if (!duplicate) { - if (!set_my_netbios_names(str_array[i], namecount)) - return False; - namecount++; - } - } - } - return True; -} - -/**************************************************************************** - Common name initialization code. -****************************************************************************/ - -bool init_names(void) -{ - int n; - - if (global_myname() == NULL || *global_myname() == '\0') { - if (!set_global_myname(myhostname())) { - DEBUG( 0, ( "init_names: malloc fail.\n" ) ); - return False; - } - } - - if (!set_netbios_aliases(lp_netbios_aliases())) { - DEBUG( 0, ( "init_names: malloc fail.\n" ) ); - return False; - } - - set_local_machine_name(global_myname(),false); - - DEBUG( 5, ("Netbios name list:-\n") ); - for( n=0; my_netbios_names(n); n++ ) { - DEBUGADD( 5, ("my_netbios_names[%d]=\"%s\"\n", - n, my_netbios_names(n) ) ); - } - - return( True ); -} - /******************************************************************* Check if a file exists - call vfs_file_exist for samba files. ********************************************************************/ @@ -295,30 +135,10 @@ SMB_OFF_T get_file_size(char *file_name) } /******************************************************************* - Return a string representing an attribute for a file. -********************************************************************/ - -char *attrib_string(uint16 mode) -{ - fstring attrstr; - - attrstr[0] = 0; - - if (mode & aVOLID) fstrcat(attrstr,"V"); - if (mode & aDIR) fstrcat(attrstr,"D"); - if (mode & aARCH) fstrcat(attrstr,"A"); - if (mode & aHIDDEN) fstrcat(attrstr,"H"); - if (mode & aSYSTEM) fstrcat(attrstr,"S"); - if (mode & aRONLY) fstrcat(attrstr,"R"); - - return talloc_strdup(talloc_tos(), attrstr); -} - -/******************************************************************* Show a smb message structure. ********************************************************************/ -void show_msg(char *buf) +void show_msg(const char *buf) { int i; int bcc=0; @@ -355,7 +175,7 @@ void show_msg(char *buf) if (DEBUGLEVEL < 50) bcc = MIN(bcc, 512); - dump_data(10, (uint8 *)smb_buf(buf), bcc); + dump_data(10, (const uint8 *)smb_buf_const(buf), bcc); } /******************************************************************* @@ -407,7 +227,7 @@ ssize_t message_push_blob(uint8 **outbuf, DATA_BLOB blob) size_t newlen = smb_len(*outbuf) + 4 + blob.length; uint8 *tmp; - if (!(tmp = TALLOC_REALLOC_ARRAY(NULL, *outbuf, uint8, newlen))) { + if (!(tmp = talloc_realloc(NULL, *outbuf, uint8, newlen))) { DEBUG(0, ("talloc failed\n")); return -1; } @@ -586,7 +406,7 @@ NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx, set_need_random_reseed(); /* tdb needs special fork handling */ - if (tdb_reopen_all(parent_longlived ? 1 : 0) == -1) { + if (tdb_reopen_all(parent_longlived ? 1 : 0) != 0) { DEBUG(0,("tdb_reopen_all failed.\n")); status = NT_STATUS_OPEN_FAILED; goto done; @@ -611,149 +431,6 @@ NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx, return status; } -#if defined(PARANOID_MALLOC_CHECKER) - -/**************************************************************************** - Internal malloc wrapper. Externally visible. -****************************************************************************/ - -void *malloc_(size_t size) -{ - if (size == 0) { - return NULL; - } -#undef malloc - return malloc(size); -#define malloc(s) __ERROR_DONT_USE_MALLOC_DIRECTLY -} - -/**************************************************************************** - Internal calloc wrapper. Not externally visible. -****************************************************************************/ - -static void *calloc_(size_t count, size_t size) -{ - if (size == 0 || count == 0) { - return NULL; - } -#undef calloc - return calloc(count, size); -#define calloc(n,s) __ERROR_DONT_USE_CALLOC_DIRECTLY -} - -/**************************************************************************** - Internal realloc wrapper. Not externally visible. -****************************************************************************/ - -static void *realloc_(void *ptr, size_t size) -{ -#undef realloc - return realloc(ptr, size); -#define realloc(p,s) __ERROR_DONT_USE_RELLOC_DIRECTLY -} - -#endif /* PARANOID_MALLOC_CHECKER */ - -/**************************************************************************** - Type-safe memalign -****************************************************************************/ - -void *memalign_array(size_t el_size, size_t align, unsigned int count) -{ - if (count >= MAX_ALLOC_SIZE/el_size) { - return NULL; - } - - return sys_memalign(align, el_size*count); -} - -/**************************************************************************** - Type-safe calloc. -****************************************************************************/ - -void *calloc_array(size_t size, size_t nmemb) -{ - if (nmemb >= MAX_ALLOC_SIZE/size) { - return NULL; - } - if (size == 0 || nmemb == 0) { - return NULL; - } -#if defined(PARANOID_MALLOC_CHECKER) - return calloc_(nmemb, size); -#else - return calloc(nmemb, size); -#endif -} - -/**************************************************************************** - Expand a pointer to be a particular size. - Note that this version of Realloc has an extra parameter that decides - whether to free the passed in storage on allocation failure or if the - new size is zero. - - This is designed for use in the typical idiom of : - - p = SMB_REALLOC(p, size) - if (!p) { - return error; - } - - and not to have to keep track of the old 'p' contents to free later, nor - to worry if the size parameter was zero. In the case where NULL is returned - we guarentee that p has been freed. - - If free later semantics are desired, then pass 'free_old_on_error' as False which - guarentees that the old contents are not freed on error, even if size == 0. To use - this idiom use : - - tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size); - if (!tmp) { - SAFE_FREE(p); - return error; - } else { - p = tmp; - } - - Changes were instigated by Coverity error checking. JRA. -****************************************************************************/ - -void *Realloc(void *p, size_t size, bool free_old_on_error) -{ - void *ret=NULL; - - if (size == 0) { - if (free_old_on_error) { - SAFE_FREE(p); - } - DEBUG(2,("Realloc asked for 0 bytes\n")); - return NULL; - } - -#if defined(PARANOID_MALLOC_CHECKER) - if (!p) { - ret = (void *)malloc_(size); - } else { - ret = (void *)realloc_(p,size); - } -#else - if (!p) { - ret = (void *)malloc(size); - } else { - ret = (void *)realloc(p,size); - } -#endif - - if (!ret) { - if (free_old_on_error && p) { - SAFE_FREE(p); - } - DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",(int)size)); - } - - return(ret); -} - /**************************************************************************** (Hopefully) efficient array append. ****************************************************************************/ @@ -1318,7 +995,7 @@ bool is_in_path(const char *name, name_compare_entry *namelist, bool case_sensit } } else { if((case_sensitive && (strcmp(last_component, namelist->name) == 0))|| - (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0))) { + (!case_sensitive && (strcasecmp_m(last_component, namelist->name) == 0))) { DEBUG(8,("is_in_path: match succeeded\n")); return True; } @@ -1334,25 +1011,31 @@ bool is_in_path(const char *name, name_compare_entry *namelist, bool case_sensit passing to is_in_path(). We do this for speed so we can pre-parse all the names in the list and don't do it for each call to is_in_path(). - namelist is modified here and is assumed to be - a copy owned by the caller. We also check if the entry contains a wildcard to remove a potentially expensive call to mask_match if possible. ********************************************************************/ -void set_namearray(name_compare_entry **ppname_array, const char *namelist) +void set_namearray(name_compare_entry **ppname_array, const char *namelist_in) { char *name_end; - char *nameptr = (char *)namelist; + char *namelist; + char *nameptr; int num_entries = 0; int i; (*ppname_array) = NULL; - if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0'))) + if((namelist_in == NULL ) || ((namelist_in != NULL) && (*namelist_in == '\0'))) return; + namelist = talloc_strdup(talloc_tos(), namelist_in); + if (namelist == NULL) { + DEBUG(0,("set_namearray: talloc fail\n")); + return; + } + nameptr = namelist; + /* We need to make two passes over the string. The first to count the number of elements, the second to split it. @@ -1378,16 +1061,19 @@ void set_namearray(name_compare_entry **ppname_array, const char *namelist) num_entries++; } - if(num_entries == 0) + if(num_entries == 0) { + talloc_free(namelist); return; + } if(( (*ppname_array) = SMB_MALLOC_ARRAY(name_compare_entry, num_entries + 1)) == NULL) { DEBUG(0,("set_namearray: malloc fail\n")); + talloc_free(namelist); return; } /* Now copy out the names */ - nameptr = (char *)namelist; + nameptr = namelist; i = 0; while(*nameptr) { if ( *nameptr == '/' ) { @@ -1409,6 +1095,7 @@ void set_namearray(name_compare_entry **ppname_array, const char *namelist) (*ppname_array)[i].is_wild = ms_has_wild(nameptr); if(((*ppname_array)[i].name = SMB_STRDUP(nameptr)) == NULL) { DEBUG(0,("set_namearray: malloc fail (1)\n")); + talloc_free(namelist); return; } @@ -1419,25 +1106,10 @@ void set_namearray(name_compare_entry **ppname_array, const char *namelist) (*ppname_array)[i].name = NULL; + talloc_free(namelist); return; } -/**************************************************************************** - Routine to free a namearray. -****************************************************************************/ - -void free_namearray(name_compare_entry *name_array) -{ - int i; - - if(name_array == NULL) - return; - - for(i=0; name_array[i].name!=NULL; i++) - SAFE_FREE(name_array[i].name); - SAFE_FREE(name_array); -} - #undef DBGC_CLASS #define DBGC_CLASS DBGC_LOCKING @@ -1635,8 +1307,9 @@ const char *tab_depth(int level, int depth) int str_checksum(const char *s) { - TDB_DATA key = string_tdb_data(s); - return tdb_jenkins_hash(&key); + if (s == NULL) + return 0; + return hash(s, strlen(s), 0); } /***************************************************************** @@ -1785,6 +1458,22 @@ char *myhostname(void) return ret; } +/***************************************************************** + Get local hostname and cache result. +*****************************************************************/ + +char *myhostname_upper(void) +{ + char *name; + static char *ret; + if (ret == NULL) { + name = get_myname(talloc_tos()); + ret = strupper_talloc(NULL, name); + talloc_free(name); + } + return ret; +} + /** * @brief Returns an absolute path to a file concatenating the provided * @a rootpath and @a basename @@ -1843,45 +1532,6 @@ char *pid_path(const char *name) } /** - * @brief Returns an absolute path to a file in the Samba lib directory. - * - * @param name File to find, relative to LIBDIR. - * - * @retval Pointer to a string containing the full path. - **/ - -char *lib_path(const char *name) -{ - return talloc_asprintf(talloc_tos(), "%s/%s", get_dyn_LIBDIR(), name); -} - -/** - * @brief Returns an absolute path to a file in the Samba modules directory. - * - * @param name File to find, relative to MODULESDIR. - * - * @retval Pointer to a string containing the full path. - **/ - -char *modules_path(const char *name) -{ - return talloc_asprintf(talloc_tos(), "%s/%s", get_dyn_MODULESDIR(), name); -} - -/** - * @brief Returns an absolute path to a file in the Samba data directory. - * - * @param name File to find, relative to CODEPAGEDIR. - * - * @retval Pointer to a talloc'ed string containing the full path. - **/ - -char *data_path(const char *name) -{ - return talloc_asprintf(talloc_tos(), "%s/%s", get_dyn_CODEPAGEDIR(), name); -} - -/** * @brief Returns an absolute path to a file in the Samba state directory. * * @param name File to find, relative to STATEDIR. @@ -1907,17 +1557,6 @@ char *cache_path(const char *name) return xx_path(name, lp_cachedir()); } -/** - * @brief Returns the platform specific shared library extension. - * - * @retval Pointer to a const char * containing the extension. - **/ - -const char *shlib_ext(void) -{ - return get_dyn_SHLIBEXT(); -} - /******************************************************************* Given a filename - get its directory name ********************************************************************/ @@ -1942,7 +1581,7 @@ bool parent_dirname(TALLOC_CTX *mem_ctx, const char *dir, char **parent, len = p-dir; - if (!(*parent = (char *)TALLOC_MEMDUP(mem_ctx, dir, len+1))) { + if (!(*parent = (char *)talloc_memdup(mem_ctx, dir, len+1))) { return False; } (*parent)[len] = '\0'; @@ -2211,7 +1850,7 @@ bool name_to_fqdn(fstring fqdn, const char *name) } } } - if (full && (StrCaseCmp(full, "localhost.localdomain") == 0)) { + if (full && (strcasecmp_m(full, "localhost.localdomain") == 0)) { DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n")); DEBUGADD(1, (" Specifing the machine hostname for address 127.0.0.1 may lead\n")); DEBUGADD(1, (" to Kerberos authentication problems as localhost.localdomain\n")); @@ -2303,6 +1942,7 @@ struct server_id pid_to_procid(pid_t pid) { struct server_id result; result.pid = pid; + result.task_id = 0; result.unique_id = my_unique_id; result.vnn = my_vnn; return result; @@ -2317,6 +1957,8 @@ bool procid_equal(const struct server_id *p1, const struct server_id *p2) { if (p1->pid != p2->pid) return False; + if (p1->task_id != p2->task_id) + return False; if (p1->vnn != p2->vnn) return False; return True; @@ -2332,6 +1974,8 @@ bool procid_is_me(const struct server_id *pid) { if (pid->pid != sys_getpid()) return False; + if (pid->task_id != 0) + return False; if (pid->vnn != my_vnn) return False; return True; @@ -2340,52 +1984,45 @@ bool procid_is_me(const struct server_id *pid) struct server_id interpret_pid(const char *pid_string) { struct server_id result; - int pid; - unsigned int vnn; - if (sscanf(pid_string, "%u:%d", &vnn, &pid) == 2) { + unsigned long long pid; + unsigned int vnn, task_id = 0; + + ZERO_STRUCT(result); + + /* We accept various forms with 1, 2 or 3 component forms + * because the server_id_str() can print different forms, and + * we want backwards compatibility for scripts that may call + * smbclient. */ + if (sscanf(pid_string, "%u:%llu.%u", &vnn, &pid, &task_id) == 3) { result.vnn = vnn; result.pid = pid; - } - else if (sscanf(pid_string, "%d", &pid) == 1) { + result.task_id = task_id; + } else if (sscanf(pid_string, "%u:%llu", &vnn, &pid) == 2) { + result.vnn = vnn; + result.pid = pid; + result.task_id = 0; + } else if (sscanf(pid_string, "%llu.%u", &pid, &task_id) == 2) { result.vnn = get_my_vnn(); result.pid = pid; - } - else { + result.task_id = task_id; + } else if (sscanf(pid_string, "%llu", &pid) == 1) { + result.vnn = get_my_vnn(); + result.pid = pid; + } else { result.vnn = NONCLUSTER_VNN; - result.pid = -1; + result.pid = (uint64_t)-1; } - /* Assigning to result.pid may have overflowed - Map negative pid to -1: i.e. error */ - if (result.pid < 0) { - result.pid = -1; - } - result.unique_id = 0; return result; } -char *procid_str(TALLOC_CTX *mem_ctx, const struct server_id *pid) -{ - if (pid->vnn == NONCLUSTER_VNN) { - return talloc_asprintf(mem_ctx, - "%d", - (int)pid->pid); - } - else { - return talloc_asprintf(mem_ctx, - "%u:%d", - (unsigned)pid->vnn, - (int)pid->pid); - } -} - char *procid_str_static(const struct server_id *pid) { - return procid_str(talloc_tos(), pid); + return server_id_str(talloc_tos(), pid); } bool procid_valid(const struct server_id *pid) { - return (pid->pid != -1); + return (pid->pid != (uint64_t)-1); } bool procid_is_local(const struct server_id *pid) @@ -2519,111 +2156,6 @@ void split_domain_user(TALLOC_CTX *mem_ctx, } } -#if 0 - -Disable these now we have checked all code paths and ensured -NULL returns on zero request. JRA. - -/**************************************************************** - talloc wrapper functions that guarentee a null pointer return - if size == 0. -****************************************************************/ - -#ifndef MAX_TALLOC_SIZE -#define MAX_TALLOC_SIZE 0x10000000 -#endif - -/* - * talloc and zero memory. - * - returns NULL if size is zero. - */ - -void *_talloc_zero_zeronull(const void *ctx, size_t size, const char *name) -{ - void *p; - - if (size == 0) { - return NULL; - } - - p = talloc_named_const(ctx, size, name); - - if (p) { - memset(p, '\0', size); - } - - return p; -} - -/* - * memdup with a talloc. - * - returns NULL if size is zero. - */ - -void *_talloc_memdup_zeronull(const void *t, const void *p, size_t size, const char *name) -{ - void *newp; - - if (size == 0) { - return NULL; - } - - newp = talloc_named_const(t, size, name); - if (newp) { - memcpy(newp, p, size); - } - - return newp; -} - -/* - * alloc an array, checking for integer overflow in the array size. - * - returns NULL if count or el_size are zero. - */ - -void *_talloc_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name) -{ - if (count >= MAX_TALLOC_SIZE/el_size) { - return NULL; - } - - if (el_size == 0 || count == 0) { - return NULL; - } - - return talloc_named_const(ctx, el_size * count, name); -} - -/* - * alloc an zero array, checking for integer overflow in the array size - * - returns NULL if count or el_size are zero. - */ - -void *_talloc_zero_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name) -{ - if (count >= MAX_TALLOC_SIZE/el_size) { - return NULL; - } - - if (el_size == 0 || count == 0) { - return NULL; - } - - return _talloc_zero(ctx, el_size * count, name); -} - -/* - * Talloc wrapper that returns NULL if size == 0. - */ -void *talloc_zeronull(const void *context, size_t size, const char *name) -{ - if (size == 0) { - return NULL; - } - return talloc_named_const(context, size, name); -} -#endif - /**************************************************************** strip off leading '\\' from a hostname ****************************************************************/ @@ -2672,3 +2204,37 @@ int timeval_to_msec(struct timeval t) { return t.tv_sec * 1000 + (t.tv_usec+999) / 1000; } + +/******************************************************************* + Check a given DOS pathname is valid for a share. +********************************************************************/ + +char *valid_share_pathname(TALLOC_CTX *ctx, const char *dos_pathname) +{ + char *ptr = NULL; + + if (!dos_pathname) { + return NULL; + } + + ptr = talloc_strdup(ctx, dos_pathname); + if (!ptr) { + return NULL; + } + /* Convert any '\' paths to '/' */ + unix_format(ptr); + ptr = unix_clean_name(ctx, ptr); + if (!ptr) { + return NULL; + } + + /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */ + if (strlen(ptr) > 2 && ptr[1] == ':' && ptr[0] != '/') + ptr += 2; + + /* Only absolute paths allowed. */ + if (*ptr != '/') + return NULL; + + return ptr; +} |