ebd0b742270a5619e17ff14cbb5b545469f3c432
[samba.git] / source4 / 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         if (c_domain_name && !user_info->client.domain_name) {
72                 return NT_STATUS_NO_MEMORY;
73         }
74
75         user_info->domain_name = talloc_strdup(user_info, domain_name);
76         NT_STATUS_HAVE_NO_MEMORY(user_info->domain_name);
77
78         user_info->workstation_name = talloc_strdup(user_info, workstation_name);
79         NT_STATUS_HAVE_NO_MEMORY(user_info->workstation_name);
80
81         DEBUG(5,("making blobs for %s's user_info struct\n", account_name));
82
83         if (lm_password) {
84                 blob = data_blob_dup_talloc(user_info, lm_password);
85                 NT_STATUS_HAVE_NO_MEMORY(blob.data);
86         } else {
87                 blob = data_blob(NULL, 0);
88         }
89         user_info->lm_resp = blob;
90
91         if (nt_password) {
92                 blob = data_blob_dup_talloc(user_info, nt_password);
93                 NT_STATUS_HAVE_NO_MEMORY(blob.data);
94         } else {
95                 blob = data_blob(NULL, 0);
96         }
97         user_info->nt_resp = blob;
98
99         if (lm_interactive_password) {
100                 blob = data_blob_dup_talloc(user_info, lm_interactive_password);
101                 NT_STATUS_HAVE_NO_MEMORY(blob.data);
102         } else {
103                 blob = data_blob(NULL, 0);
104         }
105         user_info->lm_interactive_password = blob;
106
107         if (nt_interactive_password) {
108                 blob = data_blob_dup_talloc(user_info, nt_interactive_password);
109                 NT_STATUS_HAVE_NO_MEMORY(blob.data);
110         } else {
111                 blob = data_blob(NULL, 0);
112         }
113         user_info->nt_interactive_password = blob;
114
115         if (plaintext_password) {
116                 blob = data_blob_dup_talloc(user_info, plaintext_password);
117                 NT_STATUS_HAVE_NO_MEMORY(blob.data);
118         } else {
119                 blob = data_blob(NULL, 0);
120         }
121         user_info->plaintext_password = blob;
122
123         user_info->encrypted = encrypted;
124
125         DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted ? "":"un" , account_name, c_account_name));
126
127         *_user_info = user_info;
128
129         return NT_STATUS_OK;
130 }
131
132 /****************************************************************************
133  Create an auth_usersupplied_data structure after appropriate mapping.
134 ****************************************************************************/
135
136 NTSTATUS make_user_info_map(TALLOC_CTX *mem_ctx,
137                             const char *c_account_name,
138                             const char *c_domain_name,
139                             const char *workstation_name,
140                             DATA_BLOB *lm_password, DATA_BLOB *nt_password,
141                             DATA_BLOB *lm_interactive_password, DATA_BLOB *nt_interactive_password,
142                             DATA_BLOB *plaintext, BOOL encrypted,
143                             struct auth_usersupplied_info **user_info)
144 {
145         const char *domain;
146         const char *account_name;
147         char *d;
148         DEBUG(5,("make_user_info_map: Mapping user [%s]\\[%s] from workstation [%s]\n",
149                 c_domain_name, c_account_name, workstation_name));
150
151         account_name = c_account_name;
152
153         /* don't allow "" as a domain, fixes a Win9X bug 
154            where it doens't supply a domain for logon script
155            'net use' commands.                                 */
156
157         /* Split user@realm names into user and realm components.  This is TODO to fix with proper userprincipalname support */
158         if (c_domain_name && *c_domain_name) {
159                 domain = c_domain_name;
160         } else if (strchr_m(c_account_name, '@')) {
161                 account_name = talloc_strdup(mem_ctx, c_account_name);
162                 if (!account_name) {
163                         return NT_STATUS_NO_MEMORY;
164                 }
165                 d = strchr_m(account_name, '@');
166                 if (!d) {
167                         return NT_STATUS_INTERNAL_ERROR;
168                 }
169                 d[0] = '\0';
170                 d++;
171                 domain = d;
172         } else {
173                 domain = lp_workgroup();
174         }
175
176         return make_user_info(mem_ctx,
177                               c_account_name, account_name, 
178                               c_domain_name, domain,
179                               workstation_name,
180                               lm_password, nt_password,
181                               lm_interactive_password, nt_interactive_password,
182                               plaintext, encrypted,
183                               user_info);
184 }
185
186 /****************************************************************************
187  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
188  Decrypt and encrypt the passwords.
189 ****************************************************************************/
190 NTSTATUS make_user_info_netlogon_network(TALLOC_CTX *mem_ctx,
191                                          const char *c_account_name,
192                                          const char *c_domain_name,
193                                          const char *workstation_name,
194                                          const uint8_t *lm_network_password, int lm_password_len,
195                                          const uint8_t *nt_network_password, int nt_password_len,
196                                          struct auth_usersupplied_info **user_info)
197 {
198         DATA_BLOB lm_blob = data_blob_const(lm_network_password, lm_password_len);
199         DATA_BLOB nt_blob = data_blob_const(nt_network_password, nt_password_len);
200
201         return make_user_info_map(mem_ctx,
202                                   c_account_name,
203                                   c_domain_name, 
204                                   workstation_name, 
205                                   lm_password_len ? &lm_blob : NULL, 
206                                   nt_password_len ? &nt_blob : NULL,
207                                   NULL, NULL, NULL, True,
208                                   user_info);
209 }
210
211 /****************************************************************************
212  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
213  Decrypt and encrypt the passwords.
214 ****************************************************************************/
215 NTSTATUS make_user_info_netlogon_interactive(TALLOC_CTX *mem_ctx,
216                                              const char *c_account_name,
217                                              const char *c_domain_name,
218                                              const char *workstation_name,
219                                              const uint8_t chal[8],
220                                              const struct samr_Password *lm_interactive_password,
221                                              const struct samr_Password *nt_interactive_password,
222                                              struct auth_usersupplied_info **user_info)
223 {
224         NTSTATUS nt_status;
225         DATA_BLOB local_lm_blob;
226         DATA_BLOB local_nt_blob;
227         
228         DATA_BLOB lm_interactive_blob;
229         DATA_BLOB nt_interactive_blob;
230         uint8_t local_lm_response[24];
231         uint8_t local_nt_response[24];
232
233         SMBOWFencrypt(lm_interactive_password->hash, chal, local_lm_response);
234         SMBOWFencrypt(nt_interactive_password->hash, chal, local_nt_response);
235
236         local_lm_blob = data_blob_const(local_lm_response, sizeof(local_lm_response));
237         lm_interactive_blob = data_blob_const(lm_interactive_password->hash, 
238                                               sizeof(lm_interactive_password->hash));
239
240         local_nt_blob = data_blob_const(local_nt_response, sizeof(local_nt_response));
241         nt_interactive_blob = data_blob_const(nt_interactive_password->hash, 
242                                               sizeof(nt_interactive_password->hash));
243         
244         nt_status = make_user_info_map(mem_ctx,
245                                        c_account_name,
246                                        c_domain_name, 
247                                        workstation_name,
248                                        &local_lm_blob,
249                                        &local_nt_blob,
250                                        &lm_interactive_blob,
251                                        &nt_interactive_blob,
252                                        NULL, True,
253                                        user_info);
254         return nt_status;
255 }
256
257 /****************************************************************************
258  Create an auth_usersupplied_data structure
259 ****************************************************************************/
260 NTSTATUS make_user_info_for_reply_enc(TALLOC_CTX *mem_ctx,
261                                       const char *c_account_name,
262                                       const char *c_domain_name,
263                                       const char *workstation_name,
264                                       DATA_BLOB lm_resp, DATA_BLOB nt_resp,
265                                       struct auth_usersupplied_info **user_info)
266 {
267         return make_user_info_map(mem_ctx,
268                                   c_account_name,
269                                   c_domain_name,
270                                   workstation_name,
271                                   lm_resp.data ? &lm_resp : NULL,
272                                   nt_resp.data ? &nt_resp : NULL,
273                                   NULL, NULL, NULL, True,
274                                   user_info);
275 }
276
277 /****************************************************************************
278  Create a anonymous user_info blob, for anonymous authenticaion.
279 ****************************************************************************/
280 NTSTATUS make_user_info_anonymous(TALLOC_CTX *mem_ctx, struct auth_usersupplied_info **user_info) 
281 {
282         return make_user_info(mem_ctx,
283                               "", "", "", "", "", 
284                               NULL, NULL, NULL, NULL, 
285                               NULL, True,
286                               user_info);
287 }
288
289
290 /***************************************************************************
291  Make a server_info struct from the info3 returned by a domain logon 
292 ***************************************************************************/
293 NTSTATUS make_server_info_netlogon_validation(TALLOC_CTX *mem_ctx,
294                                               const char *account_name,
295                                               uint16_t validation_level,
296                                               union netr_Validation *validation,
297                                               struct auth_serversupplied_info **_server_info)
298 {
299         struct auth_serversupplied_info *server_info;
300         struct netr_SamBaseInfo *base = NULL;
301         int i;
302
303         switch (validation_level) {
304         case 2:
305                 if (!validation || !validation->sam2) {
306                         return NT_STATUS_INVALID_PARAMETER;
307                 }
308                 base = &validation->sam2->base;
309                 break;
310         case 3:
311                 if (!validation || !validation->sam3) {
312                         return NT_STATUS_INVALID_PARAMETER;
313                 }
314                 base = &validation->sam3->base;
315                 break;
316         case 6:
317                 if (!validation || !validation->sam6) {
318                         return NT_STATUS_INVALID_PARAMETER;
319                 }
320                 base = &validation->sam6->base;
321                 break;
322         default:
323                 return NT_STATUS_INVALID_LEVEL;
324         }
325
326         server_info = talloc(mem_ctx, struct auth_serversupplied_info);
327         NT_STATUS_HAVE_NO_MEMORY(server_info);
328
329         /*
330            Here is where we should check the list of
331            trusted domains, and verify that the SID 
332            matches.
333         */
334         server_info->account_sid = dom_sid_add_rid(server_info, base->domain_sid, base->rid);
335         NT_STATUS_HAVE_NO_MEMORY(server_info->account_sid);
336
337
338         server_info->primary_group_sid = dom_sid_add_rid(server_info, base->domain_sid, base->primary_gid);
339         NT_STATUS_HAVE_NO_MEMORY(server_info->primary_group_sid);
340
341         server_info->n_domain_groups = base->groups.count;
342         if (base->groups.count) {
343                 server_info->domain_groups = talloc_array(server_info, struct dom_sid*, base->groups.count);
344                 NT_STATUS_HAVE_NO_MEMORY(server_info->domain_groups);
345         } else {
346                 server_info->domain_groups = NULL;
347         }
348
349         for (i = 0; i < base->groups.count; i++) {
350                 server_info->domain_groups[i] = dom_sid_add_rid(server_info, base->domain_sid, base->groups.rids[i].rid);
351                 NT_STATUS_HAVE_NO_MEMORY(server_info->domain_groups[i]);
352         }
353
354         /* Copy 'other' sids.  We need to do sid filtering here to
355            prevent possible elevation of privileges.  See:
356
357            http://www.microsoft.com/windows2000/techinfo/administration/security/sidfilter.asp
358          */
359
360         if (validation_level == 3) {
361                 struct dom_sid **dgrps = server_info->domain_groups;
362                 size_t sidcount = server_info->n_domain_groups + validation->sam3->sidcount;
363                 size_t n_dgrps = server_info->n_domain_groups;
364
365                 dgrps = talloc_realloc(server_info, dgrps, struct dom_sid*, sidcount);
366                 NT_STATUS_HAVE_NO_MEMORY(dgrps);
367
368                 for (i = 0; i < validation->sam3->sidcount; i++) {
369                         dgrps[n_dgrps + i] = talloc_reference(dgrps, validation->sam3->sids[i].sid);
370                 }
371
372                 server_info->n_domain_groups = sidcount;
373                 server_info->domain_groups = dgrps;
374
375                 /* Where are the 'global' sids?... */
376         }
377
378         if (base->account_name.string) {
379                 server_info->account_name = talloc_reference(server_info, base->account_name.string);
380         } else {
381                 server_info->account_name = talloc_strdup(server_info, account_name);
382                 NT_STATUS_HAVE_NO_MEMORY(server_info->account_name);
383         }
384
385         server_info->domain_name = talloc_reference(server_info, base->domain.string);
386         server_info->full_name = talloc_reference(server_info, base->full_name.string);
387         server_info->logon_script = talloc_reference(server_info, base->logon_script.string);
388         server_info->profile_path = talloc_reference(server_info, base->profile_path.string);
389         server_info->home_directory = talloc_reference(server_info, base->home_directory.string);
390         server_info->home_drive = talloc_reference(server_info, base->home_drive.string);
391         server_info->last_logon = base->last_logon;
392         server_info->last_logoff = base->last_logoff;
393         server_info->acct_expiry = base->acct_expiry;
394         server_info->last_password_change = base->last_password_change;
395         server_info->allow_password_change = base->allow_password_change;
396         server_info->force_password_change = base->force_password_change;
397         server_info->logon_count = base->logon_count;
398         server_info->bad_password_count = base->bad_password_count;
399         server_info->acct_flags = base->acct_flags;
400
401         server_info->authenticated = True;
402
403         /* ensure we are never given NULL session keys */
404
405         if (all_zero(base->key.key, sizeof(base->key.key))) {
406                 server_info->user_session_key = data_blob(NULL, 0);
407         } else {
408                 server_info->user_session_key = data_blob_talloc(server_info, base->key.key, sizeof(base->key.key));
409                 NT_STATUS_HAVE_NO_MEMORY(server_info->user_session_key.data);
410         }
411
412         if (all_zero(base->LMSessKey.key, sizeof(base->LMSessKey.key))) {
413                 server_info->lm_session_key = data_blob(NULL, 0);
414         } else {
415                 server_info->lm_session_key = data_blob_talloc(server_info, base->LMSessKey.key, sizeof(base->LMSessKey.key));
416                 NT_STATUS_HAVE_NO_MEMORY(server_info->lm_session_key.data);
417         }
418
419         *_server_info = server_info;
420         return NT_STATUS_OK;
421 }
422
423 NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx, 
424                                     struct auth_serversupplied_info *server_info, 
425                                     struct auth_session_info **_session_info) 
426 {
427         struct auth_session_info *session_info;
428         NTSTATUS nt_status;
429
430         session_info = talloc(mem_ctx, struct auth_session_info);
431         NT_STATUS_HAVE_NO_MEMORY(session_info);
432
433         session_info->server_info = talloc_reference(session_info, server_info);
434
435         /* unless set otherwise, the session key is the user session
436          * key from the auth subsystem */ 
437         session_info->session_key = server_info->user_session_key;
438
439         nt_status = security_token_create(session_info,
440                                           server_info->account_sid,
441                                           server_info->primary_group_sid,
442                                           server_info->n_domain_groups,
443                                           server_info->domain_groups,
444                                           server_info->authenticated,
445                                           &session_info->security_token);
446         NT_STATUS_NOT_OK_RETURN(nt_status);
447
448         *_session_info = session_info;
449         return NT_STATUS_OK;
450 }
451
452 /****************************************************************************
453  prints a struct auth_session_info security token to debug output.
454 ****************************************************************************/
455 void auth_session_info_debug(int dbg_lev, 
456                              const struct auth_session_info *session_info)
457 {
458         if (!session_info) {
459                 DEBUGC(dbg_class, dbg_lev, ("Session Info: (NULL)\n"));
460                 return; 
461         }
462
463         security_token_debug(dbg_lev, session_info->security_token);
464 }
465
466 /**
467  * Squash an NT_STATUS in line with security requirements.
468  * In an attempt to avoid giving the whole game away when users
469  * are authenticating, NT replaces both NT_STATUS_NO_SUCH_USER and 
470  * NT_STATUS_WRONG_PASSWORD with NT_STATUS_LOGON_FAILURE in certain situations 
471  * (session setups in particular).
472  *
473  * @param nt_status NTSTATUS input for squashing.
474  * @return the 'squashed' nt_status
475  **/
476 NTSTATUS auth_nt_status_squash(NTSTATUS nt_status)
477 {
478         if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) {
479                 /* Match WinXP and don't give the game away */
480                 return NT_STATUS_LOGON_FAILURE;
481         } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) {
482                 /* Match WinXP and don't give the game away */
483                 return NT_STATUS_LOGON_FAILURE;
484         }
485
486         return nt_status;
487 }