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.c122
1 files changed, 64 insertions, 58 deletions
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 860dc49ba79c..be012a17278a 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -39,7 +39,7 @@ extern void mdfour(unsigned char *out, unsigned char *in, int n);
39extern void E_md4hash(const unsigned char *passwd, unsigned char *p16); 39extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
40extern void SMBencrypt(unsigned char *passwd, unsigned char *c8, 40extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
41 unsigned char *p24); 41 unsigned char *p24);
42 42
43static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, 43static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
44 const struct mac_key *key, char *signature) 44 const struct mac_key *key, char *signature)
45{ 45{
@@ -69,10 +69,10 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
69 return rc; 69 return rc;
70 70
71 spin_lock(&GlobalMid_Lock); 71 spin_lock(&GlobalMid_Lock);
72 cifs_pdu->Signature.Sequence.SequenceNumber = 72 cifs_pdu->Signature.Sequence.SequenceNumber =
73 cpu_to_le32(server->sequence_number); 73 cpu_to_le32(server->sequence_number);
74 cifs_pdu->Signature.Sequence.Reserved = 0; 74 cifs_pdu->Signature.Sequence.Reserved = 0;
75 75
76 *pexpected_response_sequence_number = server->sequence_number++; 76 *pexpected_response_sequence_number = server->sequence_number++;
77 server->sequence_number++; 77 server->sequence_number++;
78 spin_unlock(&GlobalMid_Lock); 78 spin_unlock(&GlobalMid_Lock);
@@ -98,9 +98,9 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
98 98
99 MD5Init(&context); 99 MD5Init(&context);
100 MD5Update(&context, (char *)&key->data, key->len); 100 MD5Update(&context, (char *)&key->data, key->len);
101 for (i=0;i<n_vec;i++) { 101 for (i = 0; i < n_vec; i++) {
102 if (iov[i].iov_base == NULL) { 102 if (iov[i].iov_base == NULL) {
103 cERROR(1 ,("null iovec entry")); 103 cERROR(1, ("null iovec entry"));
104 return -EIO; 104 return -EIO;
105 } else if (iov[i].iov_len == 0) 105 } else if (iov[i].iov_len == 0)
106 break; /* bail out if we are sent nothing to sign */ 106 break; /* bail out if we are sent nothing to sign */
@@ -167,36 +167,38 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu,
167 return 0; 167 return 0;
168 168
169 if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) { 169 if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
170 struct smb_com_lock_req * pSMB = 170 struct smb_com_lock_req *pSMB =
171 (struct smb_com_lock_req *)cifs_pdu; 171 (struct smb_com_lock_req *)cifs_pdu;
172 if (pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE) 172 if (pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
173 return 0; 173 return 0;
174 } 174 }
175 175
176 /* BB what if signatures are supposed to be on for session but server does not 176 /* BB what if signatures are supposed to be on for session but
177 send one? BB */ 177 server does not send one? BB */
178 178
179 /* Do not need to verify session setups with signature "BSRSPYL " */ 179 /* Do not need to verify session setups with signature "BSRSPYL " */
180 if(memcmp(cifs_pdu->Signature.SecuritySignature,"BSRSPYL ",8)==0) 180 if (memcmp(cifs_pdu->Signature.SecuritySignature, "BSRSPYL ", 8) == 0)
181 cFYI(1,("dummy signature received for smb command 0x%x",cifs_pdu->Command)); 181 cFYI(1, ("dummy signature received for smb command 0x%x",
182 cifs_pdu->Command));
182 183
183 /* save off the origiginal signature so we can modify the smb and check 184 /* save off the origiginal signature so we can modify the smb and check
184 its signature against what the server sent */ 185 its signature against what the server sent */
185 memcpy(server_response_sig,cifs_pdu->Signature.SecuritySignature,8); 186 memcpy(server_response_sig, cifs_pdu->Signature.SecuritySignature, 8);
186 187
187 cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(expected_sequence_number); 188 cifs_pdu->Signature.Sequence.SequenceNumber =
189 cpu_to_le32(expected_sequence_number);
188 cifs_pdu->Signature.Sequence.Reserved = 0; 190 cifs_pdu->Signature.Sequence.Reserved = 0;
189 191
190 rc = cifs_calculate_signature(cifs_pdu, mac_key, 192 rc = cifs_calculate_signature(cifs_pdu, mac_key,
191 what_we_think_sig_should_be); 193 what_we_think_sig_should_be);
192 194
193 if(rc) 195 if (rc)
194 return rc; 196 return rc;
195 197
196 198/* cifs_dump_mem("what we think it should be: ",
197/* cifs_dump_mem("what we think it should be: ",what_we_think_sig_should_be,16); */ 199 what_we_think_sig_should_be, 16); */
198 200
199 if(memcmp(server_response_sig, what_we_think_sig_should_be, 8)) 201 if (memcmp(server_response_sig, what_we_think_sig_should_be, 8))
200 return -EACCES; 202 return -EACCES;
201 else 203 else
202 return 0; 204 return 0;
@@ -218,30 +220,30 @@ int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
218 return 0; 220 return 0;
219} 221}
220 222
221int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, 223int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *ses,
222 const struct nls_table * nls_info) 224 const struct nls_table *nls_info)
223{ 225{
224 char temp_hash[16]; 226 char temp_hash[16];
225 struct HMACMD5Context ctx; 227 struct HMACMD5Context ctx;
226 char * ucase_buf; 228 char *ucase_buf;
227 __le16 * unicode_buf; 229 __le16 *unicode_buf;
228 unsigned int i,user_name_len,dom_name_len; 230 unsigned int i, user_name_len, dom_name_len;
229 231
230 if(ses == NULL) 232 if (ses == NULL)
231 return -EINVAL; 233 return -EINVAL;
232 234
233 E_md4hash(ses->password, temp_hash); 235 E_md4hash(ses->password, temp_hash);
234 236
235 hmac_md5_init_limK_to_64(temp_hash, 16, &ctx); 237 hmac_md5_init_limK_to_64(temp_hash, 16, &ctx);
236 user_name_len = strlen(ses->userName); 238 user_name_len = strlen(ses->userName);
237 if(user_name_len > MAX_USERNAME_SIZE) 239 if (user_name_len > MAX_USERNAME_SIZE)
238 return -EINVAL; 240 return -EINVAL;
239 if(ses->domainName == NULL) 241 if (ses->domainName == NULL)
240 return -EINVAL; /* BB should we use CIFS_LINUX_DOM */ 242 return -EINVAL; /* BB should we use CIFS_LINUX_DOM */
241 dom_name_len = strlen(ses->domainName); 243 dom_name_len = strlen(ses->domainName);
242 if (dom_name_len > MAX_USERNAME_SIZE) 244 if (dom_name_len > MAX_USERNAME_SIZE)
243 return -EINVAL; 245 return -EINVAL;
244 246
245 ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL); 247 ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL);
246 if (ucase_buf == NULL) 248 if (ucase_buf == NULL)
247 return -ENOMEM; 249 return -ENOMEM;
@@ -250,18 +252,20 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses,
250 kfree(ucase_buf); 252 kfree(ucase_buf);
251 return -ENOMEM; 253 return -ENOMEM;
252 } 254 }
253 255
254 for (i = 0;i < user_name_len; i++) 256 for (i = 0; i < user_name_len; i++)
255 ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]]; 257 ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]];
256 ucase_buf[i] = 0; 258 ucase_buf[i] = 0;
257 user_name_len = cifs_strtoUCS(unicode_buf, ucase_buf, MAX_USERNAME_SIZE*2, nls_info); 259 user_name_len = cifs_strtoUCS(unicode_buf, ucase_buf,
260 MAX_USERNAME_SIZE*2, nls_info);
258 unicode_buf[user_name_len] = 0; 261 unicode_buf[user_name_len] = 0;
259 user_name_len++; 262 user_name_len++;
260 263
261 for (i = 0; i < dom_name_len; i++) 264 for (i = 0; i < dom_name_len; i++)
262 ucase_buf[i] = nls_info->charset2upper[(int)ses->domainName[i]]; 265 ucase_buf[i] = nls_info->charset2upper[(int)ses->domainName[i]];
263 ucase_buf[i] = 0; 266 ucase_buf[i] = 0;
264 dom_name_len = cifs_strtoUCS(unicode_buf+user_name_len, ucase_buf, MAX_USERNAME_SIZE*2, nls_info); 267 dom_name_len = cifs_strtoUCS(unicode_buf+user_name_len, ucase_buf,
268 MAX_USERNAME_SIZE*2, nls_info);
265 269
266 unicode_buf[user_name_len + dom_name_len] = 0; 270 unicode_buf[user_name_len + dom_name_len] = 0;
267 hmac_md5_update((const unsigned char *) unicode_buf, 271 hmac_md5_update((const unsigned char *) unicode_buf,
@@ -274,21 +278,22 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses,
274} 278}
275 279
276#ifdef CONFIG_CIFS_WEAK_PW_HASH 280#ifdef CONFIG_CIFS_WEAK_PW_HASH
277void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key) 281void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key)
278{ 282{
279 int i; 283 int i;
280 char password_with_pad[CIFS_ENCPWD_SIZE]; 284 char password_with_pad[CIFS_ENCPWD_SIZE];
281 285
282 if(ses->server == NULL) 286 if (ses->server == NULL)
283 return; 287 return;
284 288
285 memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); 289 memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
286 if(ses->password) 290 if (ses->password)
287 strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE); 291 strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
288 292
289 if((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0) 293 if ((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0)
290 if(extended_security & CIFSSEC_MAY_PLNTXT) { 294 if (extended_security & CIFSSEC_MAY_PLNTXT) {
291 memcpy(lnm_session_key, password_with_pad, CIFS_ENCPWD_SIZE); 295 memcpy(lnm_session_key, password_with_pad,
296 CIFS_ENCPWD_SIZE);
292 return; 297 return;
293 } 298 }
294 299
@@ -303,7 +308,7 @@ void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key)
303 utf8 and other multibyte codepages each need their own strupper 308 utf8 and other multibyte codepages each need their own strupper
304 function since a byte at a time will ont work. */ 309 function since a byte at a time will ont work. */
305 310
306 for(i = 0; i < CIFS_ENCPWD_SIZE; i++) { 311 for (i = 0; i < CIFS_ENCPWD_SIZE; i++) {
307 password_with_pad[i] = toupper(password_with_pad[i]); 312 password_with_pad[i] = toupper(password_with_pad[i]);
308 } 313 }
309 314
@@ -313,19 +318,19 @@ void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key)
313} 318}
314#endif /* CIFS_WEAK_PW_HASH */ 319#endif /* CIFS_WEAK_PW_HASH */
315 320
316static int calc_ntlmv2_hash(struct cifsSesInfo *ses, 321static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
317 const struct nls_table * nls_cp) 322 const struct nls_table *nls_cp)
318{ 323{
319 int rc = 0; 324 int rc = 0;
320 int len; 325 int len;
321 char nt_hash[16]; 326 char nt_hash[16];
322 struct HMACMD5Context * pctxt; 327 struct HMACMD5Context *pctxt;
323 wchar_t * user; 328 wchar_t *user;
324 wchar_t * domain; 329 wchar_t *domain;
325 330
326 pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL); 331 pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL);
327 332
328 if(pctxt == NULL) 333 if (pctxt == NULL)
329 return -ENOMEM; 334 return -ENOMEM;
330 335
331 /* calculate md4 hash of password */ 336 /* calculate md4 hash of password */
@@ -337,18 +342,18 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
337 /* convert ses->userName to unicode and uppercase */ 342 /* convert ses->userName to unicode and uppercase */
338 len = strlen(ses->userName); 343 len = strlen(ses->userName);
339 user = kmalloc(2 + (len * 2), GFP_KERNEL); 344 user = kmalloc(2 + (len * 2), GFP_KERNEL);
340 if(user == NULL) 345 if (user == NULL)
341 goto calc_exit_2; 346 goto calc_exit_2;
342 len = cifs_strtoUCS(user, ses->userName, len, nls_cp); 347 len = cifs_strtoUCS(user, ses->userName, len, nls_cp);
343 UniStrupr(user); 348 UniStrupr(user);
344 hmac_md5_update((char *)user, 2*len, pctxt); 349 hmac_md5_update((char *)user, 2*len, pctxt);
345 350
346 /* convert ses->domainName to unicode and uppercase */ 351 /* convert ses->domainName to unicode and uppercase */
347 if(ses->domainName) { 352 if (ses->domainName) {
348 len = strlen(ses->domainName); 353 len = strlen(ses->domainName);
349 354
350 domain = kmalloc(2 + (len * 2), GFP_KERNEL); 355 domain = kmalloc(2 + (len * 2), GFP_KERNEL);
351 if(domain == NULL) 356 if (domain == NULL)
352 goto calc_exit_1; 357 goto calc_exit_1;
353 len = cifs_strtoUCS(domain, ses->domainName, len, nls_cp); 358 len = cifs_strtoUCS(domain, ses->domainName, len, nls_cp);
354 /* the following line was removed since it didn't work well 359 /* the following line was removed since it didn't work well
@@ -357,24 +362,24 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
357 /* UniStrupr(domain); */ 362 /* UniStrupr(domain); */
358 363
359 hmac_md5_update((char *)domain, 2*len, pctxt); 364 hmac_md5_update((char *)domain, 2*len, pctxt);
360 365
361 kfree(domain); 366 kfree(domain);
362 } 367 }
363calc_exit_1: 368calc_exit_1:
364 kfree(user); 369 kfree(user);
365calc_exit_2: 370calc_exit_2:
366 /* BB FIXME what about bytes 24 through 40 of the signing key? 371 /* BB FIXME what about bytes 24 through 40 of the signing key?
367 compare with the NTLM example */ 372 compare with the NTLM example */
368 hmac_md5_final(ses->server->ntlmv2_hash, pctxt); 373 hmac_md5_final(ses->server->ntlmv2_hash, pctxt);
369 374
370 return rc; 375 return rc;
371} 376}
372 377
373void setup_ntlmv2_rsp(struct cifsSesInfo * ses, char * resp_buf, 378void setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf,
374 const struct nls_table * nls_cp) 379 const struct nls_table *nls_cp)
375{ 380{
376 int rc; 381 int rc;
377 struct ntlmv2_resp * buf = (struct ntlmv2_resp *)resp_buf; 382 struct ntlmv2_resp *buf = (struct ntlmv2_resp *)resp_buf;
378 struct HMACMD5Context context; 383 struct HMACMD5Context context;
379 384
380 buf->blob_signature = cpu_to_le32(0x00000101); 385 buf->blob_signature = cpu_to_le32(0x00000101);
@@ -389,8 +394,8 @@ void setup_ntlmv2_rsp(struct cifsSesInfo * ses, char * resp_buf,
389 394
390 /* calculate buf->ntlmv2_hash */ 395 /* calculate buf->ntlmv2_hash */
391 rc = calc_ntlmv2_hash(ses, nls_cp); 396 rc = calc_ntlmv2_hash(ses, nls_cp);
392 if(rc) 397 if (rc)
393 cERROR(1,("could not get v2 hash rc %d",rc)); 398 cERROR(1, ("could not get v2 hash rc %d", rc));
394 CalcNTLMv2_response(ses, resp_buf); 399 CalcNTLMv2_response(ses, resp_buf);
395 400
396 /* now calculate the MAC key for NTLMv2 */ 401 /* now calculate the MAC key for NTLMv2 */
@@ -403,16 +408,17 @@ void setup_ntlmv2_rsp(struct cifsSesInfo * ses, char * resp_buf,
403 ses->server->mac_signing_key.len = 16 + sizeof(struct ntlmv2_resp); 408 ses->server->mac_signing_key.len = 16 + sizeof(struct ntlmv2_resp);
404} 409}
405 410
406void CalcNTLMv2_response(const struct cifsSesInfo * ses, char * v2_session_response) 411void CalcNTLMv2_response(const struct cifsSesInfo *ses,
412 char *v2_session_response)
407{ 413{
408 struct HMACMD5Context context; 414 struct HMACMD5Context context;
409 /* rest of v2 struct already generated */ 415 /* rest of v2 struct already generated */
410 memcpy(v2_session_response + 8, ses->server->cryptKey,8); 416 memcpy(v2_session_response + 8, ses->server->cryptKey, 8);
411 hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context); 417 hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context);
412 418
413 hmac_md5_update(v2_session_response+8, 419 hmac_md5_update(v2_session_response+8,
414 sizeof(struct ntlmv2_resp) - 8, &context); 420 sizeof(struct ntlmv2_resp) - 8, &context);
415 421
416 hmac_md5_final(v2_session_response,&context); 422 hmac_md5_final(v2_session_response, &context);
417/* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */ 423/* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */
418} 424}