From f751d9f1d025695b4f51f2df7db47649cb881acc Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 22 Mar 2006 08:04:13 +0000 Subject: r14634: Many bug fixes thanks to train rides and overnight stays in airports * Finally fix parsing idmap uid/gid ranges not to break with spaces surrounding the '-' * Allow local groups to renamed by adding info level 2 to _samr_set_aliasinfo() * Fix parsing bug in _samr_del_dom_alias() reply * Prevent root from being deleted via Samba * Prevent builting groups from being renamed or deleted * Fix bug in pdb_tdb that broke renaming user accounts * Make sure winbindd is running when trying to create the Administrators and Users BUILTIN groups automatically from smbd (and not just check the winbind nexted groups parameter value). * Have the top level rid allocator verify that the RID it is about to grant is not already assigned in our own SAM (retries up to 250 times). This fixes passdb with existing SIDs assigned to users from the RID algorithm but not monotonically allocating the RIDs from passdb. --- source/passdb/pdb_interface.c | 86 ++++++++++++++++++++++++++++++++++++++----- source/passdb/pdb_tdb.c | 20 ++++------ 2 files changed, 84 insertions(+), 22 deletions(-) (limited to 'source/passdb') diff --git a/source/passdb/pdb_interface.c b/source/passdb/pdb_interface.c index 7ff0214c724..5fdc8ac819b 100644 --- a/source/passdb/pdb_interface.c +++ b/source/passdb/pdb_interface.c @@ -426,6 +426,13 @@ static int smb_delete_user(const char *unix_user) pstring del_script; int ret; + /* safety check */ + + if ( strequal( unix_user, "root" ) ) { + DEBUG(0,("smb_delete_user: Refusing to delete local system root account!\n")); + return -1; + } + pstrcpy(del_script, lp_deluser_script()); if (! *del_script) return -1; @@ -462,11 +469,22 @@ static NTSTATUS pdb_default_delete_user(struct pdb_methods *methods, NTSTATUS pdb_delete_user(TALLOC_CTX *mem_ctx, struct samu *sam_acct) { struct pdb_methods *pdb = pdb_get_methods(); + uid_t uid = -1; if ( !pdb ) { return NT_STATUS_UNSUCCESSFUL; } + /* sanity check to make sure we don't delete root */ + + if ( !sid_to_uid( pdb_get_user_sid(sam_acct), &uid ) ) { + return NT_STATUS_NO_SUCH_USER; + } + + if ( uid == 0 ) { + return NT_STATUS_ACCESS_DENIED; + } + return pdb->delete_user(pdb, mem_ctx, sam_acct); } @@ -516,6 +534,7 @@ NTSTATUS pdb_delete_sam_account(struct samu *sam_acct) NTSTATUS pdb_rename_sam_account(struct samu *oldname, const char *newname) { struct pdb_methods *pdb = pdb_get_methods(); + uid_t uid; if ( !pdb ) { return NT_STATUS_NOT_IMPLEMENTED; @@ -526,6 +545,16 @@ NTSTATUS pdb_rename_sam_account(struct samu *oldname, const char *newname) csamuser = NULL; } + /* sanity check to make sure we don't rename root */ + + if ( !sid_to_uid( pdb_get_user_sid(oldname), &uid ) ) { + return NT_STATUS_NO_SUCH_USER; + } + + if ( uid == 0 ) { + return NT_STATUS_ACCESS_DENIED; + } + return pdb->rename_sam_account(pdb, oldname, newname); } @@ -976,8 +1005,7 @@ BOOL pdb_find_alias(const char *name, DOM_SID *sid) return False; } - return NT_STATUS_IS_OK(pdb->find_alias(pdb, - name, sid)); + return NT_STATUS_IS_OK(pdb->find_alias(pdb, name, sid)); } NTSTATUS pdb_create_alias(const char *name, uint32 *rid) @@ -999,8 +1027,7 @@ BOOL pdb_delete_alias(const DOM_SID *sid) return False; } - return NT_STATUS_IS_OK(pdb->delete_alias(pdb, - sid)); + return NT_STATUS_IS_OK(pdb->delete_alias(pdb, sid)); } @@ -1012,8 +1039,7 @@ BOOL pdb_get_aliasinfo(const DOM_SID *sid, struct acct_info *info) return False; } - return NT_STATUS_IS_OK(pdb->get_aliasinfo(pdb, sid, - info)); + return NT_STATUS_IS_OK(pdb->get_aliasinfo(pdb, sid, info)); } BOOL pdb_set_aliasinfo(const DOM_SID *sid, struct acct_info *info) @@ -1024,8 +1050,7 @@ BOOL pdb_set_aliasinfo(const DOM_SID *sid, struct acct_info *info) return False; } - return NT_STATUS_IS_OK(pdb->set_aliasinfo(pdb, sid, - info)); + return NT_STATUS_IS_OK(pdb->set_aliasinfo(pdb, sid, info)); } NTSTATUS pdb_add_aliasmem(const DOM_SID *alias, const DOM_SID *member) @@ -1192,9 +1217,21 @@ BOOL pdb_rid_algorithm(void) return pdb->rid_algorithm(pdb); } +/******************************************************************** + Allocate a new RID from the passdb backend. Verify that it is free + by calling lookup_global_sam_rid() to verify that the RID is not + in use. This handles servers that have existing users or groups + with add RIDs (assigned from previous algorithmic mappings) +********************************************************************/ + BOOL pdb_new_rid(uint32 *rid) { struct pdb_methods *pdb = pdb_get_methods(); + const char *name = NULL; + enum SID_NAME_USE type; + uint32 allocated_rid = 0; + int i; + TALLOC_CTX *ctx; if ( !pdb ) { return False; @@ -1215,7 +1252,38 @@ BOOL pdb_new_rid(uint32 *rid) return False; } - return pdb->new_rid(pdb, rid); + if ( (ctx = talloc_init("pdb_new_rid")) == NULL ) { + DEBUG(0,("pdb_new_rid: Talloc initialization failure\n")); + return False; + } + + /* Attempt to get an unused RID (max tires is 250...yes that it is + and arbitrary number I pulkled out of my head). -- jerry */ + + for ( i=0; allocated_rid==0 && i<250; i++ ) { + /* get a new RID */ + + if ( !pdb->new_rid(pdb, &allocated_rid) ) { + return False; + } + + /* validate that the RID is not in use */ + + if ( lookup_global_sam_rid( ctx, allocated_rid, &name, &type, NULL ) ) { + allocated_rid = 0; + } + } + + TALLOC_FREE( ctx ); + + if ( allocated_rid == 0 ) { + DEBUG(0,("pdb_new_rid: Failed to find unused RID\n")); + return False; + } + + *rid = allocated_rid; + + return True; } /*************************************************************** diff --git a/source/passdb/pdb_tdb.c b/source/passdb/pdb_tdb.c index b7161ff589d..94ae3288123 100644 --- a/source/passdb/pdb_tdb.c +++ b/source/passdb/pdb_tdb.c @@ -1382,19 +1382,12 @@ static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods, BOOL interim_account = False; int rename_ret; - /* make sure we have an open handle to the tdb. Should have happened - at module initialization time */ - - if ( !tdbsam ) { - DEBUG(0,("tdbsam_getsampwrid: tdbsam not open!\n")); - return NT_STATUS_NO_SUCH_USER; - } - /* can't do anything without an external script */ pstrcpy(rename_script, lp_renameuser_script() ); - if ( ! *rename_script ) + if ( ! *rename_script ) { return NT_STATUS_ACCESS_DENIED; + } /* invalidate the existing TDB iterator if it is open */ @@ -1421,8 +1414,7 @@ static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods, /* add the new account and lock it */ - if ( !tdb_update_samacct_only(new_acct, TDB_INSERT) ) - { + if ( !tdb_update_samacct_only(new_acct, TDB_INSERT) ) { goto done; } @@ -1441,13 +1433,15 @@ static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods, DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n", rename_script, rename_ret)); - if (rename_ret) + if (rename_ret) { goto done; + } /* rewrite the rid->username record */ - if ( !tdb_update_ridrec_only( new_acct, TDB_MODIFY) ) + if ( !tdb_update_ridrec_only( new_acct, TDB_MODIFY) ) { goto done; + } interim_account = False; tdb_unlock_bystring( tdbsam, newname ); -- cgit