Fix up some DEBUG()s
[tprouty/samba.git] / source / 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 static BOOL make_user_info(auth_usersupplied_info **user_info, 
162                            const char *smb_name, 
163                            const char *internal_username,
164                            const char *client_domain, 
165                            const char *domain,
166                            const char *wksta_name, 
167                            DATA_BLOB sec_blob, 
168                            DATA_BLOB lm_pwd, DATA_BLOB nt_pwd,
169                            DATA_BLOB plaintext, 
170                            uint32 ntlmssp_flags, BOOL encrypted)
171 {
172
173         DEBUG(5,("attempting to make a user_info for %s (%s)\n", internal_username, smb_name));
174
175         *user_info = malloc(sizeof(**user_info));
176         if (!user_info) {
177                 DEBUG(0,("malloc failed for user_info (size %d)\n", sizeof(*user_info)));
178                 return False;
179         }
180
181         ZERO_STRUCTP(*user_info);
182
183         DEBUG(5,("makeing strings for %s's user_info struct\n", internal_username));
184
185         (*user_info)->smb_name.str = strdup(smb_name);
186         if ((*user_info)->smb_name.str) { 
187                 (*user_info)->smb_name.len = strlen(smb_name);
188         } else {
189                 free_user_info(user_info);
190                 return False;
191         }
192         
193         (*user_info)->internal_username.str = strdup(internal_username);
194         if ((*user_info)->internal_username.str) { 
195                 (*user_info)->internal_username.len = strlen(internal_username);
196         } else {
197                 free_user_info(user_info);
198                 return False;
199         }
200
201         (*user_info)->domain.str = strdup(domain);
202         if ((*user_info)->domain.str) { 
203                 (*user_info)->domain.len = strlen(domain);
204         } else {
205                 free_user_info(user_info);
206                 return False;
207         }
208
209         (*user_info)->client_domain.str = strdup(client_domain);
210         if ((*user_info)->client_domain.str) { 
211                 (*user_info)->client_domain.len = strlen(client_domain);
212         } else {
213                 free_user_info(user_info);
214                 return False;
215         }
216
217         (*user_info)->wksta_name.str = strdup(wksta_name);
218         if ((*user_info)->wksta_name.str) { 
219                 (*user_info)->wksta_name.len = strlen(wksta_name);
220         } else {
221                 free_user_info(user_info);
222                 return False;
223         }
224
225         DEBUG(5,("makeing blobs for %s's user_info struct\n", internal_username));
226
227         (*user_info)->sec_blob = data_blob(sec_blob.data, sec_blob.length);
228         (*user_info)->lm_resp = data_blob(lm_pwd.data, lm_pwd.length);
229         (*user_info)->nt_resp = data_blob(nt_pwd.data, nt_pwd.length);
230         (*user_info)->plaintext_password = data_blob(plaintext.data, plaintext.length);
231
232         (*user_info)->encrypted = encrypted;
233         (*user_info)->ntlmssp_flags = ntlmssp_flags;
234
235         DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted ? "":"un" , internal_username, smb_name));
236
237         return True;
238 }
239
240 /****************************************************************************
241  Create an auth_usersupplied_data structure after appropriate mapping.
242 ****************************************************************************/
243
244 BOOL make_user_info_map(auth_usersupplied_info **user_info, 
245                         const char *smb_name, 
246                         const char *client_domain, 
247                         const char *wksta_name, DATA_BLOB sec_blob, 
248                         DATA_BLOB lm_pwd, DATA_BLOB nt_pwd,
249                         DATA_BLOB plaintext, 
250                         uint32 ntlmssp_flags, BOOL encrypted)
251 {
252         const char *domain;
253         fstring internal_username;
254         fstrcpy(internal_username, smb_name);
255         map_username(internal_username); 
256         
257         if (lp_allow_trusted_domains()) {
258                 domain = client_domain;
259         } else {
260                 domain = lp_workgroup();
261         }
262         
263         return make_user_info(user_info, 
264                               smb_name, internal_username,
265                               client_domain, domain,
266                               wksta_name, sec_blob,
267                               lm_pwd, nt_pwd,
268                               plaintext, 
269                               ntlmssp_flags, encrypted);
270         
271 }
272
273 /****************************************************************************
274  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
275  Decrupt and encrypt the passwords.
276 ****************************************************************************/
277
278 BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info, 
279                                      char *smb_name, 
280                                      char *client_domain, 
281                                      char *wksta_name, uchar chal[8],
282                                      uchar *lm_network_pwd, int lm_pwd_len,
283                                      uchar *nt_network_pwd, int nt_pwd_len)
284 {
285         BOOL ret;
286         DATA_BLOB sec_blob = data_blob(chal, sizeof(chal));
287         DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
288         DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
289         DATA_BLOB plaintext_blob = data_blob(NULL, 0);
290         uint32 ntlmssp_flags = 0;
291
292         if (lm_pwd_len)
293                 ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM;
294         if (nt_pwd_len == 24) {
295                 ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; 
296         } else if (nt_pwd_len != 0) {
297                 ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM2; 
298         }
299
300         ret = make_user_info_map(user_info, 
301                                  smb_name, client_domain, 
302                                  wksta_name, sec_blob, 
303                                  nt_blob, lm_blob,
304                                  plaintext_blob, 
305                                  ntlmssp_flags, True);
306                 
307         data_blob_free(&lm_blob);
308         data_blob_free(&nt_blob);
309         return ret;
310 }
311
312 /****************************************************************************
313  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
314  Decrupt and encrypt the passwords.
315 ****************************************************************************/
316
317 BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, 
318                                          char *smb_name, 
319                                          char *client_domain, 
320                                          char *wksta_name, 
321                                          uchar lm_interactive_pwd[16], 
322                                          uchar nt_interactive_pwd[16], 
323                                          uchar *dc_sess_key)
324 {
325         char lm_pwd[16];
326         char nt_pwd[16];
327         unsigned char local_lm_response[24];
328         unsigned char local_nt_response[24];
329         unsigned char key[16];
330         uint8 chal[8];
331         uint32 ntlmssp_flags = 0;
332         
333         generate_random_buffer(chal, 8, False);
334
335         ZERO_STRUCT(key);
336         memcpy(key, dc_sess_key, 8);
337         
338         if (lm_interactive_pwd) memcpy(lm_pwd, lm_interactive_pwd, sizeof(lm_pwd));
339         if (nt_interactive_pwd) memcpy(nt_pwd, nt_interactive_pwd, sizeof(nt_pwd));
340         
341 #ifdef DEBUG_PASSWORD
342         DEBUG(100,("key:"));
343         dump_data(100, (char *)key, sizeof(key));
344         
345         DEBUG(100,("lm owf password:"));
346         dump_data(100, lm_pwd, sizeof(lm_pwd));
347         
348         DEBUG(100,("nt owf password:"));
349         dump_data(100, nt_pwd, sizeof(nt_pwd));
350 #endif
351         
352         SamOEMhash((uchar *)lm_pwd, key, sizeof(lm_pwd));
353         SamOEMhash((uchar *)nt_pwd, key, sizeof(nt_pwd));
354         
355 #ifdef DEBUG_PASSWORD
356         DEBUG(100,("decrypt of lm owf password:"));
357         dump_data(100, lm_pwd, sizeof(lm_pwd));
358         
359         DEBUG(100,("decrypt of nt owf password:"));
360         dump_data(100, nt_pwd, sizeof(nt_pwd));
361 #endif
362         
363         generate_random_buffer(chal, 8, False);
364         SMBOWFencrypt((const unsigned char *)lm_pwd, chal, local_lm_response);
365         SMBOWFencrypt((const unsigned char *)nt_pwd, chal, local_nt_response);
366         
367         /* Password info parinoia */
368         ZERO_STRUCT(lm_pwd);
369         ZERO_STRUCT(nt_pwd);
370         ZERO_STRUCT(key);
371
372         {
373                 BOOL ret;
374                 DATA_BLOB sec_blob = data_blob(chal, sizeof(chal));
375                 DATA_BLOB local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response));
376                 DATA_BLOB local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response));
377                 DATA_BLOB plaintext_blob = data_blob(NULL, 0);
378
379                 if (lm_interactive_pwd)
380                         ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM;
381                 if (nt_interactive_pwd)
382                         ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; 
383
384                 ret = make_user_info_map(user_info, 
385                                          smb_name, client_domain, 
386                                          wksta_name, sec_blob, 
387                                          local_lm_blob,
388                                          local_nt_blob,
389                                          plaintext_blob, 
390                                          ntlmssp_flags, True);
391                 
392                 data_blob_free(&local_lm_blob);
393                 data_blob_free(&local_nt_blob);
394                 return ret;
395         }
396 }
397
398 /****************************************************************************
399  Create an auth_usersupplied_data structure
400 ****************************************************************************/
401
402 BOOL make_user_info_winbind(auth_usersupplied_info **user_info, 
403                             char *username,
404                             char *domain, 
405                             char *password)
406 {
407         unsigned char local_lm_response[24];
408         unsigned char local_nt_response[24];
409         char chal[8];
410         DATA_BLOB local_lm_blob;
411         DATA_BLOB local_nt_blob;
412         DATA_BLOB plaintext_blob;
413         uint32 ntlmssp_flags = 0;
414
415         /*
416          * Not encrypted - do so.
417          */
418         
419         DEBUG(5,("pass_check_smb: User passwords not in encrypted format.\n"));
420         
421         generate_random_buffer(chal, 8, False);
422
423         if (*password) {
424                 SMBencrypt( (const uchar *)password, chal, local_lm_response);
425                 
426                 /* This encrypts the lm_pwd feild, which actualy contains the password
427                    rather than the nt_pwd field becouse that contains nothing */
428                 
429                 /* WATCH OUT. This doesn't work if the incoming password is incorrectly cased. 
430                    We might want to add a check here and only do an LM in that case */
431                 
432                 SMBNTencrypt((const uchar *)password, chal, local_nt_response);
433
434                 local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response));
435                 local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response));
436                 plaintext_blob = data_blob(password, strlen(password)+1);
437                 if ((!local_lm_blob.data) || (!local_nt_blob.data)|| (!plaintext_blob.data)) {
438                         data_blob_free(&local_lm_blob);
439                         data_blob_free(&local_nt_blob);
440                         data_blob_clear_free(&plaintext_blob);
441                         return False;
442                 }
443                 ntlmssp_flags = NTLMSSP_NEGOTIATE_OEM | NTLMSSP_NEGOTIATE_NTLM;
444         } else {
445                 local_lm_blob = data_blob(NULL, 0);
446                 local_nt_blob = data_blob(NULL, 0);
447                 plaintext_blob = data_blob(NULL, 0);
448         }
449
450         {
451                 BOOL ret;
452                 DATA_BLOB sec_blob = data_blob(chal, sizeof(chal));
453                 
454                 if (!sec_blob.data) {
455                         return False;
456                 }
457
458                 ret = make_user_info(user_info, 
459                                      username, username,
460                                      domain, domain, 
461                                      global_myname, sec_blob, 
462                                      local_nt_blob,
463                                      local_lm_blob,
464                                      plaintext_blob, 
465                                      ntlmssp_flags, False);
466                 
467                 data_blob_free(&local_lm_blob);
468                 data_blob_free(&local_nt_blob);
469                 data_blob_clear_free(&plaintext_blob);
470                 return ret;
471         }
472 }
473
474 /****************************************************************************
475  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
476  Decrupt and encrypt the passwords.
477 ****************************************************************************/
478
479 BOOL make_user_info_winbind_crap(auth_usersupplied_info **user_info, 
480                                  char *smb_name, 
481                                  char *client_domain, 
482                                  uchar chal[8],
483                                  uchar *lm_network_pwd, int lm_pwd_len,
484                                  uchar *nt_network_pwd, int nt_pwd_len)
485 {
486         BOOL ret;
487         DATA_BLOB sec_blob = data_blob(chal, sizeof(chal));
488         DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
489         DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
490         DATA_BLOB plaintext_blob = data_blob(NULL, 0);
491         uint32 ntlmssp_flags = 0;
492
493         if (lm_pwd_len)
494                 ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM;
495         if (nt_pwd_len)
496                 ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; 
497         
498         ret = make_user_info(user_info, 
499                              smb_name, smb_name, 
500                              client_domain, client_domain, 
501                              global_myname, sec_blob, 
502                              nt_blob, lm_blob,
503                              plaintext_blob, 
504                              ntlmssp_flags, True);
505
506         data_blob_free(&lm_blob);
507         data_blob_free(&nt_blob);
508         return ret;
509 }
510
511 /****************************************************************************
512  Create an auth_usersupplied_data structure
513 ****************************************************************************/
514
515 BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, 
516                               char *smb_name,
517                               char *client_domain, 
518                               DATA_BLOB lm_resp, DATA_BLOB nt_resp,
519                               DATA_BLOB plaintext_password,
520                               BOOL encrypted)
521 {
522         uchar chal[8];
523
524         DATA_BLOB local_lm_blob;
525         DATA_BLOB local_nt_blob;
526         DATA_BLOB sec_blob;
527         BOOL ret = False;
528         uint32 ntlmssp_flags = 0;
529                         
530         if (encrypted) {
531                 DATA_BLOB no_plaintext_blob = data_blob(NULL, 0); 
532                 if (!last_challenge(chal)) {
533                         DEBUG(0,("Encrypted login but no challange set!\n"));
534                         return False;
535                 }
536                 sec_blob = data_blob(chal, 8);
537                 
538                 if (lm_resp.length == 24) {
539                         ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM;
540                 }
541                 if (nt_resp.length == 0) {
542                 } else if (nt_resp.length == 24) {
543                         ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM;
544                 } else {
545                         ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM2;
546                 }
547
548                 return make_user_info_map(user_info, smb_name, 
549                                           client_domain, 
550                                           remote_machine, sec_blob,
551                                           lm_resp, 
552                                           nt_resp, 
553                                           no_plaintext_blob, 
554                                           ntlmssp_flags, encrypted);
555         }
556
557         generate_random_buffer(chal, 8, False);
558
559         sec_blob = data_blob(chal, 8);
560         
561         /*
562          * Not encrypted - do so.
563          */
564         
565         DEBUG(5,("pass_check_smb: User passwords not in encrypted format.\n"));
566         
567         if (plaintext_password.data) {
568                 unsigned char local_lm_response[24];
569
570                 SMBencrypt( (const uchar *)plaintext_password.data, chal, local_lm_response);
571                 local_lm_blob = data_blob(local_lm_response, 24);
572                 
573                 /* We can't do an NT hash here, as the password needs to be case insensitive */
574                 local_nt_blob = data_blob(NULL, 0); 
575                 
576                 ntlmssp_flags = NTLMSSP_NEGOTIATE_OEM;
577         } else {
578                 local_lm_blob = data_blob(NULL, 0); 
579                 local_nt_blob = data_blob(NULL, 0); 
580         }
581         
582         ret = make_user_info_map(user_info, smb_name,
583                                  client_domain, 
584                                  remote_machine,
585                                  sec_blob,
586                                  local_lm_blob,
587                                  local_nt_blob,
588                                  plaintext_password, 
589                                  ntlmssp_flags, encrypted);
590         
591         data_blob_free(&local_lm_blob);
592         return ret;
593 }
594
595 /****************************************************************************
596  Create a guest user_info blob, for anonymous authenticaion.
597 ****************************************************************************/
598
599 BOOL make_user_info_guest(auth_usersupplied_info **user_info) 
600 {
601         DATA_BLOB sec_blob = data_blob(NULL, 0);
602         DATA_BLOB lm_blob = data_blob(NULL, 0);
603         DATA_BLOB nt_blob = data_blob(NULL, 0);
604         DATA_BLOB plaintext_blob = data_blob(NULL, 0);
605         uint32 ntlmssp_flags = 0;
606
607         return make_user_info(user_info, 
608                               "","", 
609                               "","", 
610                               "", sec_blob,
611                               nt_blob, lm_blob,
612                               plaintext_blob, 
613                               ntlmssp_flags, True);
614 }
615
616 /***************************************************************************
617  Make a user_info struct
618 ***************************************************************************/
619
620 BOOL make_server_info(auth_serversupplied_info **server_info) 
621 {
622         *server_info = malloc(sizeof(**server_info));
623         if (!*server_info) {
624                 DEBUG(0,("make_server_info: malloc failed!\n"));
625                 return False;
626         }
627         ZERO_STRUCTP(*server_info);
628         return True;
629 }
630
631 /***************************************************************************
632  Make (and fill) a user_info struct from a SAM_ACCOUNT
633 ***************************************************************************/
634
635 BOOL make_server_info_sam(auth_serversupplied_info **server_info, SAM_ACCOUNT *sampass) 
636 {
637         if (!make_server_info(server_info)) {
638                 return False;
639         }
640
641         (*server_info)->sam_fill_level = SAM_FILL_ALL;
642         (*server_info)->sam_account = sampass;
643
644         DEBUG(5,("make_server_info_sam: made server info for user %s\n",
645                  pdb_get_username((*server_info)->sam_account)));
646         return True;
647 }
648
649 /***************************************************************************
650  Make (and fill) a user_info struct from a 'struct passwd' by conversion 
651  to a SAM_ACCOUNT
652 ***************************************************************************/
653
654 BOOL make_server_info_pw(auth_serversupplied_info **server_info, const struct passwd *pwd)
655 {
656         SAM_ACCOUNT *sampass = NULL;
657         if (!pdb_init_sam_pw(&sampass, pwd)) {          
658                 return False;
659         }
660         return make_server_info_sam(server_info, sampass);
661 }
662
663 /***************************************************************************
664  Free a user_info struct
665 ***************************************************************************/
666
667 void free_user_info(auth_usersupplied_info **user_info)
668 {
669         DEBUG(5,("attempting to free (and zero) a user_info structure\n"));
670         if (*user_info != NULL) {
671                 if ((*user_info)->smb_name.str) {
672                         DEBUG(10,("structure was created for %s\n", (*user_info)->smb_name.str));
673                 }
674                 SAFE_FREE((*user_info)->smb_name.str);
675                 SAFE_FREE((*user_info)->internal_username.str);
676                 SAFE_FREE((*user_info)->client_domain.str);
677                 SAFE_FREE((*user_info)->domain.str);
678                 data_blob_free(&(*user_info)->sec_blob);
679                 data_blob_free(&(*user_info)->lm_resp);
680                 data_blob_free(&(*user_info)->nt_resp);
681                 SAFE_FREE((*user_info)->interactive_password);
682                 data_blob_clear_free(&(*user_info)->plaintext_password);
683                 ZERO_STRUCT(**user_info);
684         }
685         SAFE_FREE(*user_info);
686 }
687
688 /***************************************************************************
689  Clear out a server_info struct that has been allocated
690 ***************************************************************************/
691
692 void free_server_info(auth_serversupplied_info **server_info)
693 {
694         if (*server_info != NULL) {
695                 pdb_free_sam(&(*server_info)->sam_account);
696                 
697                 /* call pam_end here, unless we know we are keeping it */
698                 delete_nt_token( &(*server_info)->ptok );
699                 ZERO_STRUCT(**server_info);
700         }
701         SAFE_FREE(*server_info);
702 }
703
704 /***************************************************************************
705  Make a server_info struct for a guest user 
706 ***************************************************************************/
707
708 BOOL make_server_info_guest(auth_serversupplied_info **server_info) 
709 {
710         struct passwd *pass = sys_getpwnam(lp_guestaccount());
711         
712         if (pass) {
713                 if (!make_server_info_pw(server_info, pass)) {
714                         return False;
715                 }
716                 (*server_info)->guest = True;
717                 return True;
718         }
719         DEBUG(0,("make_server_info_guest: sys_getpwnam() failed on guest account!\n")); 
720         return False;
721 }
722
723 /****************************************************************************
724  Delete a SID token.
725 ****************************************************************************/
726
727 void delete_nt_token(NT_USER_TOKEN **pptoken)
728 {
729     if (*pptoken) {
730                 NT_USER_TOKEN *ptoken = *pptoken;
731         SAFE_FREE( ptoken->user_sids );
732         ZERO_STRUCTP(ptoken);
733     }
734     SAFE_FREE(*pptoken);
735 }
736
737 /****************************************************************************
738  Duplicate a SID token.
739 ****************************************************************************/
740
741 NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken)
742 {
743         NT_USER_TOKEN *token;
744
745         if (!ptoken)
746                 return NULL;
747
748     if ((token = (NT_USER_TOKEN *)malloc( sizeof(NT_USER_TOKEN) ) ) == NULL)
749         return NULL;
750
751     ZERO_STRUCTP(token);
752
753     if ((token->user_sids = (DOM_SID *)memdup( ptoken->user_sids, sizeof(DOM_SID) * ptoken->num_sids )) == NULL) {
754         SAFE_FREE(token);
755         return NULL;
756     }
757
758     token->num_sids = ptoken->num_sids;
759
760         return token;
761 }
762
763 /****************************************************************************
764  Check for a guest logon (username = "") and if so create the required 
765  structure.
766 ****************************************************************************/
767
768 NTSTATUS check_guest_security(const auth_usersupplied_info *user_info, 
769                               auth_serversupplied_info **server_info)
770 {
771         NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
772
773         if (!(user_info->internal_username.str 
774               && *user_info->internal_username.str)) { 
775                 if (make_server_info_guest(server_info)) {
776                         nt_status = NT_STATUS_OK;
777                 } else {
778                         nt_status = NT_STATUS_NO_SUCH_USER;
779                 }
780         }
781
782         return nt_status;
783 }