d442f73a9365ef886061283a928e31d959faa438
[ira/wip.git] / source3 / auth / auth_util.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Authentication utility functions
5    Copyright (C) Andrew Tridgell 1992-1998
6    Copyright (C) Andrew Bartlett 2001
7    Copyright (C) Jeremy Allison 2000-2001
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
26 /* Data to do lanman1/2 password challenge. */
27 static unsigned char saved_challenge[8];
28 static BOOL challenge_sent=False;
29 extern fstring remote_machine;
30 extern pstring global_myname;
31
32 /*******************************************************************
33  Get the next challenge value - no repeats.
34 ********************************************************************/
35
36 void generate_next_challenge(char *challenge)
37 {
38         unsigned char buf[8];
39
40         generate_random_buffer(buf,8,False);
41         memcpy(saved_challenge, buf, 8);
42         memcpy(challenge,buf,8);
43         challenge_sent = True;
44 }
45
46 /*******************************************************************
47  Set the last challenge sent, usually from a password server.
48 ********************************************************************/
49
50 BOOL set_challenge(unsigned char *challenge)
51 {
52         memcpy(saved_challenge,challenge,8);
53         challenge_sent = True;
54         return(True);
55 }
56
57 /*******************************************************************
58  Get the last challenge sent.
59 ********************************************************************/
60
61 BOOL last_challenge(unsigned char *challenge)
62 {
63         if (!challenge_sent)
64                 return(False);
65         memcpy(challenge,saved_challenge,8);
66         return(True);
67 }
68
69 /****************************************************************************
70  Create a UNIX user on demand.
71 ****************************************************************************/
72
73 static int smb_create_user(const char *unix_user, const char *homedir)
74 {
75         pstring add_script;
76         int ret;
77
78         pstrcpy(add_script, lp_adduser_script());
79         if (! *add_script)
80                 return -1;
81         all_string_sub(add_script, "%u", unix_user, sizeof(pstring));
82         if (homedir)
83                 all_string_sub(add_script, "%H", homedir, sizeof(pstring));
84         ret = smbrun(add_script,NULL);
85         DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret));
86         return ret;
87 }
88
89 /****************************************************************************
90  Delete a UNIX user on demand.
91 ****************************************************************************/
92
93 static int smb_delete_user(char *unix_user)
94 {
95         pstring del_script;
96         int ret;
97
98         pstrcpy(del_script, lp_deluser_script());
99         if (! *del_script)
100                 return -1;
101         all_string_sub(del_script, "%u", unix_user, sizeof(pstring));
102         ret = smbrun(del_script,NULL);
103         DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
104         return ret;
105 }
106
107 /****************************************************************************
108  Add and Delete UNIX users on demand, based on NTSTATUS codes.
109 ****************************************************************************/
110
111 void smb_user_control(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info, NTSTATUS nt_status) 
112 {
113         struct passwd *pwd=NULL;
114
115         if (NT_STATUS_IS_OK(nt_status)) {
116
117                 if (!(server_info->sam_fill_level & SAM_FILL_UNIX)) {
118                         
119                         /*
120                          * User validated ok against Domain controller.
121                          * If the admin wants us to try and create a UNIX
122                          * user on the fly, do so.
123                          */
124                         
125                         if(lp_adduser_script() && !(pwd = Get_Pwnam(user_info->internal_username.str))) {
126                                 smb_create_user(user_info->internal_username.str, NULL);
127                         }
128                 } else {                        
129                         if(lp_adduser_script()) {
130                                 SMB_STRUCT_STAT st;
131                                 const char *home_dir = pdb_get_homedir(server_info->sam_account);
132                                 /*
133                                  * Also call smb_create_user if the users home directory
134                                  * doesn't exist. Used with winbindd to allow the script to
135                                  * create the home directory for a user mapped with winbindd.
136                                  */
137
138                                 if (home_dir && 
139                                     (sys_stat(home_dir, &st) == -1) && (errno == ENOENT)) {
140                                                 smb_create_user(user_info->internal_username.str, home_dir);
141                                 }
142                         }
143                 }
144         } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) {
145                 /*
146                  * User failed to validate ok against Domain controller.
147                  * If the failure was "user doesn't exist" and admin 
148                  * wants us to try and delete that UNIX user on the fly,
149                  * do so.
150                  */
151                 if (lp_deluser_script()) {
152                         smb_delete_user(user_info->internal_username.str);
153                 }
154         }
155 }
156
157 /****************************************************************************
158  Create an auth_usersupplied_data structure
159 ****************************************************************************/
160
161 BOOL make_user_info(auth_usersupplied_info **user_info, 
162                     char *smb_name, char *internal_username,
163                     char *client_domain, char *domain,
164                     char *wksta_name, DATA_BLOB sec_blob, 
165                     DATA_BLOB lm_pwd, DATA_BLOB nt_pwd,
166                     DATA_BLOB plaintext, 
167                     uint32 ntlmssp_flags, BOOL encrypted)
168 {
169
170         DEBUG(5,("attempting to make a user_info for %s (%s)\n", internal_username, smb_name));
171
172         *user_info = malloc(sizeof(**user_info));
173         if (!user_info) {
174                 DEBUG(0,("malloc failed for user_info (size %d)\n", sizeof(*user_info)));
175                 return False;
176         }
177
178         ZERO_STRUCTP(*user_info);
179
180         DEBUG(5,("makeing strings for %s's user_info struct\n", internal_username));
181
182         (*user_info)->smb_name.str = strdup(smb_name);
183         if ((*user_info)->smb_name.str) { 
184                 (*user_info)->smb_name.len = strlen(smb_name);
185         } else {
186                 free_user_info(user_info);
187                 return False;
188         }
189         
190         (*user_info)->internal_username.str = strdup(internal_username);
191         if ((*user_info)->internal_username.str) { 
192                 (*user_info)->internal_username.len = strlen(internal_username);
193         } else {
194                 free_user_info(user_info);
195                 return False;
196         }
197
198         (*user_info)->domain.str = strdup(domain);
199         if ((*user_info)->domain.str) { 
200                 (*user_info)->domain.len = strlen(domain);
201         } else {
202                 free_user_info(user_info);
203                 return False;
204         }
205
206         (*user_info)->client_domain.str = strdup(client_domain);
207         if ((*user_info)->client_domain.str) { 
208                 (*user_info)->client_domain.len = strlen(client_domain);
209         } else {
210                 free_user_info(user_info);
211                 return False;
212         }
213
214         (*user_info)->wksta_name.str = strdup(wksta_name);
215         if ((*user_info)->wksta_name.str) { 
216                 (*user_info)->wksta_name.len = strlen(wksta_name);
217         } else {
218                 free_user_info(user_info);
219                 return False;
220         }
221
222         DEBUG(5,("makeing blobs for %s's user_info struct\n", internal_username));
223
224         (*user_info)->sec_blob = data_blob(sec_blob.data, sec_blob.length);
225         (*user_info)->lm_resp = data_blob(lm_pwd.data, lm_pwd.length);
226         (*user_info)->nt_resp = data_blob(nt_pwd.data, nt_pwd.length);
227         (*user_info)->plaintext_password = data_blob(plaintext.data, plaintext.length);
228
229         (*user_info)->encrypted = encrypted;
230         (*user_info)->ntlmssp_flags = ntlmssp_flags;
231
232         DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted ? "":"un" , internal_username, smb_name));
233
234         return True;
235 }
236
237 /****************************************************************************
238  Create an auth_usersupplied_data structure after appropriate mapping.
239 ****************************************************************************/
240
241 BOOL make_user_info_map(auth_usersupplied_info **user_info, 
242                         char *smb_name, 
243                         char *client_domain, 
244                         char *wksta_name, DATA_BLOB sec_blob, 
245                         DATA_BLOB lm_pwd, DATA_BLOB nt_pwd,
246                         DATA_BLOB plaintext, 
247                         uint32 ntlmssp_flags, BOOL encrypted)
248 {
249         char *domain;
250         fstring internal_username;
251         fstrcpy(internal_username, smb_name);
252         map_username(internal_username); 
253         
254         if (lp_allow_trusted_domains()) {
255                 domain = client_domain;
256         } else {
257                 domain = lp_workgroup();
258         }
259         
260         return make_user_info(user_info, 
261                               smb_name, internal_username,
262                               client_domain, domain,
263                               wksta_name, sec_blob,
264                               lm_pwd, nt_pwd,
265                               plaintext, 
266                               ntlmssp_flags, encrypted);
267         
268 }
269
270 /****************************************************************************
271  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
272  Decrupt and encrypt the passwords.
273 ****************************************************************************/
274
275 BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info, 
276                                      char *smb_name, 
277                                      char *client_domain, 
278                                      char *wksta_name, uchar chal[8],
279                                      uchar *lm_network_pwd, int lm_pwd_len,
280                                      uchar *nt_network_pwd, int nt_pwd_len)
281 {
282         BOOL ret;
283         DATA_BLOB sec_blob = data_blob(chal, sizeof(chal));
284         DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
285         DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
286         DATA_BLOB plaintext_blob = data_blob(NULL, 0);
287         uint32 ntlmssp_flags = 0;
288
289         if (lm_pwd_len)
290                 ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM;
291         if (nt_pwd_len == 24) {
292                 ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; 
293         } else if (nt_pwd_len != 0) {
294                 ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM2; 
295         }
296
297         ret = make_user_info_map(user_info, 
298                                  smb_name, client_domain, 
299                                  wksta_name, sec_blob, 
300                                  nt_blob, lm_blob,
301                                  plaintext_blob, 
302                                  ntlmssp_flags, True);
303                 
304         data_blob_free(&lm_blob);
305         data_blob_free(&nt_blob);
306         return ret;
307 }
308
309 /****************************************************************************
310  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
311  Decrupt and encrypt the passwords.
312 ****************************************************************************/
313
314 BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, 
315                                          char *smb_name, 
316                                          char *client_domain, 
317                                          char *wksta_name, 
318                                          uchar lm_interactive_pwd[16], 
319                                          uchar nt_interactive_pwd[16], 
320                                          uchar *dc_sess_key)
321 {
322         char lm_pwd[16];
323         char nt_pwd[16];
324         unsigned char local_lm_response[24];
325         unsigned char local_nt_response[24];
326         unsigned char key[16];
327         uint8 chal[8];
328         uint32 ntlmssp_flags = 0;
329         
330         generate_random_buffer(chal, 8, False);
331
332         ZERO_STRUCT(key);
333         memcpy(key, dc_sess_key, 8);
334         
335         if (lm_interactive_pwd) memcpy(lm_pwd, lm_interactive_pwd, sizeof(lm_pwd));
336         if (nt_interactive_pwd) memcpy(nt_pwd, nt_interactive_pwd, sizeof(nt_pwd));
337         
338 #ifdef DEBUG_PASSWORD
339         DEBUG(100,("key:"));
340         dump_data(100, (char *)key, sizeof(key));
341         
342         DEBUG(100,("lm owf password:"));
343         dump_data(100, lm_pwd, sizeof(lm_pwd));
344         
345         DEBUG(100,("nt owf password:"));
346         dump_data(100, nt_pwd, sizeof(nt_pwd));
347 #endif
348         
349         SamOEMhash((uchar *)lm_pwd, key, sizeof(lm_pwd));
350         SamOEMhash((uchar *)nt_pwd, key, sizeof(nt_pwd));
351         
352 #ifdef DEBUG_PASSWORD
353         DEBUG(100,("decrypt of lm owf password:"));
354         dump_data(100, lm_pwd, sizeof(lm_pwd));
355         
356         DEBUG(100,("decrypt of nt owf password:"));
357         dump_data(100, nt_pwd, sizeof(nt_pwd));
358 #endif
359         
360         generate_random_buffer(chal, 8, False);
361         SMBOWFencrypt((const unsigned char *)lm_pwd, chal, local_lm_response);
362         SMBOWFencrypt((const unsigned char *)nt_pwd, chal, local_nt_response);
363         
364         /* Password info parinoia */
365         ZERO_STRUCT(lm_pwd);
366         ZERO_STRUCT(nt_pwd);
367         ZERO_STRUCT(key);
368
369         {
370                 BOOL ret;
371                 DATA_BLOB sec_blob = data_blob(chal, sizeof(chal));
372                 DATA_BLOB local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response));
373                 DATA_BLOB local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response));
374                 DATA_BLOB plaintext_blob = data_blob(NULL, 0);
375
376                 if (lm_interactive_pwd)
377                         ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM;
378                 if (nt_interactive_pwd)
379                         ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; 
380
381                 ret = make_user_info_map(user_info, 
382                                          smb_name, client_domain, 
383                                          wksta_name, sec_blob, 
384                                          local_lm_blob,
385                                          local_nt_blob,
386                                          plaintext_blob, 
387                                          ntlmssp_flags, True);
388                 
389                 data_blob_free(&local_lm_blob);
390                 data_blob_free(&local_nt_blob);
391                 return ret;
392         }
393 }
394
395 /****************************************************************************
396  Create an auth_usersupplied_data structure
397 ****************************************************************************/
398
399 BOOL make_user_info_winbind(auth_usersupplied_info **user_info, 
400                             char *username,
401                             char *domain, 
402                             char *password)
403 {
404         unsigned char local_lm_response[24];
405         unsigned char local_nt_response[24];
406         char chal[8];
407         DATA_BLOB local_lm_blob;
408         DATA_BLOB local_nt_blob;
409         DATA_BLOB plaintext_blob;
410         uint32 ntlmssp_flags = 0;
411
412         /*
413          * Not encrypted - do so.
414          */
415         
416         DEBUG(5,("pass_check_smb: User passwords not in encrypted format.\n"));
417         
418         generate_random_buffer(chal, 8, False);
419
420         if (*password) {
421                 SMBencrypt( (uchar *)password, chal, local_lm_response);
422                 
423                 /* This encrypts the lm_pwd feild, which actualy contains the password
424                    rather than the nt_pwd field becouse that contains nothing */
425                 
426                 /* WATCH OUT. This doesn't work if the incoming password is incorrectly cased. 
427                    We might want to add a check here and only do an LM in that case */
428                 
429                 SMBNTencrypt((uchar *)password, chal, local_nt_response);
430
431                 local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response));
432                 local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response));
433                 plaintext_blob = data_blob(password, strlen(password)+1);
434                 if ((!local_lm_blob.data) || (!local_nt_blob.data)|| (!plaintext_blob.data)) {
435                         data_blob_free(&local_lm_blob);
436                         data_blob_free(&local_nt_blob);
437                         data_blob_clear_free(&plaintext_blob);
438                         return False;
439                 }
440                 ntlmssp_flags = NTLMSSP_NEGOTIATE_OEM | NTLMSSP_NEGOTIATE_NTLM;
441         } else {
442                 local_lm_blob = data_blob(NULL, 0);
443                 local_nt_blob = data_blob(NULL, 0);
444                 plaintext_blob = data_blob(NULL, 0);
445         }
446
447         {
448                 BOOL ret;
449                 DATA_BLOB sec_blob = data_blob(chal, sizeof(chal));
450                 
451                 if (!sec_blob.data) {
452                         return False;
453                 }
454
455                 ret = make_user_info(user_info, 
456                                      username, username,
457                                      domain, domain, 
458                                      global_myname, sec_blob, 
459                                      local_nt_blob,
460                                      local_lm_blob,
461                                      plaintext_blob, 
462                                      ntlmssp_flags, False);
463                 
464                 data_blob_free(&local_lm_blob);
465                 data_blob_free(&local_nt_blob);
466                 data_blob_clear_free(&plaintext_blob);
467                 return ret;
468         }
469 }
470
471 /****************************************************************************
472  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
473  Decrupt and encrypt the passwords.
474 ****************************************************************************/
475
476 BOOL make_user_info_winbind_crap(auth_usersupplied_info **user_info, 
477                                  char *smb_name, 
478                                  char *client_domain, 
479                                  uchar chal[8],
480                                  uchar *lm_network_pwd, int lm_pwd_len,
481                                  uchar *nt_network_pwd, int nt_pwd_len)
482 {
483         BOOL ret;
484         DATA_BLOB sec_blob = data_blob(chal, sizeof(chal));
485         DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
486         DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
487         DATA_BLOB plaintext_blob = data_blob(NULL, 0);
488         uint32 ntlmssp_flags = 0;
489
490         if (lm_pwd_len)
491                 ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM;
492         if (nt_pwd_len)
493                 ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; 
494         
495         ret = make_user_info(user_info, 
496                              smb_name, smb_name, 
497                              client_domain, client_domain, 
498                              global_myname, sec_blob, 
499                              nt_blob, lm_blob,
500                              plaintext_blob, 
501                              ntlmssp_flags, True);
502
503         data_blob_free(&lm_blob);
504         data_blob_free(&nt_blob);
505         return ret;
506 }
507
508 /****************************************************************************
509  Create an auth_usersupplied_data structure
510 ****************************************************************************/
511
512 BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, 
513                               char *smb_name,
514                               char *client_domain, 
515                               DATA_BLOB lm_resp, DATA_BLOB nt_resp,
516                               DATA_BLOB plaintext_password,
517                               BOOL encrypted)
518 {
519         uchar chal[8];
520
521         DATA_BLOB local_lm_blob;
522         DATA_BLOB local_nt_blob;
523         DATA_BLOB sec_blob;
524         BOOL ret = False;
525         uint32 ntlmssp_flags = 0;
526                         
527         if (encrypted) {
528                 DATA_BLOB no_plaintext_blob = data_blob(NULL, 0); 
529                 if (!last_challenge(chal)) {
530                         DEBUG(0,("Encrypted login but no challange set!\n"));
531                         return False;
532                 }
533                 sec_blob = data_blob(chal, 8);
534                 
535                 if (lm_resp.length == 24) {
536                         ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM;
537                 }
538                 if (nt_resp.length == 0) {
539                 } else if (nt_resp.length == 24) {
540                         ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM;
541                 } else {
542                         ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM2;
543                 }
544
545                 return make_user_info_map(user_info, smb_name, 
546                                           client_domain, 
547                                           remote_machine, sec_blob,
548                                           lm_resp, 
549                                           nt_resp, 
550                                           no_plaintext_blob, 
551                                           ntlmssp_flags, encrypted);
552         }
553
554         generate_random_buffer(chal, 8, False);
555
556         sec_blob = data_blob(chal, 8);
557         
558         /*
559          * Not encrypted - do so.
560          */
561         
562         DEBUG(5,("pass_check_smb: User passwords not in encrypted format.\n"));
563         
564         if (plaintext_password.data) {
565                 unsigned char local_lm_response[24];
566
567                 SMBencrypt( (uchar *)plaintext_password.data, chal, local_lm_response);
568                 local_lm_blob = data_blob(local_lm_response, 24);
569                 
570                 /* We can't do an NT hash here, as the password needs to be case insensitive */
571                 local_nt_blob = data_blob(NULL, 0); 
572                 
573                 ntlmssp_flags = NTLMSSP_NEGOTIATE_OEM;
574         } else {
575                 local_lm_blob = data_blob(NULL, 0); 
576                 local_nt_blob = data_blob(NULL, 0); 
577         }
578         
579         ret = make_user_info_map(user_info, smb_name,
580                                  client_domain, 
581                                  remote_machine,
582                                  sec_blob,
583                                  local_lm_blob,
584                                  local_nt_blob,
585                                  plaintext_password, 
586                                  ntlmssp_flags, encrypted);
587         
588         data_blob_free(&local_lm_blob);
589         return ret;
590 }
591
592 /****************************************************************************
593  Create a guest user_info blob, for anonymous authenticaion.
594 ****************************************************************************/
595
596 BOOL make_user_info_guest(auth_usersupplied_info **user_info) 
597 {
598         DATA_BLOB sec_blob = data_blob(NULL, 0);
599         DATA_BLOB lm_blob = data_blob(NULL, 0);
600         DATA_BLOB nt_blob = data_blob(NULL, 0);
601         DATA_BLOB plaintext_blob = data_blob(NULL, 0);
602         uint32 ntlmssp_flags = 0;
603
604         return make_user_info(user_info, 
605                               "","", 
606                               "","", 
607                               "", sec_blob, 
608                               nt_blob, lm_blob,
609                               plaintext_blob, 
610                               ntlmssp_flags, True);
611 }
612
613 BOOL make_server_info(auth_serversupplied_info **server_info) 
614 {
615         *server_info = malloc(sizeof(**server_info));
616         if (!*server_info) {
617                 DEBUG(0,("make_server_info_sam: malloc failed!\n"));
618                 return False;
619         }
620         ZERO_STRUCTP(*server_info);
621         return True;
622 }
623
624 BOOL make_server_info_sam(auth_serversupplied_info **server_info, SAM_ACCOUNT *sampass) 
625 {
626         if (!make_server_info(server_info)) {
627                 return False;
628         }
629
630         (*server_info)->sam_fill_level = SAM_FILL_ALL;
631         (*server_info)->sam_account = sampass;
632
633         DEBUG(5,("make_server_info_sam: made sever info for user %s\n",
634                  pdb_get_username((*server_info)->sam_account)));
635         return True;
636 }
637
638 BOOL make_server_info_pw(auth_serversupplied_info **server_info, struct passwd *pwd)
639 {
640         SAM_ACCOUNT *sampass = NULL;
641         if (!pdb_init_sam_pw(&sampass, pwd)) {          
642                 return False;
643         }
644         return make_server_info_sam(server_info, sampass);
645 }
646
647 void free_user_info(auth_usersupplied_info **user_info)
648 {
649         DEBUG(5,("attempting to free (and zero) a user_info structure\n"));
650         if (*user_info != NULL) {
651                 if ((*user_info)->smb_name.str) {
652                         DEBUG(10,("structure was created for %s\n", (*user_info)->smb_name.str));
653                 }
654                 SAFE_FREE((*user_info)->smb_name.str);
655                 SAFE_FREE((*user_info)->internal_username.str);
656                 SAFE_FREE((*user_info)->client_domain.str);
657                 SAFE_FREE((*user_info)->domain.str);
658                 data_blob_free(&(*user_info)->sec_blob);
659                 data_blob_free(&(*user_info)->lm_resp);
660                 data_blob_free(&(*user_info)->nt_resp);
661                 SAFE_FREE((*user_info)->interactive_password);
662                 data_blob_clear_free(&(*user_info)->plaintext_password);
663                 ZERO_STRUCT(**user_info);
664         }
665         SAFE_FREE(*user_info);
666 }
667
668 /***************************************************************************
669  Clear out a server_info struct that has been allocated
670 ***************************************************************************/
671
672 void free_server_info(auth_serversupplied_info **server_info)
673 {
674         if (*server_info != NULL) {
675                 pdb_free_sam(&(*server_info)->sam_account);
676                 
677                 /* call pam_end here, unless we know we are keeping it */
678                 delete_nt_token( &(*server_info)->ptok );
679                 ZERO_STRUCT(**server_info);
680         }
681         SAFE_FREE(*server_info);
682 }
683
684 /***************************************************************************
685  Make a server_info struct for a guest user 
686 ***************************************************************************/
687
688 BOOL make_server_info_guest(auth_serversupplied_info **server_info) 
689 {
690         struct passwd *pass = sys_getpwnam(lp_guestaccount());
691         
692         if (pass) {
693                 if (!make_server_info_pw(server_info, pass)) {
694                         return False;
695                 }
696                 (*server_info)->guest = True;
697                 return True;
698         }
699         DEBUG(0,("make_server_info_guest: sys_getpwnam() failed on guest account!\n")); 
700         return False;
701 }
702
703 /****************************************************************************
704  Delete a SID token.
705 ****************************************************************************/
706
707 void delete_nt_token(NT_USER_TOKEN **pptoken)
708 {
709     if (*pptoken) {
710                 NT_USER_TOKEN *ptoken = *pptoken;
711         SAFE_FREE( ptoken->user_sids );
712         ZERO_STRUCTP(ptoken);
713     }
714     SAFE_FREE(*pptoken);
715 }
716
717 /****************************************************************************
718  Duplicate a SID token.
719 ****************************************************************************/
720
721 NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken)
722 {
723         NT_USER_TOKEN *token;
724
725         if (!ptoken)
726                 return NULL;
727
728     if ((token = (NT_USER_TOKEN *)malloc( sizeof(NT_USER_TOKEN) ) ) == NULL)
729         return NULL;
730
731     ZERO_STRUCTP(token);
732
733     if ((token->user_sids = (DOM_SID *)memdup( ptoken->user_sids, sizeof(DOM_SID) * ptoken->num_sids )) == NULL) {
734         SAFE_FREE(token);
735         return NULL;
736     }
737
738     token->num_sids = ptoken->num_sids;
739
740         return token;
741 }
742
743 /****************************************************************************
744  Check for a guest logon (username = "") and if so create the required 
745  structure.
746 ****************************************************************************/
747
748 NTSTATUS check_guest_security(const auth_usersupplied_info *user_info, 
749                               auth_serversupplied_info **server_info)
750 {
751         NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
752
753         if (!(user_info->internal_username.str 
754               && *user_info->internal_username.str)) { 
755                 if (make_server_info_guest(server_info)) {
756                         nt_status = NT_STATUS_OK;
757                 } else {
758                         nt_status = NT_STATUS_NO_SUCH_USER;
759                 }
760         }
761
762         return nt_status;
763 }