3565fbd0dc5e5c56a57385e2d4c2e466e5cf3cc0
[ira/wip.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
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25 #include "librpc/gen_ndr/ndr_samr.h"
26 #include "librpc/gen_ndr/ndr_netlogon.h"
27
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_AUTH
30
31 /****************************************************************************
32  Create an auth_usersupplied_data structure
33 ****************************************************************************/
34 static NTSTATUS make_user_info(TALLOC_CTX *mem_ctx,
35                                struct auth_usersupplied_info **user_info, 
36                                const char *smb_name, 
37                                const char *internal_username,
38                                const char *client_domain, 
39                                const char *domain,
40                                const char *wksta_name, 
41                                DATA_BLOB *lm_password, DATA_BLOB *nt_password,
42                                DATA_BLOB *lm_interactive_password, DATA_BLOB *nt_interactive_password,
43                                DATA_BLOB *plaintext, 
44                                BOOL encrypted)
45 {
46
47         DEBUG(5,("attempting to make a user_info for %s (%s)\n", internal_username, smb_name));
48
49         *user_info = talloc_p(mem_ctx, struct auth_usersupplied_info);
50         if (!user_info) {
51                 return NT_STATUS_NO_MEMORY;
52         }
53
54         ZERO_STRUCTP(*user_info);
55
56         DEBUG(5,("making strings for %s's user_info struct\n", internal_username));
57
58         (*user_info)->smb_name.str = talloc_strdup(*user_info, smb_name);
59         if ((*user_info)->smb_name.str) { 
60                 (*user_info)->smb_name.len = strlen(smb_name);
61         } else {
62                 free_user_info(user_info);
63                 return NT_STATUS_NO_MEMORY;
64         }
65         
66         (*user_info)->internal_username.str = talloc_strdup(*user_info, internal_username);
67         if ((*user_info)->internal_username.str) { 
68                 (*user_info)->internal_username.len = strlen(internal_username);
69         } else {
70                 free_user_info(user_info);
71                 return NT_STATUS_NO_MEMORY;
72         }
73
74         (*user_info)->domain.str = talloc_strdup(*user_info, domain);
75         if ((*user_info)->domain.str) { 
76                 (*user_info)->domain.len = strlen(domain);
77         } else {
78                 free_user_info(user_info);
79                 return NT_STATUS_NO_MEMORY;
80         }
81
82         (*user_info)->client_domain.str = talloc_strdup(*user_info, client_domain);
83         if ((*user_info)->client_domain.str) { 
84                 (*user_info)->client_domain.len = strlen(client_domain);
85         } else {
86                 free_user_info(user_info);
87                 return NT_STATUS_NO_MEMORY;
88         }
89
90         (*user_info)->wksta_name.str = talloc_strdup(*user_info, wksta_name);
91         if ((*user_info)->wksta_name.str) { 
92                 (*user_info)->wksta_name.len = strlen(wksta_name);
93         } else {
94                 free_user_info(user_info);
95                 return NT_STATUS_NO_MEMORY;
96         }
97
98         DEBUG(5,("making blobs for %s's user_info struct\n", internal_username));
99
100         if (lm_password)
101                 (*user_info)->lm_resp = data_blob_talloc(*user_info, 
102                                                          lm_password->data, 
103                                                          lm_password->length);
104         if (nt_password)
105                 (*user_info)->nt_resp = data_blob_talloc(*user_info,
106                                                          nt_password->data, 
107                                                          nt_password->length);
108         if (lm_interactive_password)
109                 (*user_info)->lm_interactive_password = 
110                         data_blob_talloc(*user_info,
111                                          lm_interactive_password->data, 
112                                          lm_interactive_password->length);
113         if (nt_interactive_password)
114                 (*user_info)->nt_interactive_password = 
115                         data_blob_talloc(*user_info, 
116                                          nt_interactive_password->data, 
117                                          nt_interactive_password->length);
118
119         if (plaintext)
120                 (*user_info)->plaintext_password = 
121                         data_blob_talloc(*user_info, 
122                                          plaintext->data, 
123                                          plaintext->length);
124
125         (*user_info)->encrypted = encrypted;
126
127         DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted ? "":"un" , internal_username, smb_name));
128
129         return NT_STATUS_OK;
130 }
131
132 /****************************************************************************
133  Create an auth_usersupplied_data structure after appropriate mapping.
134 ****************************************************************************/
135
136 NTSTATUS make_user_info_map(TALLOC_CTX *mem_ctx,
137                             struct auth_usersupplied_info **user_info, 
138                             const char *smb_name, 
139                             const char *client_domain, 
140                             const char *wksta_name, 
141                             DATA_BLOB *lm_password, DATA_BLOB *nt_password,
142                             DATA_BLOB *lm_interactive_password, DATA_BLOB *nt_interactive_password,
143                             DATA_BLOB *plaintext, 
144                             BOOL encrypted)
145 {
146         const char *domain;
147         
148         DEBUG(5, ("make_user_info_map: Mapping user [%s]\\[%s] from workstation [%s]\n",
149               client_domain, smb_name, wksta_name));
150         
151         /* don't allow "" as a domain, fixes a Win9X bug 
152            where it doens't supply a domain for logon script
153            'net use' commands.                                 */
154
155         if ( *client_domain )
156                 domain = client_domain;
157         else
158                 domain = lp_workgroup();
159
160         /* we know that it is a trusted domain (and we are allowing
161            them) or it is our domain */
162         
163         return make_user_info(mem_ctx, 
164                               user_info, smb_name, smb_name, 
165                               client_domain, domain, wksta_name, 
166                               lm_password, nt_password,
167                               lm_interactive_password, nt_interactive_password,
168                               plaintext, encrypted);
169 }
170
171 /****************************************************************************
172  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
173  Decrypt and encrypt the passwords.
174 ****************************************************************************/
175
176 NTSTATUS make_user_info_netlogon_network(TALLOC_CTX *mem_ctx,
177                                          struct auth_usersupplied_info **user_info, 
178                                          const char *smb_name, 
179                                          const char *client_domain, 
180                                          const char *wksta_name, 
181                                          const uint8_t *lm_network_password, int lm_password_len,
182                                          const uint8_t *nt_network_password, int nt_password_len)
183 {
184         NTSTATUS nt_status;
185         DATA_BLOB lm_blob = data_blob(lm_network_password, lm_password_len);
186         DATA_BLOB nt_blob = data_blob(nt_network_password, nt_password_len);
187
188         nt_status = make_user_info_map(mem_ctx,
189                                        user_info,
190                                        smb_name, client_domain, 
191                                        wksta_name, 
192                                        lm_password_len ? &lm_blob : NULL, 
193                                        nt_password_len ? &nt_blob : NULL,
194                                        NULL, NULL, NULL,
195                                        True);
196         
197         data_blob_free(&lm_blob);
198         data_blob_free(&nt_blob);
199         return nt_status;
200 }
201
202 /****************************************************************************
203  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
204  Decrypt and encrypt the passwords.
205 ****************************************************************************/
206
207 NTSTATUS make_user_info_netlogon_interactive(TALLOC_CTX *mem_ctx,
208                                              struct auth_usersupplied_info **user_info, 
209                                              const char *smb_name, 
210                                              const char *client_domain, 
211                                              const char *wksta_name, 
212                                              const uint8_t chal[8], 
213                                              const struct samr_Password *lm_interactive_password, 
214                                              const struct samr_Password *nt_interactive_password)
215 {
216         NTSTATUS nt_status;
217         DATA_BLOB local_lm_blob;
218         DATA_BLOB local_nt_blob;
219         
220         DATA_BLOB lm_interactive_blob;
221         DATA_BLOB nt_interactive_blob;
222         uint8_t local_lm_response[24];
223         uint8_t local_nt_response[24];
224         
225         SMBOWFencrypt(lm_interactive_password->hash, chal, local_lm_response);
226         SMBOWFencrypt(nt_interactive_password->hash, chal, local_nt_response);
227         
228         local_lm_blob = data_blob(local_lm_response, 
229                                   sizeof(local_lm_response));
230         lm_interactive_blob = data_blob(lm_interactive_password->hash, 
231                                         sizeof(lm_interactive_password->hash));
232         
233         local_nt_blob = data_blob(local_nt_response, 
234                                   sizeof(local_nt_response));
235         nt_interactive_blob = data_blob(nt_interactive_password->hash, 
236                                         sizeof(nt_interactive_password->hash));
237         
238         nt_status = make_user_info_map(mem_ctx,
239                                        user_info, 
240                                        smb_name, client_domain, 
241                                        wksta_name, 
242                                        &local_lm_blob,
243                                        &local_nt_blob,
244                                        &lm_interactive_blob,
245                                        &nt_interactive_blob,
246                                        NULL,
247                                        True);
248         
249         data_blob_free(&local_lm_blob);
250         data_blob_free(&local_nt_blob);
251         data_blob_free(&lm_interactive_blob);
252         data_blob_free(&nt_interactive_blob);
253         return nt_status;
254 }
255 /****************************************************************************
256  Create an auth_usersupplied_data structure
257 ****************************************************************************/
258
259 NTSTATUS make_user_info_for_reply_enc(TALLOC_CTX *mem_ctx,
260                                       struct auth_usersupplied_info **user_info, 
261                                       const char *smb_name,
262                                       const char *client_domain, 
263                                       const char *remote_machine,
264                                       DATA_BLOB lm_resp, DATA_BLOB nt_resp)
265 {
266         return make_user_info_map(mem_ctx,
267                                   user_info, smb_name, 
268                                   client_domain, 
269                                   remote_machine,
270                                   lm_resp.data ? &lm_resp : NULL, 
271                                   nt_resp.data ? &nt_resp : NULL, 
272                                   NULL, NULL, NULL,
273                                   True);
274 }
275
276 /****************************************************************************
277  Create a guest user_info blob, for anonymous authenticaion.
278 ****************************************************************************/
279
280 BOOL make_user_info_guest(TALLOC_CTX *mem_ctx,
281                           struct auth_usersupplied_info **user_info) 
282 {
283         NTSTATUS nt_status;
284
285         nt_status = make_user_info(mem_ctx,
286                                    user_info, 
287                                    "","", 
288                                    "","", 
289                                    "", 
290                                    NULL, NULL, 
291                                    NULL, NULL, 
292                                    NULL,
293                                    True);
294                               
295         return NT_STATUS_IS_OK(nt_status) ? True : False;
296 }
297
298 /****************************************************************************
299  prints a NT_USER_TOKEN to debug output.
300 ****************************************************************************/
301
302 void debug_nt_user_token(int dbg_class, int dbg_lev, const NT_USER_TOKEN *token)
303 {
304         TALLOC_CTX *mem_ctx;
305
306         size_t     i;
307         
308         if (!token) {
309                 DEBUGC(dbg_class, dbg_lev, ("NT user token: (NULL)\n"));
310                 return;
311         }
312         
313         mem_ctx = talloc_init("debug_nt_user_token()");
314         if (!mem_ctx) {
315                 return;
316         }
317
318         DEBUGC(dbg_class, dbg_lev, ("NT user token of user %s\n",
319                                     dom_sid_string(mem_ctx, token->user_sids[0]) ));
320         DEBUGADDC(dbg_class, dbg_lev, ("contains %lu SIDs\n", (unsigned long)token->num_sids));
321         for (i = 0; i < token->num_sids; i++)
322                 DEBUGADDC(dbg_class, dbg_lev, ("SID[%3lu]: %s\n", (unsigned long)i, 
323                                                dom_sid_string(mem_ctx, token->user_sids[i])));
324
325         talloc_destroy(mem_ctx);
326 }
327
328 /****************************************************************************
329  prints a NT_USER_TOKEN to debug output.
330 ****************************************************************************/
331
332 void debug_session_info(int dbg_class, int dbg_lev, const struct auth_session_info *session_info)
333 {
334         if (!session_info) {
335                 DEBUGC(dbg_class, dbg_lev, ("Session Info: (NULL)\n"));
336                 return; 
337         }
338
339         debug_nt_user_token(dbg_class, dbg_lev, session_info->nt_user_token);
340 }
341
342 /****************************************************************************
343  Create the SID list for this user.
344 ****************************************************************************/
345
346 NTSTATUS create_nt_user_token(TALLOC_CTX *mem_ctx, 
347                               struct dom_sid *user_sid, struct dom_sid *group_sid, 
348                               int n_groupSIDs, struct dom_sid **groupSIDs, 
349                               BOOL is_guest, struct nt_user_token **token)
350 {
351         NTSTATUS       nt_status = NT_STATUS_OK;
352         struct nt_user_token *ptoken;
353         int i;
354         int sid_ndx;
355         
356         if (!(ptoken = talloc_p(mem_ctx, struct nt_user_token))) {
357                 DEBUG(0, ("create_nt_token: Out of memory allocating token\n"));
358                 nt_status = NT_STATUS_NO_MEMORY;
359                 return nt_status;
360         }
361
362         ptoken->num_sids = 0;
363
364         if (!(ptoken->user_sids = talloc_array_p(mem_ctx, struct dom_sid*, n_groupSIDs + 5))) {
365                 DEBUG(0, ("create_nt_token: Out of memory allocating SIDs\n"));
366                 nt_status = NT_STATUS_NO_MEMORY;
367                 return nt_status;
368         }
369         
370         /*
371          * Note - user SID *MUST* be first in token !
372          * se_access_check depends on this.
373          *
374          * Primary group SID is second in token. Convention.
375          */
376
377         ptoken->user_sids[PRIMARY_USER_SID_INDEX] = user_sid;
378         ptoken->num_sids++;
379         ptoken->user_sids[PRIMARY_GROUP_SID_INDEX] = group_sid;
380         ptoken->num_sids++;
381
382         /*
383          * Finally add the "standard" SIDs.
384          * The only difference between guest and "anonymous" (which we
385          * don't really support) is the addition of Authenticated_Users.
386          */
387         ptoken->user_sids[2] = dom_sid_parse_talloc(mem_ctx, SID_WORLD);
388         ptoken->user_sids[3] = dom_sid_parse_talloc(mem_ctx, SID_NETWORK);
389
390         if (is_guest) {
391                 ptoken->user_sids[4] = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN_GUESTS);
392                 ptoken->num_sids++;
393         } else {
394                 ptoken->user_sids[4] = dom_sid_parse_talloc(mem_ctx, SID_AUTHENTICATED_USERS);
395                 ptoken->num_sids++;
396         }
397
398         sid_ndx = 5; /* next available spot */
399
400         for (i = 0; i < n_groupSIDs; i++) {
401                 size_t check_sid_idx;
402                 for (check_sid_idx = 1; check_sid_idx < ptoken->num_sids; check_sid_idx++) {
403                         if (sid_equal(ptoken->user_sids[check_sid_idx], 
404                                       groupSIDs[i])) {
405                                 break;
406                         }
407                 }
408                 
409                 if (check_sid_idx >= ptoken->num_sids) /* Not found already */ {
410                         ptoken->user_sids[sid_ndx++] = groupSIDs[i];
411                         ptoken->num_sids++;
412                 }
413         }
414         
415         debug_nt_user_token(DBGC_AUTH, 10, ptoken);
416         
417         *token = ptoken;
418
419         return nt_status;
420 }
421
422 /***************************************************************************
423  Make a user_info struct
424 ***************************************************************************/
425
426 NTSTATUS make_server_info(const TALLOC_CTX *mem_ctx,
427                           struct auth_serversupplied_info **server_info, 
428                           const char *username)
429 {
430         *server_info = talloc_p(mem_ctx, struct auth_serversupplied_info);
431         if (!*server_info) {
432                 return NT_STATUS_NO_MEMORY;
433         }
434         ZERO_STRUCTP(*server_info);
435         
436         return NT_STATUS_OK;
437 }
438
439 /***************************************************************************
440  Make (and fill) a user_info struct for a guest login.
441 ***************************************************************************/
442 NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx, struct auth_serversupplied_info **server_info)
443 {
444         NTSTATUS nt_status;
445
446         nt_status = make_server_info(mem_ctx, server_info, "");
447
448         if (!NT_STATUS_IS_OK(nt_status)) {
449                 return nt_status;
450         }
451         
452         (*server_info)->guest = True;
453
454         (*server_info)->user_sid = dom_sid_parse_talloc((*server_info), SID_ANONYMOUS);
455         (*server_info)->primary_group_sid = dom_sid_parse_talloc((*server_info), SID_BUILTIN_GUESTS);
456         (*server_info)->n_domain_groups = 0;
457         (*server_info)->domain_groups = NULL;
458         
459         /* annoying, but the Guest really does have a session key, 
460            and it is all zeros! */
461         (*server_info)->user_session_key = data_blob_talloc(*server_info, NULL, 16);
462         (*server_info)->lm_session_key = data_blob_talloc(*server_info, NULL, 16);
463
464         data_blob_clear(&(*server_info)->user_session_key);
465         data_blob_clear(&(*server_info)->lm_session_key);
466
467         (*server_info)->account_name = "";
468         (*server_info)->domain = "";
469         (*server_info)->full_name = "Anonymous";
470         (*server_info)->logon_script = "";
471         (*server_info)->profile_path = "";
472         (*server_info)->home_directory = "";
473         (*server_info)->home_drive = "";
474
475         (*server_info)->last_logon = 0;
476         (*server_info)->last_logoff = 0;
477         (*server_info)->acct_expiry = 0;
478         (*server_info)->last_password_change = 0;
479         (*server_info)->allow_password_change = 0;
480         (*server_info)->force_password_change = 0;
481
482         (*server_info)->logon_count = 0;
483         (*server_info)->bad_password_count = 0;
484
485         (*server_info)->acct_flags = ACB_NORMAL;
486
487         return nt_status;
488 }
489
490 /***************************************************************************
491  Make a server_info struct from the info3 returned by a domain logon 
492 ***************************************************************************/
493
494 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, 
495                                 const char *internal_username,
496                                 struct auth_serversupplied_info **server_info, 
497                                 struct netr_SamInfo3 *info3) 
498 {
499         NTSTATUS nt_status;
500
501         nt_status = make_server_info(mem_ctx, server_info, internal_username);
502
503         if (!NT_STATUS_IS_OK(nt_status)) {
504                 return nt_status;
505         }
506         
507         (*server_info)->guest = False;
508
509         /* 
510            Here is where we should check the list of
511            trusted domains, and verify that the SID 
512            matches.
513         */
514
515         (*server_info)->user_sid = dom_sid_add_rid(*server_info, dom_sid_dup(*server_info, info3->base.domain_sid), info3->base.rid);
516         (*server_info)->primary_group_sid = dom_sid_add_rid(*server_info, dom_sid_dup(*server_info, info3->base.domain_sid), info3->base.primary_gid);
517
518         /* TODO: pull in other groups: */
519
520         
521         (*server_info)->domain_groups = talloc_array_p((*server_info), struct dom_sid*, info3->base.group_count);
522         if (!(*server_info)->domain_groups) {
523                 return NT_STATUS_NO_MEMORY;
524         }
525         
526         for ((*server_info)->n_domain_groups = 0;
527              (*server_info)->n_domain_groups < info3->base.group_count; 
528              (*server_info)->n_domain_groups++) {
529                 struct dom_sid *sid;
530                 sid = dom_sid_dup(*server_info, info3->base.domain_sid);
531                 if (!sid) {
532                         return NT_STATUS_NO_MEMORY;
533                 }
534                 (*server_info)->domain_groups[(*server_info)->n_domain_groups]
535                         = dom_sid_add_rid(*server_info, sid, 
536                                           info3->base.groupids[(*server_info)->n_domain_groups].rid);
537                 if (!(*server_info)->domain_groups[(*server_info)->n_domain_groups]) {
538                         return NT_STATUS_NO_MEMORY;
539                 }
540         }
541
542         if (info3->base.account_name.string) {
543                 (*server_info)->account_name = talloc_reference(*server_info, info3->base.account_name.string);
544         } else {
545                 (*server_info)->account_name = talloc_strdup(*server_info, internal_username);
546         }
547
548         if (info3->base.domain.string) {
549                 (*server_info)->domain = talloc_reference(*server_info, info3->base.domain.string);
550         } else {
551                 (*server_info)->domain = NULL;
552         }
553
554         if (info3->base.full_name.string) {
555         (*server_info)->full_name = talloc_reference(*server_info, info3->base.full_name.string);
556         } else {
557                 (*server_info)->full_name = NULL;
558         }
559
560         if (info3->base.logon_script.string) {
561                 (*server_info)->logon_script = talloc_reference(*server_info, info3->base.logon_script.string);
562         } else {
563                 (*server_info)->logon_script = NULL;
564         }
565
566         if (info3->base.profile_path.string) {
567                 (*server_info)->profile_path = talloc_reference(*server_info, info3->base.profile_path.string);
568         } else {
569                 (*server_info)->profile_path = NULL;
570         }
571         
572         if (info3->base.home_directory.string) {
573                 (*server_info)->home_directory = talloc_reference(*server_info, info3->base.home_directory.string);
574         } else {
575                 (*server_info)->home_directory = NULL;
576         }
577
578         if (info3->base.home_drive.string) {
579                 (*server_info)->home_drive = talloc_reference(*server_info, info3->base.home_drive.string);
580         } else {
581                 (*server_info)->home_drive = NULL;
582         }
583         (*server_info)->last_logon = info3->base.last_logon;
584         (*server_info)->last_logoff = info3->base.last_logoff;
585         (*server_info)->acct_expiry = info3->base.acct_expiry;
586         (*server_info)->last_password_change = info3->base.last_password_change;
587         (*server_info)->allow_password_change = info3->base.allow_password_change;
588         (*server_info)->force_password_change = info3->base.force_password_change;
589
590         (*server_info)->logon_count = info3->base.logon_count;
591         (*server_info)->bad_password_count = info3->base.bad_password_count;
592
593         (*server_info)->acct_flags = info3->base.acct_flags;
594
595         /* ensure we are never given NULL session keys */
596         
597         if (all_zero(info3->base.key.key, sizeof(info3->base.key.key))) {
598                 (*server_info)->user_session_key = data_blob(NULL, 0);
599         } else {
600                 (*server_info)->user_session_key = data_blob_talloc((*server_info), info3->base.key.key, sizeof(info3->base.key.key));
601         }
602
603         if (all_zero(info3->base.LMSessKey.key, sizeof(info3->base.LMSessKey.key))) {
604                 (*server_info)->lm_session_key = data_blob(NULL, 0);
605         } else {
606                 (*server_info)->lm_session_key = data_blob_talloc((*server_info), info3->base.LMSessKey.key, sizeof(info3->base.LMSessKey.key));
607         }
608         return NT_STATUS_OK;
609 }
610
611 /***************************************************************************
612  Free a user_info struct
613 ***************************************************************************/
614
615 void free_user_info(struct auth_usersupplied_info **user_info)
616 {
617         DEBUG(5,("attempting to free (and zero) a user_info structure\n"));
618         if (*user_info) {
619                 data_blob_clear(&(*user_info)->plaintext_password);
620         }
621
622         talloc_free(*user_info);
623         *user_info = NULL;
624 }
625
626 /***************************************************************************
627  Clear out a server_info struct that has been allocated
628 ***************************************************************************/
629
630 void free_server_info(struct auth_serversupplied_info **server_info)
631 {
632         DEBUG(5,("attempting to free a server_info structure\n"));
633         talloc_free(*server_info);
634         *server_info = NULL;
635 }
636
637 /***************************************************************************
638  Make an auth_methods struct
639 ***************************************************************************/
640
641 BOOL make_auth_methods(struct auth_context *auth_context, struct auth_methods **auth_method) 
642 {
643         if (!auth_context) {
644                 smb_panic("no auth_context supplied to make_auth_methods()!\n");
645         }
646
647         if (!auth_method) {
648                 smb_panic("make_auth_methods: pointer to auth_method pointer is NULL!\n");
649         }
650
651         *auth_method = talloc_p(auth_context, struct auth_methods);
652         if (!*auth_method) {
653                 return False;
654         }
655         ZERO_STRUCTP(*auth_method);
656         
657         return True;
658 }
659
660 NTSTATUS make_session_info(TALLOC_CTX *mem_ctx, 
661                            struct auth_serversupplied_info *server_info, 
662                            struct auth_session_info **session_info) 
663 {
664         NTSTATUS nt_status;
665
666         *session_info = talloc_p(mem_ctx, struct auth_session_info);
667         if (!*session_info) {
668                 return NT_STATUS_NO_MEMORY;
669         }
670         
671         (*session_info)->server_info = server_info;
672         talloc_reference(*session_info, (*session_info)->server_info);
673
674         /* unless set otherwise, the session key is the user session
675          * key from the auth subsystem */
676  
677         (*session_info)->session_key = server_info->user_session_key;
678         
679         nt_status = create_nt_user_token((*session_info), 
680                                          server_info->user_sid, 
681                                          server_info->primary_group_sid, 
682                                          server_info->n_domain_groups, 
683                                          server_info->domain_groups,
684                                          False, 
685                                          &(*session_info)->nt_user_token);
686         
687         return nt_status;
688 }
689
690 /***************************************************************************
691  Clear out a server_info struct that has been allocated
692 ***************************************************************************/
693
694 void free_session_info(struct auth_session_info **session_info)
695 {
696         DEBUG(5,("attempting to free a session_info structure\n"));
697         talloc_free((*session_info));
698         *session_info = NULL;
699 }
700
701 /**
702  * Squash an NT_STATUS in line with security requirements.
703  * In an attempt to avoid giving the whole game away when users
704  * are authenticating, NT replaces both NT_STATUS_NO_SUCH_USER and 
705  * NT_STATUS_WRONG_PASSWORD with NT_STATUS_LOGON_FAILURE in certain situations 
706  * (session setups in particular).
707  *
708  * @param nt_status NTSTATUS input for squashing.
709  * @return the 'squashed' nt_status
710  **/
711
712 NTSTATUS nt_status_squash(NTSTATUS nt_status)
713 {
714         if NT_STATUS_IS_OK(nt_status) {
715                 return nt_status;               
716         } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) {
717                 /* Match WinXP and don't give the game away */
718                 return NT_STATUS_LOGON_FAILURE;
719                 
720         } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) {
721                 /* Match WinXP and don't give the game away */
722                 return NT_STATUS_LOGON_FAILURE;
723         } else {
724                 return nt_status;
725         }  
726 }
727
728
729