diff options
author | Gerald Carter <jerry@samba.org> | 2006-02-03 22:19:41 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 11:06:23 -0500 |
commit | 0af1500fc0bafe61019f1b2ab1d9e1d369221240 (patch) | |
tree | 653fc2533795458d5f9696402285d9f14e527a21 /source3/lib | |
parent | 21a30a1346c9f9a25659a0cea0d276d8c2e6ddca (diff) | |
download | samba-0af1500fc0bafe61019f1b2ab1d9e1d369221240.tar.gz samba-0af1500fc0bafe61019f1b2ab1d9e1d369221240.tar.xz samba-0af1500fc0bafe61019f1b2ab1d9e1d369221240.zip |
r13316: Let the carnage begin....
Sync with trunk as off r13315
(This used to be commit 17e63ac4ed8325c0d44fe62b2442449f3298559f)
Diffstat (limited to 'source3/lib')
-rw-r--r-- | source3/lib/dummysmbd.c | 9 | ||||
-rw-r--r-- | source3/lib/events.c | 125 | ||||
-rw-r--r-- | source3/lib/genrand.c | 4 | ||||
-rw-r--r-- | source3/lib/messages.c | 15 | ||||
-rw-r--r-- | source3/lib/pam_errors.c | 1 | ||||
-rw-r--r-- | source3/lib/pidfile.c | 6 | ||||
-rw-r--r-- | source3/lib/readline.c | 4 | ||||
-rw-r--r-- | source3/lib/secdesc.c | 10 | ||||
-rw-r--r-- | source3/lib/sharesec.c | 308 | ||||
-rw-r--r-- | source3/lib/smbldap.c | 221 | ||||
-rw-r--r-- | source3/lib/smbldap_util.c | 92 | ||||
-rw-r--r-- | source3/lib/system_smbd.c | 91 | ||||
-rw-r--r-- | source3/lib/username.c | 124 | ||||
-rw-r--r-- | source3/lib/util.c | 8 | ||||
-rw-r--r-- | source3/lib/util_file.c | 33 | ||||
-rw-r--r-- | source3/lib/util_pw.c | 79 | ||||
-rw-r--r-- | source3/lib/util_sid.c | 5 | ||||
-rw-r--r-- | source3/lib/util_str.c | 99 | ||||
-rw-r--r-- | source3/lib/util_unistr.c | 14 |
19 files changed, 920 insertions, 328 deletions
diff --git a/source3/lib/dummysmbd.c b/source3/lib/dummysmbd.c index 1b31dff4995..9b587224e3e 100644 --- a/source3/lib/dummysmbd.c +++ b/source3/lib/dummysmbd.c @@ -29,3 +29,12 @@ void decrement_smbd_process_count( void ) return; } +int find_service(fstring service) +{ + return -1; +} + +BOOL conn_snum_used(int snum) +{ + return False; +} diff --git a/source3/lib/events.c b/source3/lib/events.c new file mode 100644 index 00000000000..314f0749794 --- /dev/null +++ b/source3/lib/events.c @@ -0,0 +1,125 @@ +/* + Unix SMB/CIFS implementation. + Timed event library. + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Volker Lendecke 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" + +static struct timed_event *timed_events; + +static int timed_event_destructor(void *p) +{ + struct timed_event *te = talloc_get_type_abort(p, struct timed_event); + DEBUG(10, ("Destroying timed event %lx \"%s\"\n", (unsigned long)te, + te->event_name)); + DLIST_REMOVE(timed_events, te); + return 0; +} + +/**************************************************************************** + Schedule a function for future calling, cancel with talloc_free(). + It's the responsibility of the handler to call talloc_free() on the event + handed to it. +****************************************************************************/ + +struct timed_event *add_timed_event(TALLOC_CTX *mem_ctx, + struct timeval when, + const char *event_name, + void (*handler)(struct timed_event *te, + const struct timeval *now, + void *private_data), + void *private_data) +{ + struct timed_event *te, *last_te, *cur_te; + + te = TALLOC_P(mem_ctx, struct timed_event); + if (te == NULL) { + DEBUG(0, ("talloc failed\n")); + return NULL; + } + + te->when = when; + te->event_name = event_name; + te->handler = handler; + te->private_data = private_data; + + /* keep the list ordered */ + last_te = NULL; + for (cur_te = timed_events; cur_te; cur_te = cur_te->next) { + /* if the new event comes before the current one break */ + if (!timeval_is_zero(&cur_te->when) && + timeval_compare(&te->when, &cur_te->when) < 0) { + break; + } + last_te = cur_te; + } + + DLIST_ADD_AFTER(timed_events, te, last_te); + talloc_set_destructor(te, timed_event_destructor); + + DEBUG(10, ("Added timed event \"%s\": %lx\n", event_name, + (unsigned long)te)); + return te; +} + +void run_events(void) +{ + struct timeval now; + + if (timed_events == NULL) { + /* No syscall if there are no events */ + DEBUG(10, ("run_events: No events\n")); + return; + } + + GetTimeOfDay(&now); + + if (timeval_compare(&now, &timed_events->when) < 0) { + /* Nothing to do yet */ + DEBUG(10, ("run_events: Nothing to do\n")); + return; + } + + DEBUG(10, ("Running event \"%s\" %lx\n", timed_events->event_name, + (unsigned long)timed_events)); + + timed_events->handler(timed_events, &now, timed_events->private_data); + return; +} + +struct timeval *get_timed_events_timeout(struct timeval *to_ret, time_t default_to) +{ + struct timeval now; + + if (timed_events == NULL) { + if (default_to == (time_t)-1) { + return NULL; + } + *to_ret = timeval_set(default_to, 0); + return to_ret; + } + + now = timeval_current(); + *to_ret = timeval_until(&now, &timed_events->when); + + DEBUG(10, ("timed_events_timeout: %d/%d\n", (int)to_ret->tv_sec, + (int)to_ret->tv_usec)); + + return to_ret; +} diff --git a/source3/lib/genrand.c b/source3/lib/genrand.c index f37bbc9c2fd..5b643bf297e 100644 --- a/source3/lib/genrand.c +++ b/source3/lib/genrand.c @@ -114,14 +114,14 @@ static int do_reseed(BOOL use_fd, int fd) * seriously this will be secret. */ - pw = getpwnam_alloc("root"); + pw = getpwnam_alloc(NULL, "root"); if (pw && pw->pw_passwd) { size_t i; unsigned char md4_tmp[16]; mdfour(md4_tmp, (unsigned char *)pw->pw_passwd, strlen(pw->pw_passwd)); for (i=0;i<16;i++) seed_inbuf[8+i] ^= md4_tmp[i]; - passwd_free(&pw); + talloc_free(pw); } /* diff --git a/source3/lib/messages.c b/source3/lib/messages.c index 058bbc99b0b..2d6518aed6a 100644 --- a/source3/lib/messages.c +++ b/source3/lib/messages.c @@ -604,4 +604,19 @@ BOOL message_send_all(TDB_CONTEXT *conn_tdb, int msg_type, *n_sent = msg_all.n_sent; return True; } + +/* + * Block and unblock receiving of messages. Allows removal of race conditions + * when doing a fork and changing message disposition. + */ + +void message_block(void) +{ + BlockSignals(True, SIGUSR1); +} + +void message_unblock(void) +{ + BlockSignals(False, SIGUSR1); +} /** @} **/ diff --git a/source3/lib/pam_errors.c b/source3/lib/pam_errors.c index 212d3831fd5..8a4c41d7df5 100644 --- a/source3/lib/pam_errors.c +++ b/source3/lib/pam_errors.c @@ -71,6 +71,7 @@ static const struct { {NT_STATUS_PASSWORD_MUST_CHANGE, PAM_NEW_AUTHTOK_REQD}, {NT_STATUS_ACCOUNT_LOCKED_OUT, PAM_MAXTRIES}, {NT_STATUS_NO_MEMORY, PAM_BUF_ERR}, + {NT_STATUS_PASSWORD_RESTRICTION, PAM_PERM_DENIED}, {NT_STATUS_OK, PAM_SUCCESS} }; diff --git a/source3/lib/pidfile.c b/source3/lib/pidfile.c index b041eb7f1b2..08e41083b59 100644 --- a/source3/lib/pidfile.c +++ b/source3/lib/pidfile.c @@ -32,7 +32,8 @@ pid_t pidfile_pid(const char *name) { int fd; char pidstr[20]; - unsigned ret; + pid_t pid; + unsigned int ret; pstring pidFile; slprintf(pidFile, sizeof(pidFile)-1, "%s/%s.pid", lp_piddir(), name); @@ -57,7 +58,8 @@ pid_t pidfile_pid(const char *name) goto noproc; } - if (!process_exists_by_pid(ret)) { + pid = (pid_t)ret; + if (!process_exists_by_pid(pid)) { goto noproc; } diff --git a/source3/lib/readline.c b/source3/lib/readline.c index 78b99fd7fb0..c1f1dc7f400 100644 --- a/source3/lib/readline.c +++ b/source3/lib/readline.c @@ -50,7 +50,7 @@ Display the prompt and wait for input. Call callback() regularly ****************************************************************************/ -static char *smb_readline_replacement(char *prompt, void (*callback)(void), +static char *smb_readline_replacement(const char *prompt, void (*callback)(void), char **(completion_fn)(const char *text, int start, int end)) { fd_set fds; @@ -82,7 +82,7 @@ static char *smb_readline_replacement(char *prompt, void (*callback)(void), Display the prompt and wait for input. Call callback() regularly. ****************************************************************************/ -char *smb_readline(char *prompt, void (*callback)(void), +char *smb_readline(const char *prompt, void (*callback)(void), char **(completion_fn)(const char *text, int start, int end)) { #if HAVE_LIBREADLINE diff --git a/source3/lib/secdesc.c b/source3/lib/secdesc.c index ace0aee8664..273bf0f0a3f 100644 --- a/source3/lib/secdesc.c +++ b/source3/lib/secdesc.c @@ -23,6 +23,15 @@ #include "includes.h" +/* Map generic permissions to file object specific permissions */ + +struct generic_mapping file_generic_mapping = { + FILE_GENERIC_READ, + FILE_GENERIC_WRITE, + FILE_GENERIC_EXECUTE, + FILE_GENERIC_ALL +}; + /******************************************************************* Works out the linearization size of a SEC_DESC. ********************************************************************/ @@ -520,3 +529,4 @@ void init_sec_access(SEC_ACCESS *t, uint32 mask) t->mask = mask; } + diff --git a/source3/lib/sharesec.c b/source3/lib/sharesec.c new file mode 100644 index 00000000000..b98e304582a --- /dev/null +++ b/source3/lib/sharesec.c @@ -0,0 +1,308 @@ +/* + * Unix SMB/Netbios implementation. + * SEC_DESC handling functions + * Copyright (C) Jeremy R. Allison 1995-2003. + * + * 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" + +/******************************************************************* + Create the share security tdb. + ********************************************************************/ + +static TDB_CONTEXT *share_tdb; /* used for share security descriptors */ +#define SHARE_DATABASE_VERSION_V1 1 +#define SHARE_DATABASE_VERSION_V2 2 /* version id in little endian. */ + +/* Map generic permissions to file object specific permissions */ + +static struct generic_mapping file_generic_mapping = { + FILE_GENERIC_READ, + FILE_GENERIC_WRITE, + FILE_GENERIC_EXECUTE, + FILE_GENERIC_ALL +}; + + +BOOL share_info_db_init(void) +{ + const char *vstring = "INFO/version"; + int32 vers_id; + + if (share_tdb) { + return True; + } + + share_tdb = tdb_open_log(lock_path("share_info.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); + if (!share_tdb) { + DEBUG(0,("Failed to open share info database %s (%s)\n", + lock_path("share_info.tdb"), strerror(errno) )); + return False; + } + + /* handle a Samba upgrade */ + tdb_lock_bystring(share_tdb, vstring, 0); + + /* Cope with byte-reversed older versions of the db. */ + vers_id = tdb_fetch_int32(share_tdb, vstring); + if ((vers_id == SHARE_DATABASE_VERSION_V1) || (IREV(vers_id) == SHARE_DATABASE_VERSION_V1)) { + /* Written on a bigendian machine with old fetch_int code. Save as le. */ + tdb_store_int32(share_tdb, vstring, SHARE_DATABASE_VERSION_V2); + vers_id = SHARE_DATABASE_VERSION_V2; + } + + if (vers_id != SHARE_DATABASE_VERSION_V2) { + tdb_traverse(share_tdb, tdb_traverse_delete_fn, NULL); + tdb_store_int32(share_tdb, vstring, SHARE_DATABASE_VERSION_V2); + } + tdb_unlock_bystring(share_tdb, vstring); + + return True; +} + +/******************************************************************* + Fake up a Everyone, default access as a default. + def_access is a GENERIC_XXX access mode. + ********************************************************************/ + +SEC_DESC *get_share_security_default( TALLOC_CTX *ctx, size_t *psize, uint32 def_access) +{ + SEC_ACCESS sa; + SEC_ACE ace; + SEC_ACL *psa = NULL; + SEC_DESC *psd = NULL; + uint32 spec_access = def_access; + + se_map_generic(&spec_access, &file_generic_mapping); + + init_sec_access(&sa, def_access | spec_access ); + init_sec_ace(&ace, &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 0); + + if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 1, &ace)) != NULL) { + psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, psize); + } + + if (!psd) { + DEBUG(0,("get_share_security: Failed to make SEC_DESC.\n")); + return NULL; + } + + return psd; +} + +/******************************************************************* + Pull a security descriptor from the share tdb. + ********************************************************************/ + +SEC_DESC *get_share_security( TALLOC_CTX *ctx, int snum, size_t *psize) +{ + prs_struct ps; + fstring key; + SEC_DESC *psd = NULL; + + if (!share_info_db_init()) { + return NULL; + } + + *psize = 0; + + /* Fetch security descriptor from tdb */ + + slprintf(key, sizeof(key)-1, "SECDESC/%s", lp_servicename(snum)); + + if (tdb_prs_fetch(share_tdb, key, &ps, ctx)!=0 || + !sec_io_desc("get_share_security", &psd, &ps, 1)) { + + DEBUG(4,("get_share_security: using default secdesc for %s\n", lp_servicename(snum) )); + + return get_share_security_default(ctx, psize, GENERIC_ALL_ACCESS); + } + + if (psd) + *psize = sec_desc_size(psd); + + prs_mem_free(&ps); + return psd; +} + +/******************************************************************* + Store a security descriptor in the share db. + ********************************************************************/ + +BOOL set_share_security(TALLOC_CTX *ctx, const char *share_name, SEC_DESC *psd) +{ + prs_struct ps; + TALLOC_CTX *mem_ctx = NULL; + fstring key; + BOOL ret = False; + + if (!share_info_db_init()) { + return False; + } + + mem_ctx = talloc_init("set_share_security"); + if (mem_ctx == NULL) + return False; + + prs_init(&ps, (uint32)sec_desc_size(psd), mem_ctx, MARSHALL); + + if (!sec_io_desc("share_security", &psd, &ps, 1)) + goto out; + + slprintf(key, sizeof(key)-1, "SECDESC/%s", share_name); + + if (tdb_prs_store(share_tdb, key, &ps)==0) { + ret = True; + DEBUG(5,("set_share_security: stored secdesc for %s\n", share_name )); + } else { + DEBUG(1,("set_share_security: Failed to store secdesc for %s\n", share_name )); + } + + /* Free malloc'ed memory */ + +out: + + prs_mem_free(&ps); + if (mem_ctx) + talloc_destroy(mem_ctx); + return ret; +} + +/******************************************************************* + Delete a security descriptor. +********************************************************************/ + +BOOL delete_share_security(int snum) +{ + TDB_DATA kbuf; + fstring key; + + slprintf(key, sizeof(key)-1, "SECDESC/%s", lp_servicename(snum)); + kbuf.dptr = key; + kbuf.dsize = strlen(key)+1; + + if (tdb_delete(share_tdb, kbuf) != 0) { + DEBUG(0,("delete_share_security: Failed to delete entry for share %s\n", + lp_servicename(snum) )); + return False; + } + + return True; +} + +/*************************************************************************** + Parse the contents of an acl string from a usershare file. +***************************************************************************/ + +BOOL parse_usershare_acl(TALLOC_CTX *ctx, const char *acl_str, SEC_DESC **ppsd) +{ + size_t s_size = 0; + const char *pacl = acl_str; + int num_aces = 0; + SEC_ACE *ace_list = NULL; + SEC_ACL *psa = NULL; + SEC_DESC *psd = NULL; + size_t sd_size = 0; + int i; + + *ppsd = NULL; + + /* If the acl string is blank return "Everyone:R" */ + if (!*acl_str) { + SEC_DESC *default_psd = get_share_security_default(ctx, &s_size, GENERIC_READ_ACCESS); + if (!default_psd) { + return False; + } + *ppsd = default_psd; + return True; + } + + num_aces = 1; + + /* Add the number of ',' characters to get the number of aces. */ + num_aces += count_chars(pacl,','); + + ace_list = TALLOC_ARRAY(ctx, SEC_ACE, num_aces); + if (!ace_list) { + return False; + } + + for (i = 0; i < num_aces; i++) { + SEC_ACCESS sa; + uint32 g_access; + uint32 s_access; + DOM_SID sid; + fstring sidstr; + uint8 type = SEC_ACE_TYPE_ACCESS_ALLOWED; + + if (!next_token(&pacl, sidstr, ":", sizeof(sidstr))) { + DEBUG(0,("parse_usershare_acl: malformed usershare acl looking " + "for ':' in string '%s'\n", pacl)); + return False; + } + + if (!string_to_sid(&sid, sidstr)) { + DEBUG(0,("parse_usershare_acl: failed to convert %s to sid.\n", + sidstr )); + return False; + } + + switch (*pacl) { + case 'F': /* Full Control, ie. R+W */ + case 'f': /* Full Control, ie. R+W */ + s_access = g_access = GENERIC_ALL_ACCESS; + break; + case 'R': /* Read only. */ + case 'r': /* Read only. */ + s_access = g_access = GENERIC_READ_ACCESS; + break; + case 'D': /* Deny all to this SID. */ + case 'd': /* Deny all to this SID. */ + type = SEC_ACE_TYPE_ACCESS_DENIED; + s_access = g_access = GENERIC_ALL_ACCESS; + break; + default: + DEBUG(0,("parse_usershare_acl: unknown acl type at %s.\n", + pacl )); + return False; + } + + pacl++; + if (*pacl && *pacl != ',') { + DEBUG(0,("parse_usershare_acl: bad acl string at %s.\n", + pacl )); + return False; + } + pacl++; /* Go past any ',' */ + + se_map_generic(&s_access, &file_generic_mapping); + init_sec_access(&sa, g_access | s_access ); + init_sec_ace(&ace_list[i], &sid, type, sa, 0); + } + + if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, num_aces, ace_list)) != NULL) { + psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, &sd_size); + } + + if (!psd) { + DEBUG(0,("parse_usershare_acl: Failed to make SEC_DESC.\n")); + return False; + } + + *ppsd = psd; + return True; +} diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c index 609816b8774..c045be51c5f 100644 --- a/source3/lib/smbldap.c +++ b/source3/lib/smbldap.c @@ -230,7 +230,7 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = { Return the list of attribute names from a mapping table **********************************************************************/ - const char** get_attr_list( ATTRIB_MAP_ENTRY table[] ) + const char** get_attr_list( TALLOC_CTX *mem_ctx, ATTRIB_MAP_ENTRY table[] ) { const char **names; int i = 0; @@ -239,7 +239,7 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = { i++; i++; - names = SMB_MALLOC_ARRAY( const char*, i ); + names = TALLOC_ARRAY( mem_ctx, const char*, i ); if ( !names ) { DEBUG(0,("get_attr_list: out of memory\n")); return NULL; @@ -247,7 +247,7 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = { i = 0; while ( table[i].attrib != LDAP_ATTR_LIST_END ) { - names[i] = SMB_STRDUP( table[i].name ); + names[i] = talloc_strdup( names, table[i].name ); i++; } names[i] = NULL; @@ -255,29 +255,6 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = { return names; } -/********************************************************************* - Cleanup - ********************************************************************/ - - void free_attr_list( const char **list ) -{ - int i = 0; - - if ( !list ) - return; - - while ( list[i] ) { - /* SAFE_FREE generates a warning here that can't be gotten rid - * of with CONST_DISCARD */ - if (list[i] != NULL) { - free(CONST_DISCARD(char *, list[i])); - } - i+=1; - } - - SAFE_FREE( list ); -} - /******************************************************************* Search an attribute and return the first value found. ******************************************************************/ @@ -321,6 +298,88 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = { sizeof(pstring)); } + char * smbldap_talloc_single_attribute(LDAP *ldap_struct, LDAPMessage *entry, + const char *attribute, + TALLOC_CTX *mem_ctx) +{ + char **values; + char *result; + + if (attribute == NULL) { + return NULL; + } + + values = ldap_get_values(ldap_struct, entry, attribute); + + if (values == NULL) { + DEBUG(10, ("attribute %s does not exist\n", attribute)); + return NULL; + } + + if (ldap_count_values(values) != 1) { + DEBUG(10, ("attribute %s has %d values, expected only one\n", + attribute, ldap_count_values(values))); + ldap_value_free(values); + return NULL; + } + + if (pull_utf8_talloc(mem_ctx, &result, values[0]) < 0) { + DEBUG(10, ("pull_utf8_talloc failed\n")); + ldap_value_free(values); + return NULL; + } + + ldap_value_free(values); + +#ifdef DEBUG_PASSWORDS + DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n", + attribute, result)); +#endif + return result; +} + + static int ldapmsg_destructor(void *p) { + LDAPMessage **result = talloc_get_type_abort(p, LDAPMessage *); + ldap_msgfree(*result); + return 0; +} + + void talloc_autofree_ldapmsg(TALLOC_CTX *mem_ctx, LDAPMessage *result) +{ + LDAPMessage **handle; + + if (result == NULL) { + return; + } + + handle = TALLOC_P(mem_ctx, LDAPMessage *); + SMB_ASSERT(handle != NULL); + + *handle = result; + talloc_set_destructor(handle, ldapmsg_destructor); +} + + static int ldapmod_destructor(void *p) { + LDAPMod ***result = talloc_get_type_abort(p, LDAPMod **); + ldap_mods_free(*result, True); + return 0; +} + + void talloc_autofree_ldapmod(TALLOC_CTX *mem_ctx, LDAPMod **mod) +{ + LDAPMod ***handle; + + if (mod == NULL) { + return; + } + + handle = TALLOC_P(mem_ctx, LDAPMod **); + SMB_ASSERT(handle != NULL); + + *handle = mod; + talloc_set_destructor(handle, ldapmod_destructor); +} + /************************************************************************ Routine to manage the LDAPMod structure array manage memory used by the array, by each struct, and values @@ -1041,6 +1100,14 @@ static int another_ldap_try(struct smbldap_state *ldap_state, int *rc, return True; } + if (open_rc == LDAP_INSUFFICIENT_ACCESS) { + /* The fact that we are non-root or any other + * access-denied condition will not change in the next + * round of trying */ + *rc = open_rc; + break; + } + if (got_alarm) { *rc = LDAP_TIMEOUT; break; @@ -1123,12 +1190,22 @@ static int smbldap_search_ext(struct smbldap_state *ldap_state, alarm(lp_ldap_timeout()); /* End setup timeout. */ - while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) + while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) { rc = ldap_search_ext_s(ldap_state->ldap_struct, base, scope, utf8_filter, CONST_DISCARD(char **, attrs), attrsonly, sctrls, cctrls, &timeout, sizelimit, res); + if (rc != LDAP_SUCCESS) { + char *ld_error = NULL; + ldap_get_option(ldap_state->ldap_struct, + LDAP_OPT_ERROR_STRING, &ld_error); + DEBUG(10,("Failed search for base: %s, error: %s " + "(%s)\n", base, ldap_err2string(rc), + ld_error ? ld_error : "unknown")); + SAFE_FREE(ld_error); + } + } SAFE_FREE(utf8_filter); @@ -1257,8 +1334,18 @@ int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *at return LDAP_NO_MEMORY; } - while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) + while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) { rc = ldap_modify_s(ldap_state->ldap_struct, utf8_dn, attrs); + if (rc != LDAP_SUCCESS) { + char *ld_error = NULL; + ldap_get_option(ldap_state->ldap_struct, + LDAP_OPT_ERROR_STRING, &ld_error); + DEBUG(10,("Failed to modify dn: %s, error: %s " + "(%s)\n", dn, ldap_err2string(rc), + ld_error ? ld_error : "unknown")); + SAFE_FREE(ld_error); + } + } SAFE_FREE(utf8_dn); return rc; @@ -1279,8 +1366,18 @@ int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs return LDAP_NO_MEMORY; } - while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) + while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) { rc = ldap_add_s(ldap_state->ldap_struct, utf8_dn, attrs); + if (rc != LDAP_SUCCESS) { + char *ld_error = NULL; + ldap_get_option(ldap_state->ldap_struct, + LDAP_OPT_ERROR_STRING, &ld_error); + DEBUG(10,("Failed to add dn: %s, error: %s " + "(%s)\n", dn, ldap_err2string(rc), + ld_error ? ld_error : "unknown")); + SAFE_FREE(ld_error); + } + } SAFE_FREE(utf8_dn); return rc; @@ -1301,8 +1398,18 @@ int smbldap_delete(struct smbldap_state *ldap_state, const char *dn) return LDAP_NO_MEMORY; } - while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) + while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) { rc = ldap_delete_s(ldap_state->ldap_struct, utf8_dn); + if (rc != LDAP_SUCCESS) { + char *ld_error = NULL; + ldap_get_option(ldap_state->ldap_struct, + LDAP_OPT_ERROR_STRING, &ld_error); + DEBUG(10,("Failed to delete dn: %s, error: %s " + "(%s)\n", dn, ldap_err2string(rc), + ld_error ? ld_error : "unknown")); + SAFE_FREE(ld_error); + } + } SAFE_FREE(utf8_dn); return rc; @@ -1320,34 +1427,33 @@ int smbldap_extended_operation(struct smbldap_state *ldap_state, if (!ldap_state) return (-1); - while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) + while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) { rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, reqdata, serverctrls, clientctrls, retoidp, retdatap); + if (rc != LDAP_SUCCESS) { + char *ld_error = NULL; + ldap_get_option(ldap_state->ldap_struct, + LDAP_OPT_ERROR_STRING, &ld_error); + DEBUG(10,("Extended operation failed with error: %s " + "(%s)\n", ldap_err2string(rc), + ld_error ? ld_error : "unknown")); + SAFE_FREE(ld_error); + } + } + return rc; } /******************************************************************* run the search by name. ******************************************************************/ -int smbldap_search_suffix (struct smbldap_state *ldap_state, const char *filter, - const char **search_attr, LDAPMessage ** result) +int smbldap_search_suffix (struct smbldap_state *ldap_state, + const char *filter, const char **search_attr, + LDAPMessage ** result) { - int scope = LDAP_SCOPE_SUBTREE; - int rc; - - rc = smbldap_search(ldap_state, lp_ldap_suffix(), scope, filter, search_attr, 0, result); - - if (rc != LDAP_SUCCESS) { - char *ld_error = NULL; - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, - &ld_error); - DEBUG(0,("smbldap_search_suffix: Problem during the LDAP search: %s (%s)\n", - ld_error?ld_error:"(unknown)", ldap_err2string (rc))); - SAFE_FREE(ld_error); - } - - return rc; + return smbldap_search(ldap_state, lp_ldap_suffix(), LDAP_SCOPE_SUBTREE, + filter, search_attr, 0, result); } static void smbldap_idle_fn(void **data, time_t *interval, time_t now) @@ -1442,6 +1548,25 @@ char *smbldap_get_dn(LDAP *ld, LDAPMessage *entry) return unix_dn; } + const char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld, + LDAPMessage *entry) +{ + char *utf8_dn, *unix_dn; + + utf8_dn = ldap_get_dn(ld, entry); + if (!utf8_dn) { + DEBUG (5, ("smbldap_get_dn: ldap_get_dn failed\n")); + return NULL; + } + if (pull_utf8_talloc(mem_ctx, &unix_dn, utf8_dn) == (size_t)-1) { + DEBUG (0, ("smbldap_get_dn: String conversion failure utf8 " + "[%s]\n", utf8_dn)); + return NULL; + } + ldap_memfree(utf8_dn); + return unix_dn; +} + /******************************************************************* Check if root-dse has a certain Control or Extension ********************************************************************/ diff --git a/source3/lib/smbldap_util.c b/source3/lib/smbldap_util.c index 4679b864874..7b4cf4d079f 100644 --- a/source3/lib/smbldap_util.c +++ b/source3/lib/smbldap_util.c @@ -99,21 +99,17 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state, pstring filter, dn; LDAPMod **mods = NULL; int rc; - int ldap_op; LDAPMessage *result = NULL; int num_result; const char **attr_list; - uid_t u_low, u_high; - gid_t g_low, g_high; - uint32 rid_low, rid_high; slprintf (filter, sizeof (filter) - 1, "(&(%s=%s)(objectclass=%s))", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), domain_name, LDAP_OBJ_DOMINFO); - attr_list = get_attr_list( dominfo_attr_list ); + attr_list = get_attr_list( NULL, dominfo_attr_list ); rc = smbldap_search_suffix(ldap_state, filter, attr_list, &result); - free_attr_list( attr_list ); + talloc_free( attr_list ); if (rc != LDAP_SUCCESS) { return NT_STATUS_UNSUCCESSFUL; @@ -122,80 +118,72 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state, num_result = ldap_count_entries(ldap_state->ldap_struct, result); if (num_result > 1) { - DEBUG (0, ("More than domain with that name exists: bailing out!\n")); + DEBUG (0, ("More than domain with that name exists: bailing " + "out!\n")); ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } /* Check if we need to add an entry */ DEBUG(3,("Adding new domain\n")); - ldap_op = LDAP_MOD_ADD; - pstr_sprintf(dn, "%s=%s,%s", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), - domain_name, lp_ldap_suffix()); + pstr_sprintf(dn, "%s=%s,%s", + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), + domain_name, lp_ldap_suffix()); /* Free original search */ ldap_msgfree(result); - /* make the changes - the entry *must* not already have samba attributes */ - smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), - domain_name); + /* make the changes - the entry *must* not already have samba + * attributes */ - /* If we don't have an entry, then ask secrets.tdb for what it thinks. + smbldap_set_mod(&mods, LDAP_MOD_ADD, + get_attr_key2string(dominfo_attr_list, + LDAP_ATTR_DOMAIN), + domain_name); + + /* If we don't have an entry, then ask secrets.tdb for what it thinks. It may choose to make it up */ sid_to_string(sid_string, get_global_sam_sid()); - smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID), sid_string); - - slprintf(algorithmic_rid_base_string, sizeof(algorithmic_rid_base_string) - 1, "%i", algorithmic_rid_base()); - smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE), + smbldap_set_mod(&mods, LDAP_MOD_ADD, + get_attr_key2string(dominfo_attr_list, + LDAP_ATTR_DOM_SID), + sid_string); + + slprintf(algorithmic_rid_base_string, + sizeof(algorithmic_rid_base_string) - 1, "%i", + algorithmic_rid_base()); + smbldap_set_mod(&mods, LDAP_MOD_ADD, + get_attr_key2string(dominfo_attr_list, + LDAP_ATTR_ALGORITHMIC_RID_BASE), algorithmic_rid_base_string); smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_DOMINFO); - /* add the sambaNext[User|Group]Rid attributes if the idmap ranges are set. - TODO: fix all the places where the line between idmap and normal operations - needed by smbd gets fuzzy --jerry 2003-08-11 */ + /* add the sambaNextUserRid attributes. */ - if ( lp_idmap_uid(&u_low, &u_high) && lp_idmap_gid(&g_low, &g_high) - && get_free_rid_range(&rid_low, &rid_high) ) { + uint32 rid = BASE_RID; fstring rid_str; - fstr_sprintf( rid_str, "%i", rid_high|USER_RID_TYPE ); + fstr_sprintf( rid_str, "%i", rid ); DEBUG(10,("setting next available user rid [%s]\n", rid_str)); smbldap_set_mod(&mods, LDAP_MOD_ADD, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), - rid_str); - - fstr_sprintf( rid_str, "%i", rid_high|GROUP_RID_TYPE ); - DEBUG(10,("setting next available group rid [%s]\n", rid_str)); - smbldap_set_mod(&mods, LDAP_MOD_ADD, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), + get_attr_key2string(dominfo_attr_list, + LDAP_ATTR_NEXT_USERRID), rid_str); - } - switch(ldap_op) - { - case LDAP_MOD_ADD: - rc = smbldap_add(ldap_state, dn, mods); - break; - case LDAP_MOD_REPLACE: - rc = smbldap_modify(ldap_state, dn, mods); - break; - default: - DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op)); - return NT_STATUS_INVALID_PARAMETER; - } - + rc = smbldap_add(ldap_state, dn, mods); + if (rc!=LDAP_SUCCESS) { char *ld_error = NULL; - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); - DEBUG(1,("failed to %s domain dn= %s with: %s\n\t%s\n", - ldap_op == LDAP_MOD_ADD ? "add" : "modify", - dn, ldap_err2string(rc), - ld_error?ld_error:"unknown")); + ldap_get_option(ldap_state->ldap_struct, + LDAP_OPT_ERROR_STRING, &ld_error); + DEBUG(1,("failed to add domain dn= %s with: %s\n\t%s\n", + dn, ldap_err2string(rc), + ld_error?ld_error:"unknown")); SAFE_FREE(ld_error); ldap_mods_free(mods, True); @@ -227,9 +215,9 @@ NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state, DEBUG(2, ("Searching for:[%s]\n", filter)); - attr_list = get_attr_list( dominfo_attr_list ); + attr_list = get_attr_list( NULL, dominfo_attr_list ); rc = smbldap_search_suffix(ldap_state, filter, attr_list , result); - free_attr_list( attr_list ); + talloc_free( attr_list ); if (rc != LDAP_SUCCESS) { DEBUG(2,("Problem during LDAPsearch: %s\n", ldap_err2string (rc))); diff --git a/source3/lib/system_smbd.c b/source3/lib/system_smbd.c index 6c65f61ad7a..1d4f88fbb96 100644 --- a/source3/lib/system_smbd.c +++ b/source3/lib/system_smbd.c @@ -28,47 +28,6 @@ #ifndef HAVE_GETGROUPLIST -static int int_compare( int *a, int *b ) -{ - if ( *a == *b ) - return 0; - else if ( *a < *b ) - return -1; - else - return 1; -} - -void remove_duplicate_gids( int *num_groups, gid_t *groups ) -{ - int i; - int count = *num_groups; - - if ( *num_groups <= 0 || !groups ) - return; - - DEBUG(8,("remove_duplicate_gids: Enter %d gids\n", *num_groups)); - - qsort( groups, *num_groups, sizeof(gid_t), QSORT_CAST int_compare ); - - for ( i=1; i<count; ) { - if ( groups[i-1] == groups[i] ) { - memmove( &groups[i-1], &groups[i], (count - i + 1)*sizeof(gid_t) ); - - /* decrement the total number of groups and do not increment - the loop counter */ - count--; - continue; - } - i++; - } - - *num_groups = count; - - DEBUG(8,("remove_duplicate_gids: Exit %d gids\n", *num_groups)); - - return; -} - /* This is a *much* faster way of getting the list of groups for a user without changing the current supplementary group list. The old @@ -79,7 +38,8 @@ void remove_duplicate_gids( int *num_groups, gid_t *groups ) NOTE!! this function only works if it is called as root! */ -static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, int *grpcnt) +static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, + int *grpcnt) { gid_t *gids_saved; int ret, ngrp_saved, num_gids; @@ -140,9 +100,6 @@ static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, in } groups[0] = gid; *grpcnt = ret + 1; - - /* remove any duplicates gids in the list */ - remove_duplicate_gids( grpcnt, groups ); } restore_re_gid(); @@ -169,11 +126,11 @@ static int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grp /* see if we should disable winbindd lookups for local users */ if (strchr(user, *lp_winbind_separator()) == NULL) { if ( !winbind_off() ) - DEBUG(0,("sys_getgroup_list: Insufficient environment space for %s\n", - WINBINDD_DONT_ENV)); + DEBUG(0,("sys_getgroup_list: Insufficient environment space " + "for %s\n", WINBINDD_DONT_ENV)); else - DEBUG(10,("sys_getgrouplist(): disabled winbindd for group lookup [user == %s]\n", - user)); + DEBUG(10,("sys_getgrouplist(): disabled winbindd for group " + "lookup [user == %s]\n", user)); } #ifdef HAVE_GETGROUPLIST @@ -190,8 +147,9 @@ static int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grp return retval; } -static BOOL getgroups_user(const char *user, gid_t primary_gid, - gid_t **ret_groups, size_t *p_ngroups) +BOOL getgroups_unix_user(TALLOC_CTX *mem_ctx, const char *user, + gid_t primary_gid, + gid_t **ret_groups, size_t *p_ngroups) { size_t ngrp; int max_grp; @@ -229,10 +187,11 @@ static BOOL getgroups_user(const char *user, gid_t primary_gid, groups = NULL; /* Add in primary group first */ - add_gid_to_array_unique(NULL, primary_gid, &groups, &ngrp); + add_gid_to_array_unique(mem_ctx, primary_gid, &groups, &ngrp); for (i=0; i<max_grp; i++) - add_gid_to_array_unique(NULL, temp_groups[i], &groups, &ngrp); + add_gid_to_array_unique(mem_ctx, temp_groups[i], + &groups, &ngrp); *p_ngroups = ngrp; *ret_groups = groups; @@ -241,15 +200,22 @@ static BOOL getgroups_user(const char *user, gid_t primary_gid, } NTSTATUS pdb_default_enum_group_memberships(struct pdb_methods *methods, - const char *username, - gid_t primary_gid, + TALLOC_CTX *mem_ctx, + SAM_ACCOUNT *user, DOM_SID **pp_sids, gid_t **pp_gids, size_t *p_num_groups) { size_t i; + gid_t gid; + + if (!sid_to_gid(pdb_get_group_sid(user), &gid)) { + DEBUG(10, ("sid_to_gid failed\n")); + return NT_STATUS_NO_SUCH_USER; + } - if (!getgroups_user(username, primary_gid, pp_gids, p_num_groups)) { + if (!getgroups_unix_user(mem_ctx, pdb_get_username(user), gid, + pp_gids, p_num_groups)) { return NT_STATUS_NO_SUCH_USER; } @@ -257,22 +223,15 @@ NTSTATUS pdb_default_enum_group_memberships(struct pdb_methods *methods, smb_panic("primary group missing"); } - *pp_sids = SMB_MALLOC_ARRAY(DOM_SID, *p_num_groups); + *pp_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, *p_num_groups); if (*pp_sids == NULL) { - SAFE_FREE(pp_gids); + talloc_free(*pp_gids); return NT_STATUS_NO_MEMORY; } for (i=0; i<*p_num_groups; i++) { - if (!NT_STATUS_IS_OK(gid_to_sid(&(*pp_sids)[i], (*pp_gids)[i]))) { - DEBUG(1, ("get_user_groups: failed to convert " - "gid %ld to a sid!\n", - (long int)(*pp_gids)[i+1])); - SAFE_FREE(*pp_sids); - SAFE_FREE(*pp_gids); - return NT_STATUS_NO_SUCH_USER; - } + gid_to_sid(&(*pp_sids)[i], (*pp_gids)[i]); } return NT_STATUS_OK; diff --git a/source3/lib/username.c b/source3/lib/username.c index 7d66b320adf..c04dfd05da1 100644 --- a/source3/lib/username.c +++ b/source3/lib/username.c @@ -22,8 +22,12 @@ #include "includes.h" /* internal functions */ -static struct passwd *uname_string_combinations(char *s, struct passwd * (*fn) (const char *), int N); -static struct passwd *uname_string_combinations2(char *s, int offset, struct passwd * (*fn) (const char *), int N); +static struct passwd *uname_string_combinations(char *s, TALLOC_CTX *mem_ctx, + struct passwd * (*fn) (TALLOC_CTX *mem_ctx, const char *), + int N); +static struct passwd *uname_string_combinations2(char *s, TALLOC_CTX *mem_ctx, int offset, + struct passwd * (*fn) (TALLOC_CTX *mem_ctx, const char *), + int N); /***************************************************************** Check if a user or group name is local (this is a *local* name for @@ -108,7 +112,7 @@ BOOL map_username(fstring user) } numlines = 0; - qlines = fd_lines_load(fd, &numlines); + qlines = fd_lines_load(fd, &numlines,0); DEBUGADD(10,("Lines returned = [%d]\n", numlines)); close(fd); @@ -180,7 +184,8 @@ BOOL map_username(fstring user) return False; } - if (strchr_m(dosname,'*') || user_in_list(user, (const char **)dosuserlist, NULL, 0)) { + if (strchr_m(dosname,'*') || + user_in_list(user, (const char **)dosuserlist)) { DEBUG(3,("Mapped user %s to %s\n",user,unixname)); mapped_user = True; fstrcpy( last_from,user ); @@ -218,7 +223,8 @@ BOOL map_username(fstring user) static struct passwd *Get_Pwnam_ret = NULL; -static struct passwd *Get_Pwnam_internals(const char *user, char *user2) +static struct passwd *Get_Pwnam_internals(TALLOC_CTX *mem_ctx, + const char *user, char *user2) { struct passwd *ret = NULL; @@ -232,7 +238,7 @@ static struct passwd *Get_Pwnam_internals(const char *user, char *user2) common case on UNIX systems */ strlower_m(user2); DEBUG(5,("Trying _Get_Pwnam(), username as lowercase is %s\n",user2)); - ret = getpwnam_alloc(user2); + ret = getpwnam_alloc(mem_ctx, user2); if(ret) goto done; @@ -240,7 +246,7 @@ static struct passwd *Get_Pwnam_internals(const char *user, char *user2) if(strcmp(user, user2) != 0) { DEBUG(5,("Trying _Get_Pwnam(), username as given is %s\n", user)); - ret = getpwnam_alloc(user); + ret = getpwnam_alloc(mem_ctx, user); if(ret) goto done; } @@ -250,7 +256,7 @@ static struct passwd *Get_Pwnam_internals(const char *user, char *user2) if(strcmp(user, user2) != 0) { DEBUG(5,("Trying _Get_Pwnam(), username as uppercase is %s\n", user2)); - ret = getpwnam_alloc(user2); + ret = getpwnam_alloc(mem_ctx, user2); if(ret) goto done; } @@ -259,7 +265,7 @@ static struct passwd *Get_Pwnam_internals(const char *user, char *user2) strlower_m(user2); DEBUG(5,("Checking combinations of %d uppercase letters in %s\n", lp_usernamelevel(), user2)); - ret = uname_string_combinations(user2, getpwnam_alloc, + ret = uname_string_combinations(user2, mem_ctx, getpwnam_alloc, lp_usernamelevel()); done: @@ -275,7 +281,7 @@ done: This will return an allocated structure ****************************************************************************/ -struct passwd *Get_Pwnam_alloc(const char *user) +struct passwd *Get_Pwnam_alloc(TALLOC_CTX *mem_ctx, const char *user) { fstring user2; struct passwd *ret; @@ -289,7 +295,7 @@ struct passwd *Get_Pwnam_alloc(const char *user) DEBUG(5,("Finding user %s\n", user)); - ret = Get_Pwnam_internals(user, user2); + ret = Get_Pwnam_internals(mem_ctx, user, user2); return ret; } @@ -303,7 +309,7 @@ struct passwd *Get_Pwnam(const char *user) { struct passwd *ret; - ret = Get_Pwnam_alloc(user); + ret = Get_Pwnam_alloc(NULL, user); /* This call used to just return the 'passwd' static buffer. This could then have accidental reuse implications, so @@ -320,7 +326,7 @@ struct passwd *Get_Pwnam(const char *user) */ if (Get_Pwnam_ret) { - passwd_free(&Get_Pwnam_ret); + talloc_free(Get_Pwnam_ret); } Get_Pwnam_ret = ret; @@ -333,7 +339,7 @@ struct passwd *Get_Pwnam(const char *user) try lower case. ****************************************************************************/ -static BOOL user_in_netgroup_list(const char *user, const char *ngname) +BOOL user_in_netgroup(const char *user, const char *ngname) { #ifdef HAVE_NETGROUP static char *mydomain = NULL; @@ -351,7 +357,7 @@ static BOOL user_in_netgroup_list(const char *user, const char *ngname) user, mydomain, ngname)); if (innetgr(ngname, NULL, user, mydomain)) { - DEBUG(5,("user_in_netgroup_list: Found\n")); + DEBUG(5,("user_in_netgroup: Found\n")); return (True); } else { @@ -367,7 +373,7 @@ static BOOL user_in_netgroup_list(const char *user, const char *ngname) lowercase_user, mydomain, ngname)); if (innetgr(ngname, NULL, lowercase_user, mydomain)) { - DEBUG(5,("user_in_netgroup_list: Found\n")); + DEBUG(5,("user_in_netgroup: Found\n")); return (True); } } @@ -379,8 +385,8 @@ static BOOL user_in_netgroup_list(const char *user, const char *ngname) Check if a user is in a winbind group. ****************************************************************************/ -static BOOL user_in_winbind_group_list(const char *user, const char *gname, - BOOL *winbind_answered) +static BOOL user_in_winbind_group(const char *user, const char *gname, + BOOL *winbind_answered) { int i; gid_t gid, gid_low, gid_high; @@ -392,7 +398,7 @@ static BOOL user_in_winbind_group_list(const char *user, const char *gname, *winbind_answered = False; if ((gid = nametogid(gname)) == (gid_t)-1) { - DEBUG(0,("user_in_winbind_group_list: nametogid for group %s " + DEBUG(0,("user_in_winbind_group: nametogid for group %s " "failed.\n", gname )); goto err; } @@ -439,11 +445,11 @@ static BOOL user_in_winbind_group_list(const char *user, const char *gname, } else - DEBUG(10,("user_in_winbind_group_list: using cached user " + DEBUG(10,("user_in_winbind_group: using cached user " "groups for [%s]\n", user)); if ( DEBUGLEVEL >= 10 ) { - DEBUG(10,("user_in_winbind_group_list: using groups -- ")); + DEBUG(10,("user_in_winbind_group: using groups -- ")); for ( i=0; i<num_groups; i++ ) DEBUGADD(10,("%lu ", (unsigned long)groups[i])); DEBUGADD(10,("\n")); @@ -477,13 +483,13 @@ static BOOL user_in_winbind_group_list(const char *user, const char *gname, Check if a user is in a UNIX group. ****************************************************************************/ -BOOL user_in_unix_group_list(const char *user,const char *gname) +BOOL user_in_unix_group(const char *user,const char *gname) { struct passwd *pass = Get_Pwnam(user); struct sys_userlist *user_list; struct sys_userlist *member; - DEBUG(10,("user_in_unix_group_list: checking user %s in group %s\n", + DEBUG(10,("user_in_unix_group: checking user %s in group %s\n", user, gname)); /* @@ -493,7 +499,7 @@ BOOL user_in_unix_group_list(const char *user,const char *gname) if (pass) { if (strequal(gname,gidtoname(pass->pw_gid))) { - DEBUG(10,("user_in_unix_group_list: group %s is " + DEBUG(10,("user_in_unix_group: group %s is " "primary group.\n", gname )); return True; } @@ -501,13 +507,13 @@ BOOL user_in_unix_group_list(const char *user,const char *gname) user_list = get_users_in_group(gname); if (user_list == NULL) { - DEBUG(10,("user_in_unix_group_list: no such group %s\n", + DEBUG(10,("user_in_unix_group: no such group %s\n", gname )); return False; } for (member = user_list; member; member = member->next) { - DEBUG(10,("user_in_unix_group_list: checking user %s against " + DEBUG(10,("user_in_unix_group: checking user %s against " "member %s\n", user, member->unix_name )); if (strequal(member->unix_name,user)) { free_userlist(user_list); @@ -523,35 +529,17 @@ BOOL user_in_unix_group_list(const char *user,const char *gname) Check if a user is in a group list. Ask winbind first, then use UNIX. ****************************************************************************/ -BOOL user_in_group_list(const char *user, const char *gname, gid_t *groups, - size_t n_groups) +BOOL user_in_group(const char *user, const char *gname) { BOOL winbind_answered = False; BOOL ret; - gid_t gid; - unsigned i; - gid = nametogid(gname); - if (gid == (gid_t)-1) - return False; - - if (groups && n_groups > 0) { - for (i=0; i < n_groups; i++) { - if (groups[i] == gid) { - return True; - } - } - return False; - } - - /* fallback if we don't yet have the group list */ - - ret = user_in_winbind_group_list(user, gname, &winbind_answered); + ret = user_in_winbind_group(user, gname, &winbind_answered); if (!winbind_answered) - ret = user_in_unix_group_list(user, gname); + ret = user_in_unix_group(user, gname); if (ret) - DEBUG(10,("user_in_group_list: user |%s| is in group |%s|\n", + DEBUG(10,("user_in_group: user |%s| is in group |%s|\n", user, gname)); return ret; } @@ -561,8 +549,7 @@ BOOL user_in_group_list(const char *user, const char *gname, gid_t *groups, and netgroup lists. ****************************************************************************/ -BOOL user_in_list(const char *user,const char **list, gid_t *groups, - size_t n_groups) +BOOL user_in_list(const char *user,const char **list) { if (!list || !*list) return False; @@ -590,10 +577,9 @@ BOOL user_in_list(const char *user,const char **list, gid_t *groups, * Old behaviour. Check netgroup list * followed by UNIX list. */ - if(user_in_netgroup_list(user, *list +1)) + if(user_in_netgroup(user, *list +1)) return True; - if(user_in_group_list(user, *list +1, groups, - n_groups)) + if(user_in_group(user, *list +1)) return True; } else if (**list == '+') { @@ -601,10 +587,9 @@ BOOL user_in_list(const char *user,const char **list, gid_t *groups, /* * Search UNIX list followed by netgroup. */ - if(user_in_group_list(user, *list +2, groups, - n_groups)) + if(user_in_group(user, *list +2)) return True; - if(user_in_netgroup_list(user, *list +2)) + if(user_in_netgroup(user, *list +2)) return True; } else { @@ -613,8 +598,7 @@ BOOL user_in_list(const char *user,const char **list, gid_t *groups, * Just search UNIX list. */ - if(user_in_group_list(user, *list +1, groups, - n_groups)) + if(user_in_group(user, *list +1)) return True; } @@ -624,16 +608,15 @@ BOOL user_in_list(const char *user,const char **list, gid_t *groups, /* * Search netgroup list followed by UNIX list. */ - if(user_in_netgroup_list(user, *list +2)) + if(user_in_netgroup(user, *list +2)) return True; - if(user_in_group_list(user, *list +2, groups, - n_groups)) + if(user_in_group(user, *list +2)) return True; } else { /* * Just search netgroup list. */ - if(user_in_netgroup_list(user, *list +1)) + if(user_in_netgroup(user, *list +1)) return True; } } else if (!name_is_local(*list)) { @@ -676,7 +659,7 @@ BOOL user_in_list(const char *user,const char **list, gid_t *groups, /* Check if user name is in the * Windows group */ - ret = user_in_winbind_group_list( + ret = user_in_winbind_group( user, *list, &winbind_answered); @@ -705,21 +688,24 @@ BOOL user_in_list(const char *user,const char **list, gid_t *groups, it assumes the string starts lowercased ****************************************************************************/ -static struct passwd *uname_string_combinations2(char *s,int offset,struct passwd *(*fn)(const char *),int N) +static struct passwd *uname_string_combinations2(char *s, TALLOC_CTX *mem_ctx, + int offset, + struct passwd *(*fn)(TALLOC_CTX *mem_ctx, const char *), + int N) { ssize_t len = (ssize_t)strlen(s); int i; struct passwd *ret; if (N <= 0 || offset >= len) - return(fn(s)); + return(fn(mem_ctx, s)); for (i=offset;i<(len-(N-1));i++) { char c = s[i]; if (!islower_ascii((int)c)) continue; s[i] = toupper_ascii(c); - ret = uname_string_combinations2(s,i+1,fn,N-1); + ret = uname_string_combinations2(s, mem_ctx, i+1, fn, N-1); if(ret) return(ret); s[i] = c; @@ -735,13 +721,15 @@ static struct passwd *uname_string_combinations2(char *s,int offset,struct passw it assumes the string starts lowercased ****************************************************************************/ -static struct passwd * uname_string_combinations(char *s,struct passwd * (*fn)(const char *),int N) +static struct passwd * uname_string_combinations(char *s, TALLOC_CTX *mem_ctx, + struct passwd * (*fn)(TALLOC_CTX *mem_ctx, const char *), + int N) { int n; struct passwd *ret; for (n=1;n<=N;n++) { - ret = uname_string_combinations2(s,0,fn,n); + ret = uname_string_combinations2(s,mem_ctx,0,fn,n); if(ret) return(ret); } diff --git a/source3/lib/util.c b/source3/lib/util.c index 38878befc77..dc57839df34 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -1427,10 +1427,10 @@ const char *uidtoname(uid_t uid) static fstring name; struct passwd *pass; - pass = getpwuid_alloc(uid); + pass = getpwuid_alloc(NULL, uid); if (pass) { fstrcpy(name, pass->pw_name); - passwd_free(&pass); + talloc_free(pass); } else { slprintf(name, sizeof(name) - 1, "%ld",(long int)uid); } @@ -1464,10 +1464,10 @@ uid_t nametouid(const char *name) char *p; uid_t u; - pass = getpwnam_alloc(name); + pass = getpwnam_alloc(NULL, name); if (pass) { u = pass->pw_uid; - passwd_free(&pass); + talloc_free(pass); return u; } diff --git a/source3/lib/util_file.c b/source3/lib/util_file.c index 407a8b24fc9..53a9bc9b417 100644 --- a/source3/lib/util_file.c +++ b/source3/lib/util_file.c @@ -386,30 +386,37 @@ char *file_pload(char *syscmd, size_t *size) /**************************************************************************** Load a file into memory from a fd. + Truncate at maxsize. If maxsize == 0 - no limit. ****************************************************************************/ -char *fd_load(int fd, size_t *size) +char *fd_load(int fd, size_t *psize, size_t maxsize) { SMB_STRUCT_STAT sbuf; + size_t size; char *p; if (sys_fstat(fd, &sbuf) != 0) { return NULL; } - p = (char *)SMB_MALLOC(sbuf.st_size+1); + size = sbuf.st_size; + if (maxsize) { + size = MIN(size, maxsize); + } + + p = (char *)SMB_MALLOC(size+1); if (!p) { return NULL; } - if (read(fd, p, sbuf.st_size) != sbuf.st_size) { + if (read(fd, p, size) != size) { SAFE_FREE(p); return NULL; } - p[sbuf.st_size] = 0; + p[size] = 0; - if (size) { - *size = sbuf.st_size; + if (psize) { + *psize = size; } return p; @@ -419,7 +426,7 @@ char *fd_load(int fd, size_t *size) Load a file into memory. ****************************************************************************/ -char *file_load(const char *fname, size_t *size) +char *file_load(const char *fname, size_t *size, size_t maxsize) { int fd; char *p; @@ -433,7 +440,7 @@ char *file_load(const char *fname, size_t *size) return NULL; } - p = fd_load(fd, size); + p = fd_load(fd, size, maxsize); close(fd); return p; } @@ -461,7 +468,7 @@ void *map_file(char *fname, size_t size) } #endif if (!p) { - p = file_load(fname, &s2); + p = file_load(fname, &s2, 0); if (!p) { return NULL; } @@ -522,12 +529,12 @@ static char **file_lines_parse(char *p, size_t size, int *numlines) must be freed with file_lines_free(). ****************************************************************************/ -char **file_lines_load(const char *fname, int *numlines) +char **file_lines_load(const char *fname, int *numlines, size_t maxsize) { char *p; size_t size = 0; - p = file_load(fname, &size); + p = file_load(fname, &size, maxsize); if (!p) { return NULL; } @@ -541,12 +548,12 @@ char **file_lines_load(const char *fname, int *numlines) the list. ****************************************************************************/ -char **fd_lines_load(int fd, int *numlines) +char **fd_lines_load(int fd, int *numlines, size_t maxsize) { char *p; size_t size; - p = fd_load(fd, &size); + p = fd_load(fd, &size, maxsize); if (!p) { return NULL; } diff --git a/source3/lib/util_pw.c b/source3/lib/util_pw.c index 13349bad34e..e026affb447 100644 --- a/source3/lib/util_pw.c +++ b/source3/lib/util_pw.c @@ -22,69 +22,45 @@ #include "includes.h" -static struct passwd *alloc_copy_passwd(const struct passwd *from) +static struct passwd *talloc_copy_passwd(TALLOC_CTX *mem_ctx, + const struct passwd *from) { - struct passwd *ret = SMB_XMALLOC_P(struct passwd); - ZERO_STRUCTP(ret); - ret->pw_name = smb_xstrdup(from->pw_name); - ret->pw_passwd = smb_xstrdup(from->pw_passwd); + struct passwd *ret = TALLOC_P(mem_ctx, struct passwd); + ret->pw_name = talloc_strdup(ret, from->pw_name); + ret->pw_passwd = talloc_strdup(ret, from->pw_passwd); ret->pw_uid = from->pw_uid; ret->pw_gid = from->pw_gid; - ret->pw_gecos = smb_xstrdup(from->pw_gecos); - ret->pw_dir = smb_xstrdup(from->pw_dir); - ret->pw_shell = smb_xstrdup(from->pw_shell); + ret->pw_gecos = talloc_strdup(ret, from->pw_gecos); + ret->pw_dir = talloc_strdup(ret, from->pw_dir); + ret->pw_shell = talloc_strdup(ret, from->pw_shell); return ret; } -void passwd_free (struct passwd **buf) -{ - if (!*buf) { - DEBUG(0, ("attempted double-free of allocated passwd\n")); - return; - } - - SAFE_FREE((*buf)->pw_name); - SAFE_FREE((*buf)->pw_passwd); - SAFE_FREE((*buf)->pw_gecos); - SAFE_FREE((*buf)->pw_dir); - SAFE_FREE((*buf)->pw_shell); - - SAFE_FREE(*buf); -} - #define PWNAMCACHE_SIZE 4 -static struct passwd *pwnam_cache[PWNAMCACHE_SIZE]; -static BOOL pwnam_cache_initialized = False; +static struct passwd **pwnam_cache = NULL; static void init_pwnam_cache(void) { - int i; - - if (pwnam_cache_initialized) + if (pwnam_cache != NULL) return; - for (i=0; i<PWNAMCACHE_SIZE; i++) - pwnam_cache[i] = NULL; + pwnam_cache = TALLOC_ZERO_ARRAY(NULL, struct passwd *, + PWNAMCACHE_SIZE); + if (pwnam_cache == NULL) { + smb_panic("Could not init pwnam_cache\n"); + } - pwnam_cache_initialized = True; return; } void flush_pwnam_cache(void) { - int i; - + talloc_free(pwnam_cache); + pwnam_cache = NULL; init_pwnam_cache(); - - for (i=0; i<PWNAMCACHE_SIZE; i++) { - if (pwnam_cache[i] == NULL) - continue; - - passwd_free(&pwnam_cache[i]); - } } -struct passwd *getpwnam_alloc(const char *name) +struct passwd *getpwnam_alloc(TALLOC_CTX *mem_ctx, const char *name) { int i; @@ -96,7 +72,7 @@ struct passwd *getpwnam_alloc(const char *name) if ((pwnam_cache[i] != NULL) && (strcmp(name, pwnam_cache[i]->pw_name) == 0)) { DEBUG(10, ("Got %s from pwnam_cache\n", name)); - return alloc_copy_passwd(pwnam_cache[i]); + return talloc_reference(mem_ctx, pwnam_cache[i]); } } @@ -119,15 +95,20 @@ struct passwd *getpwnam_alloc(const char *name) if (i == PWNAMCACHE_SIZE) i = rand() % PWNAMCACHE_SIZE; - if (pwnam_cache[i] != NULL) - passwd_free(&pwnam_cache[i]); + if (pwnam_cache[i] != NULL) { + talloc_free(pwnam_cache[i]); + } - pwnam_cache[i] = alloc_copy_passwd(temp); + pwnam_cache[i] = talloc_copy_passwd(pwnam_cache, temp); + + if (mem_ctx != NULL) { + return talloc_reference(mem_ctx, pwnam_cache[i]); + } - return alloc_copy_passwd(temp); + return talloc_copy_passwd(NULL, pwnam_cache[i]); } -struct passwd *getpwuid_alloc(uid_t uid) +struct passwd *getpwuid_alloc(TALLOC_CTX *mem_ctx, uid_t uid) { struct passwd *temp; @@ -142,5 +123,5 @@ struct passwd *getpwuid_alloc(uid_t uid) return NULL; } - return alloc_copy_passwd(temp); + return talloc_copy_passwd(mem_ctx, temp); } diff --git a/source3/lib/util_sid.c b/source3/lib/util_sid.c index e2b2ebf28ca..c7f9dc2fdbe 100644 --- a/source3/lib/util_sid.c +++ b/source3/lib/util_sid.c @@ -75,6 +75,11 @@ const DOM_SID global_sid_Builtin_Backup_Operators = /* Builtin backup operators const DOM_SID global_sid_Builtin_Replicator = /* Builtin replicator */ { 1, 2, {0,0,0,0,0,5}, {32,552,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +const DOM_SID global_sid_Unix_Users = /* Unmapped Unix users */ +{ 1, 1, {0,0,0,0,0,22}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +const DOM_SID global_sid_Unix_Groups = /* Unmapped Unix groups */ +{ 1, 1, {0,0,0,0,0,22}, {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; + /* Unused, left here for documentary purposes */ #if 0 #define SECURITY_NULL_SID_AUTHORITY 0 diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c index 0b02487f774..85b5cfc90a7 100644 --- a/source3/lib/util_str.c +++ b/source3/lib/util_str.c @@ -1667,7 +1667,7 @@ int fstr_sprintf(fstring s, const char *fmt, ...) #define S_LIST_ABS 16 /* List Allocation Block Size */ -char **str_list_make(const char *string, const char *sep) +static char **str_list_make_internal(TALLOC_CTX *mem_ctx, const char *string, const char *sep) { char **list, **rlist; const char *str; @@ -1677,7 +1677,11 @@ char **str_list_make(const char *string, const char *sep) if (!string || !*string) return NULL; - s = SMB_STRDUP(string); + if (mem_ctx) { + s = talloc_strdup(mem_ctx, string); + } else { + s = SMB_STRDUP(string); + } if (!s) { DEBUG(0,("str_list_make: Unable to allocate memory")); return NULL; @@ -1691,32 +1695,64 @@ char **str_list_make(const char *string, const char *sep) while (next_token(&str, tok, sep, sizeof(tok))) { if (num == lsize) { lsize += S_LIST_ABS; - rlist = SMB_REALLOC_ARRAY(list, char *, lsize +1); + if (mem_ctx) { + rlist = TALLOC_REALLOC_ARRAY(mem_ctx, list, char *, lsize +1); + } else { + rlist = SMB_REALLOC_ARRAY(list, char *, lsize +1); + } if (!rlist) { DEBUG(0,("str_list_make: Unable to allocate memory")); str_list_free(&list); - SAFE_FREE(s); + if (mem_ctx) { + talloc_free(s); + } else { + SAFE_FREE(s); + } return NULL; } else list = rlist; memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1))); } + + if (mem_ctx) { + list[num] = talloc_strdup(mem_ctx, tok); + } else { + list[num] = SMB_STRDUP(tok); + } - list[num] = SMB_STRDUP(tok); if (!list[num]) { DEBUG(0,("str_list_make: Unable to allocate memory")); str_list_free(&list); - SAFE_FREE(s); + if (mem_ctx) { + talloc_free(s); + } else { + SAFE_FREE(s); + } return NULL; } num++; } - - SAFE_FREE(s); + + if (mem_ctx) { + talloc_free(s); + } else { + SAFE_FREE(s); + } + return list; } +char **str_list_make_talloc(TALLOC_CTX *mem_ctx, const char *string, const char *sep) +{ + return str_list_make_internal(mem_ctx, string, sep); +} + +char **str_list_make(const char *string, const char *sep) +{ + return str_list_make_internal(NULL, string, sep); +} + BOOL str_list_copy(char ***dest, const char **src) { char **list, **rlist; @@ -1778,16 +1814,35 @@ BOOL str_list_compare(char **list1, char **list2) return True; } -void str_list_free(char ***list) +static void str_list_free_internal(TALLOC_CTX *mem_ctx, char ***list) { char **tlist; if (!list || !*list) return; tlist = *list; - for(; *tlist; tlist++) - SAFE_FREE(*tlist); - SAFE_FREE(*list); + for(; *tlist; tlist++) { + if (mem_ctx) { + talloc_free(*tlist); + } else { + SAFE_FREE(*tlist); + } + } + if (mem_ctx) { + talloc_free(*tlist); + } else { + SAFE_FREE(*list); + } +} + +void str_list_free_talloc(TALLOC_CTX *mem_ctx, char ***list) +{ + str_list_free_internal(mem_ctx, list); +} + +void str_list_free(char ***list) +{ + str_list_free_internal(NULL, list); } /****************************************************************************** @@ -2317,3 +2372,23 @@ char *sstring_sub(const char *src, char front, char back) temp3[len-1] = '\0'; return temp3; } + +/******************************************************************** + Check a string for any occurrences of a specified list of invalid + characters. +********************************************************************/ + +BOOL validate_net_name( const char *name, const char *invalid_chars, int max_len ) +{ + int i; + + for ( i=0; i<max_len && name[i]; i++ ) { + /* fail if strchr_m() finds one of the invalid characters */ + if ( name[i] && strchr_m( invalid_chars, name[i] ) ) { + return False; + } + } + + return True; +} + diff --git a/source3/lib/util_unistr.c b/source3/lib/util_unistr.c index 880416a5491..bc90314fcec 100644 --- a/source3/lib/util_unistr.c +++ b/source3/lib/util_unistr.c @@ -291,24 +291,18 @@ int rpcstr_pull_unistr2_fstring(char *dest, UNISTR2 *src) * have been to manually talloc_strdup them in rpc_client/cli_netlogon.c. */ -size_t rpcstr_pull_unistr2_talloc(TALLOC_CTX *mem_ctx, char **dest, - UNISTR2 *src) +char *rpcstr_pull_unistr2_talloc(TALLOC_CTX *mem_ctx, UNISTR2 *src) { pstring tmp; size_t result; result = pull_ucs2(NULL, tmp, src->buffer, sizeof(tmp), src->uni_str_len * 2, 0); - if (result < 0) { - return result; - } - - *dest = talloc_strdup(mem_ctx, tmp); - if (*dest == NULL) { - return -1; + if (result == (size_t)-1) { + return NULL; } - return result; + return talloc_strdup(mem_ctx, tmp); } /* Converts a string from internal samba format to unicode |