diff options
Diffstat (limited to 'source4/smb_server/password.c')
-rw-r--r-- | source4/smb_server/password.c | 122 |
1 files changed, 58 insertions, 64 deletions
diff --git a/source4/smb_server/password.c b/source4/smb_server/password.c index 3d7723936d..1132a8ed9a 100644 --- a/source4/smb_server/password.c +++ b/source4/smb_server/password.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. Password and authentication handling Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005 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 @@ -24,39 +25,45 @@ /**************************************************************************** -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. +init the tcon structures ****************************************************************************/ -struct smbsrv_session *smbsrv_session_find(struct smbsrv_connection *smb_conn, uint16_t vuid) +void smbsrv_vuid_init(struct smbsrv_connection *smb_conn) { - struct smbsrv_session *sess; - int count=0; + smb_conn->sessions.idtree_vuid = idr_init(smb_conn); +} - if (vuid == UID_FIELD_INVALID) - return NULL; - for (sess=smb_conn->sessions.session_list; sess; sess=sess->next,count++) { - if (vuid == sess->vuid) { - if (count > 10) { - DLIST_PROMOTE(smb_conn->sessions.session_list, sess); - } - return sess; - } +/**************************************************************************** +Find the session structure assoicated with a VUID (not one from an in-progress session setup) +****************************************************************************/ +struct smbsrv_session *smbsrv_session_find(struct smbsrv_connection *smb_conn, uint16_t vuid) +{ + struct smbsrv_session *sess = idr_find(smb_conn->sessions.idtree_vuid, vuid); + if (sess && sess->finished_sesssetup) { + return sess; } - return NULL; } /**************************************************************************** -invalidate a uid + Find a VUID assoicated with an in-progress session setup ****************************************************************************/ -void smbsrv_invalidate_vuid(struct smbsrv_connection *smb_conn, uint16_t vuid) +struct smbsrv_session *smbsrv_session_find_sesssetup(struct smbsrv_connection *smb_conn, uint16_t vuid) { - struct smbsrv_session *sess = smbsrv_session_find(smb_conn, vuid); + struct smbsrv_session *sess = idr_find(smb_conn->sessions.idtree_vuid, vuid); + if (sess && !sess->finished_sesssetup) { + return sess; + } + return NULL; +} - if (sess == NULL) - return; +/**************************************************************************** +invalidate a session +****************************************************************************/ +static int smbsrv_session_destructor(void *p) +{ + struct smbsrv_session *sess = p; + struct smbsrv_connection *smb_conn = sess->smb_conn; DLIST_REMOVE(smb_conn->sessions.session_list, sess); @@ -65,20 +72,18 @@ void smbsrv_invalidate_vuid(struct smbsrv_connection *smb_conn, uint16_t vuid) /* REWRITE: conn_clear_vuid_cache(smb, vuid); */ smb_conn->sessions.num_validated_vuids--; + + idr_remove(smb_conn->sessions.idtree_vuid, sess->vuid); + return 0; } /**************************************************************************** -invalidate all vuid entries for this process +invalidate a uid ****************************************************************************/ -void smbsrv_invalidate_all_vuids(struct smbsrv_connection *smb_conn) +void smbsrv_invalidate_vuid(struct smbsrv_connection *smb_conn, uint16_t vuid) { - struct smbsrv_session *sess,*next=NULL; - - for (sess=smb_conn->sessions.session_list; sess; sess=next) { - next = sess->next; - - smbsrv_invalidate_vuid(smb_conn, sess->vuid); - } + struct smbsrv_session *sess = smbsrv_session_find(smb_conn, vuid); + talloc_free(sess); } /** @@ -93,56 +98,45 @@ void smbsrv_invalidate_all_vuids(struct smbsrv_connection *smb_conn) * */ -uint16_t smbsrv_register_session(struct smbsrv_connection *smb_conn, - struct auth_session_info *session_info, - struct gensec_security *gensec_ctx) +struct smbsrv_session *smbsrv_register_session(struct smbsrv_connection *smb_conn, + struct auth_session_info *session_info, + struct gensec_security *gensec_ctx) { struct smbsrv_session *sess = NULL; + int i; + + /* Ensure no vuid gets registered in share level security. */ + /* TODO: replace lp_security with a flag in smbsrv_connection */ + if (lp_security() == SEC_SHARE) + return UID_FIELD_INVALID; sess = talloc(smb_conn, struct smbsrv_session); - if(sess == NULL) { + if (sess == NULL) { DEBUG(0,("talloc(smb_conn->mem_ctx, struct smbsrv_session) failed\n")); - return UID_FIELD_INVALID; + return sess; } ZERO_STRUCTP(sess); - sess->vuid = UID_FIELD_INVALID; - /* Ensure no vuid gets registered in share level security. */ - /* TODO: replace lp_security with a flag in smbsrv_connection */ - if(lp_security() == SEC_SHARE) - return sess->vuid; - - /* Limit allowed vuids to 16bits - VUID_OFFSET. */ - if (smb_conn->sessions.num_validated_vuids >= 0xFFFF-VUID_OFFSET) - return sess->vuid; - - /* Allocate a free vuid. Yes this is a linear search... :-) */ - while (smbsrv_session_find(smb_conn, smb_conn->sessions.next_vuid) != NULL ) { - smb_conn->sessions.next_vuid++; - /* Check for vuid wrap. */ - if (smb_conn->sessions.next_vuid == UID_FIELD_INVALID) - smb_conn->sessions.next_vuid = VUID_OFFSET; + i = idr_get_new_above(smb_conn->sessions.idtree_vuid, sess, VUID_OFFSET, UINT16_MAX); + if (i == -1) { + DEBUG(1,("ERROR! Out of connection structures\n")); + talloc_free(sess); + return NULL; } + sess->vuid = i; - DEBUG(10,("register_vuid: allocated vuid = %u\n", - (uint_t)smb_conn->sessions.next_vuid)); - - sess->vuid = smb_conn->sessions.next_vuid; - smb_conn->sessions.next_vuid++; smb_conn->sessions.num_validated_vuids++; /* use this to keep tabs on all our info from the authentication */ - if (session_info) { - sess->session_info = talloc_reference(sess, session_info); - } - - if (gensec_ctx) { - sess->gensec_ctx = talloc_reference(sess, gensec_ctx); - } + sess->session_info = talloc_reference(sess, session_info); + + sess->gensec_ctx = talloc_reference(sess, gensec_ctx); sess->smb_conn = smb_conn; DLIST_ADD(smb_conn->sessions.session_list, sess); - return sess->vuid; + talloc_set_destructor(sess, smbsrv_session_destructor); + + return sess; } |