r23792: convert Samba4 to GPLv3
[bbaumbach/samba-autobuild/.git] / source4 / auth / credentials / credentials_ntlm.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    User credentials handling
5
6    Copyright (C) Andrew Tridgell      2001
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2001-2005
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 "librpc/gen_ndr/samr.h" /* for struct samrPassword */
26 #include "lib/crypto/crypto.h"
27 #include "libcli/auth/libcli_auth.h"
28 #include "auth/credentials/credentials.h"
29
30 void cli_credentials_get_ntlm_username_domain(struct cli_credentials *cred, TALLOC_CTX *mem_ctx, 
31                                               const char **username, 
32                                               const char **domain) 
33 {
34         if (cred->principal_obtained > cred->username_obtained) {
35                 *domain = talloc_strdup(mem_ctx, "");
36                 *username = cli_credentials_get_principal(cred, mem_ctx);
37         } else {
38                 *domain = cli_credentials_get_domain(cred);
39                 *username = cli_credentials_get_username(cred);
40         }
41 }
42
43 NTSTATUS cli_credentials_get_ntlm_response(struct cli_credentials *cred, TALLOC_CTX *mem_ctx, 
44                                            int *flags,
45                                            DATA_BLOB challenge, DATA_BLOB target_info, 
46                                            DATA_BLOB *_lm_response, DATA_BLOB *_nt_response, 
47                                            DATA_BLOB *_lm_session_key, DATA_BLOB *_session_key) 
48 {
49         const char *user, *domain;
50         DATA_BLOB lm_response, nt_response;
51         DATA_BLOB lm_session_key, session_key;
52         const struct samr_Password *nt_hash;
53         lm_session_key = data_blob(NULL, 0);
54
55         nt_hash = cli_credentials_get_nt_hash(cred, mem_ctx);
56
57         cli_credentials_get_ntlm_username_domain(cred, mem_ctx, &user, &domain);
58
59         /* If we are sending a username@realm login (see function
60          * above), then we will not send LM, it will not be
61          * accepted */
62         if (cred->principal_obtained > cred->username_obtained) {
63                 *flags = *flags & ~CLI_CRED_LANMAN_AUTH;
64         }
65
66         /* Likewise if we are a machine account (avoid protocol downgrade attacks) */
67         if (cred->machine_account) {
68                 *flags = *flags & ~CLI_CRED_LANMAN_AUTH;
69         }
70         
71         if (cred->use_kerberos == CRED_MUST_USE_KERBEROS) {
72                 return NT_STATUS_ACCESS_DENIED;
73         }
74
75         if (!nt_hash) {
76                 static const uint8_t zeros[16];
77                 /* do nothing - blobs are zero length */
78
79                 /* session key is all zeros */
80                 session_key = data_blob_talloc(mem_ctx, zeros, 16);
81                 lm_session_key = data_blob_talloc(mem_ctx, zeros, 16);
82
83                 lm_response = data_blob(NULL, 0);
84                 nt_response = data_blob(NULL, 0);
85                 
86                 /* not doing NTLM2 without a password */
87                 *flags &= ~CLI_CRED_NTLM2;
88         } else if (*flags & CLI_CRED_NTLMv2_AUTH) {
89
90                 if (!target_info.length) {
91                         /* be lazy, match win2k - we can't do NTLMv2 without it */
92                         DEBUG(1, ("Server did not provide 'target information', required for NTLMv2\n"));
93                         return NT_STATUS_INVALID_PARAMETER;
94                 }
95
96                 /* TODO: if the remote server is standalone, then we should replace 'domain'
97                    with the server name as supplied above */
98                 
99                 if (!SMBNTLMv2encrypt_hash(mem_ctx,
100                                            user, 
101                                            domain, 
102                                            nt_hash->hash, &challenge, 
103                                            &target_info, 
104                                            &lm_response, &nt_response, 
105                                            NULL, &session_key)) {
106                         return NT_STATUS_NO_MEMORY;
107                 }
108
109                 /* LM Key is incompatible... */
110                 *flags &= ~CLI_CRED_LANMAN_AUTH;
111         } else if (*flags & CLI_CRED_NTLM2) {
112                 struct MD5Context md5_session_nonce_ctx;
113                 uint8_t session_nonce[16];
114                 uint8_t session_nonce_hash[16];
115                 uint8_t user_session_key[16];
116                 
117                 lm_response = data_blob_talloc(mem_ctx, NULL, 24);
118                 generate_random_buffer(lm_response.data, 8);
119                 memset(lm_response.data+8, 0, 16);
120
121                 memcpy(session_nonce, challenge.data, 8);
122                 memcpy(&session_nonce[8], lm_response.data, 8);
123         
124                 MD5Init(&md5_session_nonce_ctx);
125                 MD5Update(&md5_session_nonce_ctx, challenge.data, 8);
126                 MD5Update(&md5_session_nonce_ctx, lm_response.data, 8);
127                 MD5Final(session_nonce_hash, &md5_session_nonce_ctx);
128
129                 DEBUG(5, ("NTLMSSP challenge set by NTLM2\n"));
130                 DEBUG(5, ("challenge is: \n"));
131                 dump_data(5, session_nonce_hash, 8);
132                 
133                 nt_response = data_blob_talloc(mem_ctx, NULL, 24);
134                 SMBOWFencrypt(nt_hash->hash,
135                               session_nonce_hash,
136                               nt_response.data);
137                 
138                 session_key = data_blob_talloc(mem_ctx, NULL, 16);
139
140                 SMBsesskeygen_ntv1(nt_hash->hash, user_session_key);
141                 hmac_md5(user_session_key, session_nonce, sizeof(session_nonce), session_key.data);
142                 dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);
143
144                 /* LM Key is incompatible... */
145                 *flags &= ~CLI_CRED_LANMAN_AUTH;
146         } else {
147                 uint8_t lm_hash[16];
148                 nt_response = data_blob_talloc(mem_ctx, NULL, 24);
149                 SMBOWFencrypt(nt_hash->hash, challenge.data,
150                               nt_response.data);
151                 
152                 session_key = data_blob_talloc(mem_ctx, NULL, 16);
153                 SMBsesskeygen_ntv1(nt_hash->hash, session_key.data);
154                 dump_data_pw("NT session key:\n", session_key.data, session_key.length);
155
156                 /* lanman auth is insecure, it may be disabled.  
157                    We may also not have a password */
158                 if (*flags & CLI_CRED_LANMAN_AUTH) {
159                         const char *password;
160                         password = cli_credentials_get_password(cred);
161                         if (!password) {
162                                 lm_response = nt_response;
163                         } else {
164                                 lm_response = data_blob_talloc(mem_ctx, NULL, 24);
165                                 if (!SMBencrypt(password,challenge.data,
166                                                 lm_response.data)) {
167                                         /* If the LM password was too long (and therefore the LM hash being
168                                            of the first 14 chars only), don't send it.
169
170                                            We don't have any better options but to send the NT response 
171                                         */
172                                         data_blob_free(&lm_response);
173                                         lm_response = nt_response;
174                                         /* LM Key is incompatible with 'long' passwords */
175                                         *flags &= ~CLI_CRED_LANMAN_AUTH;
176                                 } else {
177                                         E_deshash(password, lm_hash);
178                                         lm_session_key = data_blob_talloc(mem_ctx, NULL, 16);
179                                         memcpy(lm_session_key.data, lm_hash, 8);
180                                         memset(&lm_session_key.data[8], '\0', 8);
181                                         
182                                         if (!(*flags & CLI_CRED_NTLM_AUTH)) {
183                                                 session_key = lm_session_key;
184                                         }
185                                 }
186                         }
187                 } else {
188                         const char *password;
189
190                         /* LM Key is incompatible... */
191                         lm_response = nt_response;
192                         *flags &= ~CLI_CRED_LANMAN_AUTH;
193
194                         password = cli_credentials_get_password(cred);
195                         if (password) {
196                                 E_deshash(password, lm_hash);
197                                 lm_session_key = data_blob_talloc(mem_ctx, NULL, 16);
198                                 memcpy(lm_session_key.data, lm_hash, 8);
199                                 memset(&lm_session_key.data[8], '\0', 8);
200                         }
201                 }
202         }
203         if (_lm_response) {
204                 *_lm_response = lm_response;
205         }
206         if (_nt_response) {
207                 *_nt_response = nt_response;
208         }
209         if (_lm_session_key) {
210                 *_lm_session_key = lm_session_key;
211         }
212         if (_session_key) {
213                 *_session_key = session_key;
214         }
215         return NT_STATUS_OK;
216 }
217