challange -> challenge
[samba.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         for (;*text_list; text_list++)
83         { 
84                 DEBUG(5,("Attempting to find an auth method to match %s\n", *text_list));
85                 for (i = 0; builtin_auth_init_functions[i].name; i++)
86                 {
87                         if (strequal(builtin_auth_init_functions[i].name, *text_list))
88                         {
89                                 DEBUG(5,("Found auth method %s (at pos %d)\n", *text_list, i));
90                                 /* Malloc entry,  fill it,  link it */
91                                 t = (auth_methods *)malloc(sizeof(*t));
92                                 if (!t) {
93                                         DEBUG(0,("make_pw_chat: malloc failed!\n"));
94                                         return False;
95                                 }
96                                 
97                                 ZERO_STRUCTP(t);
98                                 
99                                 if (builtin_auth_init_functions[i].init(&t)) {
100                                         DEBUG(5,("auth method %s has a valid init\n", *text_list));
101                                         t->name = builtin_auth_init_functions[i].name;
102                                         DLIST_ADD_END(list, t, tmp);
103                                 } else {
104                                         DEBUG(5,("auth method %s DOES NOT have a valid init\n", *text_list));
105                                 }
106                                 break;
107                         }
108                 }
109         }
110         
111         make_auth_info_list(auth_info, list);
112         
113         return True;
114 }
115
116 /***************************************************************************
117  Make a auth_info struct for the auth subsystem
118 ***************************************************************************/
119
120 BOOL make_auth_info_subsystem(auth_authsupplied_info **auth_info) 
121 {
122         char **auth_method_list = NULL; 
123         
124         if (!make_auth_info(auth_info)) {
125                 return False;
126         }
127         
128         if (lp_auth_methods() && !lp_list_copy(&auth_method_list, lp_auth_methods())) {
129                 return False;
130         }
131
132         if (auth_method_list == NULL) {
133                 switch (lp_security()) 
134                 {
135                 case SEC_DOMAIN:
136                         DEBUG(5,("Making default auth method list for security=domain\n"));
137                         auth_method_list = lp_list_make("guest ntdomain local");
138                         break;
139                 case SEC_SERVER:
140                         DEBUG(5,("Making default auth method list for security=server\n"));
141                         auth_method_list = lp_list_make("guest smbserver local");
142                         break;
143                 case SEC_USER:
144                         DEBUG(5,("Making default auth method list for security=user\n"));
145                         auth_method_list = lp_list_make("guest local");
146                         break;
147                 case SEC_SHARE:
148                         DEBUG(5,("Making default auth method list for security=share\n"));
149                         auth_method_list = lp_list_make("guest local");
150                         break;
151                 }
152         } else {
153                 DEBUG(5,("Using specified auth order\n"));
154         }
155         
156         if (!make_auth_info_text_list(auth_info, auth_method_list)) {
157                 lp_list_free(&auth_method_list);
158                 return False;
159         }
160         
161         lp_list_free(&auth_method_list);
162         return True;
163 }
164
165 /***************************************************************************
166  Make a auth_info struct with a random challenge
167 ***************************************************************************/
168
169 BOOL make_auth_info_random(auth_authsupplied_info **auth_info) 
170 {
171         uchar chal[8];
172         if (!make_auth_info_subsystem(auth_info)) {
173                 return False;
174         }
175         
176         generate_random_buffer(chal, sizeof(chal), False);
177         (*auth_info)->challenge = data_blob(chal, sizeof(chal));
178
179         (*auth_info)->challenge_set_by = "random";
180
181         return True;
182 }
183
184 /***************************************************************************
185  Make a auth_info struct with a fixed challenge
186 ***************************************************************************/
187
188 BOOL make_auth_info_fixed(auth_authsupplied_info **auth_info, uchar chal[8]) 
189 {
190         if (!make_auth_info_subsystem(auth_info)) {
191                 return False;
192         }
193         
194         (*auth_info)->challenge = data_blob(chal, 8);
195         return True;
196 }
197
198 /***************************************************************************
199  Clear out a auth_info struct that has been allocated
200 ***************************************************************************/
201
202 void free_auth_info(auth_authsupplied_info **auth_info)
203 {
204         auth_methods *list;
205         if (*auth_info != NULL) {
206                 list = (*auth_info)->auth_method_list;  
207                 while (list) {
208                         auth_methods *old_head = list;
209                         if (list->free_private_data) {
210                                 list->free_private_data(&(list->private_data));
211                         }
212                         DLIST_REMOVE(list, list);                       
213                         SAFE_FREE(old_head);
214                 }
215                 
216                 data_blob_free(&(*auth_info)->challenge);
217                 ZERO_STRUCT(**auth_info);
218         }
219         SAFE_FREE(*auth_info);
220 }
221
222 /****************************************************************************
223  Try to get a challenge out of the various authenticaion modules.
224  It is up to the caller to free it.
225 ****************************************************************************/
226
227 DATA_BLOB auth_get_challenge(auth_authsupplied_info *auth_info) 
228 {
229         DATA_BLOB challenge = data_blob(NULL, 0);
230         char *challenge_set_by = NULL;
231         auth_methods *auth_method;
232
233         if (auth_info->challenge.length) {
234                 DEBUG(5, ("auth_get_challenge: returning previous challenge (normal)\n"));
235                 return data_blob(auth_info->challenge.data, auth_info->challenge.length);
236         }
237
238         for (auth_method = auth_info->auth_method_list; auth_method; auth_method = auth_method->next)
239         {
240                 if (auth_method->get_chal) {
241                         DEBUG(5, ("auth_get_challenge: getting challenge from module %s\n", auth_method->name));
242                         if (challenge_set_by) {
243                                 DEBUG(1, ("auth_get_challenge: CONFIGURATION ERROR: authenticaion method %s has already specified a challenge.  Challenge by %s ignored.\n", 
244                                           challenge_set_by, auth_method->name));
245                         } else {
246                                 challenge = auth_method->get_chal(&auth_method->private_data, auth_info);
247                                 if (challenge.length) {
248                                         DEBUG(5, ("auth_get_challenge: sucessfully got challenge from module %s\n", auth_method->name));
249                                         auth_info->challenge = challenge;
250                                         challenge_set_by = auth_method->name;
251                                         auth_info->challenge_set_method = auth_method;
252                                 } else {
253                                         DEBUG(3, ("auth_get_challenge: getting challenge from authenticaion method %s FAILED.\n", 
254                                                   auth_method->name));
255                                 }
256                         }
257                 } else {
258                         DEBUG(5, ("auth_get_challenge: module %s did not want to specify a challenge\n", auth_method->name));
259                 }
260         }
261         
262         if (!challenge_set_by) {
263                 uchar chal[8];
264                 
265                 generate_random_buffer(chal, sizeof(chal), False);
266                 auth_info->challenge = data_blob(chal, sizeof(chal));
267                 
268                 challenge_set_by = "random";
269         } 
270         
271         DEBUG(5, ("auth_info challenge created by %s\n", challenge_set_by));
272         DEBUG(5, ("challenge is: \n"));
273         dump_data(5, auth_info->challenge.data, (auth_info)->challenge.length);
274         
275         SMB_ASSERT(auth_info->challenge.length == 8);
276
277         auth_info->challenge_set_by=challenge_set_by;
278
279         return data_blob(auth_info->challenge.data, auth_info->challenge.length);
280 }
281
282