r11452: Update Heimdal to current lorikeet, including removing the ccache side
[gd/samba-autobuild/.git] / source4 / auth / auth_util.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 2 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, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26 #include "librpc/gen_ndr/ndr_samr.h"
27 #include "librpc/gen_ndr/ndr_netlogon.h"
28 #include "librpc/gen_ndr/ndr_security.h"
29 #include "auth/auth.h"
30
31 /* this default function can be used by mostly all backends
32  * which don't want to set a challlenge
33  */
34 NTSTATUS auth_get_challenge_not_implemented(struct auth_method_context *ctx, TALLOC_CTX *mem_ctx, DATA_BLOB *challenge)
35 {
36         /* we don't want to set a challenge */
37         return NT_STATUS_NOT_IMPLEMENTED;
38 }
39
40 /****************************************************************************
41  Create an auth_usersupplied_data structure after appropriate mapping.
42 ****************************************************************************/
43
44 NTSTATUS map_user_info(TALLOC_CTX *mem_ctx,
45                        const struct auth_usersupplied_info *user_info,
46                        struct auth_usersupplied_info **user_info_mapped)
47 {
48         const char *domain;
49         char *account_name;
50         char *d;
51         DEBUG(5,("map_user_info: Mapping user [%s]\\[%s] from workstation [%s]\n",
52                 user_info->client.domain_name, user_info->client.account_name, user_info->workstation_name));
53
54         account_name = talloc_strdup(mem_ctx, user_info->client.account_name);
55         if (!account_name) {
56                 return NT_STATUS_NO_MEMORY;
57         }
58         
59         /* don't allow "" as a domain, fixes a Win9X bug 
60            where it doens't supply a domain for logon script
61            'net use' commands.                                 */
62
63         /* Split user@realm names into user and realm components.  This is TODO to fix with proper userprincipalname support */
64         if (user_info->client.domain_name && *user_info->client.domain_name) {
65                 domain = user_info->client.domain_name;
66         } else if (strchr_m(user_info->client.account_name, '@')) {
67                 d = strchr_m(account_name, '@');
68                 if (!d) {
69                         return NT_STATUS_INTERNAL_ERROR;
70                 }
71                 d[0] = '\0';
72                 d++;
73                 domain = d;
74         } else {
75                 domain = lp_workgroup();
76         }
77
78         *user_info_mapped = talloc(mem_ctx, struct auth_usersupplied_info);
79         if (!*user_info_mapped) {
80                 return NT_STATUS_NO_MEMORY;
81         }
82         talloc_reference(*user_info_mapped, user_info);
83         **user_info_mapped = *user_info;
84         (*user_info_mapped)->mapped_state = True;
85         (*user_info_mapped)->mapped.domain_name = talloc_strdup(*user_info_mapped, domain);
86         (*user_info_mapped)->mapped.account_name = talloc_strdup(*user_info_mapped, account_name);
87         talloc_free(account_name);
88         if (!(*user_info_mapped)->mapped.domain_name 
89             || !(*user_info_mapped)->mapped.account_name) {
90                 return NT_STATUS_NO_MEMORY;
91         }
92
93         return NT_STATUS_OK;
94 }
95
96 /****************************************************************************
97  Create an auth_usersupplied_data structure after appropriate mapping.
98 ****************************************************************************/
99
100  NTSTATUS encrypt_user_info(TALLOC_CTX *mem_ctx, struct auth_context *auth_context, 
101                            enum auth_password_state to_state,
102                            const struct auth_usersupplied_info *user_info_in,
103                            const struct auth_usersupplied_info **user_info_encrypted)
104 {
105         NTSTATUS nt_status;
106         struct auth_usersupplied_info *user_info_temp;
107         switch (to_state) {
108         case AUTH_PASSWORD_RESPONSE:
109                 switch (user_info_in->password_state) {
110                 case AUTH_PASSWORD_PLAIN:
111                 {
112                         const struct auth_usersupplied_info *user_info_temp2;
113                         nt_status = encrypt_user_info(mem_ctx, auth_context, 
114                                                       AUTH_PASSWORD_HASH, 
115                                                       user_info_in, &user_info_temp2);
116                         if (!NT_STATUS_IS_OK(nt_status)) {
117                                 return nt_status;
118                         }
119                         user_info_in = user_info_temp2;
120                 }
121                 case AUTH_PASSWORD_HASH:
122                 {
123                         const uint8_t *challenge;
124                         DATA_BLOB chall_blob;
125                         user_info_temp = talloc(mem_ctx, struct auth_usersupplied_info);
126                         if (!user_info_temp) {
127                                 return NT_STATUS_NO_MEMORY;
128                         }
129                         talloc_reference(user_info_temp, user_info_in);
130                         *user_info_temp = *user_info_in;
131                         user_info_temp->mapped_state = to_state;
132                         
133                         nt_status = auth_get_challenge(auth_context, &challenge);
134                         if (!NT_STATUS_IS_OK(nt_status)) {
135                                 return nt_status;
136                         }
137                         
138                         chall_blob = data_blob_talloc(mem_ctx, challenge, 8);
139                         if (lp_client_ntlmv2_auth()) {
140                                 DATA_BLOB names_blob = NTLMv2_generate_names_blob(mem_ctx, lp_netbios_name(), lp_workgroup());
141                                 DATA_BLOB lmv2_response, ntlmv2_response, lmv2_session_key, ntlmv2_session_key;
142                                 
143                                 if (!SMBNTLMv2encrypt_hash(user_info_temp,
144                                                            user_info_in->client.account_name, 
145                                                            user_info_in->client.domain_name, 
146                                                            user_info_in->password.hash.nt->hash, &chall_blob,
147                                                            &names_blob,
148                                                            &lmv2_response, &ntlmv2_response, 
149                                                            &lmv2_session_key, &ntlmv2_session_key)) {
150                                         data_blob_free(&names_blob);
151                                         return NT_STATUS_NO_MEMORY;
152                                 }
153                                 data_blob_free(&names_blob);
154                                 user_info_temp->password.response.lanman = lmv2_response;
155                                 user_info_temp->password.response.nt = ntlmv2_response;
156                                 
157                                 data_blob_free(&lmv2_session_key);
158                                 data_blob_free(&ntlmv2_session_key);
159                         } else {
160                                 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, 24);
161                                 SMBOWFencrypt(user_info_in->password.hash.nt->hash, challenge, blob.data);
162
163                                 user_info_temp->password.response.nt = blob;
164                                 if (lp_client_lanman_auth() && user_info_in->password.hash.lanman) {
165                                         DATA_BLOB lm_blob = data_blob_talloc(mem_ctx, NULL, 24);
166                                         SMBOWFencrypt(user_info_in->password.hash.lanman->hash, challenge, blob.data);
167                                         user_info_temp->password.response.lanman = lm_blob;
168                                 } else {
169                                         /* if not sending the LM password, send the NT password twice */
170                                         user_info_temp->password.response.lanman = user_info_temp->password.response.nt;
171                                 }
172                         }
173
174                         user_info_in = user_info_temp;
175                 }
176                 case AUTH_PASSWORD_RESPONSE:
177                         *user_info_encrypted = user_info_in;
178                 }
179                 break;
180         case AUTH_PASSWORD_HASH:
181         {       
182                 switch (user_info_in->password_state) {
183                 case AUTH_PASSWORD_PLAIN:
184                 {
185                         struct samr_Password lanman;
186                         struct samr_Password nt;
187                         
188                         user_info_temp = talloc(mem_ctx, struct auth_usersupplied_info);
189                         if (!user_info_temp) {
190                                 return NT_STATUS_NO_MEMORY;
191                         }
192                         talloc_reference(user_info_temp, user_info_in);
193                         *user_info_temp = *user_info_in;
194                         user_info_temp->mapped_state = to_state;
195                         
196                         if (E_deshash(user_info_in->password.plaintext, lanman.hash)) {
197                                 user_info_temp->password.hash.lanman = talloc(user_info_temp,
198                                                                               struct samr_Password);
199                                 *user_info_temp->password.hash.lanman = lanman;
200                         } else {
201                                 user_info_temp->password.hash.lanman = NULL;
202                         }
203                         
204                         E_md4hash(user_info_in->password.plaintext, nt.hash);
205                         user_info_temp->password.hash.nt = talloc(user_info_temp,
206                                                                    struct samr_Password);
207                         *user_info_temp->password.hash.nt = nt;
208                         
209                         user_info_in = user_info_temp;
210                 }
211                 case AUTH_PASSWORD_HASH:
212                         *user_info_encrypted = user_info_in;
213                         break;
214                 default:
215                         return NT_STATUS_INVALID_PARAMETER;
216                         break;
217                 }
218                 break;
219         }
220         default:
221                 return NT_STATUS_INVALID_PARAMETER;
222         }
223
224         return NT_STATUS_OK;
225 }
226
227 /***************************************************************************
228  Make a server_info struct from the info3 returned by a domain logon 
229 ***************************************************************************/
230 NTSTATUS make_server_info_netlogon_validation(TALLOC_CTX *mem_ctx,
231                                               const char *account_name,
232                                               uint16_t validation_level,
233                                               union netr_Validation *validation,
234                                               struct auth_serversupplied_info **_server_info)
235 {
236         struct auth_serversupplied_info *server_info;
237         struct netr_SamBaseInfo *base = NULL;
238         int i;
239
240         switch (validation_level) {
241         case 2:
242                 if (!validation || !validation->sam2) {
243                         return NT_STATUS_INVALID_PARAMETER;
244                 }
245                 base = &validation->sam2->base;
246                 break;
247         case 3:
248                 if (!validation || !validation->sam3) {
249                         return NT_STATUS_INVALID_PARAMETER;
250                 }
251                 base = &validation->sam3->base;
252                 break;
253         case 6:
254                 if (!validation || !validation->sam6) {
255                         return NT_STATUS_INVALID_PARAMETER;
256                 }
257                 base = &validation->sam6->base;
258                 break;
259         default:
260                 return NT_STATUS_INVALID_LEVEL;
261         }
262
263         server_info = talloc(mem_ctx, struct auth_serversupplied_info);
264         NT_STATUS_HAVE_NO_MEMORY(server_info);
265
266         /*
267            Here is where we should check the list of
268            trusted domains, and verify that the SID 
269            matches.
270         */
271         server_info->account_sid = dom_sid_add_rid(server_info, base->domain_sid, base->rid);
272         NT_STATUS_HAVE_NO_MEMORY(server_info->account_sid);
273
274
275         server_info->primary_group_sid = dom_sid_add_rid(server_info, base->domain_sid, base->primary_gid);
276         NT_STATUS_HAVE_NO_MEMORY(server_info->primary_group_sid);
277
278         server_info->n_domain_groups = base->groups.count;
279         if (base->groups.count) {
280                 server_info->domain_groups = talloc_array(server_info, struct dom_sid*, base->groups.count);
281                 NT_STATUS_HAVE_NO_MEMORY(server_info->domain_groups);
282         } else {
283                 server_info->domain_groups = NULL;
284         }
285
286         for (i = 0; i < base->groups.count; i++) {
287                 server_info->domain_groups[i] = dom_sid_add_rid(server_info, base->domain_sid, base->groups.rids[i].rid);
288                 NT_STATUS_HAVE_NO_MEMORY(server_info->domain_groups[i]);
289         }
290
291         /* Copy 'other' sids.  We need to do sid filtering here to
292            prevent possible elevation of privileges.  See:
293
294            http://www.microsoft.com/windows2000/techinfo/administration/security/sidfilter.asp
295          */
296
297         if (validation_level == 3) {
298                 struct dom_sid **dgrps = server_info->domain_groups;
299                 size_t sidcount = server_info->n_domain_groups + validation->sam3->sidcount;
300                 size_t n_dgrps = server_info->n_domain_groups;
301
302                 if (validation->sam3->sidcount > 0) {
303                         dgrps = talloc_realloc(server_info, dgrps, struct dom_sid*, sidcount);
304                         NT_STATUS_HAVE_NO_MEMORY(dgrps);
305
306                         for (i = 0; i < validation->sam3->sidcount; i++) {
307                                 dgrps[n_dgrps + i] = talloc_reference(dgrps, validation->sam3->sids[i].sid);
308                         }
309                 }
310
311                 server_info->n_domain_groups = sidcount;
312                 server_info->domain_groups = dgrps;
313
314                 /* Where are the 'global' sids?... */
315         }
316
317         if (base->account_name.string) {
318                 server_info->account_name = talloc_reference(server_info, base->account_name.string);
319         } else {
320                 server_info->account_name = talloc_strdup(server_info, account_name);
321                 NT_STATUS_HAVE_NO_MEMORY(server_info->account_name);
322         }
323
324         server_info->domain_name = talloc_reference(server_info, base->domain.string);
325         server_info->full_name = talloc_reference(server_info, base->full_name.string);
326         server_info->logon_script = talloc_reference(server_info, base->logon_script.string);
327         server_info->profile_path = talloc_reference(server_info, base->profile_path.string);
328         server_info->home_directory = talloc_reference(server_info, base->home_directory.string);
329         server_info->home_drive = talloc_reference(server_info, base->home_drive.string);
330         server_info->logon_server = talloc_reference(server_info, base->logon_server.string);
331         server_info->last_logon = base->last_logon;
332         server_info->last_logoff = base->last_logoff;
333         server_info->acct_expiry = base->acct_expiry;
334         server_info->last_password_change = base->last_password_change;
335         server_info->allow_password_change = base->allow_password_change;
336         server_info->force_password_change = base->force_password_change;
337         server_info->logon_count = base->logon_count;
338         server_info->bad_password_count = base->bad_password_count;
339         server_info->acct_flags = base->acct_flags;
340
341         server_info->authenticated = True;
342
343         /* ensure we are never given NULL session keys */
344
345         if (all_zero(base->key.key, sizeof(base->key.key))) {
346                 server_info->user_session_key = data_blob(NULL, 0);
347         } else {
348                 server_info->user_session_key = data_blob_talloc(server_info, base->key.key, sizeof(base->key.key));
349                 NT_STATUS_HAVE_NO_MEMORY(server_info->user_session_key.data);
350         }
351
352         if (all_zero(base->LMSessKey.key, sizeof(base->LMSessKey.key))) {
353                 server_info->lm_session_key = data_blob(NULL, 0);
354         } else {
355                 server_info->lm_session_key = data_blob_talloc(server_info, base->LMSessKey.key, sizeof(base->LMSessKey.key));
356                 NT_STATUS_HAVE_NO_MEMORY(server_info->lm_session_key.data);
357         }
358
359         *_server_info = server_info;
360         return NT_STATUS_OK;
361 }
362
363
364 NTSTATUS auth_anonymous_server_info(TALLOC_CTX *mem_ctx, struct auth_serversupplied_info **_server_info) 
365 {
366         struct auth_serversupplied_info *server_info;
367         server_info = talloc(mem_ctx, struct auth_serversupplied_info);
368         NT_STATUS_HAVE_NO_MEMORY(server_info);
369
370         server_info->account_sid = dom_sid_parse_talloc(server_info, SID_NT_ANONYMOUS);
371         NT_STATUS_HAVE_NO_MEMORY(server_info->account_sid);
372
373         /* is this correct? */
374         server_info->primary_group_sid = dom_sid_parse_talloc(server_info, SID_BUILTIN_GUESTS);
375         NT_STATUS_HAVE_NO_MEMORY(server_info->primary_group_sid);
376
377         server_info->n_domain_groups = 0;
378         server_info->domain_groups = NULL;
379
380         /* annoying, but the Anonymous really does have a session key, 
381            and it is all zeros! */
382         server_info->user_session_key = data_blob_talloc(server_info, NULL, 16);
383         NT_STATUS_HAVE_NO_MEMORY(server_info->user_session_key.data);
384
385         server_info->lm_session_key = data_blob_talloc(server_info, NULL, 16);
386         NT_STATUS_HAVE_NO_MEMORY(server_info->lm_session_key.data);
387
388         data_blob_clear(&server_info->user_session_key);
389         data_blob_clear(&server_info->lm_session_key);
390
391         server_info->account_name = talloc_strdup(server_info, "ANONYMOUS LOGON");
392         NT_STATUS_HAVE_NO_MEMORY(server_info->account_name);
393
394         server_info->domain_name = talloc_strdup(server_info, "NT AUTHORITY");
395         NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name);
396
397         server_info->full_name = talloc_strdup(server_info, "Anonymous Logon");
398         NT_STATUS_HAVE_NO_MEMORY(server_info->full_name);
399
400         server_info->logon_script = talloc_strdup(server_info, "");
401         NT_STATUS_HAVE_NO_MEMORY(server_info->logon_script);
402
403         server_info->profile_path = talloc_strdup(server_info, "");
404         NT_STATUS_HAVE_NO_MEMORY(server_info->profile_path);
405
406         server_info->home_directory = talloc_strdup(server_info, "");
407         NT_STATUS_HAVE_NO_MEMORY(server_info->home_directory);
408
409         server_info->home_drive = talloc_strdup(server_info, "");
410         NT_STATUS_HAVE_NO_MEMORY(server_info->home_drive);
411
412         server_info->logon_server = talloc_strdup(server_info, lp_netbios_name());
413         NT_STATUS_HAVE_NO_MEMORY(server_info->logon_server);
414
415         server_info->last_logon = 0;
416         server_info->last_logoff = 0;
417         server_info->acct_expiry = 0;
418         server_info->last_password_change = 0;
419         server_info->allow_password_change = 0;
420         server_info->force_password_change = 0;
421
422         server_info->logon_count = 0;
423         server_info->bad_password_count = 0;
424
425         server_info->acct_flags = ACB_NORMAL;
426
427         server_info->authenticated = False;
428
429         *_server_info = server_info;
430
431         return NT_STATUS_OK;
432 }
433
434 NTSTATUS auth_system_server_info(TALLOC_CTX *mem_ctx, struct auth_serversupplied_info **_server_info) 
435 {
436         struct auth_serversupplied_info *server_info;
437         server_info = talloc(mem_ctx, struct auth_serversupplied_info);
438         NT_STATUS_HAVE_NO_MEMORY(server_info);
439
440         server_info->account_sid = dom_sid_parse_talloc(server_info, SID_NT_SYSTEM);
441         NT_STATUS_HAVE_NO_MEMORY(server_info->account_sid);
442
443         /* is this correct? */
444         server_info->primary_group_sid = dom_sid_parse_talloc(server_info, SID_BUILTIN_ADMINISTRATORS);
445         NT_STATUS_HAVE_NO_MEMORY(server_info->primary_group_sid);
446
447         server_info->n_domain_groups = 0;
448         server_info->domain_groups = NULL;
449
450         /* annoying, but the Anonymous really does have a session key, 
451            and it is all zeros! */
452         server_info->user_session_key = data_blob_talloc(server_info, NULL, 16);
453         NT_STATUS_HAVE_NO_MEMORY(server_info->user_session_key.data);
454
455         server_info->lm_session_key = data_blob_talloc(server_info, NULL, 16);
456         NT_STATUS_HAVE_NO_MEMORY(server_info->lm_session_key.data);
457
458         data_blob_clear(&server_info->user_session_key);
459         data_blob_clear(&server_info->lm_session_key);
460
461         server_info->account_name = talloc_strdup(server_info, "SYSTEM");
462         NT_STATUS_HAVE_NO_MEMORY(server_info->account_name);
463
464         server_info->domain_name = talloc_strdup(server_info, "NT AUTHORITY");
465         NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name);
466
467         server_info->full_name = talloc_strdup(server_info, "System");
468         NT_STATUS_HAVE_NO_MEMORY(server_info->full_name);
469
470         server_info->logon_script = talloc_strdup(server_info, "");
471         NT_STATUS_HAVE_NO_MEMORY(server_info->logon_script);
472
473         server_info->profile_path = talloc_strdup(server_info, "");
474         NT_STATUS_HAVE_NO_MEMORY(server_info->profile_path);
475
476         server_info->home_directory = talloc_strdup(server_info, "");
477         NT_STATUS_HAVE_NO_MEMORY(server_info->home_directory);
478
479         server_info->home_drive = talloc_strdup(server_info, "");
480         NT_STATUS_HAVE_NO_MEMORY(server_info->home_drive);
481
482         server_info->logon_server = talloc_strdup(server_info, lp_netbios_name());
483         NT_STATUS_HAVE_NO_MEMORY(server_info->logon_server);
484
485         server_info->last_logon = 0;
486         server_info->last_logoff = 0;
487         server_info->acct_expiry = 0;
488         server_info->last_password_change = 0;
489         server_info->allow_password_change = 0;
490         server_info->force_password_change = 0;
491
492         server_info->logon_count = 0;
493         server_info->bad_password_count = 0;
494
495         server_info->acct_flags = ACB_NORMAL;
496
497         server_info->authenticated = False;
498
499         *_server_info = server_info;
500
501         return NT_STATUS_OK;
502 }
503
504 NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx, 
505                                     struct auth_serversupplied_info *server_info, 
506                                     struct auth_session_info **_session_info) 
507 {
508         struct auth_session_info *session_info;
509         NTSTATUS nt_status;
510
511         session_info = talloc(mem_ctx, struct auth_session_info);
512         NT_STATUS_HAVE_NO_MEMORY(session_info);
513
514         session_info->server_info = talloc_reference(session_info, server_info);
515
516         /* unless set otherwise, the session key is the user session
517          * key from the auth subsystem */ 
518         session_info->session_key = server_info->user_session_key;
519
520         nt_status = security_token_create(session_info,
521                                           server_info->account_sid,
522                                           server_info->primary_group_sid,
523                                           server_info->n_domain_groups,
524                                           server_info->domain_groups,
525                                           server_info->authenticated,
526                                           &session_info->security_token);
527         NT_STATUS_NOT_OK_RETURN(nt_status);
528
529         session_info->credentials = NULL;
530
531         *_session_info = session_info;
532         return NT_STATUS_OK;
533 }
534
535 NTSTATUS auth_anonymous_session_info(TALLOC_CTX *parent_ctx, 
536                                      struct auth_session_info **_session_info) 
537 {
538         NTSTATUS nt_status;
539         struct auth_serversupplied_info *server_info = NULL;
540         struct auth_session_info *session_info = NULL;
541         TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
542         
543         nt_status = auth_anonymous_server_info(mem_ctx,
544                                                &server_info);
545         if (!NT_STATUS_IS_OK(nt_status)) {
546                 talloc_free(mem_ctx);
547                 return nt_status;
548         }
549
550         /* references the server_info into the session_info */
551         nt_status = auth_generate_session_info(parent_ctx, server_info, &session_info);
552         talloc_free(mem_ctx);
553
554         NT_STATUS_NOT_OK_RETURN(nt_status);
555
556         *_session_info = session_info;
557
558         return NT_STATUS_OK;
559 }
560
561 struct auth_session_info *anonymous_session(TALLOC_CTX *mem_ctx) 
562 {
563         NTSTATUS nt_status;
564         struct auth_session_info *session_info = NULL;
565         nt_status = auth_anonymous_session_info(mem_ctx, &session_info);
566         if (!NT_STATUS_IS_OK(nt_status)) {
567                 return NULL;
568         }
569         return session_info;
570 }
571
572 NTSTATUS auth_system_session_info(TALLOC_CTX *parent_ctx, 
573                                   struct auth_session_info **_session_info) 
574 {
575         NTSTATUS nt_status;
576         struct auth_serversupplied_info *server_info = NULL;
577         struct auth_session_info *session_info = NULL;
578         TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
579         
580         nt_status = auth_system_server_info(mem_ctx,
581                                             &server_info);
582         if (!NT_STATUS_IS_OK(nt_status)) {
583                 talloc_free(mem_ctx);
584                 return nt_status;
585         }
586
587         /* references the server_info into the session_info */
588         nt_status = auth_generate_session_info(parent_ctx, server_info, &session_info);
589         talloc_free(mem_ctx);
590
591         NT_STATUS_NOT_OK_RETURN(nt_status);
592
593         *_session_info = session_info;
594
595         return NT_STATUS_OK;
596 }
597
598 struct auth_session_info *system_session(TALLOC_CTX *mem_ctx) 
599 {
600         NTSTATUS nt_status;
601         struct auth_session_info *session_info = NULL;
602         nt_status = auth_system_session_info(mem_ctx, &session_info);
603         if (!NT_STATUS_IS_OK(nt_status)) {
604                 return NULL;
605         }
606         return session_info;
607 }
608
609 /****************************************************************************
610  prints a struct auth_session_info security token to debug output.
611 ****************************************************************************/
612 void auth_session_info_debug(int dbg_lev, 
613                              const struct auth_session_info *session_info)
614 {
615         if (!session_info) {
616                 DEBUGC(dbg_class, dbg_lev, ("Session Info: (NULL)\n"));
617                 return; 
618         }
619
620         security_token_debug(dbg_lev, session_info->security_token);
621 }
622
623 /**
624  * Squash an NT_STATUS in line with security requirements.
625  * In an attempt to avoid giving the whole game away when users
626  * are authenticating, NT replaces both NT_STATUS_NO_SUCH_USER and 
627  * NT_STATUS_WRONG_PASSWORD with NT_STATUS_LOGON_FAILURE in certain situations 
628  * (session setups in particular).
629  *
630  * @param nt_status NTSTATUS input for squashing.
631  * @return the 'squashed' nt_status
632  **/
633 NTSTATUS auth_nt_status_squash(NTSTATUS nt_status)
634 {
635         if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) {
636                 /* Match WinXP and don't give the game away */
637                 return NT_STATUS_LOGON_FAILURE;
638         } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) {
639                 /* Match WinXP and don't give the game away */
640                 return NT_STATUS_LOGON_FAILURE;
641         }
642
643         return nt_status;
644 }