r26127: Move session code out of auth_util.c. No longer making it part of auth but...
[amitay/samba.git] / source4 / auth / session.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Authentication utility functions
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett 2001
6    Copyright (C) Jeremy Allison 2000-2001
7    Copyright (C) Rafal Szczesniak 2002
8    Copyright (C) Stefan Metzmacher 2005
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "auth/auth.h"
26 #include "libcli/security/security.h"
27 #include "libcli/auth/libcli_auth.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "auth/credentials/credentials.h"
30 #include "param/param.h"
31
32 struct auth_session_info *anonymous_session(TALLOC_CTX *mem_ctx) 
33 {
34         NTSTATUS nt_status;
35         struct auth_session_info *session_info = NULL;
36         nt_status = auth_anonymous_session_info(mem_ctx, &session_info);
37         if (!NT_STATUS_IS_OK(nt_status)) {
38                 return NULL;
39         }
40         return session_info;
41 }
42
43 NTSTATUS auth_anonymous_session_info(TALLOC_CTX *parent_ctx, 
44                                      struct auth_session_info **_session_info) 
45 {
46         NTSTATUS nt_status;
47         struct auth_serversupplied_info *server_info = NULL;
48         struct auth_session_info *session_info = NULL;
49         TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
50         
51         nt_status = auth_anonymous_server_info(mem_ctx,
52                                                &server_info);
53         if (!NT_STATUS_IS_OK(nt_status)) {
54                 talloc_free(mem_ctx);
55                 return nt_status;
56         }
57
58         /* references the server_info into the session_info */
59         nt_status = auth_generate_session_info(parent_ctx, server_info, &session_info);
60         talloc_free(mem_ctx);
61
62         NT_STATUS_NOT_OK_RETURN(nt_status);
63
64         session_info->credentials = cli_credentials_init(session_info);
65         if (!session_info->credentials) {
66                 return NT_STATUS_NO_MEMORY;
67         }
68
69         cli_credentials_set_conf(session_info->credentials, global_loadparm);
70         cli_credentials_set_anonymous(session_info->credentials);
71         
72         *_session_info = session_info;
73
74         return NT_STATUS_OK;
75 }
76
77 NTSTATUS auth_anonymous_server_info(TALLOC_CTX *mem_ctx, struct auth_serversupplied_info **_server_info) 
78 {
79         struct auth_serversupplied_info *server_info;
80         server_info = talloc(mem_ctx, struct auth_serversupplied_info);
81         NT_STATUS_HAVE_NO_MEMORY(server_info);
82
83         server_info->account_sid = dom_sid_parse_talloc(server_info, SID_NT_ANONYMOUS);
84         NT_STATUS_HAVE_NO_MEMORY(server_info->account_sid);
85
86         /* is this correct? */
87         server_info->primary_group_sid = dom_sid_parse_talloc(server_info, SID_BUILTIN_GUESTS);
88         NT_STATUS_HAVE_NO_MEMORY(server_info->primary_group_sid);
89
90         server_info->n_domain_groups = 0;
91         server_info->domain_groups = NULL;
92
93         /* annoying, but the Anonymous really does have a session key, 
94            and it is all zeros! */
95         server_info->user_session_key = data_blob_talloc(server_info, NULL, 16);
96         NT_STATUS_HAVE_NO_MEMORY(server_info->user_session_key.data);
97
98         server_info->lm_session_key = data_blob_talloc(server_info, NULL, 16);
99         NT_STATUS_HAVE_NO_MEMORY(server_info->lm_session_key.data);
100
101         data_blob_clear(&server_info->user_session_key);
102         data_blob_clear(&server_info->lm_session_key);
103
104         server_info->account_name = talloc_strdup(server_info, "ANONYMOUS LOGON");
105         NT_STATUS_HAVE_NO_MEMORY(server_info->account_name);
106
107         server_info->domain_name = talloc_strdup(server_info, "NT AUTHORITY");
108         NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name);
109
110         server_info->full_name = talloc_strdup(server_info, "Anonymous Logon");
111         NT_STATUS_HAVE_NO_MEMORY(server_info->full_name);
112
113         server_info->logon_script = talloc_strdup(server_info, "");
114         NT_STATUS_HAVE_NO_MEMORY(server_info->logon_script);
115
116         server_info->profile_path = talloc_strdup(server_info, "");
117         NT_STATUS_HAVE_NO_MEMORY(server_info->profile_path);
118
119         server_info->home_directory = talloc_strdup(server_info, "");
120         NT_STATUS_HAVE_NO_MEMORY(server_info->home_directory);
121
122         server_info->home_drive = talloc_strdup(server_info, "");
123         NT_STATUS_HAVE_NO_MEMORY(server_info->home_drive);
124
125         server_info->logon_server = talloc_strdup(server_info, lp_netbios_name(global_loadparm));
126         NT_STATUS_HAVE_NO_MEMORY(server_info->logon_server);
127
128         server_info->last_logon = 0;
129         server_info->last_logoff = 0;
130         server_info->acct_expiry = 0;
131         server_info->last_password_change = 0;
132         server_info->allow_password_change = 0;
133         server_info->force_password_change = 0;
134
135         server_info->logon_count = 0;
136         server_info->bad_password_count = 0;
137
138         server_info->acct_flags = ACB_NORMAL;
139
140         server_info->authenticated = false;
141
142         *_server_info = server_info;
143
144         return NT_STATUS_OK;
145 }
146
147 NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx, 
148                                     struct auth_serversupplied_info *server_info, 
149                                     struct auth_session_info **_session_info) 
150 {
151         struct auth_session_info *session_info;
152         NTSTATUS nt_status;
153
154         session_info = talloc(mem_ctx, struct auth_session_info);
155         NT_STATUS_HAVE_NO_MEMORY(session_info);
156
157         session_info->server_info = talloc_reference(session_info, server_info);
158
159         /* unless set otherwise, the session key is the user session
160          * key from the auth subsystem */ 
161         session_info->session_key = server_info->user_session_key;
162
163         nt_status = security_token_create(session_info,
164                                           server_info->account_sid,
165                                           server_info->primary_group_sid,
166                                           server_info->n_domain_groups,
167                                           server_info->domain_groups,
168                                           server_info->authenticated,
169                                           &session_info->security_token);
170         NT_STATUS_NOT_OK_RETURN(nt_status);
171
172         session_info->credentials = NULL;
173
174         *_session_info = session_info;
175         return NT_STATUS_OK;
176 }
177
178 /**
179  * prints a struct auth_session_info security token to debug output.
180  */
181 void auth_session_info_debug(int dbg_lev, 
182                              const struct auth_session_info *session_info)
183 {
184         if (!session_info) {
185                 DEBUG(dbg_lev, ("Session Info: (NULL)\n"));
186                 return; 
187         }
188
189         security_token_debug(dbg_lev, session_info->security_token);
190 }
191
192 /**
193  * Make a server_info struct from the info3 returned by a domain logon 
194  */
195 NTSTATUS make_server_info_netlogon_validation(TALLOC_CTX *mem_ctx,
196                                               const char *account_name,
197                                               uint16_t validation_level,
198                                               union netr_Validation *validation,
199                                               struct auth_serversupplied_info **_server_info)
200 {
201         struct auth_serversupplied_info *server_info;
202         struct netr_SamBaseInfo *base = NULL;
203         int i;
204
205         switch (validation_level) {
206         case 2:
207                 if (!validation || !validation->sam2) {
208                         return NT_STATUS_INVALID_PARAMETER;
209                 }
210                 base = &validation->sam2->base;
211                 break;
212         case 3:
213                 if (!validation || !validation->sam3) {
214                         return NT_STATUS_INVALID_PARAMETER;
215                 }
216                 base = &validation->sam3->base;
217                 break;
218         case 6:
219                 if (!validation || !validation->sam6) {
220                         return NT_STATUS_INVALID_PARAMETER;
221                 }
222                 base = &validation->sam6->base;
223                 break;
224         default:
225                 return NT_STATUS_INVALID_LEVEL;
226         }
227
228         server_info = talloc(mem_ctx, struct auth_serversupplied_info);
229         NT_STATUS_HAVE_NO_MEMORY(server_info);
230
231         /*
232            Here is where we should check the list of
233            trusted domains, and verify that the SID 
234            matches.
235         */
236         server_info->account_sid = dom_sid_add_rid(server_info, base->domain_sid, base->rid);
237         NT_STATUS_HAVE_NO_MEMORY(server_info->account_sid);
238
239
240         server_info->primary_group_sid = dom_sid_add_rid(server_info, base->domain_sid, base->primary_gid);
241         NT_STATUS_HAVE_NO_MEMORY(server_info->primary_group_sid);
242
243         server_info->n_domain_groups = base->groups.count;
244         if (base->groups.count) {
245                 server_info->domain_groups = talloc_array(server_info, struct dom_sid*, base->groups.count);
246                 NT_STATUS_HAVE_NO_MEMORY(server_info->domain_groups);
247         } else {
248                 server_info->domain_groups = NULL;
249         }
250
251         for (i = 0; i < base->groups.count; i++) {
252                 server_info->domain_groups[i] = dom_sid_add_rid(server_info, base->domain_sid, base->groups.rids[i].rid);
253                 NT_STATUS_HAVE_NO_MEMORY(server_info->domain_groups[i]);
254         }
255
256         /* Copy 'other' sids.  We need to do sid filtering here to
257            prevent possible elevation of privileges.  See:
258
259            http://www.microsoft.com/windows2000/techinfo/administration/security/sidfilter.asp
260          */
261
262         if (validation_level == 3) {
263                 struct dom_sid **dgrps = server_info->domain_groups;
264                 size_t sidcount = server_info->n_domain_groups + validation->sam3->sidcount;
265                 size_t n_dgrps = server_info->n_domain_groups;
266
267                 if (validation->sam3->sidcount > 0) {
268                         dgrps = talloc_realloc(server_info, dgrps, struct dom_sid*, sidcount);
269                         NT_STATUS_HAVE_NO_MEMORY(dgrps);
270
271                         for (i = 0; i < validation->sam3->sidcount; i++) {
272                                 dgrps[n_dgrps + i] = talloc_reference(dgrps, validation->sam3->sids[i].sid);
273                         }
274                 }
275
276                 server_info->n_domain_groups = sidcount;
277                 server_info->domain_groups = dgrps;
278
279                 /* Where are the 'global' sids?... */
280         }
281
282         if (base->account_name.string) {
283                 server_info->account_name = talloc_reference(server_info, base->account_name.string);
284         } else {
285                 server_info->account_name = talloc_strdup(server_info, account_name);
286                 NT_STATUS_HAVE_NO_MEMORY(server_info->account_name);
287         }
288
289         server_info->domain_name = talloc_reference(server_info, base->domain.string);
290         server_info->full_name = talloc_reference(server_info, base->full_name.string);
291         server_info->logon_script = talloc_reference(server_info, base->logon_script.string);
292         server_info->profile_path = talloc_reference(server_info, base->profile_path.string);
293         server_info->home_directory = talloc_reference(server_info, base->home_directory.string);
294         server_info->home_drive = talloc_reference(server_info, base->home_drive.string);
295         server_info->logon_server = talloc_reference(server_info, base->logon_server.string);
296         server_info->last_logon = base->last_logon;
297         server_info->last_logoff = base->last_logoff;
298         server_info->acct_expiry = base->acct_expiry;
299         server_info->last_password_change = base->last_password_change;
300         server_info->allow_password_change = base->allow_password_change;
301         server_info->force_password_change = base->force_password_change;
302         server_info->logon_count = base->logon_count;
303         server_info->bad_password_count = base->bad_password_count;
304         server_info->acct_flags = base->acct_flags;
305
306         server_info->authenticated = true;
307
308         /* ensure we are never given NULL session keys */
309
310         if (all_zero(base->key.key, sizeof(base->key.key))) {
311                 server_info->user_session_key = data_blob(NULL, 0);
312         } else {
313                 server_info->user_session_key = data_blob_talloc(server_info, base->key.key, sizeof(base->key.key));
314                 NT_STATUS_HAVE_NO_MEMORY(server_info->user_session_key.data);
315         }
316
317         if (all_zero(base->LMSessKey.key, sizeof(base->LMSessKey.key))) {
318                 server_info->lm_session_key = data_blob(NULL, 0);
319         } else {
320                 server_info->lm_session_key = data_blob_talloc(server_info, base->LMSessKey.key, sizeof(base->LMSessKey.key));
321                 NT_STATUS_HAVE_NO_MEMORY(server_info->lm_session_key.data);
322         }
323
324         *_server_info = server_info;
325         return NT_STATUS_OK;
326 }
327
328