A number of things to clean up the auth subsytem a bit...
[ira/wip.git] / source3 / auth / auth_info.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 3.0.
4    Authentication utility functions
5    Copyright (C) Andrew Bartlett 2001
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 const struct auth_init_function builtin_auth_init_functions[] = {
25         { "guest", auth_init_guest },
26         { "rhosts", auth_init_rhosts },
27         { "hostsequiv", auth_init_hostsequiv },
28         { "sam", auth_init_sam },       
29         { "samstrict", auth_init_samstrict },
30         { "unix", auth_init_unix },
31         { "smbserver", auth_init_smbserver },
32         { "ntdomain", auth_init_ntdomain },
33         { "winbind", auth_init_winbind },
34 #ifdef DEVELOPER
35         { "name_to_ntstatus", auth_init_name_to_ntstatus },
36 #endif
37         { NULL, NULL}
38 };
39
40 /***************************************************************************
41  Make a auth_info struct
42 ***************************************************************************/
43
44 static BOOL make_auth_info(auth_authsupplied_info **auth_info) 
45 {
46         *auth_info = malloc(sizeof(**auth_info));
47         if (!*auth_info) {
48                 DEBUG(0,("make_auth_info: malloc failed!\n"));
49                 return False;
50         }
51         ZERO_STRUCTP(*auth_info);
52         
53         return True;
54 }
55
56 /***************************************************************************
57  Make a auth_info struct with a specified list.
58 ***************************************************************************/
59
60 BOOL make_auth_info_list(auth_authsupplied_info **auth_info, auth_methods *list) 
61 {
62         if (!make_auth_info(auth_info)) {
63                 return False;
64         }
65         
66         (*auth_info)->auth_method_list = list;
67         
68         return True;
69 }
70
71 /***************************************************************************
72  Make a auth_info struct for the auth subsystem
73 ***************************************************************************/
74
75 static BOOL make_auth_info_text_list(auth_authsupplied_info **auth_info, char **text_list) 
76 {
77         auth_methods *list = NULL;
78         auth_methods *t = NULL;
79         auth_methods *tmp;
80         int i;
81
82         if (!text_list) {
83                 DEBUG(2,("No auth method list!?\n"));
84                 return False;
85         }
86         
87         for (;*text_list; text_list++)
88         { 
89                 DEBUG(5,("Attempting to find an auth method to match %s\n", *text_list));
90                 for (i = 0; builtin_auth_init_functions[i].name; i++)
91                 {
92                         if (strequal(builtin_auth_init_functions[i].name, *text_list))
93                         {
94                                 DEBUG(5,("Found auth method %s (at pos %d)\n", *text_list, i));
95                                 /* Malloc entry,  fill it,  link it */
96                                 t = (auth_methods *)malloc(sizeof(*t));
97                                 if (!t) {
98                                         DEBUG(0,("make_pw_chat: malloc failed!\n"));
99                                         return False;
100                                 }
101                                 
102                                 ZERO_STRUCTP(t);
103                                 
104                                 if (builtin_auth_init_functions[i].init(&t)) {
105                                         DEBUG(5,("auth method %s has a valid init\n", *text_list));
106                                         t->name = builtin_auth_init_functions[i].name;
107                                         DLIST_ADD_END(list, t, tmp);
108                                 } else {
109                                         DEBUG(5,("auth method %s DOES NOT have a valid init\n", *text_list));
110                                 }
111                                 break;
112                         }
113                 }
114         }
115         
116         make_auth_info_list(auth_info, list);
117         
118         return True;
119 }
120
121 /***************************************************************************
122  Make a auth_info struct for the auth subsystem
123 ***************************************************************************/
124
125 BOOL make_auth_info_subsystem(auth_authsupplied_info **auth_info) 
126 {
127         char **auth_method_list = NULL; 
128         
129         if (!make_auth_info(auth_info)) {
130                 return False;
131         }
132         
133         if (lp_auth_methods() && !lp_list_copy(&auth_method_list, lp_auth_methods())) {
134                 return False;
135         }
136
137         if (auth_method_list == NULL) {
138                 switch (lp_security()) 
139                 {
140                 case SEC_DOMAIN:
141                         DEBUG(5,("Making default auth method list for security=domain\n"));
142                         auth_method_list = lp_list_make("guest samstrict ntdomain");
143                         break;
144                 case SEC_SERVER:
145                         DEBUG(5,("Making default auth method list for security=server\n"));
146                         auth_method_list = lp_list_make("guest samstrict smbserver");
147                         break;
148                 case SEC_USER:
149                         if (lp_encrypted_passwords()) { 
150                                 DEBUG(5,("Making default auth method list for security=user, encrypt passwords = yes\n"));
151                                 auth_method_list = lp_list_make("guest sam");
152                         } else {
153                                 DEBUG(5,("Making default auth method list for security=user, encrypt passwords = no\n"));
154                                 auth_method_list = lp_list_make("guest unix");
155                         }
156                         break;
157                 case SEC_SHARE:
158                         if (lp_encrypted_passwords()) {
159                                 DEBUG(5,("Making default auth method list for security=share, encrypt passwords = yes\n"));
160                                 auth_method_list = lp_list_make("guest sam");
161                         } else {
162                                 DEBUG(5,("Making default auth method list for security=share, encrypt passwords = no\n"));
163                                 auth_method_list = lp_list_make("guest unix");
164                         }
165                         break;
166                 case SEC_ADS:
167                         DEBUG(5,("Making default auth method list for security=ADS\n"));
168                         auth_method_list = lp_list_make("guest samstrict ads ntdomain");
169                         break;
170                 default:
171                         DEBUG(5,("Unknown auth method!\n"));
172                         return False;
173                 }
174         } else {
175                 DEBUG(5,("Using specified auth order\n"));
176         }
177         
178         if (!make_auth_info_text_list(auth_info, auth_method_list)) {
179                 lp_list_free(&auth_method_list);
180                 return False;
181         }
182         
183         lp_list_free(&auth_method_list);
184         return True;
185 }
186
187 /***************************************************************************
188  Make a auth_info struct with a random challenge
189 ***************************************************************************/
190
191 BOOL make_auth_info_random(auth_authsupplied_info **auth_info) 
192 {
193         uchar chal[8];
194         if (!make_auth_info_subsystem(auth_info)) {
195                 return False;
196         }
197         
198         generate_random_buffer(chal, sizeof(chal), False);
199         (*auth_info)->challenge = data_blob(chal, sizeof(chal));
200
201         (*auth_info)->challenge_set_by = "random";
202
203         return True;
204 }
205
206 /***************************************************************************
207  Make a auth_info struct with a fixed challenge
208 ***************************************************************************/
209
210 BOOL make_auth_info_fixed(auth_authsupplied_info **auth_info, uchar chal[8]) 
211 {
212         if (!make_auth_info_subsystem(auth_info)) {
213                 return False;
214         }
215         
216         (*auth_info)->challenge = data_blob(chal, 8);
217         return True;
218 }
219
220 /***************************************************************************
221  Clear out a auth_info struct that has been allocated
222 ***************************************************************************/
223
224 void free_auth_info(auth_authsupplied_info **auth_info)
225 {
226         auth_methods *list;
227         if (*auth_info != NULL) {
228                 list = (*auth_info)->auth_method_list;  
229                 while (list) {
230                         auth_methods *old_head = list;
231                         if (list->free_private_data) {
232                                 list->free_private_data(&(list->private_data));
233                         }
234                         DLIST_REMOVE(list, list);                       
235                         SAFE_FREE(old_head);
236                 }
237                 
238                 data_blob_free(&(*auth_info)->challenge);
239                 ZERO_STRUCT(**auth_info);
240         }
241         SAFE_FREE(*auth_info);
242 }
243
244 /****************************************************************************
245  Try to get a challenge out of the various authenticaion modules.
246  It is up to the caller to free it.
247 ****************************************************************************/
248
249 DATA_BLOB auth_get_challenge(auth_authsupplied_info *auth_info) 
250 {
251         DATA_BLOB challenge = data_blob(NULL, 0);
252         char *challenge_set_by = NULL;
253         auth_methods *auth_method;
254
255         if (auth_info->challenge.length) {
256                 DEBUG(5, ("auth_get_challenge: returning previous challenge (normal)\n"));
257                 return data_blob(auth_info->challenge.data, auth_info->challenge.length);
258         }
259
260         for (auth_method = auth_info->auth_method_list; auth_method; auth_method = auth_method->next)
261         {
262                 if (auth_method->get_chal) {
263                         DEBUG(5, ("auth_get_challenge: getting challenge from module %s\n", auth_method->name));
264                         if (challenge_set_by) {
265                                 DEBUG(1, ("auth_get_challenge: CONFIGURATION ERROR: authenticaion method %s has already specified a challenge.  Challenge by %s ignored.\n", 
266                                           challenge_set_by, auth_method->name));
267                         } else {
268                                 challenge = auth_method->get_chal(&auth_method->private_data, auth_info);
269                                 if (challenge.length) {
270                                         DEBUG(5, ("auth_get_challenge: sucessfully got challenge from module %s\n", auth_method->name));
271                                         auth_info->challenge = challenge;
272                                         challenge_set_by = auth_method->name;
273                                         auth_info->challenge_set_method = auth_method;
274                                 } else {
275                                         DEBUG(3, ("auth_get_challenge: getting challenge from authenticaion method %s FAILED.\n", 
276                                                   auth_method->name));
277                                 }
278                         }
279                 } else {
280                         DEBUG(5, ("auth_get_challenge: module %s did not want to specify a challenge\n", auth_method->name));
281                 }
282         }
283         
284         if (!challenge_set_by) {
285                 uchar chal[8];
286                 
287                 generate_random_buffer(chal, sizeof(chal), False);
288                 auth_info->challenge = data_blob(chal, sizeof(chal));
289                 
290                 challenge_set_by = "random";
291         } 
292         
293         DEBUG(5, ("auth_info challenge created by %s\n", challenge_set_by));
294         DEBUG(5, ("challenge is: \n"));
295         dump_data(5, auth_info->challenge.data, (auth_info)->challenge.length);
296         
297         SMB_ASSERT(auth_info->challenge.length == 8);
298
299         auth_info->challenge_set_by=challenge_set_by;
300
301         return data_blob(auth_info->challenge.data, auth_info->challenge.length);
302 }
303
304