r5137: fix types
[ira/wip.git] / source / auth / auth_util.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Authentication utility functions
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett 2001
6    Copyright (C) Jeremy Allison 2000-2001
7    Copyright (C) Rafal Szczesniak 2002
8    Copyright (C) Stefan Metzmacher 2005
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26 #include "librpc/gen_ndr/ndr_samr.h"
27 #include "librpc/gen_ndr/ndr_netlogon.h"
28 #include "libcli/security/security.h"
29 #include "auth/auth.h"
30
31 /* this default function can be used by mostly all backends
32  * which don't want to set a challlenge
33  */
34 NTSTATUS auth_get_challenge_not_implemented(struct auth_method_context *ctx, TALLOC_CTX *mem_ctx, DATA_BLOB *challenge)
35 {
36         /* we don't want to set a challenge */
37         return NT_STATUS_NOT_IMPLEMENTED;
38 }
39
40 /****************************************************************************
41  Create an auth_usersupplied_data structure
42 ****************************************************************************/
43 static NTSTATUS make_user_info(TALLOC_CTX *mem_ctx,
44                                const char *c_account_name,
45                                const char *account_name,
46                                const char *c_domain_name, 
47                                const char *domain_name,
48                                const char *workstation_name, 
49                                DATA_BLOB *lm_password, DATA_BLOB *nt_password,
50                                DATA_BLOB *lm_interactive_password, DATA_BLOB *nt_interactive_password,
51                                DATA_BLOB *plaintext_password, BOOL encrypted,
52                                struct auth_usersupplied_info **_user_info)
53 {
54         struct auth_usersupplied_info *user_info;
55         DATA_BLOB blob;
56
57         DEBUG(5,("attempting to make a user_info for %s (%s)\n", account_name, c_account_name));
58
59         user_info = talloc(mem_ctx, struct auth_usersupplied_info);
60         NT_STATUS_HAVE_NO_MEMORY(user_info);
61
62         DEBUG(5,("making strings for %s's user_info struct\n", account_name));
63
64         user_info->client.account_name = talloc_strdup(user_info, c_account_name);
65         NT_STATUS_HAVE_NO_MEMORY(user_info->client.account_name);
66
67         user_info->account_name = talloc_strdup(user_info, account_name);
68         NT_STATUS_HAVE_NO_MEMORY(user_info->account_name);
69
70         user_info->client.domain_name = talloc_strdup(user_info, c_domain_name);
71         NT_STATUS_HAVE_NO_MEMORY(user_info->client.domain_name);
72
73         user_info->domain_name = talloc_strdup(user_info, domain_name);
74         NT_STATUS_HAVE_NO_MEMORY(user_info->domain_name);
75
76         user_info->workstation_name = talloc_strdup(user_info, workstation_name);
77         NT_STATUS_HAVE_NO_MEMORY(user_info->workstation_name);
78
79         DEBUG(5,("making blobs for %s's user_info struct\n", account_name));
80
81         if (lm_password) {
82                 blob = data_blob_dup_talloc(user_info, lm_password);
83                 NT_STATUS_HAVE_NO_MEMORY(blob.data);
84         } else {
85                 blob = data_blob(NULL, 0);
86         }
87         user_info->lm_resp = blob;
88
89         if (nt_password) {
90                 blob = data_blob_dup_talloc(user_info, nt_password);
91                 NT_STATUS_HAVE_NO_MEMORY(blob.data);
92         } else {
93                 blob = data_blob(NULL, 0);
94         }
95         user_info->nt_resp = blob;
96
97         if (lm_interactive_password) {
98                 blob = data_blob_dup_talloc(user_info, lm_interactive_password);
99                 NT_STATUS_HAVE_NO_MEMORY(blob.data);
100         } else {
101                 blob = data_blob(NULL, 0);
102         }
103         user_info->lm_interactive_password = blob;
104
105         if (nt_interactive_password) {
106                 blob = data_blob_dup_talloc(user_info, nt_interactive_password);
107                 NT_STATUS_HAVE_NO_MEMORY(blob.data);
108         } else {
109                 blob = data_blob(NULL, 0);
110         }
111         user_info->nt_interactive_password = blob;
112
113         if (plaintext_password) {
114                 blob = data_blob_dup_talloc(user_info, plaintext_password);
115                 NT_STATUS_HAVE_NO_MEMORY(blob.data);
116         } else {
117                 blob = data_blob(NULL, 0);
118         }
119         user_info->plaintext_password = blob;
120
121         user_info->encrypted = encrypted;
122
123         DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted ? "":"un" , account_name, c_account_name));
124
125         *_user_info = user_info;
126
127         return NT_STATUS_OK;
128 }
129
130 /****************************************************************************
131  Create an auth_usersupplied_data structure after appropriate mapping.
132 ****************************************************************************/
133
134 NTSTATUS make_user_info_map(TALLOC_CTX *mem_ctx,
135                             const char *c_account_name,
136                             const char *c_domain_name,
137                             const char *workstation_name,
138                             DATA_BLOB *lm_password, DATA_BLOB *nt_password,
139                             DATA_BLOB *lm_interactive_password, DATA_BLOB *nt_interactive_password,
140                             DATA_BLOB *plaintext, BOOL encrypted,
141                             struct auth_usersupplied_info **user_info)
142 {
143         const char *domain;
144
145         DEBUG(5,("make_user_info_map: Mapping user [%s]\\[%s] from workstation [%s]\n",
146                 c_domain_name, c_account_name, workstation_name));
147
148         /* don't allow "" as a domain, fixes a Win9X bug 
149            where it doens't supply a domain for logon script
150            'net use' commands.                                 */
151         if (*c_domain_name) {
152                 domain = c_domain_name;
153         } else {
154                 domain = lp_workgroup();
155         }
156
157         return make_user_info(mem_ctx,
158                               c_account_name, c_account_name, 
159                               c_domain_name, domain,
160                               workstation_name,
161                               lm_password, nt_password,
162                               lm_interactive_password, nt_interactive_password,
163                               plaintext, encrypted,
164                               user_info);
165 }
166
167 /****************************************************************************
168  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
169  Decrypt and encrypt the passwords.
170 ****************************************************************************/
171 NTSTATUS make_user_info_netlogon_network(TALLOC_CTX *mem_ctx,
172                                          const char *c_account_name,
173                                          const char *c_domain_name,
174                                          const char *workstation_name,
175                                          const uint8_t *lm_network_password, int lm_password_len,
176                                          const uint8_t *nt_network_password, int nt_password_len,
177                                          struct auth_usersupplied_info **user_info)
178 {
179         DATA_BLOB lm_blob = data_blob_const(lm_network_password, lm_password_len);
180         DATA_BLOB nt_blob = data_blob_const(nt_network_password, nt_password_len);
181
182         return make_user_info_map(mem_ctx,
183                                   c_account_name,
184                                   c_domain_name, 
185                                   workstation_name, 
186                                   lm_password_len ? &lm_blob : NULL, 
187                                   nt_password_len ? &nt_blob : NULL,
188                                   NULL, NULL, NULL, True,
189                                   user_info);
190 }
191
192 /****************************************************************************
193  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
194  Decrypt and encrypt the passwords.
195 ****************************************************************************/
196 NTSTATUS make_user_info_netlogon_interactive(TALLOC_CTX *mem_ctx,
197                                              const char *c_account_name,
198                                              const char *c_domain_name,
199                                              const char *workstation_name,
200                                              const uint8_t chal[8],
201                                              const struct samr_Password *lm_interactive_password,
202                                              const struct samr_Password *nt_interactive_password,
203                                              struct auth_usersupplied_info **user_info)
204 {
205         NTSTATUS nt_status;
206         DATA_BLOB local_lm_blob;
207         DATA_BLOB local_nt_blob;
208         
209         DATA_BLOB lm_interactive_blob;
210         DATA_BLOB nt_interactive_blob;
211         uint8_t local_lm_response[24];
212         uint8_t local_nt_response[24];
213
214         SMBOWFencrypt(lm_interactive_password->hash, chal, local_lm_response);
215         SMBOWFencrypt(nt_interactive_password->hash, chal, local_nt_response);
216
217         local_lm_blob = data_blob_const(local_lm_response, sizeof(local_lm_response));
218         lm_interactive_blob = data_blob_const(lm_interactive_password->hash, 
219                                               sizeof(lm_interactive_password->hash));
220
221         local_nt_blob = data_blob_const(local_nt_response, sizeof(local_nt_response));
222         nt_interactive_blob = data_blob_const(nt_interactive_password->hash, 
223                                               sizeof(nt_interactive_password->hash));
224         
225         nt_status = make_user_info_map(mem_ctx,
226                                        c_account_name,
227                                        c_domain_name, 
228                                        workstation_name,
229                                        &local_lm_blob,
230                                        &local_nt_blob,
231                                        &lm_interactive_blob,
232                                        &nt_interactive_blob,
233                                        NULL, True,
234                                        user_info);
235         return nt_status;
236 }
237
238 /****************************************************************************
239  Create an auth_usersupplied_data structure
240 ****************************************************************************/
241 NTSTATUS make_user_info_for_reply_enc(TALLOC_CTX *mem_ctx,
242                                       const char *c_account_name,
243                                       const char *c_domain_name,
244                                       const char *workstation_name,
245                                       DATA_BLOB lm_resp, DATA_BLOB nt_resp,
246                                       struct auth_usersupplied_info **user_info)
247 {
248         return make_user_info_map(mem_ctx,
249                                   c_account_name,
250                                   c_domain_name,
251                                   workstation_name,
252                                   lm_resp.data ? &lm_resp : NULL,
253                                   nt_resp.data ? &nt_resp : NULL,
254                                   NULL, NULL, NULL, True,
255                                   user_info);
256 }
257
258 /****************************************************************************
259  Create a anonymous user_info blob, for anonymous authenticaion.
260 ****************************************************************************/
261 NTSTATUS make_user_info_anonymous(TALLOC_CTX *mem_ctx, struct auth_usersupplied_info **user_info) 
262 {
263         return make_user_info(mem_ctx,
264                               "", "", "", "", "", 
265                               NULL, NULL, NULL, NULL, 
266                               NULL, True,
267                               user_info);
268 }
269
270
271 /***************************************************************************
272  Make a server_info struct from the info3 returned by a domain logon 
273 ***************************************************************************/
274 NTSTATUS make_server_info_netlogon_validation(TALLOC_CTX *mem_ctx,
275                                               const char *account_name,
276                                               uint16_t validation_level,
277                                               union netr_Validation *validation,
278                                               struct auth_serversupplied_info **_server_info)
279 {
280         struct auth_serversupplied_info *server_info;
281         struct netr_SamBaseInfo *base = NULL;
282         int i;
283
284         switch (validation_level) {
285         case 2:
286                 if (!validation || !validation->sam2) {
287                         return NT_STATUS_INVALID_PARAMETER;
288                 }
289                 base = &validation->sam2->base;
290                 break;
291         case 3:
292                 if (!validation || !validation->sam3) {
293                         return NT_STATUS_INVALID_PARAMETER;
294                 }
295                 base = &validation->sam3->base;
296                 break;
297         case 6:
298                 if (!validation || !validation->sam6) {
299                         return NT_STATUS_INVALID_PARAMETER;
300                 }
301                 base = &validation->sam6->base;
302                 break;
303         default:
304                 return NT_STATUS_INVALID_LEVEL;
305         }
306
307         server_info = talloc(mem_ctx, struct auth_serversupplied_info);
308         NT_STATUS_HAVE_NO_MEMORY(server_info);
309
310         /*
311            Here is where we should check the list of
312            trusted domains, and verify that the SID 
313            matches.
314         */
315         server_info->account_sid = dom_sid_add_rid(server_info, base->domain_sid, base->rid);
316         NT_STATUS_HAVE_NO_MEMORY(server_info->account_sid);
317
318
319         server_info->primary_group_sid = dom_sid_add_rid(server_info, base->domain_sid, base->primary_gid);
320         NT_STATUS_HAVE_NO_MEMORY(server_info->primary_group_sid);
321
322         server_info->n_domain_groups = base->group_count;
323         if (base->group_count) {
324                 server_info->domain_groups = talloc_array(server_info, struct dom_sid*, base->group_count);
325                 NT_STATUS_HAVE_NO_MEMORY(server_info->domain_groups);
326         } else {
327                 server_info->domain_groups = NULL;
328         }
329
330         for (i = 0; i < base->group_count; i++) {
331                 server_info->domain_groups[i] = dom_sid_add_rid(server_info, base->domain_sid, base->groupids[i].rid);
332                 NT_STATUS_HAVE_NO_MEMORY(server_info->domain_groups[i]);
333         }
334
335         /* Copy 'other' sids.  We need to do sid filtering here to
336            prevent possible elevation of privileges.  See:
337
338            http://www.microsoft.com/windows2000/techinfo/administration/security/sidfilter.asp
339          */
340
341         if (validation_level == 3) {
342                 struct dom_sid **dgrps = server_info->domain_groups;
343                 size_t sidcount = server_info->n_domain_groups + validation->sam3->sidcount;
344                 size_t n_dgrps = server_info->n_domain_groups;
345
346                 dgrps = talloc_realloc(server_info, dgrps, struct dom_sid*, sidcount);
347                 NT_STATUS_HAVE_NO_MEMORY(dgrps);
348
349                 for (i = 0; i < validation->sam3->sidcount; i++) {
350                         dgrps[n_dgrps + i] = talloc_reference(dgrps, validation->sam3->sids[i].sid);
351                 }
352
353                 server_info->n_domain_groups = sidcount;
354                 server_info->domain_groups = dgrps;
355
356                 /* Where are the 'global' sids?... */
357         }
358
359         if (base->account_name.string) {
360                 server_info->account_name = talloc_reference(server_info, base->account_name.string);
361         } else {
362                 server_info->account_name = talloc_strdup(server_info, account_name);
363                 NT_STATUS_HAVE_NO_MEMORY(server_info->account_name);
364         }
365
366         server_info->domain_name = talloc_reference(server_info, base->domain.string);
367         server_info->full_name = talloc_reference(server_info, base->full_name.string);
368         server_info->logon_script = talloc_reference(server_info, base->logon_script.string);
369         server_info->profile_path = talloc_reference(server_info, base->profile_path.string);
370         server_info->home_directory = talloc_reference(server_info, base->home_directory.string);
371         server_info->home_drive = talloc_reference(server_info, base->home_drive.string);
372         server_info->last_logon = base->last_logon;
373         server_info->last_logoff = base->last_logoff;
374         server_info->acct_expiry = base->acct_expiry;
375         server_info->last_password_change = base->last_password_change;
376         server_info->allow_password_change = base->allow_password_change;
377         server_info->force_password_change = base->force_password_change;
378         server_info->logon_count = base->logon_count;
379         server_info->bad_password_count = base->bad_password_count;
380         server_info->acct_flags = base->acct_flags;
381
382         server_info->authenticated = True;
383
384         /* ensure we are never given NULL session keys */
385
386         if (all_zero(base->key.key, sizeof(base->key.key))) {
387                 server_info->user_session_key = data_blob(NULL, 0);
388         } else {
389                 server_info->user_session_key = data_blob_talloc(server_info, base->key.key, sizeof(base->key.key));
390                 NT_STATUS_HAVE_NO_MEMORY(server_info->user_session_key.data);
391         }
392
393         if (all_zero(base->LMSessKey.key, sizeof(base->LMSessKey.key))) {
394                 server_info->lm_session_key = data_blob(NULL, 0);
395         } else {
396                 server_info->lm_session_key = data_blob_talloc(server_info, base->LMSessKey.key, sizeof(base->LMSessKey.key));
397                 NT_STATUS_HAVE_NO_MEMORY(server_info->lm_session_key.data);
398         }
399
400         *_server_info = server_info;
401         return NT_STATUS_OK;
402 }
403
404 NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx, 
405                                     struct auth_serversupplied_info *server_info, 
406                                     struct auth_session_info **_session_info) 
407 {
408         struct auth_session_info *session_info;
409         NTSTATUS nt_status;
410
411         session_info = talloc(mem_ctx, struct auth_session_info);
412         NT_STATUS_HAVE_NO_MEMORY(session_info);
413
414         session_info->server_info = talloc_reference(session_info, server_info);
415
416         /* unless set otherwise, the session key is the user session
417          * key from the auth subsystem */ 
418         session_info->session_key = server_info->user_session_key;
419
420         nt_status = security_token_create(session_info,
421                                           server_info->account_sid,
422                                           server_info->primary_group_sid,
423                                           server_info->n_domain_groups,
424                                           server_info->domain_groups,
425                                           server_info->authenticated,
426                                           &session_info->security_token);
427         NT_STATUS_NOT_OK_RETURN(nt_status);
428
429         *_session_info = session_info;
430         return NT_STATUS_OK;
431 }
432
433 /****************************************************************************
434  prints a struct auth_session_info security token to debug output.
435 ****************************************************************************/
436 void auth_session_info_debug(int dbg_lev, 
437                              const struct auth_session_info *session_info)
438 {
439         if (!session_info) {
440                 DEBUGC(dbg_class, dbg_lev, ("Session Info: (NULL)\n"));
441                 return; 
442         }
443
444         security_token_debug(dbg_lev, session_info->security_token);
445 }
446
447 /**
448  * Squash an NT_STATUS in line with security requirements.
449  * In an attempt to avoid giving the whole game away when users
450  * are authenticating, NT replaces both NT_STATUS_NO_SUCH_USER and 
451  * NT_STATUS_WRONG_PASSWORD with NT_STATUS_LOGON_FAILURE in certain situations 
452  * (session setups in particular).
453  *
454  * @param nt_status NTSTATUS input for squashing.
455  * @return the 'squashed' nt_status
456  **/
457 NTSTATUS auth_nt_status_squash(NTSTATUS nt_status)
458 {
459         if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) {
460                 /* Match WinXP and don't give the game away */
461                 return NT_STATUS_LOGON_FAILURE;
462         } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) {
463                 /* Match WinXP and don't give the game away */
464                 return NT_STATUS_LOGON_FAILURE;
465         }
466
467         return nt_status;
468 }