diff options
author | Gerald Carter <jerry@samba.org> | 2006-02-24 21:36:40 +0000 |
---|---|---|
committer | Gerald Carter <jerry@samba.org> | 2006-02-24 21:36:40 +0000 |
commit | 0c0a59c2d67b9f0f808a3705722160caa209d9a1 (patch) | |
tree | 6b17ffb65466f12a87a7f6151926b23c1ee07330 | |
parent | ef630cfe9e465c0f807c9f734fa8f96c64b03a55 (diff) | |
download | samba-0c0a59c2d67b9f0f808a3705722160caa209d9a1.tar.gz samba-0c0a59c2d67b9f0f808a3705722160caa209d9a1.tar.xz samba-0c0a59c2d67b9f0f808a3705722160caa209d9a1.zip |
r13679: Commiting the rm_primary_group.patch posted on samba-technical
* ignore the primary group SID attribute from struct samu*
* generate the primary group SID strictlky from the Unix
primary group when dealing with passdb users
* Fix memory leak in original patch caused by failing to free a
talloc *
* add wrapper around samu_set_unix() to prevent exposing the create
BOOL to callers. Wrappers are samu_set_unix() and samu-allic_rid_unix()
-rw-r--r-- | source/auth/auth_util.c | 14 | ||||
-rw-r--r-- | source/include/passdb.h | 5 | ||||
-rw-r--r-- | source/nsswitch/winbindd_cm.c | 4 | ||||
-rw-r--r-- | source/nsswitch/winbindd_pam.c | 1 | ||||
-rw-r--r-- | source/passdb/passdb.c | 376 | ||||
-rw-r--r-- | source/passdb/pdb_compat.c | 2 | ||||
-rw-r--r-- | source/passdb/pdb_get_set.c | 116 | ||||
-rw-r--r-- | source/passdb/pdb_interface.c | 31 | ||||
-rw-r--r-- | source/passdb/pdb_ldap.c | 24 | ||||
-rw-r--r-- | source/passdb/pdb_smbpasswd.c | 14 | ||||
-rw-r--r-- | source/passdb/pdb_tdb.c | 10 | ||||
-rw-r--r-- | source/rpc_server/srv_samr_nt.c | 19 | ||||
-rw-r--r-- | source/utils/pdbedit.c | 83 |
13 files changed, 292 insertions, 407 deletions
diff --git a/source/auth/auth_util.c b/source/auth/auth_util.c index bc929fc81df..1d6a3a21a8f 100644 --- a/source/auth/auth_util.c +++ b/source/auth/auth_util.c @@ -1273,14 +1273,18 @@ static auth_serversupplied_info *copy_serverinfo(auth_serversupplied_info *src) sizeof(gid_t)*dst->n_groups); else dst->groups = NULL; + dst->ptok = dup_nt_token(dst, src->ptok); - dst->user_session_key = data_blob_talloc( - dst, src->user_session_key.data, + + dst->user_session_key = data_blob_talloc( dst, src->user_session_key.data, src->user_session_key.length); - dst->lm_session_key = data_blob_talloc( - dst, src->lm_session_key.data, + + dst->lm_session_key = data_blob_talloc(dst, src->lm_session_key.data, src->lm_session_key.length); - pdb_copy_sam_account(src->sam_account, &dst->sam_account); + + if ( (dst->sam_account = samu_new( NULL )) != NULL ) + pdb_copy_sam_account(dst->sam_account, src->sam_account); + dst->pam_handle = NULL; dst->unix_name = talloc_strdup(dst, src->unix_name); diff --git a/source/include/passdb.h b/source/include/passdb.h index 3c1e9bb5b74..0e64653fe6b 100644 --- a/source/include/passdb.h +++ b/source/include/passdb.h @@ -163,8 +163,8 @@ struct samu { const char *unknown_str; /* don't know what this is, yet. */ const char *munged_dial; /* munged path name and dial-back tel number */ - DOM_SID user_sid; /* Primary User SID */ - DOM_SID group_sid; /* Primary Group SID */ + DOM_SID user_sid; + DOM_SID *group_sid; DATA_BLOB lm_pw; /* .data is Null if no password */ DATA_BLOB nt_pw; /* .data is Null if no password */ @@ -185,6 +185,7 @@ struct samu { uint32 unknown_6; /* 0x0000 04ec */ /* a tag for who added the private methods */ + const struct pdb_methods *backend_private_methods; void *backend_private_data; void (*backend_private_data_free_fn)(void **); diff --git a/source/nsswitch/winbindd_cm.c b/source/nsswitch/winbindd_cm.c index 988d6d6b189..579c20b7d24 100644 --- a/source/nsswitch/winbindd_cm.c +++ b/source/nsswitch/winbindd_cm.c @@ -1438,7 +1438,9 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, if (conn->netlogon_pipe == NULL) { DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error " "was %s\n", nt_errstr(result))); - return result; + + /* make sure we return something besides OK */ + return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE; } *cli = conn->netlogon_pipe; diff --git a/source/nsswitch/winbindd_pam.c b/source/nsswitch/winbindd_pam.c index e6fb77f24fa..2b9b13caf8a 100644 --- a/source/nsswitch/winbindd_pam.c +++ b/source/nsswitch/winbindd_pam.c @@ -1416,6 +1416,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, ZERO_STRUCT(info3); retry = False; + netlogon_pipe = NULL; result = cm_connect_netlogon(contact_domain, &netlogon_pipe); if (!NT_STATUS_IS_OK(result)) { diff --git a/source/passdb/passdb.c b/source/passdb/passdb.c index 6c84303947d..c0cf3f2a23a 100644 --- a/source/passdb/passdb.c +++ b/source/passdb/passdb.c @@ -47,13 +47,39 @@ const char *my_sam_name(void) return lp_workgroup(); } -/************************************************************ - Fill the struct samu with default values. - ***********************************************************/ +/********************************************************************** +***********************************************************************/ -static void samu_init( struct samu *user ) +static int samu_destroy(void *p) { + struct samu *user = p; + + data_blob_clear_free( &user->lm_pw ); + data_blob_clear_free( &user->nt_pw ); + + if ( user->plaintext_pw ) + memset( user->plaintext_pw, 0x0, strlen(user->plaintext_pw) ); + + return 0; +} + +/********************************************************************** + generate a new struct samuser +***********************************************************************/ + +struct samu* samu_new( TALLOC_CTX *ctx ) +{ + struct samu *user; + + if ( !(user = TALLOC_ZERO_P( ctx, struct samu )) ) { + DEBUG(0,("samuser_new: Talloc failed!\n")); + return NULL; + } + + talloc_set_destructor( user, samu_destroy ); + /* no initial methods */ + user->methods = NULL; /* Don't change these timestamp settings without a good reason. @@ -90,132 +116,53 @@ static void samu_init( struct samu *user ) user->plaintext_pw = NULL; - /* - Unless we know otherwise have a Account Control Bit + /* Unless we know otherwise have a Account Control Bit value of 'normal user'. This helps User Manager, which - asks for a filtered list of users. - */ + asks for a filtered list of users. */ user->acct_ctrl = ACB_NORMAL; -} - -/********************************************************************** -***********************************************************************/ - -static int samu_destroy(void *p) -{ - struct samu *user = p; - - data_blob_clear_free( &user->lm_pw ); - data_blob_clear_free( &user->nt_pw ); - - if ( user->plaintext_pw ) - memset( user->plaintext_pw, 0x0, strlen(user->plaintext_pw) ); - - return 0; -} - -/********************************************************************** - generate a new struct samuser -***********************************************************************/ - -struct samu* samu_new( TALLOC_CTX *ctx ) -{ - struct samu *user; - - if ( !(user = TALLOC_ZERO_P( ctx, struct samu )) ) { - DEBUG(0,("samuser_new: Talloc failed!\n")); - return NULL; - } - - samu_init( user ); - talloc_set_destructor( user, samu_destroy ); return user; } /********************************************************************* Initialize a struct samu from a struct passwd including the user - and group SIDs + and group SIDs. The *user structure is filled out with the Unix + attributes and a user SID. *********************************************************************/ -NTSTATUS samu_set_unix(struct samu *user, const struct passwd *pwd) +static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *pwd, BOOL create) { const char *guest_account = lp_guestaccount(); - GROUP_MAP map; - BOOL ret; + const char *domain = global_myname(); + uint32 urid; - /* Set the Unix attributes */ - if ( !pwd ) { return NT_STATUS_NO_SUCH_USER; } /* Basic properties based upon the Unix account information */ - + pdb_set_username(user, pwd->pw_name, PDB_SET); pdb_set_fullname(user, pwd->pw_gecos, PDB_SET); pdb_set_domain (user, get_global_sam_name(), PDB_DEFAULT); - + /* save the password structure for later use */ - + user->unix_pw = tcopy_passwd( user, pwd ); - /* Special case for the guest account which must have a RID of 501. - By default the guest account is a member of of the domain users - group as well as the domain guests group. Verified against - Windows NT - 2003 */ - - if ( !guest_account ) { - DEBUG(0,("samu_set_unix: No guest user defined!\n")); - return NT_STATUS_INVALID_ACCOUNT_NAME; - } + /* Special case for the guest account which must have a RID of 501 */ - if ( strequal( pwd->pw_name, guest_account ) ) - { + if ( strequal( pwd->pw_name, guest_account ) ) { if ( !pdb_set_user_sid_from_rid(user, DOMAIN_USER_RID_GUEST, PDB_DEFAULT)) { return NT_STATUS_NO_SUCH_USER; } - - if ( !pdb_set_group_sid_from_rid(user, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT) ) { - return NT_STATUS_NO_SUCH_USER; - } return NT_STATUS_OK; } - - /* normal user setup -- we really need to throw away the mapping algorithm here */ - if (!pdb_set_user_sid_from_rid(user, algorithmic_pdb_uid_to_user_rid(pwd->pw_uid), PDB_SET)) { - DEBUG(0,("Can't set User SID from RID!\n")); - return NT_STATUS_INVALID_PARAMETER; - } + /* Non-guest accounts...Check for a workstation or user account */ -#if 1 /* I think we could throw away the primaryGroupSID attribute altogether - and just build it from the UNIX_TOKEN. --jerry */ - - /* call the mapping code here */ - - become_root(); - ret = pdb_getgrgid(&map, pwd->pw_gid); - unbecome_root(); - - /* We do not want to fall back to the rid mapping algorithm. Windows - standalone servers set the 0x201 rid as the primary group and - LookupSid( S-1...-513 ) returns SERVER\None. Do something similar. - Use the Domain Users RID as a a placeholder. This is a workaround only. */ - - if( ret ) { - if ( !pdb_set_group_sid(user, &map.sid, PDB_SET) ) { - DEBUG(0,("Can't set Group SID!\n")); - return NT_STATUS_INVALID_PARAMETER; - } - } else { - if ( !pdb_set_group_sid_from_rid(user, DOMAIN_GROUP_RID_USERS, PDB_SET)) - return NT_STATUS_INVALID_PARAMETER; - } -#endif - if (pwd->pw_name[strlen(pwd->pw_name)-1] == '$') { /* workstation */ @@ -223,11 +170,7 @@ NTSTATUS samu_set_unix(struct samu *user, const struct passwd *pwd) DEBUG(1, ("Failed to set 'workstation account' flags for user %s.\n", pwd->pw_name)); return NT_STATUS_INVALID_COMPUTER_NAME; - } - - /* we're done here for a machine account */ - - return NT_STATUS_OK; + } } else { /* user */ @@ -237,160 +180,72 @@ NTSTATUS samu_set_unix(struct samu *user, const struct passwd *pwd) pwd->pw_name)); return NT_STATUS_INVALID_ACCOUNT_NAME; } - } - - /* set some basic attributes */ - - pdb_set_profile_path(user, talloc_sub_specified(user, - lp_logon_path(), pwd->pw_name, global_myname(), pwd->pw_uid, pwd->pw_gid), - PDB_DEFAULT); - pdb_set_homedir(user, talloc_sub_specified(user, - lp_logon_home(), pwd->pw_name, global_myname(), pwd->pw_uid, pwd->pw_gid), - PDB_DEFAULT); - pdb_set_dir_drive(user, talloc_sub_specified(user, - lp_logon_drive(), pwd->pw_name, global_myname(), pwd->pw_uid, pwd->pw_gid), - PDB_DEFAULT); - pdb_set_logon_script(user, talloc_sub_specified(user, - lp_logon_script(), pwd->pw_name, global_myname(), pwd->pw_uid, pwd->pw_gid), - PDB_DEFAULT); - return NT_STATUS_OK; -} - -/************************************************************* - Initialises a struct samu ready to add a new account, based - on the UNIX user. - ************************************************************/ - -NTSTATUS pdb_init_sam_new(struct samu **new_sam_acct, const char *username) -{ - NTSTATUS result; - struct passwd *pwd; - uint32 user_rid; - DOM_SID user_sid, group_sid; - TALLOC_CTX *mem_ctx; - enum SID_NAME_USE type; - - mem_ctx = talloc_new(NULL); - if (mem_ctx == NULL) { - DEBUG(0, ("talloc_new failed\n")); - return NT_STATUS_NO_MEMORY; - } + /* set some basic attributes */ - if ( !(pwd = Get_Pwnam_alloc(mem_ctx, username)) ) { - DEBUG(10, ("Could not find user %s\n", username)); - result = NT_STATUS_NO_SUCH_USER; - goto done; - } - - if ( !(*new_sam_acct = samu_new( NULL )) ) { - result = NT_STATUS_NO_MEMORY; - goto done; + pdb_set_profile_path(user, talloc_sub_specified(user, + lp_logon_path(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid), + PDB_DEFAULT); + pdb_set_homedir(user, talloc_sub_specified(user, + lp_logon_home(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid), + PDB_DEFAULT); + pdb_set_dir_drive(user, talloc_sub_specified(user, + lp_logon_drive(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid), + PDB_DEFAULT); + pdb_set_logon_script(user, talloc_sub_specified(user, + lp_logon_script(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid), + PDB_DEFAULT); } + + /* Now deal with the user SID. If we have a backend that can generate + RIDs, then do so. But sometimes the caller just wanted a structure + initialized and will fill in these fields later (such as from a + NET_USER_INFO_3 structure) */ - result = samu_set_unix( *new_sam_acct, pwd ); - - if (!NT_STATUS_IS_OK(result)) { - DEBUG(10, ("samu_set_unix failed: %s\n", nt_errstr(result))); - goto done; - } + if ( create && !pdb_rid_algorithm() ) { + uint32 user_rid; + DOM_SID user_sid; - if (pdb_rid_algorithm()) { - if (!pdb_set_user_sid_from_rid( - *new_sam_acct, - algorithmic_pdb_uid_to_user_rid(pwd->pw_uid), - PDB_SET)) { - result = NT_STATUS_INTERNAL_ERROR; - goto done; + if ( !pdb_new_rid( &user_rid ) ) { + DEBUG(3, ("Could not allocate a new RID\n")); + return NT_STATUS_ACCESS_DENIED; } - if (!pdb_set_group_sid_from_rid( - *new_sam_acct, pdb_gid_to_group_rid(pwd->pw_gid), - PDB_SET)) { - result = NT_STATUS_INTERNAL_ERROR; - goto done; - } - result = NT_STATUS_OK; - goto done; - } - - /* No algorithmic mapping, meaning that we have to figure out the - * primary group SID according to group mapping and the user SID must - * be a newly allocated one */ - - if (!pdb_gid_to_sid(pwd->pw_gid, &group_sid)) { - struct group *grp; - GROUP_MAP map; - grp = getgrgid(pwd->pw_gid); - if (grp == NULL) { - DEBUG(1, ("Primary group %d of user %s does not " - "exist.\n", pwd->pw_gid, username)); - result = NT_STATUS_INVALID_PRIMARY_GROUP; - goto done; - } + sid_copy( &user_sid, get_global_sam_sid() ); + sid_append_rid( &user_sid, user_rid ); - DEBUG(5, ("Primary group %s of user %s is not mapped to " - "a domain group, auto-mapping it\n", - grp->gr_name, username)); - result = map_unix_group(grp, &map); - if (!NT_STATUS_IS_OK(result)) { - DEBUG(1, ("Failed to map group %s\n", grp->gr_name)); - goto done; + if ( !pdb_set_user_sid(user, &user_sid, PDB_SET) ) { + DEBUG(3, ("pdb_set_user_sid failed\n")); + return NT_STATUS_INTERNAL_ERROR; } - sid_copy(&group_sid, &map.sid); - DEBUG(5, ("Mapped unix group %s to SID %s\n", - grp->gr_name, sid_string_static(&group_sid))); - } - - /* Now check that it's actually a domain group and not something - * else */ - - if (!lookup_sid(mem_ctx, &group_sid, NULL, NULL, &type)) { - DEBUG(3, ("Could not lookup %s's primary group sid %s\n", - username, sid_string_static(&group_sid))); - result = NT_STATUS_INVALID_PRIMARY_GROUP; - goto done; - } - - if (type != SID_NAME_DOM_GRP) { - DEBUG(3, ("Primary group for user %s is a %s and not a domain " - "group\n", username, sid_type_lookup(type))); - result = NT_STATUS_INVALID_PRIMARY_GROUP; - goto done; - } - - if (!pdb_set_group_sid(*new_sam_acct, &group_sid, PDB_SET)) { - DEBUG(3, ("Could not set group SID\n")); - result = NT_STATUS_INTERNAL_ERROR; - goto done; - } - - if (!pdb_new_rid(&user_rid)) { - DEBUG(3, ("Could not allocate a new RID\n")); - result = NT_STATUS_ACCESS_DENIED; - goto done; + + return NT_STATUS_OK; } - sid_copy(&user_sid, get_global_sam_sid()); - sid_append_rid(&user_sid, user_rid); - - if (!pdb_set_user_sid(*new_sam_acct, &user_sid, PDB_SET)) { - DEBUG(3, ("pdb_set_user_sid failed\n")); - result = NT_STATUS_INTERNAL_ERROR; - goto done; + /* generate a SID for the user ewith the RID algorithm */ + + urid = algorithmic_pdb_uid_to_user_rid( user->unix_pw->pw_uid ); + + if ( !pdb_set_user_sid_from_rid( user, urid, PDB_SET) ) { + return NT_STATUS_INTERNAL_ERROR; } + + return NT_STATUS_OK; +} - result = NT_STATUS_OK; - - done: - if (!NT_STATUS_IS_OK(result) && (*new_sam_acct != NULL)) { - TALLOC_FREE(new_sam_acct); - } +/******************************************************************** + Set the Unix user attributes +********************************************************************/ - TALLOC_FREE(mem_ctx); - return result; +NTSTATUS samu_set_unix(struct samu *user, const struct passwd *pwd) +{ + return samu_set_unix_internal( user, pwd, False ); } +NTSTATUS samu_alloc_rid_unix(struct samu *user, const struct passwd *pwd) +{ + return samu_set_unix_internal( user, pwd, True ); +} /********************************************************** Encode the account control bits into a string. @@ -574,6 +429,9 @@ BOOL pdb_gethexhours(const char *p, unsigned char *hours) return (True); } +/******************************************************************** +********************************************************************/ + int algorithmic_rid_base(void) { static int rid_offset = 0; @@ -654,7 +512,7 @@ uint32 pdb_gid_to_group_rid(gid_t gid) Decides if a RID is a well known RID. ********************************************************************/ -static BOOL pdb_rid_is_well_known(uint32 rid) +static BOOL rid_is_well_known(uint32 rid) { /* Not using rid_offset here, because this is the actual NT fixed value (1000) */ @@ -668,7 +526,7 @@ static BOOL pdb_rid_is_well_known(uint32 rid) BOOL algorithmic_pdb_rid_is_user(uint32 rid) { - if(pdb_rid_is_well_known(rid)) { + if ( rid_is_well_known(rid) ) { /* * The only well known user RIDs are DOMAIN_USER_RID_ADMIN * and DOMAIN_USER_RID_GUEST. @@ -781,6 +639,7 @@ NTSTATUS local_password_change(const char *user_name, int local_flags, if ((local_flags & LOCAL_ADD_USER) || (local_flags & LOCAL_DELETE_USER)) { int tmp_debug = DEBUGLEVEL; + struct passwd *pwd; /* Might not exist in /etc/passwd. */ @@ -788,16 +647,29 @@ NTSTATUS local_password_change(const char *user_name, int local_flags, DEBUGLEVEL = 1; } - result = pdb_init_sam_new(&sam_pass, user_name); + if ( !(pwd = getpwnam_alloc( NULL, user_name)) ) { + return NT_STATUS_NO_SUCH_USER; + } + + /* create the struct samu and initialize the basic Unix properties */ + + if ( !(sam_pass = samu_new( NULL )) ) { + return NT_STATUS_NO_MEMORY; + } + + result = samu_set_unix( sam_pass, pwd ); + DEBUGLEVEL = tmp_debug; + + TALLOC_FREE( pwd ); + if (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PRIMARY_GROUP)) { return result; } if (!NT_STATUS_IS_OK(result)) { - slprintf(err_str, err_str_len-1, "Failed to " - "initialize account for user %s: %s\n", - user_name, nt_errstr(result)); + slprintf(err_str, err_str_len-1, "Failed to " "initialize account for user %s: %s\n", + user_name, nt_errstr(result)); return result; } } else { @@ -1130,7 +1002,6 @@ BOOL init_sam_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen) } pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET); - pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET); pdb_set_hours_len(sampass, hours_len, PDB_SET); pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET); pdb_set_logon_count(sampass, logon_count, PDB_SET); @@ -1164,7 +1035,7 @@ done: /********************************************************************* *********************************************************************/ -uint32 init_buffer_from_sam_v2 (uint8 **buf, const struct samu *sampass, BOOL size_only) +uint32 init_buffer_from_sam_v2 (uint8 **buf, struct samu *sampass, BOOL size_only) { size_t len, buflen; @@ -1440,13 +1311,13 @@ uint32 init_buffer_from_sam_v2 (uint8 **buf, const struct samu *sampass, BOOL si /********************************************************************* *********************************************************************/ -BOOL pdb_copy_sam_account(const struct samu *src, struct samu **dst) +BOOL pdb_copy_sam_account(struct samu *dst, struct samu *src ) { BOOL result; uint8 *buf; int len; - if ( !*dst && !(*dst = samu_new(NULL)) ) + if ( !dst ) return False; len = init_buffer_from_sam_v2(&buf, src, False); @@ -1454,8 +1325,11 @@ BOOL pdb_copy_sam_account(const struct samu *src, struct samu **dst) if (len == -1) return False; - result = init_sam_from_buffer_v2(*dst, buf, len); - (*dst)->methods = src->methods; + result = init_sam_from_buffer_v2( dst, buf, len ); + dst->methods = src->methods; + + if ( src->unix_pw ) + dst->unix_pw = tcopy_passwd( dst, src->unix_pw ); free(buf); diff --git a/source/passdb/pdb_compat.c b/source/passdb/pdb_compat.c index 900fcc29fa1..788663f27a4 100644 --- a/source/passdb/pdb_compat.c +++ b/source/passdb/pdb_compat.c @@ -38,7 +38,7 @@ uint32 pdb_get_user_rid (const struct samu *sampass) return (0); } -uint32 pdb_get_group_rid (const struct samu *sampass) +uint32 pdb_get_group_rid (struct samu *sampass) { uint32 g_rid; diff --git a/source/passdb/pdb_get_set.c b/source/passdb/pdb_get_set.c index 92bc228e012..921e13a3d21 100644 --- a/source/passdb/pdb_get_set.c +++ b/source/passdb/pdb_get_set.c @@ -181,16 +181,77 @@ const DOM_SID *pdb_get_user_sid(const struct samu *sampass) { if (sampass) return &sampass->user_sid; - else - return (NULL); + + return NULL; } -const DOM_SID *pdb_get_group_sid(const struct samu *sampass) +const DOM_SID *pdb_get_group_sid(struct samu *sampass) { - if (sampass) - return &sampass->group_sid; - else - return (NULL); + DOM_SID *gsid; + struct passwd *pwd; + + /* sanity check */ + + if ( !sampass ) { + return NULL; + } + + /* Return the cached group SID if we have that */ + + if ( sampass->group_sid ) { + return sampass->group_sid; + } + + /* generate the group SID from the user's primary Unix group */ + + if ( !(gsid = TALLOC_P( sampass, DOM_SID )) ) { + return NULL; + } + + /* No algorithmic mapping, meaning that we have to figure out the + primary group SID according to group mapping and the user SID must + be a newly allocated one. We rely on the user's Unix primary gid. + We have no choice but to fail if we can't find it. */ + + if ( sampass->unix_pw ) + pwd = sampass->unix_pw; + else + pwd = getpwnam_alloc( sampass, pdb_get_username(sampass) ); + + if ( !pwd ) { + DEBUG(0,("pdb_get_group_sid: Failed to find Unix account for %s\n", pdb_get_username(sampass) )); + return NULL; + } + + if ( pdb_gid_to_sid(pwd->pw_gid, gsid) ) { + enum SID_NAME_USE type = SID_NAME_UNKNOWN; + TALLOC_CTX *mem_ctx = talloc_init("pdb_get_group_sid"); + BOOL lookup_ret; + + /* Now check that it's actually a domain group and not something else */ + + lookup_ret = lookup_sid(mem_ctx, gsid, NULL, NULL, &type); + + TALLOC_FREE( mem_ctx ); + + if ( lookup_ret && (type == SID_NAME_DOM_GRP) ) { + sampass->group_sid = gsid; + return sampass->group_sid; + } + + DEBUG(3, ("Primary group for user %s is a %s and not a domain group\n", + pwd->pw_name, sid_type_lookup(type))); + } + + /* Just set it to the 'Domain Users' RID of 512 which will + always resolve to a name */ + + sid_copy( gsid, get_global_sam_sid() ); + sid_append_rid( gsid, DOMAIN_GROUP_RID_USERS ); + + sampass->group_sid = gsid; + + return sampass->group_sid; } /** @@ -569,6 +630,14 @@ BOOL pdb_set_user_sid_from_string (struct samu *sampass, fstring u_sid, enum pdb return True; } +/******************************************************************** + We never fill this in from a passdb backend but rather set is + based on the user's primary group membership. However, the + struct samu* is overloaded and reused in domain memship code + as well and built from the NET_USER_INFO_3 or PAC so we + have to allow the explicitly setting of a group SID here. +********************************************************************/ + BOOL pdb_set_group_sid (struct samu *sampass, const DOM_SID *g_sid, enum pdb_value_state flag) { gid_t gid; @@ -576,43 +645,26 @@ BOOL pdb_set_group_sid (struct samu *sampass, const DOM_SID *g_sid, enum pdb_val if (!sampass || !g_sid) return False; + if ( !(sampass->group_sid = TALLOC_P( sampass, DOM_SID )) ) { + return False; + } + /* if we cannot resolve the SID to gid, then just ignore it and store DOMAIN_USERS as the primary groupSID */ if ( sid_to_gid( g_sid, &gid ) ) { - sid_copy(&sampass->group_sid, g_sid); + sid_copy(sampass->group_sid, g_sid); } else { - sid_copy( &sampass->group_sid, get_global_sam_sid() ); - sid_append_rid( &sampass->group_sid, DOMAIN_GROUP_RID_USERS ); + sid_copy( sampass->group_sid, get_global_sam_sid() ); + sid_append_rid( sampass->group_sid, DOMAIN_GROUP_RID_USERS ); } DEBUG(10, ("pdb_set_group_sid: setting group sid %s\n", - sid_string_static(&sampass->group_sid))); + sid_string_static(sampass->group_sid))); return pdb_set_init_flags(sampass, PDB_GROUPSID, flag); } -BOOL pdb_set_group_sid_from_string (struct samu *sampass, fstring g_sid, enum pdb_value_state flag) -{ - DOM_SID new_sid; - if (!sampass || !g_sid) - return False; - - DEBUG(10, ("pdb_set_group_sid_from_string: setting group sid %s\n", - g_sid)); - - if (!string_to_sid(&new_sid, g_sid)) { - DEBUG(1, ("pdb_set_group_sid_from_string: %s isn't a valid SID!\n", g_sid)); - return False; - } - - if (!pdb_set_group_sid(sampass, &new_sid, flag)) { - DEBUG(1, ("pdb_set_group_sid_from_string: could not set sid %s on struct samu!\n", g_sid)); - return False; - } - return True; -} - /********************************************************************* Set the user's UNIX name. ********************************************************************/ diff --git a/source/passdb/pdb_interface.c b/source/passdb/pdb_interface.c index 294cd513487..2fa02cafd98 100644 --- a/source/passdb/pdb_interface.c +++ b/source/passdb/pdb_interface.c @@ -274,7 +274,9 @@ BOOL pdb_getsampwnam(struct samu *sam_acct, const char *username) } pdb_force_pw_initialization( sam_acct ); - pdb_copy_sam_account(sam_acct, &csamuser); + + if ( (csamuser = samu_new( NULL )) != NULL ) + pdb_copy_sam_account(csamuser, sam_acct); return True; } @@ -294,12 +296,11 @@ BOOL guest_user_info( struct samu *user ) return False; } - result = samu_set_unix(user, pwd); + result = samu_set_unix(user, pwd ); TALLOC_FREE( pwd ); return NT_STATUS_IS_OK( result ); - } /********************************************************************** @@ -327,7 +328,7 @@ BOOL pdb_getsampwsid(struct samu *sam_acct, const DOM_SID *sid) /* check the cache first */ if ( csamuser && sid_equal(sid, pdb_get_user_sid(csamuser) ) ) - return pdb_copy_sam_account(csamuser, &sam_acct); + return pdb_copy_sam_account(sam_acct, csamuser); return NT_STATUS_IS_OK(pdb->getsampwsid(pdb, sam_acct, sid)); } @@ -338,8 +339,9 @@ static NTSTATUS pdb_default_create_user(struct pdb_methods *methods, { struct samu *sam_pass = NULL; NTSTATUS status; + struct passwd *pwd; - if (Get_Pwnam_alloc(tmp_ctx, name) == NULL) { + if ( !(pwd = Get_Pwnam_alloc(tmp_ctx, name)) ) { pstring add_script; int add_ret; @@ -357,19 +359,21 @@ static NTSTATUS pdb_default_create_user(struct pdb_methods *methods, all_string_sub(add_script, "%u", name, sizeof(add_script)); add_ret = smbrun(add_script,NULL); - DEBUG(add_ret ? 0 : 3, ("_samr_create_user: Running the " - "command `%s' gave %d\n", + DEBUG(add_ret ? 0 : 3, ("_samr_create_user: Running the command `%s' gave %d\n", add_script, add_ret)); + flush_pwnam_cache(); + + pwd = Get_Pwnam_alloc(tmp_ctx, name); } - /* implicit call to getpwnam() next. we have a valid SID coming out - * of this call */ + /* we have a valid SID coming out of this call */ - flush_pwnam_cache(); - status = pdb_init_sam_new(&sam_pass, name); + status = samu_alloc_rid_unix( sam_pass, pwd ); + + TALLOC_FREE( pwd ); if (!NT_STATUS_IS_OK(status)) { - DEBUG(3, ("pdb_init_sam_new failed: %s\n", nt_errstr(status))); + DEBUG(3, ("pdb_default_create_user: failed to create a new user structure: %s\n", nt_errstr(status))); return status; } @@ -379,8 +383,7 @@ static NTSTATUS pdb_default_create_user(struct pdb_methods *methods, return NT_STATUS_INTERNAL_ERROR; } - /* Disable the account on creation, it does not have a reasonable - * password yet. */ + /* Disable the account on creation, it does not have a reasonable password yet. */ acb_info |= ACB_DISABLED; diff --git a/source/passdb/pdb_ldap.c b/source/passdb/pdb_ldap.c index a29097031aa..f559dae71db 100644 --- a/source/passdb/pdb_ldap.c +++ b/source/passdb/pdb_ldap.c @@ -552,36 +552,12 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), temp)) { pdb_set_user_sid_from_string(sampass, temp, PDB_SET); } - - if (smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_SID), temp)) { - pdb_set_group_sid_from_string(sampass, temp, PDB_SET); - } else { - pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT); - } } else { if (smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID), temp)) { user_rid = (uint32)atol(temp); pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET); } - - if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_RID), temp)) { - pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT); - } else { - uint32 group_rid; - - group_rid = (uint32)atol(temp); - - /* for some reason, we often have 0 as a primary group RID. - Make sure that we treat this just as a 'default' value */ - - if ( group_rid > 0 ) - pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET); - else - pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT); - } } if (pdb_get_init_flags(sampass,PDB_USERSID) == PDB_DEFAULT) { diff --git a/source/passdb/pdb_smbpasswd.c b/source/passdb/pdb_smbpasswd.c index 2cc6d5947ea..d4070b8d2fc 100644 --- a/source/passdb/pdb_smbpasswd.c +++ b/source/passdb/pdb_smbpasswd.c @@ -1203,7 +1203,7 @@ static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state, return False; } - if ( !NT_STATUS_IS_OK( samu_set_unix(sam_pass, pwfile)) ) + if ( !NT_STATUS_IS_OK( samu_set_unix(sam_pass, pwfile )) ) return False; TALLOC_FREE(pwfile); @@ -1474,10 +1474,16 @@ static NTSTATUS smbpasswd_rename_sam_account (struct pdb_methods *my_methods, if (!*(lp_renameuser_script())) goto done; - if (!pdb_copy_sam_account(old_acct, &new_acct) || - !pdb_set_username(new_acct, newname, PDB_CHANGED)) + if ( !(new_acct = samu_new( NULL )) ) { + return NT_STATUS_NO_MEMORY; + } + + if ( !pdb_copy_sam_account( new_acct, old_acct ) + || !pdb_set_username(new_acct, newname, PDB_CHANGED)) + { goto done; - + } + ret = smbpasswd_add_sam_account(my_methods, new_acct); if (!NT_STATUS_IS_OK(ret)) goto done; diff --git a/source/passdb/pdb_tdb.c b/source/passdb/pdb_tdb.c index 26b60dcc3ca..e905b026ec1 100644 --- a/source/passdb/pdb_tdb.c +++ b/source/passdb/pdb_tdb.c @@ -216,7 +216,6 @@ static BOOL init_sam_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buf pdb_set_pw_history(sampass, NULL, 0, PDB_SET); pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET); - pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET); pdb_set_hours_len(sampass, hours_len, PDB_SET); pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET); pdb_set_logon_count(sampass, logon_count, PDB_SET); @@ -404,7 +403,6 @@ static BOOL init_sam_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buf pdb_set_pw_history(sampass, NULL, 0, PDB_SET); pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET); - pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET); pdb_set_hours_len(sampass, hours_len, PDB_SET); pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET); pdb_set_logon_count(sampass, logon_count, PDB_SET); @@ -447,7 +445,7 @@ static BOOL init_sam_from_buffer(struct samu *sampass, uint8 *buf, uint32 buflen Intialize a BYTE buffer from a struct samu struct *********************************************************************/ -static uint32 init_buffer_from_sam (uint8 **buf, const struct samu *sampass, BOOL size_only) +static uint32 init_buffer_from_sam (uint8 **buf, struct samu *sampass, BOOL size_only) { return init_buffer_from_sam_v2(buf, sampass, size_only); } @@ -1171,7 +1169,11 @@ static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods, tdbsam_endsampwent( my_methods ); - if ( !pdb_copy_sam_account(old_acct, &new_acct) + if ( !(new_acct = samu_new( NULL )) ) { + return NT_STATUS_NO_MEMORY; + } + + if ( !pdb_copy_sam_account(new_acct, old_acct) || !pdb_set_username(new_acct, newname, PDB_CHANGED)) { TALLOC_FREE(new_acct ); diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c index 33de292d226..47e1a31535e 100644 --- a/source/rpc_server/srv_samr_nt.c +++ b/source/rpc_server/srv_samr_nt.c @@ -3121,17 +3121,16 @@ static NTSTATUS set_user_info_21(TALLOC_CTX *mem_ctx, SAM_USER_INFO_21 *id21, * id21. I don't know if they need to be set. --jerry */ - if (IS_SAM_CHANGED(pwd, PDB_GROUPSID) && - !NT_STATUS_IS_OK(status = pdb_set_unix_primary_group(mem_ctx, - pwd))) { - return status; + if ( IS_SAM_CHANGED(pwd, PDB_GROUPSID) ) { + status = pdb_set_unix_primary_group(mem_ctx, pwd); + if ( !NT_STATUS_IS_OK(status) ) { + return status; + } } - - /* write the change out */ - if(!NT_STATUS_IS_OK(status = pdb_update_sam_account(pwd))) { - TALLOC_FREE(pwd); - return status; - } + + /* Don't worry about writing out the user account since the + primary group SID is generated solely from the user's Unix + primary group. */ TALLOC_FREE(pwd); diff --git a/source/utils/pdbedit.c b/source/utils/pdbedit.c index bd336765474..471b8988776 100644 --- a/source/utils/pdbedit.c +++ b/source/utils/pdbedit.c @@ -277,8 +277,7 @@ static int set_user_info (struct pdb_methods *in, const char *username, const char *acct_desc, const char *drive, const char *script, const char *profile, const char *account_control, - const char *user_sid, const char *group_sid, - const char *user_domain, + const char *user_sid, const char *user_domain, const BOOL badpw, const BOOL hours, time_t pwd_can_change, time_t pwd_must_change) { @@ -369,21 +368,6 @@ static int set_user_info (struct pdb_methods *in, const char *username, } pdb_set_user_sid (sam_pwent, &u_sid, PDB_CHANGED); } - if (group_sid) { - DOM_SID g_sid; - if (!string_to_sid(&g_sid, group_sid)) { - /* not a complete sid, may be a RID, try building a SID */ - int g_rid; - - if (sscanf(group_sid, "%d", &g_rid) != 1) { - fprintf(stderr, "Error passed string is not a complete group SID or RID!\n"); - return -1; - } - sid_copy(&g_sid, get_global_sam_sid()); - sid_append_rid(&g_sid, g_rid); - } - pdb_set_group_sid (sam_pwent, &g_sid, PDB_CHANGED); - } if (badpw) { pdb_set_bad_password_count(sam_pwent, 0, PDB_CHANGED); @@ -407,17 +391,28 @@ static int set_user_info (struct pdb_methods *in, const char *username, static int new_user (struct pdb_methods *in, const char *username, const char *fullname, const char *homedir, const char *drive, const char *script, - const char *profile, char *user_sid, char *group_sid, - BOOL stdin_get) + const char *profile, char *user_sid, BOOL stdin_get) { - struct samu *sam_pwent=NULL; - + struct samu *sam_pwent; char *password1, *password2; int rc_pwd_cmp; + struct passwd *pwd; get_global_sam_sid(); - if (!NT_STATUS_IS_OK(pdb_init_sam_new(&sam_pwent, username))) { + if ( !(pwd = getpwnam_alloc( NULL, username )) ) { + DEBUG(0,("Cannot locate Unix account for %s\n", username)); + return -1; + } + + if ( !(sam_pwent = samu_new( NULL )) ) { + DEBUG(0, ("Memory allocation failure!\n")); + return -1; + } + + if (!NT_STATUS_IS_OK(samu_alloc_rid_unix(sam_pwent, pwd ))) { + TALLOC_FREE( sam_pwent ); + TALLOC_FREE( pwd ); DEBUG(0, ("could not create account to add new user %s\n", username)); return -1; } @@ -465,21 +460,6 @@ static int new_user (struct pdb_methods *in, const char *username, } pdb_set_user_sid (sam_pwent, &u_sid, PDB_CHANGED); } - if (group_sid) { - DOM_SID g_sid; - if (!string_to_sid(&g_sid, group_sid)) { - /* not a complete sid, may be a RID, try building a SID */ - int g_rid; - - if (sscanf(group_sid, "%d", &g_rid) != 1) { - fprintf(stderr, "Error passed string is not a complete group SID or RID!\n"); - return -1; - } - sid_copy(&g_sid, get_global_sam_sid()); - sid_append_rid(&g_sid, g_rid); - } - pdb_set_group_sid (sam_pwent, &g_sid, PDB_CHANGED); - } pdb_set_acct_ctrl (sam_pwent, ACB_NORMAL, PDB_CHANGED); @@ -526,7 +506,7 @@ static int new_machine (struct pdb_methods *in, const char *machine_in) return -1; } - if ( !NT_STATUS_IS_OK(samu_set_unix(sam_pwent, pwd)) ) { + if ( !NT_STATUS_IS_OK(samu_set_unix(sam_pwent, pwd )) ) { fprintf(stderr, "Could not init sam from pw\n"); TALLOC_FREE(pwd); return -1; @@ -541,13 +521,9 @@ static int new_machine (struct pdb_methods *in, const char *machine_in) } pdb_set_plaintext_passwd (sam_pwent, machinename); - - pdb_set_username (sam_pwent, machineaccount, PDB_CHANGED); - + pdb_set_username (sam_pwent, machineaccount, PDB_CHANGED); pdb_set_acct_ctrl (sam_pwent, ACB_WSTRUST, PDB_CHANGED); - pdb_set_group_sid_from_rid(sam_pwent, DOMAIN_GROUP_RID_COMPUTERS, PDB_CHANGED); - if (NT_STATUS_IS_OK(in->add_sam_account (in, sam_pwent))) { print_user_info (in, machineaccount, True, False); } else { @@ -647,7 +623,6 @@ int main (int argc, char **argv) static char *account_control = NULL; static char *account_policy = NULL; static char *user_sid = NULL; - static char *group_sid = NULL; static long int account_policy_value = 0; BOOL account_policy_value_set = False; static BOOL badpw_reset = False; @@ -673,7 +648,6 @@ int main (int argc, char **argv) {"profile", 'p', POPT_ARG_STRING, &profile_path, 0, "set profile path", NULL}, {"domain", 'I', POPT_ARG_STRING, &user_domain, 0, "set a users' domain", NULL}, {"user SID", 'U', POPT_ARG_STRING, &user_sid, 0, "set user SID or RID", NULL}, - {"group SID", 'G', POPT_ARG_STRING, &group_sid, 0, "set group SID or RID", NULL}, {"create", 'a', POPT_ARG_NONE, &add_user, 0, "create user", NULL}, {"modify", 'r', POPT_ARG_NONE, &modify_user, 0, "modify user", NULL}, {"machine", 'm', POPT_ARG_NONE, &machine, 0, "account is a machine account", NULL}, @@ -743,7 +717,6 @@ int main (int argc, char **argv) (list_users ? BIT_LIST : 0) + (force_initialised_password ? BIT_FIX_INIT : 0) + (user_sid ? BIT_USERSIDS : 0) + - (group_sid ? BIT_USERSIDS : 0) + (modify_user ? BIT_MODIFY : 0) + (add_user ? BIT_CREATE : 0) + (delete_user ? BIT_DELETE : 0) + @@ -868,9 +841,7 @@ int main (int argc, char **argv) return new_machine (bdef, user_name); } else { return new_user (bdef, user_name, full_name, home_dir, - home_drive, logon_script, - profile_path, user_sid, group_sid, - pw_from_stdin); + home_drive, logon_script, profile_path, user_sid, pw_from_stdin); } } @@ -939,16 +910,10 @@ int main (int argc, char **argv) } } } - return set_user_info (bdef, user_name, full_name, - home_dir, - acct_desc, - home_drive, - logon_script, - profile_path, account_control, - user_sid, group_sid, - user_domain, - badpw_reset, hours_reset, - pwd_can_change, pwd_must_change); + return set_user_info (bdef, user_name, full_name, home_dir, + acct_desc, home_drive, logon_script, profile_path, account_control, + user_sid, user_domain, badpw_reset, hours_reset, pwd_can_change, + pwd_must_change); error: fprintf (stderr, "Error parsing the time in pwd-%s-change-time!\n", errstr); return -1; |