Spelling fix, reformatted comment.
[samba.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 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 field, which actualy contains
427                    the password rather than the nt_pwd field becouse that
428                    contains nothing */
429                 
430                 /* WATCH OUT. This doesn't work if the incoming password is
431                    incorrectly cased.  We might want to add a check here
432                    and only do an LM in that case */
433                 
434                 SMBNTencrypt((const uchar *)password, chal, local_nt_response);
435
436                 local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response));
437                 local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response));
438                 plaintext_blob = data_blob(password, strlen(password)+1);
439                 if ((!local_lm_blob.data) || (!local_nt_blob.data)|| (!plaintext_blob.data)) {
440                         data_blob_free(&local_lm_blob);
441                         data_blob_free(&local_nt_blob);
442                         data_blob_clear_free(&plaintext_blob);
443                         return False;
444                 }
445                 ntlmssp_flags = NTLMSSP_NEGOTIATE_OEM | NTLMSSP_NEGOTIATE_NTLM;
446         } else {
447                 local_lm_blob = data_blob(NULL, 0);
448                 local_nt_blob = data_blob(NULL, 0);
449                 plaintext_blob = data_blob(NULL, 0);
450         }
451
452         {
453                 BOOL ret;
454                 DATA_BLOB sec_blob = data_blob(chal, sizeof(chal));
455                 
456                 if (!sec_blob.data) {
457                         return False;
458                 }
459
460                 ret = make_user_info(user_info, 
461                                      username, username,
462                                      domain, domain, 
463                                      global_myname, sec_blob, 
464                                      local_nt_blob,
465                                      local_lm_blob,
466                                      plaintext_blob, 
467                                      ntlmssp_flags, False);
468                 
469                 data_blob_free(&local_lm_blob);
470                 data_blob_free(&local_nt_blob);
471                 data_blob_clear_free(&plaintext_blob);
472                 return ret;
473         }
474 }
475
476 /****************************************************************************
477  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
478  Decrypt and encrypt the passwords.
479 ****************************************************************************/
480
481 BOOL make_user_info_winbind_crap(auth_usersupplied_info **user_info, 
482                                  char *smb_name, 
483                                  char *client_domain, 
484                                  uchar chal[8],
485                                  uchar *lm_network_pwd, int lm_pwd_len,
486                                  uchar *nt_network_pwd, int nt_pwd_len)
487 {
488         BOOL ret;
489         DATA_BLOB sec_blob = data_blob(chal, 8);
490         DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
491         DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
492         DATA_BLOB plaintext_blob = data_blob(NULL, 0);
493         uint32 ntlmssp_flags = 0;
494
495         if (lm_pwd_len)
496                 ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM;
497         if (nt_pwd_len)
498                 ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; 
499         
500         ret = make_user_info(user_info, 
501                              smb_name, smb_name, 
502                              client_domain, client_domain, 
503                              global_myname, sec_blob, 
504                              nt_blob, lm_blob,
505                              plaintext_blob, 
506                              ntlmssp_flags, True);
507
508         data_blob_free(&lm_blob);
509         data_blob_free(&nt_blob);
510         return ret;
511 }
512
513 /****************************************************************************
514  Create an auth_usersupplied_data structure
515 ****************************************************************************/
516
517 BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, 
518                               char *smb_name,
519                               char *client_domain, 
520                               DATA_BLOB lm_resp, DATA_BLOB nt_resp,
521                               DATA_BLOB plaintext_password,
522                               BOOL encrypted)
523 {
524         uchar chal[8];
525
526         DATA_BLOB local_lm_blob;
527         DATA_BLOB local_nt_blob;
528         DATA_BLOB sec_blob;
529         BOOL ret = False;
530         uint32 ntlmssp_flags = 0;
531                         
532         if (encrypted) {
533                 DATA_BLOB no_plaintext_blob = data_blob(NULL, 0); 
534                 if (!last_challenge(chal)) {
535                         DEBUG(0,("Encrypted login but no challange set!\n"));
536                         return False;
537                 }
538                 sec_blob = data_blob(chal, 8);
539                 
540                 if (lm_resp.length == 24) {
541                         ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM;
542                 }
543                 if (nt_resp.length == 0) {
544                 } else if (nt_resp.length == 24) {
545                         ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM;
546                 } else {
547                         ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM2;
548                 }
549
550                 return make_user_info_map(user_info, smb_name, 
551                                           client_domain, 
552                                           remote_machine, sec_blob,
553                                           lm_resp, 
554                                           nt_resp, 
555                                           no_plaintext_blob, 
556                                           ntlmssp_flags, encrypted);
557         }
558
559         generate_random_buffer(chal, 8, False);
560
561         sec_blob = data_blob(chal, 8);
562         
563         /*
564          * Not encrypted - do so.
565          */
566         
567         DEBUG(5,("pass_check_smb: User passwords not in encrypted format.\n"));
568         
569         if (plaintext_password.data) {
570                 unsigned char local_lm_response[24];
571
572                 SMBencrypt( (const uchar *)plaintext_password.data, chal, local_lm_response);
573                 local_lm_blob = data_blob(local_lm_response, 24);
574                 
575                 /* We can't do an NT hash here, as the password needs to be case insensitive */
576                 local_nt_blob = data_blob(NULL, 0); 
577                 
578                 ntlmssp_flags = NTLMSSP_NEGOTIATE_OEM;
579         } else {
580                 local_lm_blob = data_blob(NULL, 0); 
581                 local_nt_blob = data_blob(NULL, 0); 
582         }
583         
584         ret = make_user_info_map(user_info, smb_name,
585                                  client_domain, 
586                                  remote_machine,
587                                  sec_blob,
588                                  local_lm_blob,
589                                  local_nt_blob,
590                                  plaintext_password, 
591                                  ntlmssp_flags, encrypted);
592         
593         data_blob_free(&local_lm_blob);
594         return ret;
595 }
596
597 /****************************************************************************
598  Create a guest user_info blob, for anonymous authenticaion.
599 ****************************************************************************/
600
601 BOOL make_user_info_guest(auth_usersupplied_info **user_info) 
602 {
603         DATA_BLOB sec_blob = data_blob(NULL, 0);
604         DATA_BLOB lm_blob = data_blob(NULL, 0);
605         DATA_BLOB nt_blob = data_blob(NULL, 0);
606         DATA_BLOB plaintext_blob = data_blob(NULL, 0);
607         uint32 ntlmssp_flags = 0;
608
609         return make_user_info(user_info, 
610                               "","", 
611                               "","", 
612                               "", sec_blob,
613                               nt_blob, lm_blob,
614                               plaintext_blob, 
615                               ntlmssp_flags, True);
616 }
617
618 /***************************************************************************
619  Make a user_info struct
620 ***************************************************************************/
621
622 BOOL make_server_info(auth_serversupplied_info **server_info) 
623 {
624         *server_info = malloc(sizeof(**server_info));
625         if (!*server_info) {
626                 DEBUG(0,("make_server_info: malloc failed!\n"));
627                 return False;
628         }
629         ZERO_STRUCTP(*server_info);
630         return True;
631 }
632
633 /***************************************************************************
634  Make (and fill) a user_info struct from a SAM_ACCOUNT
635 ***************************************************************************/
636
637 BOOL make_server_info_sam(auth_serversupplied_info **server_info, SAM_ACCOUNT *sampass) 
638 {
639         if (!make_server_info(server_info)) {
640                 return False;
641         }
642
643         (*server_info)->sam_fill_level = SAM_FILL_ALL;
644         (*server_info)->sam_account = sampass;
645
646         DEBUG(5,("make_server_info_sam: made server info for user %s\n",
647                  pdb_get_username((*server_info)->sam_account)));
648         return True;
649 }
650
651 /***************************************************************************
652  Make (and fill) a user_info struct from a 'struct passwd' by conversion 
653  to a SAM_ACCOUNT
654 ***************************************************************************/
655
656 BOOL make_server_info_pw(auth_serversupplied_info **server_info, const struct passwd *pwd)
657 {
658         SAM_ACCOUNT *sampass = NULL;
659         if (!pdb_init_sam_pw(&sampass, pwd)) {          
660                 return False;
661         }
662         return make_server_info_sam(server_info, sampass);
663 }
664
665 /***************************************************************************
666  Free a user_info struct
667 ***************************************************************************/
668
669 void free_user_info(auth_usersupplied_info **user_info)
670 {
671         DEBUG(5,("attempting to free (and zero) a user_info structure\n"));
672         if (*user_info != NULL) {
673                 if ((*user_info)->smb_name.str) {
674                         DEBUG(10,("structure was created for %s\n", (*user_info)->smb_name.str));
675                 }
676                 SAFE_FREE((*user_info)->smb_name.str);
677                 SAFE_FREE((*user_info)->internal_username.str);
678                 SAFE_FREE((*user_info)->client_domain.str);
679                 SAFE_FREE((*user_info)->domain.str);
680                 data_blob_free(&(*user_info)->sec_blob);
681                 data_blob_free(&(*user_info)->lm_resp);
682                 data_blob_free(&(*user_info)->nt_resp);
683                 SAFE_FREE((*user_info)->interactive_password);
684                 data_blob_clear_free(&(*user_info)->plaintext_password);
685                 ZERO_STRUCT(**user_info);
686         }
687         SAFE_FREE(*user_info);
688 }
689
690 /***************************************************************************
691  Clear out a server_info struct that has been allocated
692 ***************************************************************************/
693
694 void free_server_info(auth_serversupplied_info **server_info)
695 {
696         if (*server_info != NULL) {
697                 pdb_free_sam(&(*server_info)->sam_account);
698                 
699                 /* call pam_end here, unless we know we are keeping it */
700                 delete_nt_token( &(*server_info)->ptok );
701                 ZERO_STRUCT(**server_info);
702         }
703         SAFE_FREE(*server_info);
704 }
705
706 /***************************************************************************
707  Make a server_info struct for a guest user 
708 ***************************************************************************/
709
710 BOOL make_server_info_guest(auth_serversupplied_info **server_info) 
711 {
712         struct passwd *pass = sys_getpwnam(lp_guestaccount());
713         
714         if (pass) {
715                 if (!make_server_info_pw(server_info, pass)) {
716                         return False;
717                 }
718                 (*server_info)->guest = True;
719                 return True;
720         }
721         DEBUG(0,("make_server_info_guest: sys_getpwnam() failed on guest account!\n")); 
722         return False;
723 }
724
725 /****************************************************************************
726  Delete a SID token.
727 ****************************************************************************/
728
729 void delete_nt_token(NT_USER_TOKEN **pptoken)
730 {
731     if (*pptoken) {
732                 NT_USER_TOKEN *ptoken = *pptoken;
733         SAFE_FREE( ptoken->user_sids );
734         ZERO_STRUCTP(ptoken);
735     }
736     SAFE_FREE(*pptoken);
737 }
738
739 /****************************************************************************
740  Duplicate a SID token.
741 ****************************************************************************/
742
743 NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken)
744 {
745         NT_USER_TOKEN *token;
746
747         if (!ptoken)
748                 return NULL;
749
750     if ((token = (NT_USER_TOKEN *)malloc( sizeof(NT_USER_TOKEN) ) ) == NULL)
751         return NULL;
752
753     ZERO_STRUCTP(token);
754
755     if ((token->user_sids = (DOM_SID *)memdup( ptoken->user_sids, sizeof(DOM_SID) * ptoken->num_sids )) == NULL) {
756         SAFE_FREE(token);
757         return NULL;
758     }
759
760     token->num_sids = ptoken->num_sids;
761
762         return token;
763 }
764
765 /****************************************************************************
766  Check for a guest logon (username = "") and if so create the required 
767  structure.
768 ****************************************************************************/
769
770 NTSTATUS check_guest_security(const auth_usersupplied_info *user_info, 
771                               auth_serversupplied_info **server_info)
772 {
773         NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
774
775         if (!(user_info->internal_username.str 
776               && *user_info->internal_username.str)) { 
777                 if (make_server_info_guest(server_info)) {
778                         nt_status = NT_STATUS_OK;
779                 } else {
780                         nt_status = NT_STATUS_NO_SUCH_USER;
781                 }
782         }
783
784         return nt_status;
785 }