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