aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifsencrypt.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/cifsencrypt.c')
-rw-r--r--fs/cifs/cifsencrypt.c214
1 files changed, 192 insertions, 22 deletions
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 35042d8f7338..7ac0056294cf 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -27,6 +27,7 @@
27#include "md5.h" 27#include "md5.h"
28#include "cifs_unicode.h" 28#include "cifs_unicode.h"
29#include "cifsproto.h" 29#include "cifsproto.h"
30#include "ntlmssp.h"
30#include <linux/ctype.h> 31#include <linux/ctype.h>
31#include <linux/random.h> 32#include <linux/random.h>
32 33
@@ -42,7 +43,7 @@ extern void SMBencrypt(unsigned char *passwd, const unsigned char *c8,
42 unsigned char *p24); 43 unsigned char *p24);
43 44
44static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, 45static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
45 const struct mac_key *key, char *signature) 46 const struct session_key *key, char *signature)
46{ 47{
47 struct MD5Context context; 48 struct MD5Context context;
48 49
@@ -78,7 +79,7 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
78 server->sequence_number++; 79 server->sequence_number++;
79 spin_unlock(&GlobalMid_Lock); 80 spin_unlock(&GlobalMid_Lock);
80 81
81 rc = cifs_calculate_signature(cifs_pdu, &server->mac_signing_key, 82 rc = cifs_calculate_signature(cifs_pdu, &server->session_key,
82 smb_signature); 83 smb_signature);
83 if (rc) 84 if (rc)
84 memset(cifs_pdu->Signature.SecuritySignature, 0, 8); 85 memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
@@ -89,7 +90,7 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
89} 90}
90 91
91static int cifs_calc_signature2(const struct kvec *iov, int n_vec, 92static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
92 const struct mac_key *key, char *signature) 93 const struct session_key *key, char *signature)
93{ 94{
94 struct MD5Context context; 95 struct MD5Context context;
95 int i; 96 int i;
@@ -145,7 +146,7 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
145 server->sequence_number++; 146 server->sequence_number++;
146 spin_unlock(&GlobalMid_Lock); 147 spin_unlock(&GlobalMid_Lock);
147 148
148 rc = cifs_calc_signature2(iov, n_vec, &server->mac_signing_key, 149 rc = cifs_calc_signature2(iov, n_vec, &server->session_key,
149 smb_signature); 150 smb_signature);
150 if (rc) 151 if (rc)
151 memset(cifs_pdu->Signature.SecuritySignature, 0, 8); 152 memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
@@ -156,14 +157,14 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
156} 157}
157 158
158int cifs_verify_signature(struct smb_hdr *cifs_pdu, 159int cifs_verify_signature(struct smb_hdr *cifs_pdu,
159 const struct mac_key *mac_key, 160 const struct session_key *session_key,
160 __u32 expected_sequence_number) 161 __u32 expected_sequence_number)
161{ 162{
162 unsigned int rc; 163 unsigned int rc;
163 char server_response_sig[8]; 164 char server_response_sig[8];
164 char what_we_think_sig_should_be[20]; 165 char what_we_think_sig_should_be[20];
165 166
166 if ((cifs_pdu == NULL) || (mac_key == NULL)) 167 if (cifs_pdu == NULL || session_key == NULL)
167 return -EINVAL; 168 return -EINVAL;
168 169
169 if (cifs_pdu->Command == SMB_COM_NEGOTIATE) 170 if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
@@ -192,7 +193,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu,
192 cpu_to_le32(expected_sequence_number); 193 cpu_to_le32(expected_sequence_number);
193 cifs_pdu->Signature.Sequence.Reserved = 0; 194 cifs_pdu->Signature.Sequence.Reserved = 0;
194 195
195 rc = cifs_calculate_signature(cifs_pdu, mac_key, 196 rc = cifs_calculate_signature(cifs_pdu, session_key,
196 what_we_think_sig_should_be); 197 what_we_think_sig_should_be);
197 198
198 if (rc) 199 if (rc)
@@ -209,7 +210,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu,
209} 210}
210 211
211/* We fill in key by putting in 40 byte array which was allocated by caller */ 212/* We fill in key by putting in 40 byte array which was allocated by caller */
212int cifs_calculate_mac_key(struct mac_key *key, const char *rn, 213int cifs_calculate_session_key(struct session_key *key, const char *rn,
213 const char *password) 214 const char *password)
214{ 215{
215 char temp_key[16]; 216 char temp_key[16];
@@ -262,6 +263,148 @@ void calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt,
262} 263}
263#endif /* CIFS_WEAK_PW_HASH */ 264#endif /* CIFS_WEAK_PW_HASH */
264 265
266/* Build a proper attribute value/target info pairs blob.
267 * Fill in netbios and dns domain name and workstation name
268 * and client time (total five av pairs and + one end of fields indicator.
269 * Allocate domain name which gets freed when session struct is deallocated.
270 */
271static int
272build_avpair_blob(struct cifsSesInfo *ses, const struct nls_table *nls_cp)
273{
274 unsigned int dlen;
275 unsigned int wlen;
276 unsigned int size = 6 * sizeof(struct ntlmssp2_name);
277 __le64 curtime;
278 char *defdmname = "WORKGROUP";
279 unsigned char *blobptr;
280 struct ntlmssp2_name *attrptr;
281
282 if (!ses->domainName) {
283 ses->domainName = kstrdup(defdmname, GFP_KERNEL);
284 if (!ses->domainName)
285 return -ENOMEM;
286 }
287
288 dlen = strlen(ses->domainName);
289 wlen = strlen(ses->server->hostname);
290
291 /* The length of this blob is a size which is
292 * six times the size of a structure which holds name/size +
293 * two times the unicode length of a domain name +
294 * two times the unicode length of a server name +
295 * size of a timestamp (which is 8 bytes).
296 */
297 ses->tilen = size + 2 * (2 * dlen) + 2 * (2 * wlen) + 8;
298 ses->tiblob = kzalloc(ses->tilen, GFP_KERNEL);
299 if (!ses->tiblob) {
300 ses->tilen = 0;
301 cERROR(1, "Challenge target info allocation failure");
302 return -ENOMEM;
303 }
304
305 blobptr = ses->tiblob;
306 attrptr = (struct ntlmssp2_name *) blobptr;
307
308 attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME);
309 attrptr->length = cpu_to_le16(2 * dlen);
310 blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
311 cifs_strtoUCS((__le16 *)blobptr, ses->domainName, dlen, nls_cp);
312
313 blobptr += 2 * dlen;
314 attrptr = (struct ntlmssp2_name *) blobptr;
315
316 attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_COMPUTER_NAME);
317 attrptr->length = cpu_to_le16(2 * wlen);
318 blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
319 cifs_strtoUCS((__le16 *)blobptr, ses->server->hostname, wlen, nls_cp);
320
321 blobptr += 2 * wlen;
322 attrptr = (struct ntlmssp2_name *) blobptr;
323
324 attrptr->type = cpu_to_le16(NTLMSSP_AV_DNS_DOMAIN_NAME);
325 attrptr->length = cpu_to_le16(2 * dlen);
326 blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
327 cifs_strtoUCS((__le16 *)blobptr, ses->domainName, dlen, nls_cp);
328
329 blobptr += 2 * dlen;
330 attrptr = (struct ntlmssp2_name *) blobptr;
331
332 attrptr->type = cpu_to_le16(NTLMSSP_AV_DNS_COMPUTER_NAME);
333 attrptr->length = cpu_to_le16(2 * wlen);
334 blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
335 cifs_strtoUCS((__le16 *)blobptr, ses->server->hostname, wlen, nls_cp);
336
337 blobptr += 2 * wlen;
338 attrptr = (struct ntlmssp2_name *) blobptr;
339
340 attrptr->type = cpu_to_le16(NTLMSSP_AV_TIMESTAMP);
341 attrptr->length = cpu_to_le16(sizeof(__le64));
342 blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
343 curtime = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
344 memcpy(blobptr, &curtime, sizeof(__le64));
345
346 return 0;
347}
348
349/* Server has provided av pairs/target info in the type 2 challenge
350 * packet and we have plucked it and stored within smb session.
351 * We parse that blob here to find netbios domain name to be used
352 * as part of ntlmv2 authentication (in Target String), if not already
353 * specified on the command line.
354 * If this function returns without any error but without fetching
355 * domain name, authentication may fail against some server but
356 * may not fail against other (those who are not very particular
357 * about target string i.e. for some, just user name might suffice.
358 */
359static int
360find_domain_name(struct cifsSesInfo *ses)
361{
362 unsigned int attrsize;
363 unsigned int type;
364 unsigned int onesize = sizeof(struct ntlmssp2_name);
365 unsigned char *blobptr;
366 unsigned char *blobend;
367 struct ntlmssp2_name *attrptr;
368
369 if (!ses->tilen || !ses->tiblob)
370 return 0;
371
372 blobptr = ses->tiblob;
373 blobend = ses->tiblob + ses->tilen;
374
375 while (blobptr + onesize < blobend) {
376 attrptr = (struct ntlmssp2_name *) blobptr;
377 type = le16_to_cpu(attrptr->type);
378 if (type == NTLMSSP_AV_EOL)
379 break;
380 blobptr += 2; /* advance attr type */
381 attrsize = le16_to_cpu(attrptr->length);
382 blobptr += 2; /* advance attr size */
383 if (blobptr + attrsize > blobend)
384 break;
385 if (type == NTLMSSP_AV_NB_DOMAIN_NAME) {
386 if (!attrsize)
387 break;
388 if (!ses->domainName) {
389 struct nls_table *default_nls;
390 ses->domainName =
391 kmalloc(attrsize + 1, GFP_KERNEL);
392 if (!ses->domainName)
393 return -ENOMEM;
394 default_nls = load_nls_default();
395 cifs_from_ucs2(ses->domainName,
396 (__le16 *)blobptr, attrsize, attrsize,
397 default_nls, false);
398 unload_nls(default_nls);
399 break;
400 }
401 }
402 blobptr += attrsize; /* advance attr value */
403 }
404
405 return 0;
406}
407
265static int calc_ntlmv2_hash(struct cifsSesInfo *ses, 408static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
266 const struct nls_table *nls_cp) 409 const struct nls_table *nls_cp)
267{ 410{
@@ -315,13 +458,14 @@ calc_exit_1:
315calc_exit_2: 458calc_exit_2:
316 /* BB FIXME what about bytes 24 through 40 of the signing key? 459 /* BB FIXME what about bytes 24 through 40 of the signing key?
317 compare with the NTLM example */ 460 compare with the NTLM example */
318 hmac_md5_final(ses->server->ntlmv2_hash, pctxt); 461 hmac_md5_final(ses->ntlmv2_hash, pctxt);
319 462
320 kfree(pctxt); 463 kfree(pctxt);
321 return rc; 464 return rc;
322} 465}
323 466
324void setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf, 467int
468setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf,
325 const struct nls_table *nls_cp) 469 const struct nls_table *nls_cp)
326{ 470{
327 int rc; 471 int rc;
@@ -333,25 +477,48 @@ void setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf,
333 buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); 477 buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
334 get_random_bytes(&buf->client_chal, sizeof(buf->client_chal)); 478 get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
335 buf->reserved2 = 0; 479 buf->reserved2 = 0;
336 buf->names[0].type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE); 480
337 buf->names[0].length = 0; 481 if (ses->server->secType == RawNTLMSSP) {
338 buf->names[1].type = 0; 482 if (!ses->domainName) {
339 buf->names[1].length = 0; 483 rc = find_domain_name(ses);
484 if (rc) {
485 cERROR(1, "error %d finding domain name", rc);
486 goto setup_ntlmv2_rsp_ret;
487 }
488 }
489 } else {
490 rc = build_avpair_blob(ses, nls_cp);
491 if (rc) {
492 cERROR(1, "error %d building av pair blob", rc);
493 return rc;
494 }
495 }
340 496
341 /* calculate buf->ntlmv2_hash */ 497 /* calculate buf->ntlmv2_hash */
342 rc = calc_ntlmv2_hash(ses, nls_cp); 498 rc = calc_ntlmv2_hash(ses, nls_cp);
343 if (rc) 499 if (rc) {
344 cERROR(1, "could not get v2 hash rc %d", rc); 500 cERROR(1, "could not get v2 hash rc %d", rc);
501 goto setup_ntlmv2_rsp_ret;
502 }
345 CalcNTLMv2_response(ses, resp_buf); 503 CalcNTLMv2_response(ses, resp_buf);
346 504
347 /* now calculate the MAC key for NTLMv2 */ 505 /* now calculate the session key for NTLMv2 */
348 hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context); 506 hmac_md5_init_limK_to_64(ses->ntlmv2_hash, 16, &context);
349 hmac_md5_update(resp_buf, 16, &context); 507 hmac_md5_update(resp_buf, 16, &context);
350 hmac_md5_final(ses->server->mac_signing_key.data.ntlmv2.key, &context); 508 hmac_md5_final(ses->auth_key.data.ntlmv2.key, &context);
351 509
352 memcpy(&ses->server->mac_signing_key.data.ntlmv2.resp, resp_buf, 510 memcpy(&ses->auth_key.data.ntlmv2.resp, resp_buf,
353 sizeof(struct ntlmv2_resp)); 511 sizeof(struct ntlmv2_resp));
354 ses->server->mac_signing_key.len = 16 + sizeof(struct ntlmv2_resp); 512 ses->auth_key.len = 16 + sizeof(struct ntlmv2_resp);
513
514 return 0;
515
516setup_ntlmv2_rsp_ret:
517 kfree(ses->tiblob);
518 ses->tiblob = NULL;
519 ses->tilen = 0;
520
521 return rc;
355} 522}
356 523
357void CalcNTLMv2_response(const struct cifsSesInfo *ses, 524void CalcNTLMv2_response(const struct cifsSesInfo *ses,
@@ -359,12 +526,15 @@ void CalcNTLMv2_response(const struct cifsSesInfo *ses,
359{ 526{
360 struct HMACMD5Context context; 527 struct HMACMD5Context context;
361 /* rest of v2 struct already generated */ 528 /* rest of v2 struct already generated */
362 memcpy(v2_session_response + 8, ses->server->cryptKey, 8); 529 memcpy(v2_session_response + 8, ses->cryptKey, 8);
363 hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context); 530 hmac_md5_init_limK_to_64(ses->ntlmv2_hash, 16, &context);
364 531
365 hmac_md5_update(v2_session_response+8, 532 hmac_md5_update(v2_session_response+8,
366 sizeof(struct ntlmv2_resp) - 8, &context); 533 sizeof(struct ntlmv2_resp) - 8, &context);
367 534
535 if (ses->tilen)
536 hmac_md5_update(ses->tiblob, ses->tilen, &context);
537
368 hmac_md5_final(v2_session_response, &context); 538 hmac_md5_final(v2_session_response, &context);
369/* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */ 539/* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */
370} 540}