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