492f5700ad47fc1e59a204ccb64c8f5b156e656e
[jra/samba/.git] / source4 / smb_server / password.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Password and authentication handling
4    Copyright (C) Andrew Tridgell 1992-1998
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23
24 /****************************************************************************
25 check if a uid has been validated, and return an pointer to the user_struct
26 if it has. NULL if not. vuid is biased by an offset. This allows us to
27 tell random client vuid's (normally zero) from valid vuids.
28 ****************************************************************************/
29 struct smbsrv_session *smbsrv_session_find(struct smbsrv_connection *smb_conn, uint16_t vuid)
30 {
31         struct smbsrv_session *sess;
32         int count=0;
33
34         if (vuid == UID_FIELD_INVALID)
35                 return NULL;
36
37         for (sess=smb_conn->sessions.session_list; sess; sess=sess->next,count++) {
38                 if (vuid == sess->vuid) {
39                         if (count > 10) {
40                                 DLIST_PROMOTE(smb_conn->sessions.session_list, sess);
41                         }
42                         return sess;
43                 }
44         }
45
46         return NULL;
47 }
48
49 /****************************************************************************
50 invalidate a uid
51 ****************************************************************************/
52 void smbsrv_invalidate_vuid(struct smbsrv_connection *smb_conn, uint16_t vuid)
53 {
54         struct smbsrv_session *sess = smbsrv_session_find(smb_conn, vuid);
55
56         if (sess == NULL)
57                 return;
58
59         session_yield(sess);
60
61         free_session_info(&sess->session_info);
62
63         DLIST_REMOVE(smb_conn->sessions.session_list, sess);
64
65         /* clear the vuid from the 'cache' on each connection, and
66            from the vuid 'owner' of connections */
67         /* REWRITE: conn_clear_vuid_cache(smb, vuid); */
68
69         smb_conn->sessions.num_validated_vuids--;
70 }
71
72 /****************************************************************************
73 invalidate all vuid entries for this process
74 ****************************************************************************/
75 void smbsrv_invalidate_all_vuids(struct smbsrv_connection *smb_conn)
76 {
77         struct smbsrv_session *sess,*next=NULL;
78
79         for (sess=smb_conn->sessions.session_list; sess; sess=next) {
80                 next = sess->next;
81                 
82                 smbsrv_invalidate_vuid(smb_conn, sess->vuid);
83         }
84 }
85
86 /**
87  *  register that a valid login has been performed, establish 'session'.
88  *  @param session_info The token returned from the authentication process (if the authentication has completed)
89  *   (now 'owned' by register_vuid)
90  *
91  *  @param smb_name The untranslated name of the user
92  *
93  *  @return Newly allocated vuid, biased by an offset. (This allows us to
94  *   tell random client vuid's (normally zero) from valid vuids.)
95  *
96  */
97
98 uint16_t smbsrv_register_session(struct smbsrv_connection *smb_conn,
99                                  struct auth_session_info *session_info,
100                                  struct gensec_security *gensec_ctx)
101 {
102         struct smbsrv_session *sess = NULL;
103
104         sess = talloc_p(smb_conn->mem_ctx, struct smbsrv_session);
105         if(sess == NULL) {
106                 DEBUG(0,("talloc_p(smb_conn->mem_ctx, struct smbsrv_session) failed\n"));
107                 return UID_FIELD_INVALID;
108         }
109
110         ZERO_STRUCTP(sess);
111         sess->vuid = UID_FIELD_INVALID;
112
113         /* Ensure no vuid gets registered in share level security. */
114         /* TODO: replace lp_security with a flag in smbsrv_connection */
115         if(lp_security() == SEC_SHARE)
116                 return sess->vuid;
117
118         /* Limit allowed vuids to 16bits - VUID_OFFSET. */
119         if (smb_conn->sessions.num_validated_vuids >= 0xFFFF-VUID_OFFSET)
120                 return sess->vuid;
121
122         /* Allocate a free vuid. Yes this is a linear search... :-) */
123         while (smbsrv_session_find(smb_conn, smb_conn->sessions.next_vuid) != NULL ) {
124                 smb_conn->sessions.next_vuid++;
125                 /* Check for vuid wrap. */
126                 if (smb_conn->sessions.next_vuid == UID_FIELD_INVALID)
127                         smb_conn->sessions.next_vuid = VUID_OFFSET;
128         }
129
130         DEBUG(10,("register_vuid: allocated vuid = %u\n", 
131                   (uint_t)smb_conn->sessions.next_vuid));
132
133         sess->vuid = smb_conn->sessions.next_vuid;
134         smb_conn->sessions.next_vuid++;
135         smb_conn->sessions.num_validated_vuids++;
136
137         /* use this to keep tabs on all our info from the authentication */
138         sess->session_info = session_info;
139         sess->gensec_ctx = gensec_ctx;
140
141         sess->smb_conn = smb_conn;
142         DLIST_ADD(smb_conn->sessions.session_list, sess);
143
144         /* we only need to do session_claim() when the session_setup is complete
145          * for spnego session_info is NULL the first time
146          */
147         if (session_info && !session_claim(sess)) {
148                 DEBUG(1,("Failed to claim session for vuid=%d\n", sess->vuid));
149                 smbsrv_invalidate_vuid(smb_conn, sess->vuid);
150                 return UID_FIELD_INVALID;
151         }
152
153         return sess->vuid;
154 }