Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into openchange
[sfrench/samba-autobuild/.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 #include "auth/session_proto.h"
32
33 _PUBLIC_ struct auth_session_info *anonymous_session(TALLOC_CTX *mem_ctx, 
34                                             struct loadparm_context *lp_ctx) 
35 {
36         NTSTATUS nt_status;
37         struct auth_session_info *session_info = NULL;
38         nt_status = auth_anonymous_session_info(mem_ctx, lp_ctx, &session_info);
39         if (!NT_STATUS_IS_OK(nt_status)) {
40                 return NULL;
41         }
42         return session_info;
43 }
44
45 _PUBLIC_ NTSTATUS auth_anonymous_session_info(TALLOC_CTX *parent_ctx, 
46                                      struct loadparm_context *lp_ctx,
47                                      struct auth_session_info **_session_info) 
48 {
49         NTSTATUS nt_status;
50         struct auth_serversupplied_info *server_info = NULL;
51         struct auth_session_info *session_info = NULL;
52         TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
53         
54         nt_status = auth_anonymous_server_info(mem_ctx,
55                                                lp_netbios_name(lp_ctx),
56                                                &server_info);
57         if (!NT_STATUS_IS_OK(nt_status)) {
58                 talloc_free(mem_ctx);
59                 return nt_status;
60         }
61
62         /* references the server_info into the session_info */
63         nt_status = auth_generate_session_info(parent_ctx, lp_ctx, server_info, &session_info);
64         talloc_free(mem_ctx);
65
66         NT_STATUS_NOT_OK_RETURN(nt_status);
67
68         session_info->credentials = cli_credentials_init(session_info);
69         if (!session_info->credentials) {
70                 return NT_STATUS_NO_MEMORY;
71         }
72
73         cli_credentials_set_conf(session_info->credentials, lp_ctx);
74         cli_credentials_set_anonymous(session_info->credentials);
75         
76         *_session_info = session_info;
77
78         return NT_STATUS_OK;
79 }
80
81 _PUBLIC_ NTSTATUS auth_anonymous_server_info(TALLOC_CTX *mem_ctx, 
82                                     const char *netbios_name,
83                                     struct auth_serversupplied_info **_server_info) 
84 {
85         struct auth_serversupplied_info *server_info;
86         server_info = talloc(mem_ctx, struct auth_serversupplied_info);
87         NT_STATUS_HAVE_NO_MEMORY(server_info);
88
89         server_info->account_sid = dom_sid_parse_talloc(server_info, SID_NT_ANONYMOUS);
90         NT_STATUS_HAVE_NO_MEMORY(server_info->account_sid);
91
92         /* is this correct? */
93         server_info->primary_group_sid = dom_sid_parse_talloc(server_info, SID_BUILTIN_GUESTS);
94         NT_STATUS_HAVE_NO_MEMORY(server_info->primary_group_sid);
95
96         server_info->n_domain_groups = 0;
97         server_info->domain_groups = NULL;
98
99         /* annoying, but the Anonymous really does have a session key, 
100            and it is all zeros! */
101         server_info->user_session_key = data_blob_talloc(server_info, NULL, 16);
102         NT_STATUS_HAVE_NO_MEMORY(server_info->user_session_key.data);
103
104         server_info->lm_session_key = data_blob_talloc(server_info, NULL, 16);
105         NT_STATUS_HAVE_NO_MEMORY(server_info->lm_session_key.data);
106
107         data_blob_clear(&server_info->user_session_key);
108         data_blob_clear(&server_info->lm_session_key);
109
110         server_info->account_name = talloc_strdup(server_info, "ANONYMOUS LOGON");
111         NT_STATUS_HAVE_NO_MEMORY(server_info->account_name);
112
113         server_info->domain_name = talloc_strdup(server_info, "NT AUTHORITY");
114         NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name);
115
116         server_info->full_name = talloc_strdup(server_info, "Anonymous Logon");
117         NT_STATUS_HAVE_NO_MEMORY(server_info->full_name);
118
119         server_info->logon_script = talloc_strdup(server_info, "");
120         NT_STATUS_HAVE_NO_MEMORY(server_info->logon_script);
121
122         server_info->profile_path = talloc_strdup(server_info, "");
123         NT_STATUS_HAVE_NO_MEMORY(server_info->profile_path);
124
125         server_info->home_directory = talloc_strdup(server_info, "");
126         NT_STATUS_HAVE_NO_MEMORY(server_info->home_directory);
127
128         server_info->home_drive = talloc_strdup(server_info, "");
129         NT_STATUS_HAVE_NO_MEMORY(server_info->home_drive);
130
131         server_info->logon_server = talloc_strdup(server_info, netbios_name);
132         NT_STATUS_HAVE_NO_MEMORY(server_info->logon_server);
133
134         server_info->last_logon = 0;
135         server_info->last_logoff = 0;
136         server_info->acct_expiry = 0;
137         server_info->last_password_change = 0;
138         server_info->allow_password_change = 0;
139         server_info->force_password_change = 0;
140
141         server_info->logon_count = 0;
142         server_info->bad_password_count = 0;
143
144         server_info->acct_flags = ACB_NORMAL;
145
146         server_info->authenticated = false;
147
148         *_server_info = server_info;
149
150         return NT_STATUS_OK;
151 }
152
153 _PUBLIC_ NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx, 
154                                     struct loadparm_context *lp_ctx,
155                                     struct auth_serversupplied_info *server_info, 
156                                     struct auth_session_info **_session_info) 
157 {
158         struct auth_session_info *session_info;
159         NTSTATUS nt_status;
160
161         session_info = talloc(mem_ctx, struct auth_session_info);
162         NT_STATUS_HAVE_NO_MEMORY(session_info);
163
164         session_info->server_info = talloc_reference(session_info, server_info);
165
166         /* unless set otherwise, the session key is the user session
167          * key from the auth subsystem */ 
168         session_info->session_key = server_info->user_session_key;
169
170         nt_status = security_token_create(session_info,
171                                           lp_ctx,
172                                           server_info->account_sid,
173                                           server_info->primary_group_sid,
174                                           server_info->n_domain_groups,
175                                           server_info->domain_groups,
176                                           server_info->authenticated,
177                                           &session_info->security_token);
178         NT_STATUS_NOT_OK_RETURN(nt_status);
179
180         session_info->credentials = NULL;
181
182         *_session_info = session_info;
183         return NT_STATUS_OK;
184 }
185
186 /**
187  * prints a struct auth_session_info security token to debug output.
188  */
189 void auth_session_info_debug(int dbg_lev, 
190                              const struct auth_session_info *session_info)
191 {
192         if (!session_info) {
193                 DEBUG(dbg_lev, ("Session Info: (NULL)\n"));
194                 return; 
195         }
196
197         security_token_debug(dbg_lev, session_info->security_token);
198 }
199
200 /**
201  * Make a server_info struct from the info3 returned by a domain logon 
202  */
203 _PUBLIC_ NTSTATUS make_server_info_netlogon_validation(TALLOC_CTX *mem_ctx,
204                                               const char *account_name,
205                                               uint16_t validation_level,
206                                               union netr_Validation *validation,
207                                               struct auth_serversupplied_info **_server_info)
208 {
209         struct auth_serversupplied_info *server_info;
210         struct netr_SamBaseInfo *base = NULL;
211         int i;
212
213         switch (validation_level) {
214         case 2:
215                 if (!validation || !validation->sam2) {
216                         return NT_STATUS_INVALID_PARAMETER;
217                 }
218                 base = &validation->sam2->base;
219                 break;
220         case 3:
221                 if (!validation || !validation->sam3) {
222                         return NT_STATUS_INVALID_PARAMETER;
223                 }
224                 base = &validation->sam3->base;
225                 break;
226         case 6:
227                 if (!validation || !validation->sam6) {
228                         return NT_STATUS_INVALID_PARAMETER;
229                 }
230                 base = &validation->sam6->base;
231                 break;
232         default:
233                 return NT_STATUS_INVALID_LEVEL;
234         }
235
236         server_info = talloc(mem_ctx, struct auth_serversupplied_info);
237         NT_STATUS_HAVE_NO_MEMORY(server_info);
238
239         /*
240            Here is where we should check the list of
241            trusted domains, and verify that the SID 
242            matches.
243         */
244         server_info->account_sid = dom_sid_add_rid(server_info, base->domain_sid, base->rid);
245         NT_STATUS_HAVE_NO_MEMORY(server_info->account_sid);
246
247
248         server_info->primary_group_sid = dom_sid_add_rid(server_info, base->domain_sid, base->primary_gid);
249         NT_STATUS_HAVE_NO_MEMORY(server_info->primary_group_sid);
250
251         server_info->n_domain_groups = base->groups.count;
252         if (base->groups.count) {
253                 server_info->domain_groups = talloc_array(server_info, struct dom_sid*, base->groups.count);
254                 NT_STATUS_HAVE_NO_MEMORY(server_info->domain_groups);
255         } else {
256                 server_info->domain_groups = NULL;
257         }
258
259         for (i = 0; i < base->groups.count; i++) {
260                 server_info->domain_groups[i] = dom_sid_add_rid(server_info, base->domain_sid, base->groups.rids[i].rid);
261                 NT_STATUS_HAVE_NO_MEMORY(server_info->domain_groups[i]);
262         }
263
264         /* Copy 'other' sids.  We need to do sid filtering here to
265            prevent possible elevation of privileges.  See:
266
267            http://www.microsoft.com/windows2000/techinfo/administration/security/sidfilter.asp
268          */
269
270         if (validation_level == 3) {
271                 struct dom_sid **dgrps = server_info->domain_groups;
272                 size_t sidcount = server_info->n_domain_groups + validation->sam3->sidcount;
273                 size_t n_dgrps = server_info->n_domain_groups;
274
275                 if (validation->sam3->sidcount > 0) {
276                         dgrps = talloc_realloc(server_info, dgrps, struct dom_sid*, sidcount);
277                         NT_STATUS_HAVE_NO_MEMORY(dgrps);
278
279                         for (i = 0; i < validation->sam3->sidcount; i++) {
280                                 dgrps[n_dgrps + i] = talloc_reference(dgrps, validation->sam3->sids[i].sid);
281                         }
282                 }
283
284                 server_info->n_domain_groups = sidcount;
285                 server_info->domain_groups = dgrps;
286
287                 /* Where are the 'global' sids?... */
288         }
289
290         if (base->account_name.string) {
291                 server_info->account_name = talloc_reference(server_info, base->account_name.string);
292         } else {
293                 server_info->account_name = talloc_strdup(server_info, account_name);
294                 NT_STATUS_HAVE_NO_MEMORY(server_info->account_name);
295         }
296
297         server_info->domain_name = talloc_reference(server_info, base->domain.string);
298         server_info->full_name = talloc_reference(server_info, base->full_name.string);
299         server_info->logon_script = talloc_reference(server_info, base->logon_script.string);
300         server_info->profile_path = talloc_reference(server_info, base->profile_path.string);
301         server_info->home_directory = talloc_reference(server_info, base->home_directory.string);
302         server_info->home_drive = talloc_reference(server_info, base->home_drive.string);
303         server_info->logon_server = talloc_reference(server_info, base->logon_server.string);
304         server_info->last_logon = base->last_logon;
305         server_info->last_logoff = base->last_logoff;
306         server_info->acct_expiry = base->acct_expiry;
307         server_info->last_password_change = base->last_password_change;
308         server_info->allow_password_change = base->allow_password_change;
309         server_info->force_password_change = base->force_password_change;
310         server_info->logon_count = base->logon_count;
311         server_info->bad_password_count = base->bad_password_count;
312         server_info->acct_flags = base->acct_flags;
313
314         server_info->authenticated = true;
315
316         /* ensure we are never given NULL session keys */
317
318         if (all_zero(base->key.key, sizeof(base->key.key))) {
319                 server_info->user_session_key = data_blob(NULL, 0);
320         } else {
321                 server_info->user_session_key = data_blob_talloc(server_info, base->key.key, sizeof(base->key.key));
322                 NT_STATUS_HAVE_NO_MEMORY(server_info->user_session_key.data);
323         }
324
325         if (all_zero(base->LMSessKey.key, sizeof(base->LMSessKey.key))) {
326                 server_info->lm_session_key = data_blob(NULL, 0);
327         } else {
328                 server_info->lm_session_key = data_blob_talloc(server_info, base->LMSessKey.key, sizeof(base->LMSessKey.key));
329                 NT_STATUS_HAVE_NO_MEMORY(server_info->lm_session_key.data);
330         }
331
332         *_server_info = server_info;
333         return NT_STATUS_OK;
334 }
335
336