8087be48f2f47266b68afb274b0ae640adf75833
[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         { "unix", auth_init_unix },
30         { "local", auth_init_local },
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 ntdomain local");
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 smbserver local");
147                         break;
148                 case SEC_USER:
149                         DEBUG(5,("Making default auth method list for security=user\n"));
150                         auth_method_list = lp_list_make("guest local");
151                         break;
152                 case SEC_SHARE:
153                         DEBUG(5,("Making default auth method list for security=share\n"));
154                         auth_method_list = lp_list_make("guest local");
155                         break;
156                 case SEC_ADS:
157                         DEBUG(5,("Making default auth method list for security=ADS\n"));
158                         auth_method_list = lp_list_make("guest ads ntdomain local");
159                         break;
160                 default:
161                         DEBUG(5,("Unknown auth method!\n"));
162                         return False;
163                 }
164         } else {
165                 DEBUG(5,("Using specified auth order\n"));
166         }
167         
168         if (!make_auth_info_text_list(auth_info, auth_method_list)) {
169                 lp_list_free(&auth_method_list);
170                 return False;
171         }
172         
173         lp_list_free(&auth_method_list);
174         return True;
175 }
176
177 /***************************************************************************
178  Make a auth_info struct with a random challenge
179 ***************************************************************************/
180
181 BOOL make_auth_info_random(auth_authsupplied_info **auth_info) 
182 {
183         uchar chal[8];
184         if (!make_auth_info_subsystem(auth_info)) {
185                 return False;
186         }
187         
188         generate_random_buffer(chal, sizeof(chal), False);
189         (*auth_info)->challenge = data_blob(chal, sizeof(chal));
190
191         (*auth_info)->challenge_set_by = "random";
192
193         return True;
194 }
195
196 /***************************************************************************
197  Make a auth_info struct with a fixed challenge
198 ***************************************************************************/
199
200 BOOL make_auth_info_fixed(auth_authsupplied_info **auth_info, uchar chal[8]) 
201 {
202         if (!make_auth_info_subsystem(auth_info)) {
203                 return False;
204         }
205         
206         (*auth_info)->challenge = data_blob(chal, 8);
207         return True;
208 }
209
210 /***************************************************************************
211  Clear out a auth_info struct that has been allocated
212 ***************************************************************************/
213
214 void free_auth_info(auth_authsupplied_info **auth_info)
215 {
216         auth_methods *list;
217         if (*auth_info != NULL) {
218                 list = (*auth_info)->auth_method_list;  
219                 while (list) {
220                         auth_methods *old_head = list;
221                         if (list->free_private_data) {
222                                 list->free_private_data(&(list->private_data));
223                         }
224                         DLIST_REMOVE(list, list);                       
225                         SAFE_FREE(old_head);
226                 }
227                 
228                 data_blob_free(&(*auth_info)->challenge);
229                 ZERO_STRUCT(**auth_info);
230         }
231         SAFE_FREE(*auth_info);
232 }
233
234 /****************************************************************************
235  Try to get a challenge out of the various authenticaion modules.
236  It is up to the caller to free it.
237 ****************************************************************************/
238
239 DATA_BLOB auth_get_challenge(auth_authsupplied_info *auth_info) 
240 {
241         DATA_BLOB challenge = data_blob(NULL, 0);
242         char *challenge_set_by = NULL;
243         auth_methods *auth_method;
244
245         if (auth_info->challenge.length) {
246                 DEBUG(5, ("auth_get_challenge: returning previous challenge (normal)\n"));
247                 return data_blob(auth_info->challenge.data, auth_info->challenge.length);
248         }
249
250         for (auth_method = auth_info->auth_method_list; auth_method; auth_method = auth_method->next)
251         {
252                 if (auth_method->get_chal) {
253                         DEBUG(5, ("auth_get_challenge: getting challenge from module %s\n", auth_method->name));
254                         if (challenge_set_by) {
255                                 DEBUG(1, ("auth_get_challenge: CONFIGURATION ERROR: authenticaion method %s has already specified a challenge.  Challenge by %s ignored.\n", 
256                                           challenge_set_by, auth_method->name));
257                         } else {
258                                 challenge = auth_method->get_chal(&auth_method->private_data, auth_info);
259                                 if (challenge.length) {
260                                         DEBUG(5, ("auth_get_challenge: sucessfully got challenge from module %s\n", auth_method->name));
261                                         auth_info->challenge = challenge;
262                                         challenge_set_by = auth_method->name;
263                                         auth_info->challenge_set_method = auth_method;
264                                 } else {
265                                         DEBUG(3, ("auth_get_challenge: getting challenge from authenticaion method %s FAILED.\n", 
266                                                   auth_method->name));
267                                 }
268                         }
269                 } else {
270                         DEBUG(5, ("auth_get_challenge: module %s did not want to specify a challenge\n", auth_method->name));
271                 }
272         }
273         
274         if (!challenge_set_by) {
275                 uchar chal[8];
276                 
277                 generate_random_buffer(chal, sizeof(chal), False);
278                 auth_info->challenge = data_blob(chal, sizeof(chal));
279                 
280                 challenge_set_by = "random";
281         } 
282         
283         DEBUG(5, ("auth_info challenge created by %s\n", challenge_set_by));
284         DEBUG(5, ("challenge is: \n"));
285         dump_data(5, auth_info->challenge.data, (auth_info)->challenge.length);
286         
287         SMB_ASSERT(auth_info->challenge.length == 8);
288
289         auth_info->challenge_set_by=challenge_set_by;
290
291         return data_blob(auth_info->challenge.data, auth_info->challenge.length);
292 }
293
294