summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2003-07-11 05:33:40 +0000
committerGerald Carter <jerry@samba.org>2003-07-11 05:33:40 +0000
commit03d5867d529f126da368ebda70bf2d997aa602e0 (patch)
tree6bed479ab42b3bcbd5ac6b70157c16232ff69869
parentd117c83ca9fc1b598d09f5d24805560e9c49f65c (diff)
downloadsamba-03d5867d529f126da368ebda70bf2d997aa602e0.tar.gz
samba-03d5867d529f126da368ebda70bf2d997aa602e0.tar.bz2
samba-03d5867d529f126da368ebda70bf2d997aa602e0.zip
moving more code around.
* move rid allocation into IDMAP. See comments in _api_samr_create_user() * add winbind delete user/group functions I'm checking this in to sync up with everyone. But I'm going to split the add a separate winbindd_allocate_rid() function for systems that have an 'add user script' but need idmap to give them a RID. Life would be so much simplier without 'enable rid algorithm'. The current RID allocation is horrible due to this one fact. Tested idmap_tdb but not idmap_ldap yet. Will do that tomorrow. Nothing has changed in the way a samba domain is represented, stored, or search in the directory so things should be ok with previous installations. going to bed now. (This used to be commit 0463045cc7ff177fab44b25faffad5bf7140244d)
-rw-r--r--source3/auth/auth_util.c6
-rw-r--r--source3/groupdb/mapping.c6
-rw-r--r--source3/include/idmap.h1
-rw-r--r--source3/lib/smbldap.c148
-rw-r--r--source3/nsswitch/wb_client.c74
-rw-r--r--source3/nsswitch/wbinfo.c82
-rw-r--r--source3/nsswitch/winbindd_acct.c226
-rw-r--r--source3/nsswitch/winbindd_nss.h2
-rw-r--r--source3/nsswitch/winbindd_user.c13
-rw-r--r--source3/passdb/passdb.c171
-rw-r--r--source3/passdb/pdb_ldap.c489
-rw-r--r--source3/passdb/pdb_smbpasswd.c112
-rw-r--r--source3/passdb/pdb_tdb.c77
-rw-r--r--source3/rpc_server/srv_samr_nt.c35
-rw-r--r--source3/sam/idmap.c15
-rw-r--r--source3/sam/idmap_ldap.c283
-rw-r--r--source3/sam/idmap_tdb.c41
-rw-r--r--source3/sam/idmap_util.c114
-rw-r--r--source3/utils/net_rpc_samsync.c4
-rw-r--r--source3/utils/pdbedit.c2
20 files changed, 1059 insertions, 842 deletions
diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c
index 51cd1994f9..3f9c120cfb 100644
--- a/source3/auth/auth_util.c
+++ b/source3/auth/auth_util.c
@@ -56,10 +56,12 @@ static int smb_create_user(const char *domain, const char *unix_username, const
/****************************************************************************
Add and Delete UNIX users on demand, based on NTSTATUS codes.
+ We don't care about RID's here so ignore.
****************************************************************************/
void auth_add_user_script(const char *domain, const char *username)
{
+ uint32 rid;
/*
* User validated ok against Domain controller.
* If the admin wants us to try and create a UNIX
@@ -75,8 +77,10 @@ void auth_add_user_script(const char *domain, const char *username)
However, a host set for 'security = server' might run winbindd for
account allocation */
- if ( !winbind_create_user(username) )
+ if ( !winbind_create_user(username, NULL) ) {
DEBUG(5,("auth_add_user_script: winbindd_create_user() failed\n"));
+ rid = 0;
+ }
}
}
diff --git a/source3/groupdb/mapping.c b/source3/groupdb/mapping.c
index e769b4dd9d..8a6f514860 100644
--- a/source3/groupdb/mapping.c
+++ b/source3/groupdb/mapping.c
@@ -756,7 +756,7 @@ int smb_create_group(char *unix_group, gid_t *new_gid)
/* Try winbindd */
- if ( winbind_create_group( unix_group ) ) {
+ if ( winbind_create_group( unix_group, NULL ) ) {
DEBUG(3,("smb_create_group: winbindd created the group (%s)\n",
unix_group));
return 0;
@@ -783,15 +783,13 @@ int smb_delete_group(char *unix_group)
DEBUG(3,("smb_delete_group: Running the command `%s' gave %d\n",del_script,ret));
return ret;
}
-#if 0
+
if ( winbind_delete_group( unix_group ) ) {
DEBUG(3,("smb_delete_group: winbindd deleted the group (%s)\n",
unix_group));
return 0;
}
-#endif
-
return -1;
}
diff --git a/source3/include/idmap.h b/source3/include/idmap.h
index 7da3718d19..ae7e4e5101 100644
--- a/source3/include/idmap.h
+++ b/source3/include/idmap.h
@@ -42,6 +42,7 @@ struct idmap_methods {
/* Called when backend is first loaded */
NTSTATUS (*init)( char *params );
+ NTSTATUS (*allocate_rid)(uint32 *rid, int rid_type);
NTSTATUS (*allocate_id)(unid_t *id, int id_type);
NTSTATUS (*get_sid_from_id)(DOM_SID *sid, unid_t id, int id_type);
NTSTATUS (*get_id_from_sid)(unid_t *id, int *id_type, const DOM_SID *sid);
diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c
index cba73d386c..21e3383acd 100644
--- a/source3/lib/smbldap.c
+++ b/source3/lib/smbldap.c
@@ -1110,3 +1110,151 @@ NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx, const char *location, struct smbldap_
return NT_STATUS_OK;
}
+/**********************************************************************
+ Add the sambaDomain to LDAP, so we don't have to search for this stuff
+ again. This is a once-add operation for now.
+
+ TODO: Add other attributes, and allow modification.
+*********************************************************************/
+static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state,
+ const char *domain_name)
+{
+ fstring sid_string;
+ fstring algorithmic_rid_base_string;
+ pstring filter, dn;
+ LDAPMod **mods = NULL;
+ int rc;
+ int ldap_op;
+ LDAPMessage *result = NULL;
+ int num_result;
+ char **attr_list;
+
+ 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 );
+ rc = smbldap_search_suffix(ldap_state, filter, attr_list, &result);
+ free_attr_list( attr_list );
+
+ if (rc != LDAP_SUCCESS) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ 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"));
+ 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;
+
+ snprintf(dn, sizeof(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);
+
+ /* 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),
+ algorithmic_rid_base_string);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_DOMINFO);
+
+ 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;
+ }
+
+ 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"));
+ SAFE_FREE(ld_error);
+
+ ldap_mods_free(mods, True);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ DEBUG(2,("added: domain = %s in the LDAP database\n", domain_name));
+ ldap_mods_free(mods, True);
+ return NT_STATUS_OK;
+}
+
+/**********************************************************************
+Search for the domain info entry
+*********************************************************************/
+NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state,
+ LDAPMessage ** result, const char *domain_name,
+ BOOL try_add)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ pstring filter;
+ int rc;
+ char **attr_list;
+ int count;
+
+ snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%s))",
+ LDAP_OBJ_DOMINFO,
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
+ domain_name);
+
+ DEBUG(2, ("Searching for:[%s]\n", filter));
+
+
+ attr_list = get_attr_list( dominfo_attr_list );
+ rc = smbldap_search_suffix(ldap_state, filter, attr_list , result);
+ free_attr_list( attr_list );
+
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(2,("Problem during LDAPsearch: %s\n", ldap_err2string (rc)));
+ DEBUG(2,("Query was: %s, %s\n", lp_ldap_suffix(), filter));
+ } else if (ldap_count_entries(ldap_state->ldap_struct, *result) < 1) {
+ DEBUG(3, ("Got no domain info entries for domain\n"));
+ ldap_msgfree(*result);
+ *result = NULL;
+ if (try_add && NT_STATUS_IS_OK(ret = add_new_domain_info(ldap_state, domain_name))) {
+ return smbldap_search_domain_info(ldap_state, result, domain_name, False);
+ }
+ else {
+ DEBUG(0, ("Adding domain info for %s failed with %s\n",
+ domain_name, nt_errstr(ret)));
+ return ret;
+ }
+ } else if ((count = ldap_count_entries(ldap_state->ldap_struct, *result)) > 1) {
+ DEBUG(0, ("Got too many (%d) domain info entries for domain %s\n",
+ count, domain_name));
+ ldap_msgfree(*result);
+ *result = NULL;
+ return ret;
+ } else {
+ return NT_STATUS_OK;
+ }
+
+ return ret;
+}
+
diff --git a/source3/nsswitch/wb_client.c b/source3/nsswitch/wb_client.c
index 26a0e58191..eb9a7e9995 100644
--- a/source3/nsswitch/wb_client.c
+++ b/source3/nsswitch/wb_client.c
@@ -371,7 +371,7 @@ BOOL winbind_ping( void )
Ask winbindd to create a local user
**********************************************************************/
-BOOL winbind_create_user( const char *name )
+BOOL winbind_create_user( const char *name, uint32 *rid )
{
struct winbindd_request request;
struct winbindd_response response;
@@ -384,6 +384,11 @@ BOOL winbind_create_user( const char *name )
return False;
DEBUG(10,("winbind_create_user: %s\n", name));
+
+ /* see if the caller wants a new RID returned */
+
+ if ( rid )
+ request.flags = WBFLAG_ALLOCATE_RID;
fstrcpy( request.data.acct_mgt.username, name );
fstrcpy( request.data.acct_mgt.groupname, "" );
@@ -392,6 +397,9 @@ BOOL winbind_create_user( const char *name )
result = winbindd_request( WINBINDD_CREATE_USER, &request, &response);
+ if ( rid )
+ *rid = response.data.rid;
+
return result == NSS_STATUS_SUCCESS;
}
@@ -399,7 +407,7 @@ BOOL winbind_create_user( const char *name )
Ask winbindd to create a local group
**********************************************************************/
-BOOL winbind_create_group( const char *name )
+BOOL winbind_create_group( const char *name, uint32 *rid )
{
struct winbindd_request request;
struct winbindd_response response;
@@ -413,12 +421,20 @@ BOOL winbind_create_group( const char *name )
DEBUG(10,("winbind_create_group: %s\n", name));
+ /* see if the caller wants a new RID returned */
+
+ if ( rid )
+ request.flags = WBFLAG_ALLOCATE_RID;
+
fstrcpy( request.data.acct_mgt.groupname, name );
ZERO_STRUCT(response);
result = winbindd_request( WINBINDD_CREATE_GROUP, &request, &response);
+ if ( rid )
+ *rid = response.data.rid;
+
return result == NSS_STATUS_SUCCESS;
}
@@ -510,4 +526,58 @@ BOOL winbind_set_user_primary_group( const char *user, const char *group )
}
+/**********************************************************************
+ Ask winbindd to remove a user from its lists of accounts
+**********************************************************************/
+
+BOOL winbind_delete_user( const char *user )
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ NSS_STATUS result;
+
+ if ( !lp_winbind_enable_local_accounts() )
+ return False;
+
+ if ( !user )
+ return False;
+
+ DEBUG(10,("winbind_delete_user: user (%s)\n", user));
+
+ fstrcpy( request.data.acct_mgt.username, user );
+
+ ZERO_STRUCT(response);
+
+ result = winbindd_request( WINBINDD_DELETE_USER, &request, &response);
+
+ return result == NSS_STATUS_SUCCESS;
+}
+
+/**********************************************************************
+ Ask winbindd to remove a group from its lists of accounts
+**********************************************************************/
+
+BOOL winbind_delete_group( const char *group )
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ NSS_STATUS result;
+
+ if ( !lp_winbind_enable_local_accounts() )
+ return False;
+
+ if ( !group )
+ return False;
+
+ DEBUG(10,("winbind_delete_group: group (%s)\n", group));
+
+ fstrcpy( request.data.acct_mgt.groupname, group );
+
+ ZERO_STRUCT(response);
+
+ result = winbindd_request( WINBINDD_DELETE_GROUP, &request, &response);
+
+ return result == NSS_STATUS_SUCCESS;
+}
+
diff --git a/source3/nsswitch/wbinfo.c b/source3/nsswitch/wbinfo.c
index 6ebf6effa7..f533799370 100644
--- a/source3/nsswitch/wbinfo.c
+++ b/source3/nsswitch/wbinfo.c
@@ -526,16 +526,36 @@ static BOOL wbinfo_create_user(char *username)
ZERO_STRUCT(request);
ZERO_STRUCT(response);
+ request.flags = WBFLAG_ALLOCATE_RID;
fstrcpy(request.data.acct_mgt.username, username);
result = winbindd_request(WINBINDD_CREATE_USER, &request, &response);
- if (response.data.auth.nt_status)
- d_printf("error code was %s (0x%x)\nerror messsage was: %s\n",
- response.data.auth.nt_status_string,
- response.data.auth.nt_status,
- response.data.auth.error_string);
+ if ( result == NSS_STATUS_SUCCESS )
+ d_printf("New RID is %d\n", response.data.rid);
+
+ return result == NSS_STATUS_SUCCESS;
+}
+/******************************************************************
+ remove a winbindd user
+******************************************************************/
+
+static BOOL wbinfo_delete_user(char *username)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ NSS_STATUS result;
+
+ /* Send off request */
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ fstrcpy(request.data.acct_mgt.username, username);
+
+ result = winbindd_request(WINBINDD_DELETE_USER, &request, &response);
+
return result == NSS_STATUS_SUCCESS;
}
@@ -558,12 +578,28 @@ static BOOL wbinfo_create_group(char *groupname)
result = winbindd_request(WINBINDD_CREATE_GROUP, &request, &response);
- if (response.data.auth.nt_status)
- d_printf("error code was %s (0x%x)\nerror messsage was: %s\n",
- response.data.auth.nt_status_string,
- response.data.auth.nt_status,
- response.data.auth.error_string);
+ return result == NSS_STATUS_SUCCESS;
+}
+/******************************************************************
+ remove a winbindd group
+******************************************************************/
+
+static BOOL wbinfo_delete_group(char *groupname)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ NSS_STATUS result;
+
+ /* Send off request */
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ fstrcpy(request.data.acct_mgt.groupname, groupname);
+
+ result = winbindd_request(WINBINDD_DELETE_GROUP, &request, &response);
+
return result == NSS_STATUS_SUCCESS;
}
@@ -614,12 +650,6 @@ static BOOL wbinfo_add_user_to_group(char *string)
result = winbindd_request(WINBINDD_ADD_USER_TO_GROUP, &request, &response);
- if (response.data.auth.nt_status)
- d_printf("error code was %s (0x%x)\nerror messsage was: %s\n",
- response.data.auth.nt_status_string,
- response.data.auth.nt_status,
- response.data.auth.error_string);
-
return result == NSS_STATUS_SUCCESS;
}
@@ -647,12 +677,6 @@ static BOOL wbinfo_remove_user_from_group(char *string)
result = winbindd_request(WINBINDD_REMOVE_USER_FROM_GROUP, &request, &response);
- if (response.data.auth.nt_status)
- d_printf("error code was %s (0x%x)\nerror messsage was: %s\n",
- response.data.auth.nt_status_string,
- response.data.auth.nt_status,
- response.data.auth.error_string);
-
return result == NSS_STATUS_SUCCESS;
}
@@ -851,7 +875,9 @@ int main(int argc, char **argv)
{ "sid-to-uid", 'S', POPT_ARG_STRING, &string_arg, 'S', "Converts sid to uid", "SID" },
{ "sid-to-gid", 'Y', POPT_ARG_STRING, &string_arg, 'Y', "Converts sid to gid", "SID" },
{ "create-user", 'c', POPT_ARG_STRING, &string_arg, 'c', "Create a local user account", "name" },
+ { "delete-user", 'x', POPT_ARG_STRING, &string_arg, 'x', "Delete a local user account", "name" },
{ "create-group", 'C', POPT_ARG_STRING, &string_arg, 'C', "Create a local group", "name" },
+ { "delete-group", 'X', POPT_ARG_STRING, &string_arg, 'X', "Delete a local group", "name" },
{ "add-to-group", 'o', POPT_ARG_STRING, &string_arg, 'o', "Add user to group", "user:group" },
{ "del-from-group", 'O', POPT_ARG_STRING, &string_arg, 'O', "Remove user from group", "user:group" },
{ "check-secret", 't', POPT_ARG_NONE, 0, 't', "Check shared secret" },
@@ -1036,6 +1062,18 @@ int main(int argc, char **argv)
goto done;
}
break;
+ case 'x':
+ if ( !wbinfo_delete_user(string_arg) ) {
+ d_printf("Could not delete user account\n");
+ goto done;
+ }
+ break;
+ case 'X':
+ if ( !wbinfo_delete_group(string_arg) ) {
+ d_printf("Could not delete group\n");
+ goto done;
+ }
+ break;
case 'P':
if (!wbinfo_ping()) {
d_printf("could not ping winbindd!\n");
diff --git a/source3/nsswitch/winbindd_acct.c b/source3/nsswitch/winbindd_acct.c
index 2a3a6eb2bb..a1cd1d5f19 100644
--- a/source3/nsswitch/winbindd_acct.c
+++ b/source3/nsswitch/winbindd_acct.c
@@ -37,6 +37,29 @@ static TDB_CONTEXT *account_tdb;
extern userdom_struct current_user_info;
+struct _check_primary_grp {
+ gid_t gid;
+ BOOL found;
+};
+
+/**********************************************************************
+**********************************************************************/
+
+static void free_winbindd_gr( WINBINDD_GR *grp )
+{
+ int i;
+
+ if ( !grp )
+ return;
+
+ for ( i=0; i<grp->num_gr_mem; i++ )
+ SAFE_FREE( grp->gr_mem[i] );
+
+ SAFE_FREE( grp->gr_mem );
+
+ return;
+}
+
/*****************************************************************************
Initialise auto-account database.
*****************************************************************************/
@@ -649,8 +672,17 @@ static BOOL wb_delgrpmember( WINBINDD_GR *grp, const char *user )
if ( !found )
return False;
- memmove( grp->gr_mem[i], grp->gr_mem[i+1], sizeof(char*)*(grp->num_gr_mem-(i+1)) );
- grp->num_gr_mem--;
+ /* still some remaining members */
+
+ if ( grp->num_gr_mem > 1 ) {
+ memmove( grp->gr_mem[i], grp->gr_mem[i+1], sizeof(char*)*(grp->num_gr_mem-(i+1)) );
+ grp->num_gr_mem--;
+ }
+ else { /* last one */
+ free_winbindd_gr( grp );
+ grp->gr_mem = NULL;
+ grp->num_gr_mem = 0;
+ }
return True;
}
@@ -658,34 +690,59 @@ static BOOL wb_delgrpmember( WINBINDD_GR *grp, const char *user )
/**********************************************************************
**********************************************************************/
-static void free_winbindd_gr( WINBINDD_GR *grp )
+static int cleangroups_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf,
+ void *state)
{
- int i;
-
- if ( !grp )
- return;
+ int len;
+ fstring key;
+ char *name = (char*)state;
+
+ snprintf( key, sizeof(key), "%s/NAME", WBKEY_GROUP );
+ len = strlen(key);
+
+ /* if this is a group entry then, check the members */
+
+ if ( (strncmp(kbuf.dptr, key, len) == 0) && dbuf.dptr ) {
+ WINBINDD_GR *grp;
- for ( i=0; i<grp->num_gr_mem; i++ )
- SAFE_FREE( grp->gr_mem[i] );
+ if ( !(grp = string2group( dbuf.dptr )) ) {
+ DEBUG(0,("cleangroups_traverse_fn: Failure to parse [%s]\n",
+ dbuf.dptr));
+ return 0;
+ }
+
+ /* just try to delete the user and rely on wb_delgrpmember()
+ to tell you whether or not the group changed. This is more
+ effecient than testing group membership first since the
+ checks for deleting a user from a group is essentially the
+ same as checking if he/she is a member */
+
+ if ( wb_delgrpmember( grp, name ) ) {
+ DEBUG(10,("cleanupgroups_traverse_fn: Removed user (%s) from group (%s)\n",
+ name, grp->gr_name));
+ wb_storegrnam( grp );
+ }
+
+ free_winbindd_gr( grp );
+ }
- SAFE_FREE( grp->gr_mem );
-
- return;
+ return 0;
}
/**********************************************************************
**********************************************************************/
-static BOOL wb_delete_user( const char *name)
+static BOOL wb_delete_user( WINBINDD_PW *pw)
{
char *namekey;
+ char *uidkey;
if ( !account_tdb && !winbindd_accountdb_init() ) {
- DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n"));
+ DEBUG(0,("wb_delete_user: Failed to open winbindd account db\n"));
return False;
}
- namekey = acct_userkey_byname( name );
+ namekey = acct_userkey_byname( pw->pw_name );
/* lock the main entry first */
@@ -694,20 +751,101 @@ static BOOL wb_delete_user( const char *name)
return False;
}
+ /* remove user from all groups */
+
+ tdb_traverse(account_tdb, cleangroups_traverse_fn, (void *)pw->pw_name);
+
+ /* remove the user */
+ uidkey = acct_userkey_byuid( pw->pw_uid );
tdb_delete_bystring( account_tdb, namekey );
+ tdb_delete_bystring( account_tdb, uidkey );
+
tdb_unlock_bystring( account_tdb, namekey );
return True;
}
+/**********************************************************************
+**********************************************************************/
+
+static int isprimarygroup_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf,
+ TDB_DATA dbuf, void *params)
+{
+ int len;
+ fstring key;
+ struct _check_primary_grp *check = (struct _check_primary_grp*)params;
+
+ snprintf( key, sizeof(key), "%s/NAME", WBKEY_PASSWD );
+ len = strlen(key);
+
+ /* if this is a group entry then, check the members */
+
+ if ( (strncmp(kbuf.dptr, key, len) == 0) && dbuf.dptr ) {
+ WINBINDD_PW *pw;;
+
+ if ( !(pw = string2passwd( dbuf.dptr )) ) {
+ DEBUG(0,("isprimarygroup_traverse_fn: Failure to parse [%s]\n",
+ dbuf.dptr));
+ return 0;
+ }
+
+ if ( check->gid == pw->pw_gid ) {
+ check->found = True;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
/**********************************************************************
**********************************************************************/
-static BOOL wb_delete_group( const char *name)
+static BOOL wb_delete_group( WINBINDD_GR *grp )
{
- return False;
+ struct _check_primary_grp check;
+ char *namekey;
+ char *gidkey;
+
+ if ( !account_tdb && !winbindd_accountdb_init() ) {
+ DEBUG(0,("wb_delete_group: Failed to open winbindd account db\n"));
+ return False;
+ }
+
+ /* lock the main entry first */
+
+ namekey = acct_groupkey_byname( grp->gr_name );
+ if ( tdb_lock_bystring(account_tdb, namekey, 0) == -1 ) {
+ DEBUG(0,("wb_delete_group: Failed to lock %s\n", namekey));
+ return False;
+ }
+
+ /* is this group the primary group for any user? If
+ so deny delete */
+
+ check.found = False;
+ tdb_traverse(account_tdb, isprimarygroup_traverse_fn, (void *)&check);
+
+ if ( check.found ) {
+ DEBUG(4,("wb_delete_group: Cannot delete group (%s) since it "
+ "is the primary group for some users\n", grp->gr_name));
+ return False;
+ }
+
+ /* We're clear. Delete the group */
+
+ DEBUG(5,("wb_delete_group: Removing group (%s)\n", grp->gr_name));
+
+ gidkey = acct_groupkey_bygid( grp->gr_gid );
+
+ tdb_delete_bystring( account_tdb, namekey );
+ tdb_delete_bystring( account_tdb, gidkey );
+
+ tdb_unlock_bystring( account_tdb, namekey );
+
+ return True;
}
/**********************************************************************
@@ -722,6 +860,8 @@ enum winbindd_result winbindd_create_user(struct winbindd_cli_state *state)
WINBINDD_GR *wb_grp;
struct group *unix_grp;
gid_t primary_gid;
+ uint32 flags = state->request.flags;
+ uint32 rid;
if ( !state->privileged ) {
DEBUG(2, ("winbindd_create_user: non-privileged access denied!\n"));
@@ -781,8 +921,27 @@ enum winbindd_result winbindd_create_user(struct winbindd_cli_state *state)
pw.pw_uid = id.uid;
pw.pw_gid = primary_gid;
+
+ /* store the new entry */
+
+ if ( !wb_storepwnam(&pw) )
+ return WINBINDD_ERROR;
+
+ /* do we need a new RID? */
+
+ if ( flags & WBFLAG_ALLOCATE_RID ) {
+ if ( !NT_STATUS_IS_OK(idmap_allocate_rid(&rid, USER_RID_TYPE)) ) {
+ DEBUG(0,("winbindd_create_user: RID allocation failure! Cannot create user (%s)\n",
+ user));
+ wb_delete_user( &pw );
+
+ return WINBINDD_ERROR;
+ }
+
+ state->response.data.rid = rid;
+ }
- return ( wb_storepwnam(&pw) ? WINBINDD_OK : WINBINDD_ERROR );
+ return WINBINDD_OK;
}
/**********************************************************************
@@ -794,6 +953,8 @@ enum winbindd_result winbindd_create_group(struct winbindd_cli_state *state)
char *group;
unid_t id;
WINBINDD_GR grp;
+ uint32 flags = state->request.flags;
+ uint32 rid;
if ( !state->privileged ) {
DEBUG(2, ("winbindd_create_group: non-privileged access denied!\n"));
@@ -821,8 +982,25 @@ enum winbindd_result winbindd_create_group(struct winbindd_cli_state *state)
grp.gr_gid = id.gid;
grp.gr_mem = NULL; /* start with no members */
grp.num_gr_mem = 0;
+
+ if ( !wb_storegrnam(&grp) )
+ return WINBINDD_ERROR;
+
+ /* do we need a new RID? */
+
+ if ( flags & WBFLAG_ALLOCATE_RID ) {
+ if ( !NT_STATUS_IS_OK(idmap_allocate_rid(&rid, GROUP_RID_TYPE)) ) {
+ DEBUG(0,("winbindd_create_group: RID allocation failure! Cannot create group (%s)\n",
+ group));
+ wb_delete_group( &grp );
+
+ return WINBINDD_ERROR;
+ }
+
+ state->response.data.rid = rid;
+ }
- return ( wb_storegrnam(&grp) ? WINBINDD_OK : WINBINDD_ERROR );
+ return WINBINDD_OK;
}
/**********************************************************************
@@ -989,8 +1167,7 @@ enum winbindd_result winbindd_delete_user(struct winbindd_cli_state *state)
return WINBINDD_ERROR;
}
-
- return ( wb_delete_user(user) ? WINBINDD_OK : WINBINDD_ERROR );
+ return ( wb_delete_user(pw) ? WINBINDD_OK : WINBINDD_ERROR );
}
/**********************************************************************
@@ -1001,6 +1178,7 @@ enum winbindd_result winbindd_delete_group(struct winbindd_cli_state *state)
{
WINBINDD_GR *grp;
char *group;
+ BOOL ret;
if ( !state->privileged ) {
DEBUG(2, ("winbindd_delete_group: non-privileged access denied!\n"));
@@ -1016,13 +1194,15 @@ enum winbindd_result winbindd_delete_group(struct winbindd_cli_state *state)
/* make sure it is a valid group */
if ( !(grp = wb_getgrnam( group )) ) {
- DEBUG(4,("winbindd_delete_user: Cannot delete a non-existent group\n"));
+ DEBUG(4,("winbindd_delete_group: Cannot delete a non-existent group\n"));
return WINBINDD_ERROR;
}
+ ret = wb_delete_group(grp);
+
free_winbindd_gr( grp );
- return ( wb_delete_group(group) ? WINBINDD_OK : WINBINDD_ERROR );
+ return ( ret ? WINBINDD_OK : WINBINDD_ERROR );
}
diff --git a/source3/nsswitch/winbindd_nss.h b/source3/nsswitch/winbindd_nss.h
index a2d9e82c7c..c4407bbe31 100644
--- a/source3/nsswitch/winbindd_nss.h
+++ b/source3/nsswitch/winbindd_nss.h
@@ -148,6 +148,7 @@ typedef struct winbindd_gr {
#define WBFLAG_PAM_LMKEY 0x0008
#define WBFLAG_PAM_CONTACT_TRUSTDOM 0x0010
#define WBFLAG_QUERY_ONLY 0x0020
+#define WBFLAG_ALLOCATE_RID 0x0040
/* Winbind request structure */
@@ -257,6 +258,7 @@ struct winbindd_response {
char nt_session_key[16];
char first_8_lm_hash[8];
} auth;
+ uint32 rid; /* create user or group */
} data;
/* Variable length return data */
diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c
index 7c95ba8470..c49c41687b 100644
--- a/source3/nsswitch/winbindd_user.c
+++ b/source3/nsswitch/winbindd_user.c
@@ -308,6 +308,19 @@ enum winbindd_result winbindd_setpwent(struct winbindd_cli_state *state)
free_getent_state(state->getpwent_state);
state->getpwent_state = NULL;
}
+
+#if 0 /* JERRY */
+ /* add any local users we have */
+
+ if ( (domain_state = (struct getent_state *)malloc(sizeof(struct getent_state))) == NULL )
+ return WINBINDD_ERROR;
+
+ ZERO_STRUCTP(domain_state);
+
+ /* Add to list of open domains */
+
+ DLIST_ADD(state->getpwent_state, domain_state);
+#endif
/* Create sam pipes for each domain we know about */
diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c
index a2623ff3d7..408695d4bd 100644
--- a/source3/passdb/passdb.c
+++ b/source3/passdb/passdb.c
@@ -290,41 +290,37 @@ NTSTATUS pdb_init_sam_pw(SAM_ACCOUNT **new_sam_acct, const struct passwd *pwd)
/*************************************************************
Initialises a SAM_ACCOUNT ready to add a new account, based
- on the unix user if possible.
+ on the UNIX user. Pass in a RID if you have one
************************************************************/
-NTSTATUS pdb_init_sam_new(SAM_ACCOUNT **new_sam_acct, const char *username)
+NTSTATUS pdb_init_sam_new(SAM_ACCOUNT **new_sam_acct, const char *username,
+ uint32 rid)
{
- NTSTATUS nt_status = NT_STATUS_NO_MEMORY;
-
- struct passwd *pwd;
+ NTSTATUS nt_status = NT_STATUS_NO_MEMORY;
+ struct passwd *pwd;
+ BOOL ret;
pwd = Get_Pwnam(username);
- if (pwd) {
- if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_pw(new_sam_acct, pwd))) {
- *new_sam_acct = NULL;
- return nt_status;
- }
- } else {
- DOM_SID g_sid;
- if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(new_sam_acct))) {
- *new_sam_acct = NULL;
- return nt_status;
- }
- if (!pdb_set_username(*new_sam_acct, username, PDB_SET)) {
- pdb_free_sam(new_sam_acct);
- return nt_status;
- }
-
- pdb_set_domain (*new_sam_acct, get_global_sam_name(), PDB_DEFAULT);
-
- /* set Domain Users by default ! */
- sid_copy(&g_sid, get_global_sam_sid());
- sid_append_rid(&g_sid, DOMAIN_GROUP_RID_USERS);
- pdb_set_group_sid(*new_sam_acct, &g_sid, PDB_SET);
+ if (!pwd)
+ return NT_STATUS_NO_SUCH_USER;
+
+ if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_pw(new_sam_acct, pwd))) {
+ *new_sam_acct = NULL;
+ return nt_status;
}
- return NT_STATUS_OK;
+
+ /* see if we need to generate a new rid using the 2.2 algorithm */
+ if ( rid == 0 && lp_enable_rid_algorithm() ) {
+ DEBUG(10,("pdb_init_sam_new: no RID specified. Generating one via old algorithm\n"));
+ rid = fallback_pdb_uid_to_user_rid(pwd->pw_uid);
+ }
+
+ /* set the new SID */
+
+ ret = pdb_set_user_sid_from_rid( *new_sam_acct, rid, PDB_SET );
+
+ return (ret ? NT_STATUS_OK : NT_STATUS_NO_SUCH_USER);
}
@@ -920,8 +916,8 @@ BOOL local_password_change(const char *user_name, int local_flags,
pdb_free_sam(&sam_pass);
if ((local_flags & LOCAL_ADD_USER) || (local_flags & LOCAL_DELETE_USER)) {
- /* Might not exist in /etc/passwd */
- if (!NT_STATUS_IS_OK(pdb_init_sam_new(&sam_pass, user_name))) {
+ /* Might not exist in /etc/passwd. Use rid algorithm here */
+ if (!NT_STATUS_IS_OK(pdb_init_sam_new(&sam_pass, user_name, 0))) {
slprintf(err_str, err_str_len-1, "Failed initialise SAM_ACCOUNT for user %s.\n", user_name);
return False;
}
@@ -1248,121 +1244,6 @@ BOOL local_sid_to_gid(gid_t *pgid, const DOM_SID *psid, enum SID_NAME_USE *name_
}
/**********************************************************************
-**********************************************************************/
-
-BOOL pdb_get_free_ugid_range(uint32 *low, uint32 *high)
-{
- uid_t u_low, u_high;
- gid_t g_low, g_high;
-
- if (!lp_idmap_uid(&u_low, &u_high) || !lp_idmap_gid(&g_low, &g_high)) {
- return False;
- }
-
- *low = (u_low < g_low) ? u_low : g_low;
- *high = (u_high < g_high) ? u_high : g_high;
-
- return True;
-}
-
-/******************************************************************
- Get the the non-algorithmic RID range if idmap range are defined
-******************************************************************/
-
-BOOL pdb_get_free_rid_range(uint32 *low, uint32 *high)
-{
- uint32 id_low, id_high;
-
- if (!lp_enable_rid_algorithm()) {
- *low = BASE_RID;
- *high = (uint32)-1;
- }
-
- if (!pdb_get_free_ugid_range(&id_low, &id_high)) {
- return False;
- }
-
- *low = fallback_pdb_uid_to_user_rid(id_low);
- if (fallback_pdb_user_rid_to_uid((uint32)-1) < id_high) {
- *high = (uint32)-1;
- } else {
- *high = fallback_pdb_uid_to_user_rid(id_high);
- }
-
- return True;
-}
-
-/**********************************************************************
- Get the free RID base if idmap is configured, otherwise return 0
-**********************************************************************/
-
-uint32 pdb_get_free_rid_base(void)
-{
- uint32 low, high;
- if (pdb_get_free_rid_range(&low, &high)) {
- return low;
- }
- return 0;
-}
-
-/**********************************************************************
-**********************************************************************/
-
-BOOL pdb_check_ugid_is_in_free_range(uint32 id)
-{
- uint32 low, high;
-
- if (!pdb_get_free_ugid_range(&low, &high)) {
- return False;
- }
- if (id < low || id > high) {
- return False;
- }
- return True;
-}
-
-/**********************************************************************
-**********************************************************************/
-
-BOOL pdb_check_rid_is_in_free_range(uint32 rid)
-{
- uint32 low, high;
-
- if (!pdb_get_free_rid_range(&low, &high)) {
- return False;
- }
- if (rid < algorithmic_rid_base()) {
- return True;
- }
-
- if (rid < low || rid > high) {
- return False;
- }
-
- return True;
-}
-
-/**********************************************************************
- if it is a foreign SID or if the SID is in the free range, return true
-**********************************************************************/
-
-BOOL pdb_check_sid_is_in_free_range(const DOM_SID *sid)
-{
- if (sid_compare_domain(get_global_sam_sid(), sid) == 0) {
-
- uint32 rid;
-
- if (sid_peek_rid(sid, &rid)) {
- return pdb_check_rid_is_in_free_range(rid);
- }
-
- return False;
- }
-
- return True;
-}
-
-/**********************************************************************
Marshall/unmarshall SAM_ACCOUNT structs.
*********************************************************************/
diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c
index 886fd809f3..e32f566a7d 100644
--- a/source3/passdb/pdb_ldap.c
+++ b/source3/passdb/pdb_ldap.c
@@ -96,15 +96,6 @@ struct ldapsam_privates {
/* configuration items */
int schema_ver;
-
- BOOL permit_non_unix_accounts;
-
- uint32 low_allocated_user_rid;
- uint32 high_allocated_user_rid;
-
- uint32 low_allocated_group_rid;
- uint32 high_allocated_group_rid;
-
};
/**********************************************************************
@@ -338,423 +329,7 @@ static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
ldap_memfree(dn);
return NT_STATUS_OK;
}
-
-/**********************************************************************
- Add the sambaDomain to LDAP, so we don't have to search for this stuff
- again. This is a once-add operation for now.
-
- TODO: Add other attributes, and allow modification.
-*********************************************************************/
-static NTSTATUS add_new_domain_info(struct ldapsam_privates *ldap_state)
-{
- fstring sid_string;
- fstring algorithmic_rid_base_string;
- pstring filter, dn;
- LDAPMod **mods = NULL;
- int rc;
- int ldap_op;
- LDAPMessage *result = NULL;
- int num_result;
- char **attr_list;
-
- slprintf (filter, sizeof (filter) - 1, "(&(%s=%s)(objectclass=%s))",
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
- ldap_state->domain_name, LDAP_OBJ_DOMINFO);
-
- attr_list = get_attr_list( dominfo_attr_list );
- rc = smbldap_search_suffix(ldap_state->smbldap_state, filter,
- attr_list, &result);
- free_attr_list( attr_list );
-
- if (rc != LDAP_SUCCESS) {
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
-
- if (num_result > 1) {
- 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;
-
- snprintf(dn, sizeof(dn), "%s=%s,%s", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
- ldap_state->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),
- ldap_state->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),
- algorithmic_rid_base_string);
- smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_DOMINFO);
-
- switch(ldap_op)
- {
- case LDAP_MOD_ADD:
- rc = smbldap_add(ldap_state->smbldap_state, dn, mods);
- break;
- case LDAP_MOD_REPLACE:
- rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
- break;
- default:
- DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- if (rc!=LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_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"));
- SAFE_FREE(ld_error);
-
- ldap_mods_free(mods, True);
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- DEBUG(2,("added: domain = %s in the LDAP database\n", ldap_state->domain_name));
- ldap_mods_free(mods, True);
- return NT_STATUS_OK;
-}
-
-/**********************************************************************
-Search for the domain info entry
-*********************************************************************/
-static NTSTATUS ldapsam_search_domain_info(struct ldapsam_privates *ldap_state,
- LDAPMessage ** result, BOOL try_add)
-{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- pstring filter;
- int rc;
- char **attr_list;
- int count;
-
- snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%s))",
- LDAP_OBJ_DOMINFO,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
- ldap_state->domain_name);
-
- DEBUG(2, ("Searching for:[%s]\n", filter));
-
-
- attr_list = get_attr_list( dominfo_attr_list );
- rc = smbldap_search_suffix(ldap_state->smbldap_state, filter,
- attr_list , result);
- free_attr_list( attr_list );
-
- if (rc != LDAP_SUCCESS) {
- DEBUG(2,("Problem during LDAPsearch: %s\n", ldap_err2string (rc)));
- DEBUG(2,("Query was: %s, %s\n", lp_ldap_suffix(), filter));
- } else if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, *result) < 1) {
- DEBUG(3, ("Got no domain info entries for domain %s\n",
- ldap_state->domain_name));
- ldap_msgfree(*result);
- *result = NULL;
- if (try_add && NT_STATUS_IS_OK(ret = add_new_domain_info(ldap_state))) {
- return ldapsam_search_domain_info(ldap_state, result, False);
- } else {
- DEBUG(0, ("Adding domain info failed with %s\n", nt_errstr(ret)));
- return ret;
- }
- } else if ((count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, *result)) > 1) {
- DEBUG(0, ("Got too many (%d) domain info entries for domain %s\n",
- count, ldap_state->domain_name));
- ldap_msgfree(*result);
- *result = NULL;
- return ret;
- } else {
- return NT_STATUS_OK;
- }
-
- return ret;
-}
-
-/**********************************************************************
- Even if the sambaDomain attribute in LDAP tells us that this RID is
- safe to use, always check before use.
-*********************************************************************/
-static BOOL sid_in_use(struct ldapsam_privates *ldap_state,
- const DOM_SID *sid, int *error)
-{
- fstring filter;
- fstring sid_string;
- LDAPMessage *result = NULL;
- int count;
- int rc;
- char *sid_attr[] = {LDAP_ATTRIBUTE_SID, NULL};
-
- slprintf(filter, sizeof(filter)-1, "(%s=%s)", LDAP_ATTRIBUTE_SID, sid_to_string(sid_string, sid));
-
- rc = smbldap_search_suffix(ldap_state->smbldap_state,
- filter, sid_attr, &result);
-
- if (rc != LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
- DEBUG(2, ("Failed to check if sid %s is alredy in use: %s\n",
- sid_string, ld_error));
- SAFE_FREE(ld_error);
-
- *error = rc;
- return True;
- }
-
- if ((count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result)) > 0) {
- DEBUG(3, ("Sid %s already in use - trying next RID\n",
- sid_string));
- ldap_msgfree(result);
- return True;
- }
-
- ldap_msgfree(result);
-
- /* good, sid is not in use */
- return False;
-}
-
-/**********************************************************************
- Set the new nextRid attribute, and return one we can use.
-
- This also checks that this RID is actually free - in case the admin
- manually stole it :-).
-*********************************************************************/
-static NTSTATUS ldapsam_next_rid(struct ldapsam_privates *ldap_state, uint32 *rid, int rid_type)
-{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- int rc;
- LDAPMessage *domain_result = NULL;
- LDAPMessage *entry = NULL;
- char *dn;
- LDAPMod **mods = NULL;
- fstring old_rid_string;
- fstring next_rid_string;
- fstring algorithmic_rid_base_string;
- uint32 next_rid;
- uint32 alg_rid_base;
- int attempts = 0;
- char *ld_error = NULL;
-
- if ( ldap_state->schema_ver != SCHEMAVER_SAMBASAMACCOUNT ) {
- DEBUG(0, ("Allocated RIDs require the %s objectclass used by 'ldapsam'\n",
- LDAP_OBJ_SAMBASAMACCOUNT));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- while (attempts < 10)
- {
- if (!NT_STATUS_IS_OK(ret = ldapsam_search_domain_info(ldap_state, &domain_result, True))) {
- return ret;
- }
-
- entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, domain_result);
- if (!entry) {
- DEBUG(0, ("Could not get domain info entry\n"));
- ldap_msgfree(domain_result);
- return ret;
- }
-
- if ((dn = ldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry)) == NULL) {
- DEBUG(0, ("Could not get domain info DN\n"));
- ldap_msgfree(domain_result);
- return ret;
- }
-
- /* yes, we keep 3 seperate counters, one for rids between 1000 (BASE_RID) and
- algorithmic_rid_base. The other two are to avoid stomping on the
- different sets of algorithmic RIDs */
-
- if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE),
- algorithmic_rid_base_string))
- {
-
- alg_rid_base = (uint32)atol(algorithmic_rid_base_string);
- } else {
- alg_rid_base = algorithmic_rid_base();
- /* Try to make the modification atomically by enforcing the
- old value in the delete mod. */
- slprintf(algorithmic_rid_base_string, sizeof(algorithmic_rid_base_string)-1, "%d", alg_rid_base);
- smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE),
- algorithmic_rid_base_string);
- }
-
- next_rid = 0;
-
- if (alg_rid_base > BASE_RID) {
- /* we have a non-default 'algorithmic rid base', so we have 'low' rids that we
- can allocate to new users */
- if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_RID),
- old_rid_string))
- {
- *rid = (uint32)atol(old_rid_string);
- } else {
- *rid = BASE_RID;
- }
-
- next_rid = *rid+1;
- if (next_rid >= alg_rid_base) {
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_rid);
-
- /* Try to make the modification atomically by enforcing the
- old value in the delete mod. */
- smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_RID),
- next_rid_string);
- }
-
- if (!next_rid) { /* not got one already */
- switch (rid_type) {
- case USER_RID_TYPE:
- if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID),
- old_rid_string))
- {
-
- *rid = (uint32)atol(old_rid_string);
-
- } else {
- *rid = ldap_state->low_allocated_user_rid;
- }
- break;
- case GROUP_RID_TYPE:
- if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID),
- old_rid_string))
- {
- *rid = (uint32)atol(old_rid_string);
- } else {
- *rid = ldap_state->low_allocated_group_rid;
- }
- break;
- }
-
- /* This is the core of the whole routine. If we had
- scheme-style closures, there would be a *lot* less code
- duplication... */
-
- next_rid = *rid+RID_MULTIPLIER;
- slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_rid);
-
- switch (rid_type) {
- case USER_RID_TYPE:
- if (next_rid > ldap_state->high_allocated_user_rid) {
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- /* Try to make the modification atomically by enforcing the
- old value in the delete mod. */
- smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID),
- next_rid_string);
- break;
-
- case GROUP_RID_TYPE:
- if (next_rid > ldap_state->high_allocated_group_rid) {
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- /* Try to make the modification atomically by enforcing the
- old value in the delete mod. */
- smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID),
- next_rid_string);
- break;
- }
- }
-
- if ((rc = ldap_modify_s(ldap_state->smbldap_state->ldap_struct, dn, mods)) == LDAP_SUCCESS) {
- DOM_SID dom_sid;
- DOM_SID sid;
- pstring domain_sid_string;
- int error = 0;
-
- if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, domain_result,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID),
- domain_sid_string))
- {
- ldap_mods_free(mods, True);
- ldap_memfree(dn);
- ldap_msgfree(domain_result);
- return ret;
- }
-
- if (!string_to_sid(&dom_sid, domain_sid_string)) {
- ldap_mods_free(mods, True);
- ldap_memfree(dn);
- ldap_msgfree(domain_result);
- return ret;
- }
-
- ldap_mods_free(mods, True);
- mods = NULL;
- ldap_memfree(dn);
- ldap_msgfree(domain_result);
-
- sid_copy(&sid, &dom_sid);
- sid_append_rid(&sid, *rid);
-
- /* check RID is not in use */
- if (sid_in_use(ldap_state, &sid, &error)) {
- if (error) {
- return ret;
- }
- continue;
- }
-
- return NT_STATUS_OK;
- }
-
- ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
- DEBUG(2, ("Failed to modify rid: %s\n", ld_error ? ld_error : "(NULL"));
- SAFE_FREE(ld_error);
-
- ldap_mods_free(mods, True);
- mods = NULL;
-
- ldap_memfree(dn);
- dn = NULL;
-
- ldap_msgfree(domain_result);
- domain_result = NULL;
-
- {
- /* Sleep for a random timeout */
- unsigned sleeptime = (sys_random()*sys_getpid()*attempts);
- attempts += 1;
-
- sleeptime %= 100;
- msleep(sleeptime);
- }
- }
-
- DEBUG(0, ("Failed to set new RID\n"));
- return ret;
-}
+
/* New Interface is being implemented here */
@@ -1192,34 +767,6 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass)));
- if (pdb_get_init_flags(sampass, PDB_USERSID) == PDB_DEFAULT) {
- if (ldap_state->permit_non_unix_accounts) {
- if (!NT_STATUS_IS_OK(ldapsam_next_rid(ldap_state, &rid, USER_RID_TYPE))) {
- DEBUG(0, ("NO user RID specified on account %s, and "
- "finding next available NUA RID failed, "
- "cannot store!\n",
- pdb_get_username(sampass)));
- ldap_mods_free(*mods, True);
- return False;
- }
- } else {
- DEBUG(0, ("NO user RID specified on account %s, "
- "cannot store!\n", pdb_get_username(sampass)));
- ldap_mods_free(*mods, True);
- return False;
- }
-
- /* now that we have figured out the RID, always store it, as
- the schema requires it (either as a SID or a RID) */
-
- if (!pdb_set_user_sid_from_rid(sampass, rid, PDB_CHANGED)) {
- DEBUG(0, ("Could not store RID back onto SAM_ACCOUNT for user %s!\n",
- pdb_get_username(sampass)));
- ldap_mods_free(*mods, True);
- return False;
- }
- }
-
/* only update the RID if we actually need to */
if (need_update(sampass, PDB_USERSID))
{
@@ -2733,10 +2280,8 @@ static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_met
struct ldapsam_privates *ldap_state;
uint32 alg_rid_base;
pstring alg_rid_base_string;
- uint32 low_idmap_uid, high_idmap_uid;
- uint32 low_idmap_gid, high_idmap_gid;
- LDAPMessage *result;
- LDAPMessage *entry;
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
DOM_SID ldap_domain_sid;
DOM_SID secrets_domain_sid;
pstring domain_sid_string;
@@ -2748,14 +2293,17 @@ static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_met
(*pdb_method)->name = "ldapsam";
ldap_state = (*pdb_method)->private_data;
- ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
- ldap_state->permit_non_unix_accounts = False;
+ ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
/* Try to setup the Domain Name, Domain SID, algorithmic rid base */
-
- if (!NT_STATUS_IS_OK(nt_status = ldapsam_search_domain_info(ldap_state, &result, True))) {
+
+ nt_status = smbldap_search_domain_info(ldap_state->smbldap_state, &result,
+ ldap_state->domain_name, True);
+
+ if ( !NT_STATUS_IS_OK(nt_status) ) {
DEBUG(2, ("WARNING: Could not get domain info, nor add one to the domain\n"));
- DEBUGADD(2, ("Continuing on regardless, will be unable to allocate new users/groups, and will risk BDCs having inconsistant SIDs\n"));
+ DEBUGADD(2, ("Continuing on regardless, will be unable to allocate new users/groups, "
+ "and will risk BDCs having inconsistant SIDs\n"));
sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
return NT_STATUS_OK;
}
@@ -2796,21 +2344,6 @@ static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_met
}
}
ldap_msgfree(result);
-
- /* check for non-unix account ranges */
-
- if (lp_idmap_uid(&low_idmap_uid, &high_idmap_uid)
- && lp_idmap_gid(&low_idmap_gid, &high_idmap_gid))
- {
- DEBUG(2, ("Enabling non-unix account ranges\n"));
-
- ldap_state->permit_non_unix_accounts = True;
-
- ldap_state->low_allocated_user_rid = fallback_pdb_uid_to_user_rid(low_idmap_uid);
- ldap_state->high_allocated_user_rid = fallback_pdb_uid_to_user_rid(high_idmap_uid);
- ldap_state->low_allocated_group_rid = pdb_gid_to_group_rid(low_idmap_gid);
- ldap_state->high_allocated_group_rid = pdb_gid_to_group_rid(high_idmap_gid);
- }
return NT_STATUS_OK;
}
diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c
index 0e7dd77b40..055e8e71ba 100644
--- a/source3/passdb/pdb_smbpasswd.c
+++ b/source3/passdb/pdb_smbpasswd.c
@@ -1,10 +1,10 @@
/*
* Unix SMB/CIFS implementation.
* SMB parameters and setup
- * Copyright (C) Andrew Tridgell 1992-1998
- * Modified by Jeremy Allison 1995.
- * Modified by Gerald (Jerry) Carter 2000-2001
- * Modified by Andrew Bartlett 2002.
+ * Copyright (C) Andrew Tridgell 1992-1998
+ * Modified by Jeremy Allison 1995.
+ * Modified by Gerald (Jerry) Carter 2000-2001,2003
+ * Modified by Andrew Bartlett 2002.
*
* 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
@@ -34,14 +34,13 @@
struct smb_passwd
{
- BOOL smb_userid_set; /* this is actually the unix uid_t */
- uint32 smb_userid; /* this is actually the unix uid_t */
+ uint32 smb_userid; /* this is actually the unix uid_t */
const char *smb_name; /* username string */
- const unsigned char *smb_passwd; /* Null if no password */
+ const unsigned char *smb_passwd; /* Null if no password */
const unsigned char *smb_nt_passwd; /* Null if no password */
- uint16 acct_ctrl; /* account info (ACB_xxxx bit-mask) */
+ uint16 acct_ctrl; /* account info (ACB_xxxx bit-mask) */
time_t pass_last_set_time; /* password last set time */
};
@@ -61,12 +60,6 @@ struct smbpasswd_privates
/* retrive-once info */
const char *smbpasswd_file;
-
- BOOL permit_non_unix_accounts;
-
- uid_t low_nua_userid;
- uid_t high_nua_userid;
-
};
enum pwf_access_type { PWF_READ, PWF_UPDATE, PWF_CREATE };
@@ -591,28 +584,6 @@ static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, str
/* Ok - entry doesn't exist. We can add it */
- /* Account not in /etc/passwd hack!!! */
- if (!newpwd->smb_userid_set) {
- if (!smbpasswd_state->permit_non_unix_accounts) {
- DEBUG(0, ("add_smbfilepwd_entry: cannot add account %s without unix identity\n", newpwd->smb_name));
- endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
- return False;
- }
-
- if (max_found_uid < smbpasswd_state->low_nua_userid) {
- newpwd->smb_userid = smbpasswd_state->low_nua_userid;
- newpwd->smb_userid_set = True;
- } else if (max_found_uid >= smbpasswd_state->high_nua_userid) {
- DEBUG(0, ("add_smbfilepwd_entry: cannot add machine %s, no uids are free! \n", newpwd->smb_name));
- endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
- return False;
- } else {
- newpwd->smb_userid = max_found_uid + 1;
- newpwd->smb_userid_set = True;
- }
- }
-
-
/* Create a new smb passwd entry and set it to the given password. */
/*
* The add user write needs to be atomic - so get the fd from
@@ -1149,12 +1120,10 @@ static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampas
DEBUG(0, ("Could not find gest account via getpwnam()! (%s)\n", lp_guestaccount()));
return False;
}
- smb_pw->smb_userid_set = True;
smb_pw->smb_userid=passwd->pw_uid;
passwd_free(&passwd);
} else if (fallback_pdb_rid_is_user(rid)) {
- smb_pw->smb_userid_set = True;
smb_pw->smb_userid=fallback_pdb_user_rid_to_uid(rid);
} else {
DEBUG(0,("build_sam_pass: Failing attempt to store user with non-uid based user RID. \n"));
@@ -1170,25 +1139,6 @@ static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampas
smb_pw->acct_ctrl=pdb_get_acct_ctrl(sampass);
smb_pw->pass_last_set_time=pdb_get_pass_last_set_time(sampass);
-#if 0
- /*
- * ifdef'out by JFM on 11/29/2001.
- * this assertion is no longer valid
- * and I don't understand the goal
- * and doing the same thing with the group mapping code
- * is hairy !
- *
- * We just have the RID, in which SID is it valid ?
- * our domain SID ? well known SID ? local SID ?
- */
-
- if (gid != pdb_group_rid_to_gid(pdb_get_group_rid(sampass))) {
- DEBUG(0,("build_sam_pass: Failing attempt to store user with non-gid based primary group RID. \n"));
- DEBUG(0,("build_sam_pass: %d %d %d. \n", *gid, pdb_group_rid_to_gid(pdb_get_group_rid(sampass)), pdb_get_group_rid(sampass)));
- return False;
- }
-#endif
-
return True;
}
@@ -1204,49 +1154,28 @@ static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state,
DEBUG(5,("build_sam_account: SAM_ACCOUNT is NULL\n"));
return False;
}
-
- pwfile = getpwnam_alloc(pw_buf->smb_name);
- if (pwfile == NULL) {
- if ((smbpasswd_state->permit_non_unix_accounts)
- && (pw_buf->smb_userid >= smbpasswd_state->low_nua_userid)
- && (pw_buf->smb_userid <= smbpasswd_state->high_nua_userid)) {
- pdb_set_user_sid_from_rid(sam_pass, fallback_pdb_uid_to_user_rid (pw_buf->smb_userid), PDB_SET);
-
- /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here.
-
- This was down the bottom for machines, but it looks pretty good as
- a general default for non-unix users. --abartlet 2002-01-08
- */
- pdb_set_group_sid_from_rid (sam_pass, DOMAIN_GROUP_RID_USERS, PDB_SET);
- pdb_set_username (sam_pass, pw_buf->smb_name, PDB_SET);
- pdb_set_domain (sam_pass, get_global_sam_name(), PDB_DEFAULT);
+ /* verify the user account exists */
- } else {
- DEBUG(0,("build_sam_account: smbpasswd database is corrupt! username %s with uid %u is not in unix passwd database!\n", pw_buf->smb_name, pw_buf->smb_userid));
- return False;
- }
- } else {
- if (!NT_STATUS_IS_OK(pdb_fill_sam_pw(sam_pass, pwfile))) {
+ if ( !(pwfile = getpwnam_alloc(pw_buf->smb_name)) ) {
+ DEBUG(0,("build_sam_account: smbpasswd database is corrupt! username %s with uid "
+ "%u is not in unix passwd database!\n", pw_buf->smb_name, pw_buf->smb_userid));
return False;
- }
-
- passwd_free(&pwfile);
}
+ if (!NT_STATUS_IS_OK(pdb_fill_sam_pw(sam_pass, pwfile)))
+ return False;
+
+ passwd_free(&pwfile);
+
+ /* set remaining fields */
+
pdb_set_nt_passwd (sam_pass, pw_buf->smb_nt_passwd, PDB_SET);
pdb_set_lanman_passwd (sam_pass, pw_buf->smb_passwd, PDB_SET);
pdb_set_acct_ctrl (sam_pass, pw_buf->acct_ctrl, PDB_SET);
pdb_set_pass_last_set_time (sam_pass, pw_buf->pass_last_set_time, PDB_SET);
pdb_set_pass_can_change_time (sam_pass, pw_buf->pass_last_set_time, PDB_SET);
-#if 0 /* JERRY */
- /* the smbpasswd format doesn't have a must change time field, so
- we can't get this right. The best we can do is to set this to
- some time in the future. 21 days seems as reasonable as any other value :)
- */
- pdb_set_pass_must_change_time (sam_pass, pw_buf->pass_last_set_time + MAX_PASSWORD_AGE, PDB_DEFAULT);
-#endif
return True;
}
@@ -1558,11 +1487,6 @@ static NTSTATUS pdb_init_smbpasswd(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_m
(*pdb_method)->free_private_data = free_private_data;
- if (lp_idmap_uid(&privates->low_nua_userid, &privates->high_nua_userid)) {
- DEBUG(3, ("idmap uid range defined, non unix accounts enabled\n"));
- privates->permit_non_unix_accounts = True;
- }
-
return NT_STATUS_OK;
}
diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c
index a166697b4b..6f5d348ce1 100644
--- a/source3/passdb/pdb_tdb.c
+++ b/source3/passdb/pdb_tdb.c
@@ -1,11 +1,11 @@
/*
* Unix SMB/CIFS implementation.
* SMB parameters and setup
- * Copyright (C) Andrew Tridgell 1992-1998
- * Copyright (C) Simo Sorce 2000-2002
- * Copyright (C) Gerald Carter 2000
- * Copyright (C) Jeremy Allison 2001
- * Copyright (C) Andrew Bartlett 2002
+ * Copyright (C) Andrew Tridgell 1992-1998
+ * Copyright (C) Simo Sorce 2000-2002
+ * Copyright (C) Gerald Carter 2000
+ * Copyright (C) Jeremy Allison 2001
+ * Copyright (C) Andrew Bartlett 2002
*
* 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
@@ -48,13 +48,6 @@ struct tdbsam_privates {
/* retrive-once info */
const char *tdbsam_location;
-
- BOOL permit_non_unix_accounts;
-
- BOOL algorithmic_rids;
-
- uint32 low_nua_rid;
- uint32 high_nua_rid;
};
/***************************************************************
@@ -342,61 +335,31 @@ static BOOL tdb_update_sam(struct pdb_methods *my_methods, SAM_ACCOUNT* newpwd,
fstring name;
BOOL ret = True;
uint32 user_rid;
- BOOL tdb_ret;
/* invalidate the existing TDB iterator if it is open */
+
if (tdb_state->passwd_tdb) {
tdb_close(tdb_state->passwd_tdb);
tdb_state->passwd_tdb = NULL;
}
/* open the account TDB passwd*/
+
pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600);
- if (!pwd_tdb)
- {
- DEBUG(0, ("tdb_update_sam: Unable to open TDB passwd (%s)!\n", tdb_state->tdbsam_location));
+
+ if (!pwd_tdb) {
+ DEBUG(0, ("tdb_update_sam: Unable to open TDB passwd (%s)!\n",
+ tdb_state->tdbsam_location));
return False;
}
if (!pdb_get_group_rid(newpwd)) {
- DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a primary group RID\n",pdb_get_username(newpwd)));
+ DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a primary group RID\n",
+ pdb_get_username(newpwd)));
ret = False;
goto done;
}
- /* if flag == TDB_INSERT then make up a new RID else throw an error. */
- if (!(user_rid = pdb_get_user_rid(newpwd))) {
- if ((flag & TDB_INSERT) && tdb_state->permit_non_unix_accounts) {
- uint32 lowrid, highrid;
- if (!pdb_get_free_rid_range(&lowrid, &highrid)) {
- /* should never happen */
- DEBUG(0, ("tdbsam: something messed up, no high/low rids but nua enabled ?!\n"));
- ret = False;
- goto done;
- }
- user_rid = lowrid;
- tdb_ret = tdb_change_uint32_atomic(pwd_tdb, "RID_COUNTER", &user_rid, RID_MULTIPLIER);
- if (!tdb_ret) {
- ret = False;
- goto done;
- }
- if (user_rid > highrid) {
- DEBUG(0, ("tdbsam: no NUA rids available, cannot add user %s!\n", pdb_get_username(newpwd)));
- ret = False;
- goto done;
- }
- if (!pdb_set_user_sid_from_rid(newpwd, user_rid, PDB_CHANGED)) {
- DEBUG(0, ("tdbsam: not able to set new allocated user RID into sam account!\n"));
- ret = False;
- goto done;
- }
- } else {
- DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a RID\n",pdb_get_username(newpwd)));
- ret = False;
- goto done;
- }
- }
-
/* copy the SAM_ACCOUNT struct into a BYTE buffer for storage */
if ((data.dsize=init_buffer_from_sam (&buf, newpwd, False)) == -1) {
DEBUG(0,("tdb_update_sam: ERROR - Unable to copy SAM_ACCOUNT info BYTE buffer!\n"));
@@ -531,7 +494,6 @@ static NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_meth
{
NTSTATUS nt_status;
struct tdbsam_privates *tdb_state;
- uid_t low_nua_uid, high_nua_uid;
if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
return nt_status;
@@ -569,19 +531,6 @@ static NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_meth
(*pdb_method)->free_private_data = free_private_data;
- if (lp_idmap_uid(&low_nua_uid, &high_nua_uid)) {
- DEBUG(3, ("idmap uid range defined, non unix accounts enabled\n"));
-
- tdb_state->permit_non_unix_accounts = True;
-
- tdb_state->low_nua_rid=fallback_pdb_uid_to_user_rid(low_nua_uid);
-
- tdb_state->high_nua_rid=fallback_pdb_uid_to_user_rid(high_nua_uid);
-
- } else {
- tdb_state->algorithmic_rids = True;
- }
-
return NT_STATUS_OK;
}
diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c
index dfa3a8b62e..9324fd4765 100644
--- a/source3/rpc_server/srv_samr_nt.c
+++ b/source3/rpc_server/srv_samr_nt.c
@@ -2204,6 +2204,7 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_
uint32 acc_granted;
SEC_DESC *psd;
size_t sd_size;
+ uint32 new_rid = 0;
/* check this, when giving away 'add computer to domain' privs */
uint32 des_access = GENERIC_RIGHTS_USER_ALL_ACCESS;
@@ -2272,6 +2273,17 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_
pw = Get_Pwnam(account);
+ /*********************************************************************
+ * HEADS UP! If we have to create a new user account, we have to get
+ * a new RID from somewhere. This used to be done by the passdb
+ * backend. It has been moved into idmap now. Since idmap is now
+ * wrapped up behind winbind, this means you have to run winbindd if you
+ * want new accounts to get a new RID when "enable rid algorithm = no".
+ * Tough. We now have a uniform way of allocating RIDs regardless
+ * of what ever passdb backend people may use.
+ * --jerry (2003-07-10)
+ *********************************************************************/
+
if ( !pw ) {
/*
* we can't check both the ending $ and the acb_info.
@@ -2293,15 +2305,17 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_
}
else /* no add user script -- ask winbindd to do it */
{
- if ( !winbind_create_user( account ) )
- DEBUG(3,("_api_samr_create_user: winbind_create_user(%s) failed\n", account));
+ if ( !winbind_create_user( account, &new_rid ) ) {
+ DEBUG(3,("_api_samr_create_user: winbind_create_user(%s) failed\n",
+ account));
+ }
}
}
- /* implicit call to getpwnam() next */
+ /* implicit call to getpwnam() next. we have a valid SID coming out of this call */
- if ( !NT_STATUS_IS_OK(nt_status = pdb_init_sam_new(&sam_pass, account)) )
+ if ( !NT_STATUS_IS_OK(nt_status = pdb_init_sam_new(&sam_pass, account, new_rid)) )
return nt_status;
pdb_set_acct_ctrl(sam_pass, acb_info, PDB_CHANGED);
@@ -3711,12 +3725,25 @@ static int smb_delete_user(const char *unix_user)
pstring del_script;
int ret;
+ /* try winbindd first since it is impossible to determine where
+ a user came from via NSS. Try the delete user script if this fails
+ meaning the user did not exist in winbindd's list of accounts */
+
+ if ( winbind_delete_user( unix_user ) ) {
+ DEBUG(3,("winbind_delete_user: removed user (%s)\n", unix_user));
+ return 0;
+ }
+
+
+ /* fall back to 'delete user script' */
+
pstrcpy(del_script, lp_deluser_script());
if (! *del_script)
return -1;
all_string_sub(del_script, "%u", unix_user, sizeof(pstring));
ret = smbrun(del_script,NULL);
DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
+
return ret;
}
diff --git a/source3/sam/idmap.c b/source3/sam/idmap.c
index 1db89eba24..7a8f270e15 100644
--- a/source3/sam/idmap.c
+++ b/source3/sam/idmap.c
@@ -252,7 +252,7 @@ NTSTATUS idmap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
}
/**************************************************************************
- Get ID from SID. This can create a mapping for a SID to a POSIX id.
+ Alloocate a new UNIX uid/gid
**************************************************************************/
NTSTATUS idmap_allocate_id(unid_t *id, int id_type)
@@ -265,6 +265,19 @@ NTSTATUS idmap_allocate_id(unid_t *id, int id_type)
return cache_map->allocate_id( id, id_type );
}
+/**************************************************************************
+ Alloocate a new RID
+**************************************************************************/
+
+NTSTATUS idmap_allocate_rid(uint32 *rid, int type)
+{
+ /* we have to allocate from the authoritative backend */
+
+ if ( remote_map )
+ return remote_map->allocate_rid( rid, type );
+
+ return cache_map->allocate_rid( rid, type );
+}
/**************************************************************************
Shutdown maps.
diff --git a/source3/sam/idmap_ldap.c b/source3/sam/idmap_ldap.c
index 2901b1fc49..9a1ee039d0 100644
--- a/source3/sam/idmap_ldap.c
+++ b/source3/sam/idmap_ldap.c
@@ -42,7 +42,11 @@ struct ldap_idmap_state {
struct smbldap_state *smbldap_state;
TALLOC_CTX *mem_ctx;
- /* struct ldap_idmap_state *prev, *next; */
+ uint32 low_allocated_user_rid;
+ uint32 high_allocated_user_rid;
+ uint32 low_allocated_group_rid;
+ uint32 high_allocated_group_rid;
+
};
#define LDAP_MAX_ALLOC_ID 128 /* number tries while allocating
@@ -56,6 +60,282 @@ static NTSTATUS ldap_set_mapping_internals(const DOM_SID *sid, unid_t id, int id
static NTSTATUS ldap_idmap_close(void);
+/**********************************************************************
+ Even if the sambaDomain attribute in LDAP tells us that this RID is
+ safe to use, always check before use.
+*********************************************************************/
+
+static BOOL sid_in_use(struct ldap_idmap_state *state,
+ const DOM_SID *sid, int *error)
+{
+ fstring filter;
+ fstring sid_string;
+ LDAPMessage *result = NULL;
+ int count;
+ int rc;
+ char *sid_attr[] = {LDAP_ATTRIBUTE_SID, NULL};
+
+ slprintf(filter, sizeof(filter)-1, "(%s=%s)", LDAP_ATTRIBUTE_SID, sid_to_string(sid_string, sid));
+
+ rc = smbldap_search_suffix(state->smbldap_state,
+ filter, sid_attr, &result);
+
+ if (rc != LDAP_SUCCESS) {
+ char *ld_error = NULL;
+ ldap_get_option(state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
+ DEBUG(2, ("Failed to check if sid %s is alredy in use: %s\n",
+ sid_string, ld_error));
+ SAFE_FREE(ld_error);
+
+ *error = rc;
+ return True;
+ }
+
+ if ((count = ldap_count_entries(state->smbldap_state->ldap_struct, result)) > 0) {
+ DEBUG(3, ("Sid %s already in use - trying next RID\n",
+ sid_string));
+ ldap_msgfree(result);
+ return True;
+ }
+
+ ldap_msgfree(result);
+
+ /* good, sid is not in use */
+ return False;
+}
+
+/**********************************************************************
+ Set the new nextRid attribute, and return one we can use.
+
+ This also checks that this RID is actually free - in case the admin
+ manually stole it :-).
+*********************************************************************/
+static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid,
+ int rid_type)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ int rc;
+ LDAPMessage *domain_result = NULL;
+ LDAPMessage *entry = NULL;
+ char *dn;
+ LDAPMod **mods = NULL;
+ fstring old_rid_string;
+ fstring next_rid_string;
+ fstring algorithmic_rid_base_string;
+ uint32 next_rid;
+ uint32 alg_rid_base;
+ int attempts = 0;
+ char *ld_error = NULL;
+
+ while (attempts < 10)
+ {
+ if (!NT_STATUS_IS_OK(ret = smbldap_search_domain_info(state->smbldap_state,
+ &domain_result, get_global_sam_name(), True)))
+ {
+ return ret;
+ }
+
+ entry = ldap_first_entry(state->smbldap_state->ldap_struct, domain_result);
+ if (!entry) {
+ DEBUG(0, ("Could not get domain info entry\n"));
+ ldap_msgfree(domain_result);
+ return ret;
+ }
+
+ if ((dn = ldap_get_dn(state->smbldap_state->ldap_struct, entry)) == NULL) {
+ DEBUG(0, ("Could not get domain info DN\n"));
+ ldap_msgfree(domain_result);
+ return ret;
+ }
+
+ /* yes, we keep 3 seperate counters, one for rids between 1000 (BASE_RID) and
+ algorithmic_rid_base. The other two are to avoid stomping on the
+ different sets of algorithmic RIDs */
+
+ if (smbldap_get_single_attribute(state->smbldap_state->ldap_struct, entry,
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE),
+ algorithmic_rid_base_string))
+ {
+
+ alg_rid_base = (uint32)atol(algorithmic_rid_base_string);
+ } else {
+ alg_rid_base = algorithmic_rid_base();
+ /* Try to make the modification atomically by enforcing the
+ old value in the delete mod. */
+ slprintf(algorithmic_rid_base_string, sizeof(algorithmic_rid_base_string)-1, "%d", alg_rid_base);
+ smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods,
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE),
+ algorithmic_rid_base_string);
+ }
+
+ next_rid = 0;
+
+ if (alg_rid_base > BASE_RID) {
+ /* we have a non-default 'algorithmic rid base', so we have 'low' rids that we
+ can allocate to new users */
+ if (smbldap_get_single_attribute(state->smbldap_state->ldap_struct, entry,
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_RID),
+ old_rid_string))
+ {
+ *rid = (uint32)atol(old_rid_string);
+ } else {
+ *rid = BASE_RID;
+ }
+
+ next_rid = *rid+1;
+ if (next_rid >= alg_rid_base) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_rid);
+
+ /* Try to make the modification atomically by enforcing the
+ old value in the delete mod. */
+ smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods,
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_RID),
+ next_rid_string);
+ }
+
+ if (!next_rid) { /* not got one already */
+ switch (rid_type) {
+ case USER_RID_TYPE:
+ if (smbldap_get_single_attribute(state->smbldap_state->ldap_struct, entry,
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID),
+ old_rid_string))
+ {
+
+ *rid = (uint32)atol(old_rid_string);
+
+ } else {
+ *rid = state->low_allocated_user_rid;
+ }
+ break;
+ case GROUP_RID_TYPE:
+ if (smbldap_get_single_attribute(state->smbldap_state->ldap_struct, entry,
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID),
+ old_rid_string))
+ {
+ *rid = (uint32)atol(old_rid_string);
+ } else {
+ *rid = state->low_allocated_group_rid;
+ }
+ break;
+ }
+
+ /* This is the core of the whole routine. If we had
+ scheme-style closures, there would be a *lot* less code
+ duplication... */
+
+ next_rid = *rid+RID_MULTIPLIER;
+ slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_rid);
+
+ switch (rid_type) {
+ case USER_RID_TYPE:
+ if (next_rid > state->high_allocated_user_rid) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* Try to make the modification atomically by enforcing the
+ old value in the delete mod. */
+ smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods,
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID),
+ next_rid_string);
+ break;
+
+ case GROUP_RID_TYPE:
+ if (next_rid > state->high_allocated_group_rid) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* Try to make the modification atomically by enforcing the
+ old value in the delete mod. */
+ smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods,
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID),
+ next_rid_string);
+ break;
+ }
+ }
+
+ if ((rc = ldap_modify_s(state->smbldap_state->ldap_struct, dn, mods)) == LDAP_SUCCESS) {
+ DOM_SID dom_sid;
+ DOM_SID sid;
+ pstring domain_sid_string;
+ int error = 0;
+
+ if (!smbldap_get_single_attribute(state->smbldap_state->ldap_struct, domain_result,
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID),
+ domain_sid_string))
+ {
+ ldap_mods_free(mods, True);
+ ldap_memfree(dn);
+ ldap_msgfree(domain_result);
+ return ret;
+ }
+
+ if (!string_to_sid(&dom_sid, domain_sid_string)) {
+ ldap_mods_free(mods, True);
+ ldap_memfree(dn);
+ ldap_msgfree(domain_result);
+ return ret;
+ }
+
+ ldap_mods_free(mods, True);
+ mods = NULL;
+ ldap_memfree(dn);
+ ldap_msgfree(domain_result);
+
+ sid_copy(&sid, &dom_sid);
+ sid_append_rid(&sid, *rid);
+
+ /* check RID is not in use */
+ if (sid_in_use(state, &sid, &error)) {
+ if (error) {
+ return ret;
+ }
+ continue;
+ }
+
+ return NT_STATUS_OK;
+ }
+
+ ld_error = NULL;
+ ldap_get_option(state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
+ DEBUG(2, ("Failed to modify rid: %s\n", ld_error ? ld_error : "(NULL"));
+ SAFE_FREE(ld_error);
+
+ ldap_mods_free(mods, True);
+ mods = NULL;
+
+ ldap_memfree(dn);
+ dn = NULL;
+
+ ldap_msgfree(domain_result);
+ domain_result = NULL;
+
+ {
+ /* Sleep for a random timeout */
+ unsigned sleeptime = (sys_random()*sys_getpid()*attempts);
+ attempts += 1;
+
+ sleeptime %= 100;
+ msleep(sleeptime);
+ }
+ }
+
+ DEBUG(0, ("Failed to set new RID\n"));
+ return ret;
+}
+
+
+/*****************************************************************************
+ Allocate a new RID
+*****************************************************************************/
+
+static NTSTATUS ldap_allocate_rid(uint32 *rid, int rid_type)
+{
+ return ldap_next_rid( &ldap_state, rid, rid_type );
+}
+
/*****************************************************************************
Allocate a new uid or gid
*****************************************************************************/
@@ -675,6 +955,7 @@ static void ldap_idmap_status(void)
static struct idmap_methods ldap_methods = {
ldap_idmap_init,
+ ldap_allocate_rid,
ldap_allocate_id,
ldap_get_sid_from_id,
ldap_get_id_from_sid,
diff --git a/source3/sam/idmap_tdb.c b/source3/sam/idmap_tdb.c
index 4643b7db59..7f8dce1f1a 100644
--- a/source3/sam/idmap_tdb.c
+++ b/source3/sam/idmap_tdb.c
@@ -59,7 +59,45 @@ TDB_CONTEXT *idmap_tdb_handle( void )
return NULL;
}
-/* Allocate either a user or group id from the pool */
+/**********************************************************************
+ allocate a new RID; We don't care if is a user or group
+**********************************************************************/
+
+static NTSTATUS db_allocate_rid(uint32 *rid, int rid_type)
+{
+ uint32 lowrid, highrid;
+ uint32 tmp_rid;
+
+ /* can't handle group rids right now. This is such a mess.... */
+
+ if ( rid_type == GROUP_RID_TYPE )
+ return NT_STATUS_UNSUCCESSFUL;
+
+ /* cannot fail since idmap is only called winbindd */
+
+ idmap_get_free_rid_range( &lowrid, &highrid );
+
+ tmp_rid = lowrid;
+
+ if ( !tdb_change_uint32_atomic(idmap_tdb, "RID_COUNTER", &tmp_rid, RID_MULTIPLIER) ) {
+ DEBUG(3,("db_allocate_rid: Failed to locate next rid record in idmap db\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ if ( tmp_rid > highrid ) {
+ DEBUG(0, ("db_allocate_rid: no RIDs available!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ *rid = tmp_rid;
+
+ return NT_STATUS_OK;
+}
+
+/**********************************************************************
+ Allocate either a user or group id from the pool
+**********************************************************************/
+
static NTSTATUS db_allocate_id(unid_t *id, int id_type)
{
BOOL ret;
@@ -609,6 +647,7 @@ static void db_idmap_status(void)
static struct idmap_methods db_methods = {
db_idmap_init,
+ db_allocate_rid,
db_allocate_id,
db_get_sid_from_id,
db_get_id_from_sid,
diff --git a/source3/sam/idmap_util.c b/source3/sam/idmap_util.c
index 94de30a5ce..f767cc898c 100644
--- a/source3/sam/idmap_util.c
+++ b/source3/sam/idmap_util.c
@@ -22,6 +22,120 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_IDMAP
+/**********************************************************************
+**********************************************************************/
+
+BOOL idmap_get_free_ugid_range(uint32 *low, uint32 *high)
+{
+ uid_t u_low, u_high;
+ gid_t g_low, g_high;
+
+ if (!lp_idmap_uid(&u_low, &u_high) || !lp_idmap_gid(&g_low, &g_high)) {
+ return False;
+ }
+
+ *low = (u_low < g_low) ? u_low : g_low;
+ *high = (u_high < g_high) ? u_high : g_high;
+
+ return True;
+}
+
+/******************************************************************
+ Get the the non-algorithmic RID range if idmap range are defined
+******************************************************************/
+
+BOOL idmap_get_free_rid_range(uint32 *low, uint32 *high)
+{
+ uint32 id_low, id_high;
+
+ if (!lp_enable_rid_algorithm()) {
+ *low = BASE_RID;
+ *high = (uint32)-1;
+ }
+
+ if (!idmap_get_free_ugid_range(&id_low, &id_high)) {
+ return False;
+ }
+
+ *low = fallback_pdb_uid_to_user_rid(id_low);
+ if (fallback_pdb_user_rid_to_uid((uint32)-1) < id_high) {
+ *high = (uint32)-1;
+ } else {
+ *high = fallback_pdb_uid_to_user_rid(id_high);
+ }
+
+ return True;
+}
+
+/**********************************************************************
+ Get the free RID base if idmap is configured, otherwise return 0
+**********************************************************************/
+
+uint32 idmap_get_free_rid_base(void)
+{
+ uint32 low, high;
+ if (idmap_get_free_rid_range(&low, &high)) {
+ return low;
+ }
+ return 0;
+}
+
+/**********************************************************************
+**********************************************************************/
+
+BOOL idmap_check_ugid_is_in_free_range(uint32 id)
+{
+ uint32 low, high;
+
+ if (!idmap_get_free_ugid_range(&low, &high)) {
+ return False;
+ }
+ if (id < low || id > high) {
+ return False;
+ }
+ return True;
+}
+
+/**********************************************************************
+**********************************************************************/
+
+BOOL idmap_check_rid_is_in_free_range(uint32 rid)
+{
+ uint32 low, high;
+
+ if (!idmap_get_free_rid_range(&low, &high)) {
+ return False;
+ }
+ if (rid < algorithmic_rid_base()) {
+ return True;
+ }
+
+ if (rid < low || rid > high) {
+ return False;
+ }
+
+ return True;
+}
+
+/**********************************************************************
+ if it is a foreign SID or if the SID is in the free range, return true
+**********************************************************************/
+
+BOOL idmap_check_sid_is_in_free_range(const DOM_SID *sid)
+{
+ if (sid_compare_domain(get_global_sam_sid(), sid) == 0) {
+
+ uint32 rid;
+
+ if (sid_peek_rid(sid, &rid)) {
+ return idmap_check_rid_is_in_free_range(rid);
+ }
+
+ return False;
+ }
+
+ return True;
+}
/*****************************************************************
Returns SID pointer.
diff --git a/source3/utils/net_rpc_samsync.c b/source3/utils/net_rpc_samsync.c
index 4b31c061f3..31535f7945 100644
--- a/source3/utils/net_rpc_samsync.c
+++ b/source3/utils/net_rpc_samsync.c
@@ -444,7 +444,9 @@ fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta)
}
else {
DEBUG(8,("fetch_account_info: no add user/machine script. Asking winbindd\n"));
- if ( !winbind_create_user( account ) )
+
+ /* don't need a RID allocated since the user already has a SID */
+ if ( !winbind_create_user( account, NULL ) )
DEBUG(4,("fetch_account_info: winbind_create_user() failed\n"));
}
diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c
index b79972aa35..96d0d3c057 100644
--- a/source3/utils/pdbedit.c
+++ b/source3/utils/pdbedit.c
@@ -350,7 +350,7 @@ static int new_user (struct pdb_context *in, const char *username,
NTSTATUS nt_status;
char *password1, *password2, *staticpass;
- if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_new(&sam_pwent, username))) {
+ if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_new(&sam_pwent, username, 0))) {
DEBUG(0, ("could not create account to add new user %s\n", username));
return -1;
}