diff options
author | Jeremy Allison <jra@samba.org> | 2000-08-02 02:11:55 +0000 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2000-08-02 02:11:55 +0000 |
commit | 17dcd9a834fc915fb1ff2d8042a23000eeb7acfa (patch) | |
tree | 18a9a8cfa2883baf163da29265fd08b8a3b81c9f /source3/smbd | |
parent | 7f36df301e28dc8ca0e5bfadc109d6e907d9ba2b (diff) | |
download | samba-17dcd9a834fc915fb1ff2d8042a23000eeb7acfa.tar.gz samba-17dcd9a834fc915fb1ff2d8042a23000eeb7acfa.tar.bz2 samba-17dcd9a834fc915fb1ff2d8042a23000eeb7acfa.zip |
Started to canonicalize our handling of uid -> sid code in order to
get ready and fix se_access_check().
Added cannonical lookup_name(), lookup_sid(), uid_to_sid(), gid_to_sid()
functions that look via winbind first the fall back on local lookup.
All Samba should use these rather than trying to call winbindd code
directly.
Added NT_USER_TOKEN struct in user_struct, contains list of NT sids
associated with this user.
se_access_check() should use this (cached) value rather than attempting
to do the same thing itself when given a uid/gid pair.
More work needs to be done to preserve these things accross security
context changes (especially with the tricky pipe problem) but I'm
beginning to see how this will be done..... probably by registering
a new vuid for an authenticated RPC pipe and not treating the
pipe calls specially.
More thoughts needed - but we're almost there...
Jeremy.
(This used to be commit 5e5cc6efe2e4687be59085f562caea1e2e05d0a8)
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/password.c | 113 | ||||
-rw-r--r-- | source3/smbd/process.c | 3 | ||||
-rw-r--r-- | source3/smbd/sec_ctx.c | 34 | ||||
-rw-r--r-- | source3/smbd/service.c | 4 | ||||
-rw-r--r-- | source3/smbd/uid.c | 23 | ||||
-rw-r--r-- | source3/smbd/unix_acls.c | 8 |
6 files changed, 91 insertions, 94 deletions
diff --git a/source3/smbd/password.c b/source3/smbd/password.c index f9291b8705..0372e7a0f9 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -113,6 +113,16 @@ user_struct *get_valid_user_struct(uint16 vuid) } /**************************************************************************** + Delete the SID list for this user. +****************************************************************************/ + +static void delete_nt_token(NT_USER_TOKEN *token) +{ + safe_free( token->user_sids ); + ZERO_STRUCTP(token); +} + +/**************************************************************************** invalidate a uid ****************************************************************************/ void invalidate_vuid(uint16 vuid) @@ -133,8 +143,7 @@ void invalidate_vuid(uint16 vuid) vuser->groups = NULL; - if (vuser->group_sids != NULL) - free (vuser->group_sids); + delete_nt_token(&vuser->nt_user_token); } @@ -162,61 +171,54 @@ char *validated_domain(uint16 vuid) /**************************************************************************** -Setup the groups a user belongs to. + Initialize the groups a user belongs to. ****************************************************************************/ -int setup_groups(char *user, char *domain, - uid_t uid, gid_t gid, int *p_ngroups, gid_t **p_groups) -{ - int i,ngroups; - gid_t grp = 0; - gid_t *groups = NULL; - if (-1 == initgroups(user,gid)) - { +int initialize_groups(char *user, uid_t uid, gid_t gid) +{ + if (initgroups(user,gid) == -1) { DEBUG(0,("Unable to initgroups. Error was %s\n", strerror(errno) )); - if (getuid() == 0) - { - if (gid < 0 || gid > 32767 || uid < 0 || uid > 32767) - { + if (getuid() == 0) { + if (gid < 0 || gid > 32767 || uid < 0 || uid > 32767) { DEBUG(0,("This is probably a problem with the account %s\n", user)); } } return -1; } + return 0; +} - ngroups = sys_getgroups(0,&grp); - if (ngroups <= 0) - { - ngroups = groups_max(); - } +/**************************************************************************** + Create the SID list for this user. +****************************************************************************/ - if((groups = (gid_t *)malloc(sizeof(gid_t)*ngroups)) == NULL) - { - DEBUG(0,("setup_groups malloc fail !\n")); - return -1; - } +void setup_nt_token(NT_USER_TOKEN *token, uid_t uid, gid_t gid, int ngroups, gid_t *groups) +{ + DOM_SID *psids; + int i; - ngroups = sys_getgroups(ngroups,groups); + ZERO_STRUCTP(token); - (*p_ngroups) = ngroups; - (*p_groups) = groups; + if ((token->user_sids = (DOM_SID *)malloc( (ngroups + 2)*sizeof(DOM_SID))) == NULL) + return; - DEBUG( 3, ( "%s is in %d groups: ", user, ngroups ) ); - for (i = 0; i < ngroups; i++ ) - { - DEBUG( 3, ( "%s%d", (i ? ", " : ""), (int)groups[i] ) ); - } - DEBUG( 3, ( "\n" ) ); + psids = token->user_sids; - return 0; -} + token->num_sids = ngroups + 2; + + uid_to_sid( &psids[0], uid); + gid_to_sid( &psids[1], gid); + for (i = 0; i < ngroups; i++) + gid_to_sid( &psids[i+2], groups[i]); +} /**************************************************************************** register a uid/name pair as being valid and that a valid password has been given. vuid is biased by an offset. This allows us to tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ + uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, char *domain,BOOL guest) { @@ -227,37 +229,15 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, if(lp_security() == SEC_SHARE) return UID_FIELD_INVALID; -#if 0 - /* - * After observing MS-Exchange services writing to a Samba share - * I belive this code is incorrect. Each service does its own - * sessionsetup_and_X for the same user, and as each service shuts - * down, it does a user_logoff_and_X. As we are consolidating multiple - * sessionsetup_and_X's onto the same vuid here, when the first service - * shuts down, it invalidates all the open files for the other services. - * Hence I am removing this code and forcing each sessionsetup_and_X - * to get a new vuid. - * Jeremy Allison. (jallison@whistle.com). - */ - - int i; - for(i = 0; i < num_validated_users; i++) { - vuser = &validated_users[i]; - if ( vuser->uid == uid ) - return (uint16)(i + VUID_OFFSET); /* User already validated */ - } -#endif - validated_users = (user_struct *)Realloc(validated_users, sizeof(user_struct)* (num_validated_users+1)); - if (!validated_users) - { + if (!validated_users) { DEBUG(0,("Failed to realloc users struct!\n")); num_validated_users = 0; return UID_FIELD_INVALID; - } + } vuser = &validated_users[num_validated_users]; num_validated_users++; @@ -274,22 +254,21 @@ uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, /* Find all the groups this uid is in and store them. Used by become_user() */ - setup_groups(unix_name,domain,uid,gid, - &vuser->n_groups, - &vuser->groups); + initialize_groups(unix_name, uid, gid); + get_current_groups( &vuser->n_groups, &vuser->groups); - setup_user_sids(vuser); + /* Create an NT_USER_TOKEN struct for this user. */ + setup_nt_token(&vuser->nt_user_token, uid,gid, vuser->n_groups, vuser->groups); DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name)); DEBUG(3, ("Clearing default real name\n")); fstrcpy(vuser->user.full_name, "<Full Name>"); if (lp_unix_realname()) { - if ((pwfile=sys_getpwnam(vuser->user.unix_name))!= NULL) - { + if ((pwfile=sys_getpwnam(vuser->user.unix_name))!= NULL) { DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,pwfile->pw_gecos)); fstrcpy(vuser->user.full_name, pwfile->pw_gecos); - } + } } memset(&vuser->dc, '\0', sizeof(vuser->dc)); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 2662db5896..37d8f8dd73 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -561,8 +561,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize } /* load service specific parameters */ - if (conn && - !become_service(conn,(flags & AS_USER)?True:False)) { + if (conn && !become_service(conn,(flags & AS_USER)?True:False)) { return(ERROR(ERRSRV,ERRaccess)); } diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index f7ea1e2d86..432cb223e2 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -125,17 +125,37 @@ static void gain_root(void) /* Get the list of current groups */ -static void get_current_groups(int *ngroups, gid_t **groups) +int get_current_groups(int *p_ngroups, gid_t **p_groups) { - *ngroups = getgroups(0, NULL); - *groups = (gid_t *)malloc(*ngroups * sizeof(gid_t)); + int i; + gid_t grp; + int ngroups = sys_getgroups(0,&grp); + gid_t *groups; + + (*p_ngroups) = 0; + (*p_groups) = NULL; + + if (ngroups <= 0) + return -1; + + if((groups = (gid_t *)malloc(sizeof(gid_t)*ngroups)) == NULL) { + DEBUG(0,("setup_groups malloc fail !\n")); + return -1; + } + + if ((ngroups = sys_getgroups(ngroups,groups)) == -1) + return -1; + + (*p_ngroups) = ngroups; + (*p_groups) = groups; - if (!groups) { - DEBUG(0, ("Out of memory in get_current_groups\n")); - return; + DEBUG( 3, ( "get_current_groups: uid %u is in %u groups: ", (unsigned int)getuid() , ngroups ) ); + for (i = 0; i < ngroups; i++ ) { + DEBUG( 3, ( "%s%d", (i ? ", " : ""), (int)groups[i] ) ); } + DEBUG( 3, ( "\n" ) ); - getgroups(*ngroups, *groups); + return ngroups; } /* Create a new security context on the stack. It is the same as the old diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 2eab50c482..d4760ca92d 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -511,8 +511,8 @@ connection_struct *make_connection(char *service,char *user,char *password, int if (!IS_IPC(conn)) { /* Find all the groups this uid is in and store them. Used by become_user() */ - setup_groups(conn->user,validated_domain(vuid),conn->uid,conn->gid, - &conn->ngroups,&conn->groups); + initialize_groups(conn->user, conn->uid, conn->gid); + get_current_groups(&conn->ngroups,&conn->groups); /* check number of connections */ if (!claim_connection(conn, diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 172e872020..4cb2c512b6 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -38,7 +38,8 @@ BOOL become_guest(void) if (!pass) pass = Get_Pwnam(lp_guestaccount(-1),True); - if (!pass) return(False); + if (!pass) + return(False); #ifdef AIX /* MWW: From AIX FAQ patch to WU-ftpd: call initgroups before @@ -60,19 +61,21 @@ BOOL become_guest(void) static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum) { - int i; - for (i=0;i<conn->uid_cache.entries;i++) - if (conn->uid_cache.list[i] == vuser->uid) return(True); + int i; + for (i=0;i<conn->uid_cache.entries;i++) + if (conn->uid_cache.list[i] == vuser->uid) + return(True); - if (!user_ok(vuser->user.unix_name,snum)) return(False); + if (!user_ok(vuser->user.unix_name,snum)) + return(False); - i = conn->uid_cache.entries % UID_CACHE_SIZE; - conn->uid_cache.list[i] = vuser->uid; + i = conn->uid_cache.entries % UID_CACHE_SIZE; + conn->uid_cache.list[i] = vuser->uid; - if (conn->uid_cache.entries < UID_CACHE_SIZE) - conn->uid_cache.entries++; + if (conn->uid_cache.entries < UID_CACHE_SIZE) + conn->uid_cache.entries++; - return(True); + return(True); } /**************************************************************************** diff --git a/source3/smbd/unix_acls.c b/source3/smbd/unix_acls.c index 7a2dc6ab6e..46c57af5de 100644 --- a/source3/smbd/unix_acls.c +++ b/source3/smbd/unix_acls.c @@ -28,12 +28,8 @@ static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SID *pgroup_sid) { - extern DOM_SID global_sam_sid; - - sid_copy(powner_sid, &global_sam_sid); - sid_copy(pgroup_sid, &global_sam_sid); - sid_append_rid(powner_sid, pdb_uid_to_user_rid(psbuf->st_uid)); - sid_append_rid(pgroup_sid, pdb_gid_to_group_rid(psbuf->st_gid)); + uid_to_sid( powner_sid, psbuf->st_uid ); + gid_to_sid( pgroup_sid, psbuf->st_gid ); } /**************************************************************************** |