s4-auth Rename auth -> auth4 to avoid conflict with s3 auth
[samba.git] / source4 / auth / ntlm / 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 3 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, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "auth/auth.h"
26 #include "libcli/auth/libcli_auth.h"
27 #include "param/param.h"
28 #include "auth/ntlm/auth_proto.h"
29
30 /* this default function can be used by mostly all backends
31  * which don't want to set a challenge
32  */
33 NTSTATUS auth_get_challenge_not_implemented(struct auth_method_context *ctx, TALLOC_CTX *mem_ctx, uint8_t chal[8])
34 {
35         /* we don't want to set a challenge */
36         return NT_STATUS_NOT_IMPLEMENTED;
37 }
38
39 /****************************************************************************
40  Create an auth_usersupplied_data structure after appropriate mapping.
41 ****************************************************************************/
42
43 NTSTATUS map_user_info(TALLOC_CTX *mem_ctx,
44                        const char *default_domain,
45                        const struct auth_usersupplied_info *user_info,
46                        struct auth_usersupplied_info **user_info_mapped)
47 {
48         const char *domain;
49         char *account_name;
50         char *d;
51         DEBUG(5,("map_user_info: Mapping user [%s]\\[%s] from workstation [%s]\n",
52                 user_info->client.domain_name, user_info->client.account_name, user_info->workstation_name));
53
54         account_name = talloc_strdup(mem_ctx, user_info->client.account_name);
55         if (!account_name) {
56                 return NT_STATUS_NO_MEMORY;
57         }
58         
59         /* don't allow "" as a domain, fixes a Win9X bug 
60            where it doesn't supply a domain for logon script
61            'net use' commands.                                 */
62
63         /* Split user@realm names into user and realm components.  This is TODO to fix with proper userprincipalname support */
64         if (user_info->client.domain_name && *user_info->client.domain_name) {
65                 domain = user_info->client.domain_name;
66         } else if (strchr_m(user_info->client.account_name, '@')) {
67                 d = strchr_m(account_name, '@');
68                 if (!d) {
69                         return NT_STATUS_INTERNAL_ERROR;
70                 }
71                 d[0] = '\0';
72                 d++;
73                 domain = d;
74         } else {
75                 domain = default_domain;
76         }
77
78         *user_info_mapped = talloc_zero(mem_ctx, struct auth_usersupplied_info);
79         if (!*user_info_mapped) {
80                 return NT_STATUS_NO_MEMORY;
81         }
82         if (!talloc_reference(*user_info_mapped, user_info)) {
83                 return NT_STATUS_NO_MEMORY;
84         }
85         **user_info_mapped = *user_info;
86         (*user_info_mapped)->mapped_state = true;
87         (*user_info_mapped)->mapped.domain_name = talloc_strdup(*user_info_mapped, domain);
88         (*user_info_mapped)->mapped.account_name = talloc_strdup(*user_info_mapped, account_name);
89         talloc_free(account_name);
90         if (!(*user_info_mapped)->mapped.domain_name 
91             || !(*user_info_mapped)->mapped.account_name) {
92                 return NT_STATUS_NO_MEMORY;
93         }
94
95         return NT_STATUS_OK;
96 }
97
98 /****************************************************************************
99  Create an auth_usersupplied_data structure after appropriate mapping.
100 ****************************************************************************/
101
102 NTSTATUS encrypt_user_info(TALLOC_CTX *mem_ctx, struct auth4_context *auth_context, 
103                            enum auth_password_state to_state,
104                            const struct auth_usersupplied_info *user_info_in,
105                            const struct auth_usersupplied_info **user_info_encrypted)
106 {
107         NTSTATUS nt_status;
108         struct auth_usersupplied_info *user_info_temp;
109         switch (to_state) {
110         case AUTH_PASSWORD_RESPONSE:
111                 switch (user_info_in->password_state) {
112                 case AUTH_PASSWORD_PLAIN:
113                 {
114                         const struct auth_usersupplied_info *user_info_temp2;
115                         nt_status = encrypt_user_info(mem_ctx, auth_context, 
116                                                       AUTH_PASSWORD_HASH, 
117                                                       user_info_in, &user_info_temp2);
118                         if (!NT_STATUS_IS_OK(nt_status)) {
119                                 return nt_status;
120                         }
121                         user_info_in = user_info_temp2;
122                         /* fall through */
123                 }
124                 case AUTH_PASSWORD_HASH:
125                 {
126                         uint8_t chal[8];
127                         DATA_BLOB chall_blob;
128                         user_info_temp = talloc_zero(mem_ctx, struct auth_usersupplied_info);
129                         if (!user_info_temp) {
130                                 return NT_STATUS_NO_MEMORY;
131                         }
132                         if (!talloc_reference(user_info_temp, user_info_in)) {
133                                 return NT_STATUS_NO_MEMORY;
134                         }
135                         *user_info_temp = *user_info_in;
136                         user_info_temp->mapped_state = to_state;
137                         
138                         nt_status = auth_get_challenge(auth_context, chal);
139                         if (!NT_STATUS_IS_OK(nt_status)) {
140                                 return nt_status;
141                         }
142                         
143                         chall_blob = data_blob_talloc(mem_ctx, chal, 8);
144                         if (lpcfg_client_ntlmv2_auth(auth_context->lp_ctx)) {
145                                 DATA_BLOB names_blob = NTLMv2_generate_names_blob(mem_ctx,  lpcfg_netbios_name(auth_context->lp_ctx), lpcfg_workgroup(auth_context->lp_ctx));
146                                 DATA_BLOB lmv2_response, ntlmv2_response, lmv2_session_key, ntlmv2_session_key;
147                                 
148                                 if (!SMBNTLMv2encrypt_hash(user_info_temp,
149                                                            user_info_in->client.account_name, 
150                                                            user_info_in->client.domain_name, 
151                                                            user_info_in->password.hash.nt->hash, &chall_blob,
152                                                            &names_blob,
153                                                            &lmv2_response, &ntlmv2_response, 
154                                                            &lmv2_session_key, &ntlmv2_session_key)) {
155                                         data_blob_free(&names_blob);
156                                         return NT_STATUS_NO_MEMORY;
157                                 }
158                                 data_blob_free(&names_blob);
159                                 user_info_temp->password.response.lanman = lmv2_response;
160                                 user_info_temp->password.response.nt = ntlmv2_response;
161                                 
162                                 data_blob_free(&lmv2_session_key);
163                                 data_blob_free(&ntlmv2_session_key);
164                         } else {
165                                 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, 24);
166                                 SMBOWFencrypt(user_info_in->password.hash.nt->hash, chal, blob.data);
167
168                                 user_info_temp->password.response.nt = blob;
169                                 if (lpcfg_client_lanman_auth(auth_context->lp_ctx) && user_info_in->password.hash.lanman) {
170                                         DATA_BLOB lm_blob = data_blob_talloc(mem_ctx, NULL, 24);
171                                         SMBOWFencrypt(user_info_in->password.hash.lanman->hash, chal, blob.data);
172                                         user_info_temp->password.response.lanman = lm_blob;
173                                 } else {
174                                         /* if not sending the LM password, send the NT password twice */
175                                         user_info_temp->password.response.lanman = user_info_temp->password.response.nt;
176                                 }
177                         }
178
179                         user_info_in = user_info_temp;
180                         /* fall through */
181                 }
182                 case AUTH_PASSWORD_RESPONSE:
183                         *user_info_encrypted = user_info_in;
184                 }
185                 break;
186         case AUTH_PASSWORD_HASH:
187         {       
188                 switch (user_info_in->password_state) {
189                 case AUTH_PASSWORD_PLAIN:
190                 {
191                         struct samr_Password lanman;
192                         struct samr_Password nt;
193                         
194                         user_info_temp = talloc_zero(mem_ctx, struct auth_usersupplied_info);
195                         if (!user_info_temp) {
196                                 return NT_STATUS_NO_MEMORY;
197                         }
198                         if (!talloc_reference(user_info_temp, user_info_in)) {
199                                 return NT_STATUS_NO_MEMORY;
200                         }
201                         *user_info_temp = *user_info_in;
202                         user_info_temp->mapped_state = to_state;
203                         
204                         if (E_deshash(user_info_in->password.plaintext, lanman.hash)) {
205                                 user_info_temp->password.hash.lanman = talloc(user_info_temp,
206                                                                               struct samr_Password);
207                                 *user_info_temp->password.hash.lanman = lanman;
208                         } else {
209                                 user_info_temp->password.hash.lanman = NULL;
210                         }
211                         
212                         E_md4hash(user_info_in->password.plaintext, nt.hash);
213                         user_info_temp->password.hash.nt = talloc(user_info_temp,
214                                                                    struct samr_Password);
215                         *user_info_temp->password.hash.nt = nt;
216                         
217                         user_info_in = user_info_temp;
218                         /* fall through */
219                 }
220                 case AUTH_PASSWORD_HASH:
221                         *user_info_encrypted = user_info_in;
222                         break;
223                 default:
224                         return NT_STATUS_INVALID_PARAMETER;
225                         break;
226                 }
227                 break;
228         }
229         default:
230                 return NT_STATUS_INVALID_PARAMETER;
231         }
232
233         return NT_STATUS_OK;
234 }