summaryrefslogtreecommitdiff
path: root/source3/smbd/password.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2007-08-21 01:43:22 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:30:08 -0500
commit57e2718e097bba57c96632064956f6ce048d8f28 (patch)
tree87afa5d9f5602334409b989cf122529a58fc0b20 /source3/smbd/password.c
parentb0b080799c542d1314870dcbfebd8e84d8002392 (diff)
downloadsamba-57e2718e097bba57c96632064956f6ce048d8f28.tar.gz
samba-57e2718e097bba57c96632064956f6ce048d8f28.tar.bz2
samba-57e2718e097bba57c96632064956f6ce048d8f28.zip
r24589: Refactor our vuid code so that we keep the same
vuid that was allocated whilst the connection is being constructed and after the connection has been set up. This is what Windows does and at least one client (and HP printer) depends on this behaviour. As it depends on the req struct not yet ported to SAMBA_3_2_0 (Volker, hint hint.... :-) I am not yet adding this to that branch, but will investigate that tomorrow. Jeremy. (This used to be commit a54f2805df92c67e74a6764568eedebe394fd500)
Diffstat (limited to 'source3/smbd/password.c')
-rw-r--r--source3/smbd/password.c297
1 files changed, 165 insertions, 132 deletions
diff --git a/source3/smbd/password.c b/source3/smbd/password.c
index 1a7dc33c61..847b8db082 100644
--- a/source3/smbd/password.c
+++ b/source3/smbd/password.c
@@ -30,13 +30,12 @@ static user_struct *validated_users;
static int next_vuid = VUID_OFFSET;
static int num_validated_vuids;
-/****************************************************************************
- Check if a uid has been validated, and return an pointer to the user_struct
- if it has. NULL if not. vuid is biased by an offset. This allows us to
- tell random client vuid's (normally zero) from valid vuids.
-****************************************************************************/
+enum server_allocated_state { SERVER_ALLOCATED_REQUIRED_YES,
+ SERVER_ALLOCATED_REQUIRED_NO,
+ SERVER_ALLOCATED_REQUIRED_ANY};
-user_struct *get_valid_user_struct(uint16 vuid)
+static user_struct *get_valid_user_struct_internal(uint16 vuid,
+ enum server_allocated_state server_allocated)
{
user_struct *usp;
int count=0;
@@ -45,7 +44,20 @@ user_struct *get_valid_user_struct(uint16 vuid)
return NULL;
for (usp=validated_users;usp;usp=usp->next,count++) {
- if (vuid == usp->vuid && usp->server_info) {
+ if (vuid == usp->vuid) {
+ switch (server_allocated) {
+ case SERVER_ALLOCATED_REQUIRED_YES:
+ if (usp->server_info == NULL) {
+ continue;
+ }
+ break;
+ case SERVER_ALLOCATED_REQUIRED_NO:
+ if (usp->server_info != NULL) {
+ continue;
+ }
+ case SERVER_ALLOCATED_REQUIRED_ANY:
+ break;
+ }
if (count > 10) {
DLIST_PROMOTE(validated_users, usp);
}
@@ -57,27 +69,33 @@ user_struct *get_valid_user_struct(uint16 vuid)
}
/****************************************************************************
- Get the user struct of a partial NTLMSSP login
+ Check if a uid has been validated, and return an pointer to the user_struct
+ if it has. NULL if not. vuid is biased by an offset. This allows us to
+ tell random client vuid's (normally zero) from valid vuids.
****************************************************************************/
-user_struct *get_partial_auth_user_struct(uint16 vuid)
+user_struct *get_valid_user_struct(uint16 vuid)
{
- user_struct *usp;
- int count=0;
-
- if (vuid == UID_FIELD_INVALID)
- return NULL;
+ return get_valid_user_struct_internal(vuid, SERVER_ALLOCATED_REQUIRED_YES);
+}
- for (usp=validated_users;usp;usp=usp->next,count++) {
- if (vuid == usp->vuid && !usp->server_info) {
- if (count > 10) {
- DLIST_PROMOTE(validated_users, usp);
- }
- return usp;
- }
+BOOL is_partial_auth_vuid(uint16 vuid)
+{
+ if (vuid == UID_FIELD_INVALID) {
+ return False;
}
+ return get_valid_user_struct_internal(vuid,
+ SERVER_ALLOCATED_REQUIRED_NO) ? True : False;
+}
- return NULL;
+/****************************************************************************
+ Get the user struct of a partial NTLMSSP login
+****************************************************************************/
+
+user_struct *get_partial_auth_user_struct(uint16 vuid)
+{
+ return get_valid_user_struct_internal(vuid,
+ SERVER_ALLOCATED_REQUIRED_NO);
}
/****************************************************************************
@@ -86,11 +104,18 @@ user_struct *get_partial_auth_user_struct(uint16 vuid)
void invalidate_vuid(uint16 vuid)
{
- user_struct *vuser = get_valid_user_struct(vuid);
+ user_struct *vuser = NULL;
- if (vuser == NULL)
+ if (vuid == UID_FIELD_INVALID) {
return;
-
+ }
+
+ vuser = get_valid_user_struct_internal(vuid,
+ SERVER_ALLOCATED_REQUIRED_ANY);
+ if (vuser == NULL) {
+ return;
+ }
+
session_yield(vuser);
data_blob_free(&vuser->session_key);
@@ -115,116 +140,127 @@ void invalidate_all_vuids(void)
for (usp=validated_users;usp;usp=next) {
next = usp->next;
-
invalidate_vuid(usp->vuid);
}
}
-/**
- * register that a valid login has been performed, establish 'session'.
- * @param server_info The token returned from the authentication process.
- * (now 'owned' by register_vuid)
- *
- * @param session_key The User session key for the login session (now also
- * 'owned' by register_vuid)
- *
- * @param respose_blob The NT challenge-response, if available. (May be
- * freed after this call)
- *
- * @param smb_name The untranslated name of the user
- *
- * @return Newly allocated vuid, biased by an offset. (This allows us to
- * tell random client vuid's (normally zero) from valid vuids.)
- *
- */
+/****************************************************
+ Create a new partial auth user struct.
+*****************************************************/
-int register_vuid(auth_serversupplied_info *server_info,
- DATA_BLOB session_key, DATA_BLOB response_blob,
- const char *smb_name)
+int register_initial_vuid(void)
{
user_struct *vuser;
/* Paranoia check. */
if(lp_security() == SEC_SHARE) {
- smb_panic("Tried to register uid in security=share");
+ smb_panic("register_initial_vuid: "
+ "Tried to register uid in security=share");
}
/* Limit allowed vuids to 16bits - VUID_OFFSET. */
if (num_validated_vuids >= 0xFFFF-VUID_OFFSET) {
- data_blob_free(&session_key);
return UID_FIELD_INVALID;
}
- if((vuser = TALLOC_ZERO_P(NULL, user_struct)) == NULL) {
- DEBUG(0,("Failed to talloc users struct!\n"));
- data_blob_free(&session_key);
+ if((vuser = talloc_zero(NULL, user_struct)) == NULL) {
+ DEBUG(0,("register_initial_vuid: "
+ "Failed to talloc users struct!\n"));
return UID_FIELD_INVALID;
}
- /* Allocate a free vuid. Yes this is a linear search... :-) */
- while( get_valid_user_struct(next_vuid) != NULL ) {
+ /* Allocate a free vuid. Yes this is a linear search... */
+ while( get_valid_user_struct_internal(next_vuid,
+ SERVER_ALLOCATED_REQUIRED_ANY) != NULL ) {
next_vuid++;
/* Check for vuid wrap. */
- if (next_vuid == UID_FIELD_INVALID)
+ if (next_vuid == UID_FIELD_INVALID) {
next_vuid = VUID_OFFSET;
+ }
}
- DEBUG(10,("register_vuid: allocated vuid = %u\n",
- (unsigned int)next_vuid ));
+ DEBUG(10,("register_initial_vuid: allocated vuid = %u\n",
+ (unsigned int)next_vuid ));
vuser->vuid = next_vuid;
- if (!server_info) {
- /*
- * This happens in an unfinished NTLMSSP session setup. We
- * need to allocate a vuid between the first and second calls
- * to NTLMSSP.
- */
- next_vuid++;
- num_validated_vuids++;
-
- vuser->server_info = NULL;
-
- DLIST_ADD(validated_users, vuser);
-
- return vuser->vuid;
+ /*
+ * This happens in an unfinished NTLMSSP session setup. We
+ * need to allocate a vuid between the first and second calls
+ * to NTLMSSP.
+ */
+ next_vuid++;
+ num_validated_vuids++;
+
+ DLIST_ADD(validated_users, vuser);
+ return vuser->vuid;
+}
+
+/**
+ * register that a valid login has been performed, establish 'session'.
+ * @param server_info The token returned from the authentication process.
+ * (now 'owned' by register_existing_vuid)
+ *
+ * @param session_key The User session key for the login session (now also
+ * 'owned' by register_existing_vuid)
+ *
+ * @param respose_blob The NT challenge-response, if available. (May be
+ * freed after this call)
+ *
+ * @param smb_name The untranslated name of the user
+ *
+ * @return Newly allocated vuid, biased by an offset. (This allows us to
+ * tell random client vuid's (normally zero) from valid vuids.)
+ *
+ */
+
+int register_existing_vuid(uint16 vuid,
+ auth_serversupplied_info *server_info,
+ DATA_BLOB session_key,
+ DATA_BLOB response_blob,
+ const char *smb_name)
+{
+ user_struct *vuser = get_partial_auth_user_struct(vuid);
+ if (!vuser) {
+ goto fail;
}
- /* use this to keep tabs on all our info from the authentication */
+ /* Use this to keep tabs on all our info from the authentication */
vuser->server_info = server_info;
- /* Ensure that the server_info will dissapear with the vuser it is now attached to */
+
+ /* Ensure that the server_info will disappear with
+ * the vuser it is now attached to */
+
talloc_steal(vuser, vuser->server_info);
/* the next functions should be done by a SID mapping system (SMS) as
* the new real sam db won't have reference to unix uids or gids
*/
-
+
vuser->uid = server_info->uid;
vuser->gid = server_info->gid;
-
+
vuser->n_groups = server_info->n_groups;
if (vuser->n_groups) {
- if (!(vuser->groups = (gid_t *)talloc_memdup(vuser, server_info->groups,
- sizeof(gid_t) *
- vuser->n_groups))) {
- DEBUG(0,("register_vuid: failed to talloc_memdup "
- "vuser->groups\n"));
- data_blob_free(&session_key);
- TALLOC_FREE(vuser);
- return UID_FIELD_INVALID;
+ if (!(vuser->groups = (gid_t *)talloc_memdup(vuser,
+ server_info->groups,
+ sizeof(gid_t)*vuser->n_groups))) {
+ DEBUG(0,("register_existing_vuid: "
+ "failed to talloc_memdup vuser->groups\n"));
+ goto fail;
}
}
vuser->guest = server_info->guest;
- fstrcpy(vuser->user.unix_name, server_info->unix_name);
+ fstrcpy(vuser->user.unix_name, server_info->unix_name);
/* This is a potentially untrusted username */
alpha_strcpy(vuser->user.smb_name, smb_name, ". _-$",
- sizeof(vuser->user.smb_name));
+ sizeof(vuser->user.smb_name));
fstrcpy(vuser->user.domain, pdb_get_domain(server_info->sam_account));
fstrcpy(vuser->user.full_name,
- pdb_get_fullname(server_info->sam_account));
+ pdb_get_fullname(server_info->sam_account));
{
/* Keep the homedir handy */
@@ -234,7 +270,7 @@ int register_vuid(auth_serversupplied_info *server_info,
pdb_get_logon_script(server_info->sam_account);
if (!IS_SAM_DEFAULT(server_info->sam_account,
- PDB_UNIXHOMEDIR)) {
+ PDB_UNIXHOMEDIR)) {
const char *unix_homedir =
pdb_get_unix_homedir(server_info->sam_account);
if (unix_homedir) {
@@ -252,7 +288,7 @@ int register_vuid(auth_serversupplied_info *server_info,
TALLOC_FREE(passwd);
}
}
-
+
if (homedir) {
vuser->homedir = homedir;
}
@@ -260,86 +296,83 @@ int register_vuid(auth_serversupplied_info *server_info,
vuser->logon_script = logon_script;
}
}
-
vuser->session_key = session_key;
- DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n",
- (unsigned int)vuser->uid,
- (unsigned int)vuser->gid,
- vuser->user.unix_name, vuser->user.smb_name,
- vuser->user.domain, vuser->guest ));
+ DEBUG(10,("register_existing_vuid: (%u,%u) %s %s %s guest=%d\n",
+ (unsigned int)vuser->uid,
+ (unsigned int)vuser->gid,
+ vuser->user.unix_name, vuser->user.smb_name,
+ vuser->user.domain, vuser->guest ));
- DEBUG(3, ("User name: %s\tReal name: %s\n", vuser->user.unix_name,
- vuser->user.full_name));
+ DEBUG(3, ("register_existing_vuid: User name: %s\t"
+ "Real name: %s\n", vuser->user.unix_name,
+ vuser->user.full_name));
- if (server_info->ptok) {
+ if (server_info->ptok) {
vuser->nt_user_token = dup_nt_token(vuser, server_info->ptok);
} else {
- DEBUG(1, ("server_info does not contain a user_token - "
- "cannot continue\n"));
- TALLOC_FREE(vuser);
- data_blob_free(&session_key);
- return UID_FIELD_INVALID;
+ DEBUG(1, ("register_existing_vuid: server_info does not "
+ "contain a user_token - cannot continue\n"));
+ goto fail;
}
- DEBUG(3,("UNIX uid %d is UNIX user %s, and will be vuid %u\n",
- (int)vuser->uid,vuser->user.unix_name, vuser->vuid));
+ DEBUG(3,("register_existing_vuid: UNIX uid %d is UNIX user %s, "
+ "and will be vuid %u\n",
+ (int)vuser->uid,vuser->user.unix_name, vuser->vuid));
next_vuid++;
num_validated_vuids++;
- DLIST_ADD(validated_users, vuser);
-
if (!session_claim(vuser)) {
- DEBUG(1, ("Failed to claim session for vuid=%d\n",
- vuser->vuid));
- invalidate_vuid(vuser->vuid);
- return UID_FIELD_INVALID;
+ DEBUG(1, ("register_existing_vuid: Failed to claim session "
+ "for vuid=%d\n",
+ vuser->vuid));
+ goto fail;
}
- /* Register a home dir service for this user iff
-
- (a) This is not a guest connection,
- (b) we have a home directory defined
- (c) there s not an existing static share by that name
-
- If a share exists by this name (autoloaded or not) reuse it . */
+ /* Register a home dir service for this user if
+ (a) This is not a guest connection,
+ (b) we have a home directory defined
+ (c) there s not an existing static share by that name
+ If a share exists by this name (autoloaded or not) reuse it . */
vuser->homes_snum = -1;
-
- if ( (!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir))
- {
+ if ( (!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir)) {
int servicenumber = lp_servicenumber(vuser->user.unix_name);
-
if ( servicenumber == -1 ) {
DEBUG(3, ("Adding homes service for user '%s' using "
- "home directory: '%s'\n",
+ "home directory: '%s'\n",
vuser->user.unix_name, vuser->unix_homedir));
vuser->homes_snum =
- add_home_service(vuser->user.unix_name,
- vuser->user.unix_name,
- vuser->unix_homedir);
+ add_home_service(vuser->user.unix_name,
+ vuser->user.unix_name,
+ vuser->unix_homedir);
} else {
DEBUG(3, ("Using static (or previously created) "
- "service for user '%s'; path = '%s'\n",
- vuser->user.unix_name,
- lp_pathname(servicenumber) ));
+ "service for user '%s'; path = '%s'\n",
+ vuser->user.unix_name,
+ lp_pathname(servicenumber) ));
vuser->homes_snum = servicenumber;
}
- }
-
+ }
+
if (srv_is_signing_negotiated() && !vuser->guest &&
- !srv_signing_started()) {
+ !srv_signing_started()) {
/* Try and turn on server signing on the first non-guest
* sessionsetup. */
srv_set_signing(vuser->session_key, response_blob);
}
-
+
/* fill in the current_user_info struct */
set_current_user_info( &vuser->user );
+ return vuser->vuid;
+ fail:
- return vuser->vuid;
+ if (vuser) {
+ invalidate_vuid(vuid);
+ }
+ return UID_FIELD_INVALID;
}
/****************************************************************************