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