aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/connect.c
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2006-06-22 22:33:48 -0400
committerSteve French <sfrench@us.ibm.com>2006-06-22 22:33:48 -0400
commit189acaaef81b1d71aedd0d28810de24160c2e781 (patch)
tree7360484f3e255557641053f170ab324572d4b855 /fs/cifs/connect.c
parent75ba632a01d4dc70d0a0f3a92b5ec9b4a3644b2d (diff)
[CIFS] Enable sec flags on mount for cifs (part one)
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r--fs/cifs/connect.c338
1 files changed, 23 insertions, 315 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index faaf9eb15b9f..01608bb4d673 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -68,6 +68,7 @@ struct smb_vol {
68 gid_t linux_gid; 68 gid_t linux_gid;
69 mode_t file_mode; 69 mode_t file_mode;
70 mode_t dir_mode; 70 mode_t dir_mode;
71 unsigned secFlg;
71 unsigned rw:1; 72 unsigned rw:1;
72 unsigned retry:1; 73 unsigned retry:1;
73 unsigned intr:1; 74 unsigned intr:1;
@@ -81,12 +82,7 @@ struct smb_vol {
81 unsigned remap:1; /* set to remap seven reserved chars in filenames */ 82 unsigned remap:1; /* set to remap seven reserved chars in filenames */
82 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */ 83 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
83 unsigned sfu_emul:1; 84 unsigned sfu_emul:1;
84 unsigned krb5:1;
85 unsigned ntlm:1;
86 unsigned ntlmv2:1;
87 unsigned nullauth:1; /* attempt to authenticate with null user */ 85 unsigned nullauth:1; /* attempt to authenticate with null user */
88 unsigned sign:1;
89 unsigned seal:1; /* encrypt */
90 unsigned nocase; /* request case insensitive filenames */ 86 unsigned nocase; /* request case insensitive filenames */
91 unsigned nobrl; /* disable sending byte range locks to srv */ 87 unsigned nobrl; /* disable sending byte range locks to srv */
92 unsigned int rsize; 88 unsigned int rsize;
@@ -789,7 +785,6 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
789 785
790 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ 786 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
791 vol->rw = TRUE; 787 vol->rw = TRUE;
792 vol->ntlm = TRUE;
793 /* default is always to request posix paths. */ 788 /* default is always to request posix paths. */
794 vol->posix_paths = 1; 789 vol->posix_paths = 1;
795 790
@@ -920,30 +915,35 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
920 cERROR(1,("no security value specified")); 915 cERROR(1,("no security value specified"));
921 continue; 916 continue;
922 } else if (strnicmp(value, "krb5i", 5) == 0) { 917 } else if (strnicmp(value, "krb5i", 5) == 0) {
923 vol->sign = 1; 918 vol->secFlg = CIFSSEC_MAY_KRB5 |
924 vol->krb5 = 1; 919 CIFSSEC_MUST_SIGN;
925 } else if (strnicmp(value, "krb5p", 5) == 0) { 920 } else if (strnicmp(value, "krb5p", 5) == 0) {
926 /* vol->seal = 1; 921 /* vol->secFlg = CIFSSEC_MUST_SEAL |
927 vol->krb5 = 1; */ 922 CIFSSEC_MAY_KRB5; */
928 cERROR(1,("Krb5 cifs privacy not supported")); 923 cERROR(1,("Krb5 cifs privacy not supported"));
929 return 1; 924 return 1;
930 } else if (strnicmp(value, "krb5", 4) == 0) { 925 } else if (strnicmp(value, "krb5", 4) == 0) {
931 vol->krb5 = 1; 926 vol->secFlg = CIFSSEC_MAY_KRB5;
932 } else if (strnicmp(value, "ntlmv2i", 7) == 0) { 927 } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
933 vol->ntlmv2 = 1; 928 vol->secFlg = CIFSSEC_MAY_NTLMV2 |
934 vol->sign = 1; 929 CIFSSEC_MUST_SIGN;
935 } else if (strnicmp(value, "ntlmv2", 6) == 0) { 930 } else if (strnicmp(value, "ntlmv2", 6) == 0) {
936 vol->ntlmv2 = 1; 931 vol->secFlg = CIFSSEC_MAY_NTLMV2;
937 } else if (strnicmp(value, "ntlmi", 5) == 0) { 932 } else if (strnicmp(value, "ntlmi", 5) == 0) {
938 vol->ntlm = 1; 933 vol->secFlg = CIFSSEC_MAY_NTLM |
939 vol->sign = 1; 934 CIFSSEC_MUST_SIGN;
940 } else if (strnicmp(value, "ntlm", 4) == 0) { 935 } else if (strnicmp(value, "ntlm", 4) == 0) {
941 /* ntlm is default so can be turned off too */ 936 /* ntlm is default so can be turned off too */
942 vol->ntlm = 1; 937 vol->secFlg = CIFSSEC_MAY_NTLM;
943 } else if (strnicmp(value, "nontlm", 6) == 0) { 938 } else if (strnicmp(value, "nontlm", 6) == 0) {
944 vol->ntlm = 0; 939 /* BB is there a better way to do this? */
940 vol->secFlg = CIFSSEC_MAY_NTLMV2;
941#ifdef CONFIG_CIFS_WEAK_PW_HASH
942 } else if (strnicmp(value, "lanman", 6) == 0) {
943 vol->secFlg = CIFSSEC_MAY_LANMAN;
944#endif
945 } else if (strnicmp(value, "none", 4) == 0) { 945 } else if (strnicmp(value, "none", 4) == 0) {
946 vol->nullauth = 1; 946 vol->nullauth = 1;
947 } else { 947 } else {
948 cERROR(1,("bad security option: %s", value)); 948 cERROR(1,("bad security option: %s", value));
949 return 1; 949 return 1;
@@ -1777,6 +1777,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1777 } 1777 }
1778 pSesInfo->linux_uid = volume_info.linux_uid; 1778 pSesInfo->linux_uid = volume_info.linux_uid;
1779 down(&pSesInfo->sesSem); 1779 down(&pSesInfo->sesSem);
1780 /* BB FIXME need to pass vol->secFlgs BB */
1780 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls); 1781 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1781 up(&pSesInfo->sesSem); 1782 up(&pSesInfo->sesSem);
1782 if(!rc) 1783 if(!rc)
@@ -2284,292 +2285,6 @@ sesssetup_nomem: /* do not return an error on nomem for the info strings,
2284} 2285}
2285 2286
2286static int 2287static int
2287CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2288 char *SecurityBlob,int SecurityBlobLength,
2289 const struct nls_table *nls_codepage)
2290{
2291 struct smb_hdr *smb_buffer;
2292 struct smb_hdr *smb_buffer_response;
2293 SESSION_SETUP_ANDX *pSMB;
2294 SESSION_SETUP_ANDX *pSMBr;
2295 char *bcc_ptr;
2296 char *user;
2297 char *domain;
2298 int rc = 0;
2299 int remaining_words = 0;
2300 int bytes_returned = 0;
2301 int len;
2302 __u32 capabilities;
2303 __u16 count;
2304
2305 cFYI(1, ("In spnego sesssetup "));
2306 if(ses == NULL)
2307 return -EINVAL;
2308 user = ses->userName;
2309 domain = ses->domainName;
2310
2311 smb_buffer = cifs_buf_get();
2312 if (smb_buffer == NULL) {
2313 return -ENOMEM;
2314 }
2315 smb_buffer_response = smb_buffer;
2316 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2317
2318 /* send SMBsessionSetup here */
2319 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2320 NULL /* no tCon exists yet */ , 12 /* wct */ );
2321
2322 smb_buffer->Mid = GetNextMid(ses->server);
2323 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2324 pSMB->req.AndXCommand = 0xFF;
2325 if(ses->server->maxBuf > 64*1024)
2326 ses->server->maxBuf = (64*1023);
2327 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2328 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2329
2330 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2331 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2332
2333 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2334 CAP_EXTENDED_SECURITY;
2335 if (ses->capabilities & CAP_UNICODE) {
2336 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2337 capabilities |= CAP_UNICODE;
2338 }
2339 if (ses->capabilities & CAP_STATUS32) {
2340 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2341 capabilities |= CAP_STATUS32;
2342 }
2343 if (ses->capabilities & CAP_DFS) {
2344 smb_buffer->Flags2 |= SMBFLG2_DFS;
2345 capabilities |= CAP_DFS;
2346 }
2347 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2348
2349 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2350 bcc_ptr = pByteArea(smb_buffer);
2351 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
2352 bcc_ptr += SecurityBlobLength;
2353
2354 if (ses->capabilities & CAP_UNICODE) {
2355 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
2356 *bcc_ptr = 0;
2357 bcc_ptr++;
2358 }
2359 bytes_returned =
2360 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, nls_codepage);
2361 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
2362 bcc_ptr += 2; /* trailing null */
2363 if (domain == NULL)
2364 bytes_returned =
2365 cifs_strtoUCS((__le16 *) bcc_ptr,
2366 "CIFS_LINUX_DOM", 32, nls_codepage);
2367 else
2368 bytes_returned =
2369 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2370 nls_codepage);
2371 bcc_ptr += 2 * bytes_returned;
2372 bcc_ptr += 2;
2373 bytes_returned =
2374 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2375 32, nls_codepage);
2376 bcc_ptr += 2 * bytes_returned;
2377 bytes_returned =
2378 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
2379 nls_codepage);
2380 bcc_ptr += 2 * bytes_returned;
2381 bcc_ptr += 2;
2382 bytes_returned =
2383 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2384 64, nls_codepage);
2385 bcc_ptr += 2 * bytes_returned;
2386 bcc_ptr += 2;
2387 } else {
2388 strncpy(bcc_ptr, user, 200);
2389 bcc_ptr += strnlen(user, 200);
2390 *bcc_ptr = 0;
2391 bcc_ptr++;
2392 if (domain == NULL) {
2393 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2394 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2395 } else {
2396 strncpy(bcc_ptr, domain, 64);
2397 bcc_ptr += strnlen(domain, 64);
2398 *bcc_ptr = 0;
2399 bcc_ptr++;
2400 }
2401 strcpy(bcc_ptr, "Linux version ");
2402 bcc_ptr += strlen("Linux version ");
2403 strcpy(bcc_ptr, system_utsname.release);
2404 bcc_ptr += strlen(system_utsname.release) + 1;
2405 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2406 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2407 }
2408 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2409 smb_buffer->smb_buf_length += count;
2410 pSMB->req.ByteCount = cpu_to_le16(count);
2411
2412 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2413 &bytes_returned, 1);
2414 if (rc) {
2415/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2416 } else if ((smb_buffer_response->WordCount == 3)
2417 || (smb_buffer_response->WordCount == 4)) {
2418 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2419 __u16 blob_len =
2420 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2421 if (action & GUEST_LOGIN)
2422 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2423 if (ses) {
2424 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2425 cFYI(1, ("UID = %d ", ses->Suid));
2426 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
2427
2428 /* BB Fix below to make endian neutral !! */
2429
2430 if ((pSMBr->resp.hdr.WordCount == 3)
2431 || ((pSMBr->resp.hdr.WordCount == 4)
2432 && (blob_len <
2433 pSMBr->resp.ByteCount))) {
2434 if (pSMBr->resp.hdr.WordCount == 4) {
2435 bcc_ptr +=
2436 blob_len;
2437 cFYI(1,
2438 ("Security Blob Length %d ",
2439 blob_len));
2440 }
2441
2442 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2443 if ((long) (bcc_ptr) % 2) {
2444 remaining_words =
2445 (BCC(smb_buffer_response)
2446 - 1) / 2;
2447 bcc_ptr++; /* Unicode strings must be word aligned */
2448 } else {
2449 remaining_words =
2450 BCC
2451 (smb_buffer_response) / 2;
2452 }
2453 len =
2454 UniStrnlen((wchar_t *) bcc_ptr,
2455 remaining_words - 1);
2456/* We look for obvious messed up bcc or strings in response so we do not go off
2457 the end since (at least) WIN2K and Windows XP have a major bug in not null
2458 terminating last Unicode string in response */
2459 if(ses->serverOS)
2460 kfree(ses->serverOS);
2461 ses->serverOS =
2462 kzalloc(2 * (len + 1), GFP_KERNEL);
2463 cifs_strfromUCS_le(ses->serverOS,
2464 (__le16 *)
2465 bcc_ptr, len,
2466 nls_codepage);
2467 bcc_ptr += 2 * (len + 1);
2468 remaining_words -= len + 1;
2469 ses->serverOS[2 * len] = 0;
2470 ses->serverOS[1 + (2 * len)] = 0;
2471 if (remaining_words > 0) {
2472 len = UniStrnlen((wchar_t *)bcc_ptr,
2473 remaining_words
2474 - 1);
2475 if(ses->serverNOS)
2476 kfree(ses->serverNOS);
2477 ses->serverNOS =
2478 kzalloc(2 * (len + 1),
2479 GFP_KERNEL);
2480 cifs_strfromUCS_le(ses->serverNOS,
2481 (__le16 *)bcc_ptr,
2482 len,
2483 nls_codepage);
2484 bcc_ptr += 2 * (len + 1);
2485 ses->serverNOS[2 * len] = 0;
2486 ses->serverNOS[1 + (2 * len)] = 0;
2487 remaining_words -= len + 1;
2488 if (remaining_words > 0) {
2489 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2490 /* last string not null terminated (e.g.Windows XP/2000) */
2491 if(ses->serverDomain)
2492 kfree(ses->serverDomain);
2493 ses->serverDomain = kzalloc(2*(len+1),GFP_KERNEL);
2494 cifs_strfromUCS_le(ses->serverDomain,
2495 (__le16 *)bcc_ptr,
2496 len, nls_codepage);
2497 bcc_ptr += 2*(len+1);
2498 ses->serverDomain[2*len] = 0;
2499 ses->serverDomain[1+(2*len)] = 0;
2500 } /* else no more room so create dummy domain string */
2501 else {
2502 if(ses->serverDomain)
2503 kfree(ses->serverDomain);
2504 ses->serverDomain =
2505 kzalloc(2,GFP_KERNEL);
2506 }
2507 } else {/* no room use dummy domain&NOS */
2508 if(ses->serverDomain)
2509 kfree(ses->serverDomain);
2510 ses->serverDomain = kzalloc(2, GFP_KERNEL);
2511 if(ses->serverNOS)
2512 kfree(ses->serverNOS);
2513 ses->serverNOS = kzalloc(2, GFP_KERNEL);
2514 }
2515 } else { /* ASCII */
2516
2517 len = strnlen(bcc_ptr, 1024);
2518 if (((long) bcc_ptr + len) - (long)
2519 pByteArea(smb_buffer_response)
2520 <= BCC(smb_buffer_response)) {
2521 if(ses->serverOS)
2522 kfree(ses->serverOS);
2523 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
2524 strncpy(ses->serverOS, bcc_ptr, len);
2525
2526 bcc_ptr += len;
2527 bcc_ptr[0] = 0; /* null terminate the string */
2528 bcc_ptr++;
2529
2530 len = strnlen(bcc_ptr, 1024);
2531 if(ses->serverNOS)
2532 kfree(ses->serverNOS);
2533 ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
2534 strncpy(ses->serverNOS, bcc_ptr, len);
2535 bcc_ptr += len;
2536 bcc_ptr[0] = 0;
2537 bcc_ptr++;
2538
2539 len = strnlen(bcc_ptr, 1024);
2540 if(ses->serverDomain)
2541 kfree(ses->serverDomain);
2542 ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
2543 strncpy(ses->serverDomain, bcc_ptr, len);
2544 bcc_ptr += len;
2545 bcc_ptr[0] = 0;
2546 bcc_ptr++;
2547 } else
2548 cFYI(1,
2549 ("Variable field of length %d extends beyond end of smb ",
2550 len));
2551 }
2552 } else {
2553 cERROR(1,
2554 (" Security Blob Length extends beyond end of SMB"));
2555 }
2556 } else {
2557 cERROR(1, ("No session structure passed in."));
2558 }
2559 } else {
2560 cERROR(1,
2561 (" Invalid Word count %d: ",
2562 smb_buffer_response->WordCount));
2563 rc = -EIO;
2564 }
2565
2566 if (smb_buffer)
2567 cifs_buf_release(smb_buffer);
2568
2569 return rc;
2570}
2571
2572static int
2573CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, 2288CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2574 struct cifsSesInfo *ses, int * pNTLMv2_flag, 2289 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2575 const struct nls_table *nls_codepage) 2290 const struct nls_table *nls_codepage)
@@ -3550,20 +3265,13 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3550 pSesInfo->server->secMode, 3265 pSesInfo->server->secMode,
3551 pSesInfo->server->capabilities, 3266 pSesInfo->server->capabilities,
3552 pSesInfo->server->timeZone)); 3267 pSesInfo->server->timeZone));
3553#ifdef CONFIG_CIFS_EXPERIMENTAL 3268 if(experimEnabled < 2)
3554 if(experimEnabled > 1)
3555 rc = CIFS_SessSetup(xid, pSesInfo, 3269 rc = CIFS_SessSetup(xid, pSesInfo,
3556 first_time, nls_info); 3270 first_time, nls_info);
3557 else 3271 else if (extended_security
3558#endif
3559 if (extended_security
3560 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) 3272 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3561 && (pSesInfo->server->secType == NTLMSSP)) { 3273 && (pSesInfo->server->secType == NTLMSSP)) {
3562 cFYI(1, ("New style sesssetup")); 3274 rc = -EOPNOTSUPP;
3563 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3564 NULL /* security blob */,
3565 0 /* blob length */,
3566 nls_info);
3567 } else if (extended_security 3275 } else if (extended_security
3568 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) 3276 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3569 && (pSesInfo->server->secType == RawNTLMSSP)) { 3277 && (pSesInfo->server->secType == RawNTLMSSP)) {