aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/connect.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-19 15:00:58 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-19 15:00:58 -0400
commit2843483d2eb02ad104edbe8b2429fb6a39d25063 (patch)
tree7a63d1fa408ab50277666b2d73d2553ea4cfc7a7 /fs/cifs/connect.c
parent26790656d7dc34206f78eeca0f4be5caede788ce (diff)
parenta761ac579b89bc1f00212a42401398108deba65c (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: (51 commits) [CIFS] log better errors on failed mounts [CIFS] Return better error when server requires signing but client forbids [CIFS] fix typo [CIFS] acl support part 4 [CIFS] Fix minor problems noticed by scan [CIFS] fix bad handling of EAGAIN error on kernel_recvmsg in cifs_demultiplex_thread [CIFS] build break [CIFS] endian fixes [CIFS] endian fixes in new acl code [CIFS] Fix some endianness problems in new acl code [CIFS] missing #endif from a previous patch [CIFS] formatting fixes [CIFS] Break up unicode_sessetup string functions [CIFS] parse server_GUID in SPNEGO negProt response [CIFS] [CIFS] Fix endian conversion problem in posix mkdir [CIFS] fix build break when lanman not enabled [CIFS] remove two sparse warnings [CIFS] remove compile warnings when debug disabled [CIFS] CIFS ACL support part 3 ...
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r--fs/cifs/connect.c262
1 files changed, 139 insertions, 123 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 370866cb3d48..19ee11f7f35a 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -124,7 +124,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
124 struct mid_q_entry *mid_entry; 124 struct mid_q_entry *mid_entry;
125 125
126 spin_lock(&GlobalMid_Lock); 126 spin_lock(&GlobalMid_Lock);
127 if ( kthread_should_stop() ) { 127 if (kthread_should_stop()) {
128 /* the demux thread will exit normally 128 /* the demux thread will exit normally
129 next time through the loop */ 129 next time through the loop */
130 spin_unlock(&GlobalMid_Lock); 130 spin_unlock(&GlobalMid_Lock);
@@ -151,9 +151,8 @@ cifs_reconnect(struct TCP_Server_Info *server)
151 } 151 }
152 list_for_each(tmp, &GlobalTreeConnectionList) { 152 list_for_each(tmp, &GlobalTreeConnectionList) {
153 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); 153 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
154 if ((tcon) && (tcon->ses) && (tcon->ses->server == server)) { 154 if ((tcon) && (tcon->ses) && (tcon->ses->server == server))
155 tcon->tidStatus = CifsNeedReconnect; 155 tcon->tidStatus = CifsNeedReconnect;
156 }
157 } 156 }
158 read_unlock(&GlobalSMBSeslock); 157 read_unlock(&GlobalSMBSeslock);
159 /* do not want to be sending data on a socket we are freeing */ 158 /* do not want to be sending data on a socket we are freeing */
@@ -187,7 +186,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
187 spin_unlock(&GlobalMid_Lock); 186 spin_unlock(&GlobalMid_Lock);
188 up(&server->tcpSem); 187 up(&server->tcpSem);
189 188
190 while ( (!kthread_should_stop()) && (server->tcpStatus != CifsGood)) { 189 while ((!kthread_should_stop()) && (server->tcpStatus != CifsGood)) {
191 try_to_freeze(); 190 try_to_freeze();
192 if (server->protocolType == IPV6) { 191 if (server->protocolType == IPV6) {
193 rc = ipv6_connect(&server->addr.sockAddr6, 192 rc = ipv6_connect(&server->addr.sockAddr6,
@@ -204,7 +203,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
204 } else { 203 } else {
205 atomic_inc(&tcpSesReconnectCount); 204 atomic_inc(&tcpSesReconnectCount);
206 spin_lock(&GlobalMid_Lock); 205 spin_lock(&GlobalMid_Lock);
207 if ( !kthread_should_stop() ) 206 if (!kthread_should_stop())
208 server->tcpStatus = CifsGood; 207 server->tcpStatus = CifsGood;
209 server->sequence_number = 0; 208 server->sequence_number = 0;
210 spin_unlock(&GlobalMid_Lock); 209 spin_unlock(&GlobalMid_Lock);
@@ -358,11 +357,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
358 length = tcpSesAllocCount.counter; 357 length = tcpSesAllocCount.counter;
359 write_unlock(&GlobalSMBSeslock); 358 write_unlock(&GlobalSMBSeslock);
360 complete(&cifsd_complete); 359 complete(&cifsd_complete);
361 if (length > 1) { 360 if (length > 1)
362 mempool_resize(cifs_req_poolp, 361 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
363 length + cifs_min_rcv, 362 GFP_KERNEL);
364 GFP_KERNEL);
365 }
366 363
367 set_freezable(); 364 set_freezable();
368 while (!kthread_should_stop()) { 365 while (!kthread_should_stop()) {
@@ -378,7 +375,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
378 } 375 }
379 } else if (isLargeBuf) { 376 } else if (isLargeBuf) {
380 /* we are reusing a dirty large buf, clear its start */ 377 /* we are reusing a dirty large buf, clear its start */
381 memset(bigbuf, 0, sizeof (struct smb_hdr)); 378 memset(bigbuf, 0, sizeof(struct smb_hdr));
382 } 379 }
383 380
384 if (smallbuf == NULL) { 381 if (smallbuf == NULL) {
@@ -391,7 +388,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
391 } 388 }
392 /* beginning of smb buffer is cleared in our buf_get */ 389 /* beginning of smb buffer is cleared in our buf_get */
393 } else /* if existing small buf clear beginning */ 390 } else /* if existing small buf clear beginning */
394 memset(smallbuf, 0, sizeof (struct smb_hdr)); 391 memset(smallbuf, 0, sizeof(struct smb_hdr));
395 392
396 isLargeBuf = FALSE; 393 isLargeBuf = FALSE;
397 isMultiRsp = FALSE; 394 isMultiRsp = FALSE;
@@ -400,11 +397,13 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
400 iov.iov_len = 4; 397 iov.iov_len = 4;
401 smb_msg.msg_control = NULL; 398 smb_msg.msg_control = NULL;
402 smb_msg.msg_controllen = 0; 399 smb_msg.msg_controllen = 0;
400 pdu_length = 4; /* enough to get RFC1001 header */
401incomplete_rcv:
403 length = 402 length =
404 kernel_recvmsg(csocket, &smb_msg, 403 kernel_recvmsg(csocket, &smb_msg,
405 &iov, 1, 4, 0 /* BB see socket.h flags */); 404 &iov, 1, pdu_length, 0 /* BB other flags? */);
406 405
407 if ( kthread_should_stop() ) { 406 if (kthread_should_stop()) {
408 break; 407 break;
409 } else if (server->tcpStatus == CifsNeedReconnect) { 408 } else if (server->tcpStatus == CifsNeedReconnect) {
410 cFYI(1, ("Reconnect after server stopped responding")); 409 cFYI(1, ("Reconnect after server stopped responding"));
@@ -416,7 +415,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
416 msleep(1); /* minimum sleep to prevent looping 415 msleep(1); /* minimum sleep to prevent looping
417 allowing socket to clear and app threads to set 416 allowing socket to clear and app threads to set
418 tcpStatus CifsNeedReconnect if server hung */ 417 tcpStatus CifsNeedReconnect if server hung */
419 continue; 418 if (pdu_length < 4)
419 goto incomplete_rcv;
420 else
421 continue;
420 } else if (length <= 0) { 422 } else if (length <= 0) {
421 if (server->tcpStatus == CifsNew) { 423 if (server->tcpStatus == CifsNew) {
422 cFYI(1, ("tcp session abend after SMBnegprot")); 424 cFYI(1, ("tcp session abend after SMBnegprot"));
@@ -437,13 +439,11 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
437 wake_up(&server->response_q); 439 wake_up(&server->response_q);
438 continue; 440 continue;
439 } else if (length < 4) { 441 } else if (length < 4) {
440 cFYI(1, 442 cFYI(1, ("less than four bytes received (%d bytes)",
441 ("Frame under four bytes received (%d bytes long)",
442 length)); 443 length));
443 cifs_reconnect(server); 444 pdu_length -= length;
444 csocket = server->ssocket; 445 msleep(1);
445 wake_up(&server->response_q); 446 goto incomplete_rcv;
446 continue;
447 } 447 }
448 448
449 /* The right amount was read from socket - 4 bytes */ 449 /* The right amount was read from socket - 4 bytes */
@@ -504,7 +504,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
504 504
505 /* else we have an SMB response */ 505 /* else we have an SMB response */
506 if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) || 506 if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
507 (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) { 507 (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) {
508 cERROR(1, ("Invalid size SMB length %d pdu_length %d", 508 cERROR(1, ("Invalid size SMB length %d pdu_length %d",
509 length, pdu_length+4)); 509 length, pdu_length+4));
510 cifs_reconnect(server); 510 cifs_reconnect(server);
@@ -528,7 +528,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
528 total_read += length) { 528 total_read += length) {
529 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1, 529 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
530 pdu_length - total_read, 0); 530 pdu_length - total_read, 0);
531 if ( kthread_should_stop() || 531 if (kthread_should_stop() ||
532 (length == -EINTR)) { 532 (length == -EINTR)) {
533 /* then will exit */ 533 /* then will exit */
534 reconnect = 2; 534 reconnect = 2;
@@ -546,6 +546,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
546 allowing socket to clear and app 546 allowing socket to clear and app
547 threads to set tcpStatus 547 threads to set tcpStatus
548 CifsNeedReconnect if server hung*/ 548 CifsNeedReconnect if server hung*/
549 length = 0;
549 continue; 550 continue;
550 } else if (length <= 0) { 551 } else if (length <= 0) {
551 cERROR(1, ("Received no data, expecting %d", 552 cERROR(1, ("Received no data, expecting %d",
@@ -631,9 +632,9 @@ multi_t2_fnd:
631 /* Was previous buf put in mpx struct for multi-rsp? */ 632 /* Was previous buf put in mpx struct for multi-rsp? */
632 if (!isMultiRsp) { 633 if (!isMultiRsp) {
633 /* smb buffer will be freed by user thread */ 634 /* smb buffer will be freed by user thread */
634 if (isLargeBuf) { 635 if (isLargeBuf)
635 bigbuf = NULL; 636 bigbuf = NULL;
636 } else 637 else
637 smallbuf = NULL; 638 smallbuf = NULL;
638 } 639 }
639 wake_up_process(task_to_wake); 640 wake_up_process(task_to_wake);
@@ -676,9 +677,8 @@ multi_t2_fnd:
676 server->ssocket = NULL; 677 server->ssocket = NULL;
677 } 678 }
678 /* buffer usuallly freed in free_mid - need to free it here on exit */ 679 /* buffer usuallly freed in free_mid - need to free it here on exit */
679 if (bigbuf != NULL) 680 cifs_buf_release(bigbuf);
680 cifs_buf_release(bigbuf); 681 if (smallbuf) /* no sense logging a debug message if NULL */
681 if (smallbuf != NULL)
682 cifs_small_buf_release(smallbuf); 682 cifs_small_buf_release(smallbuf);
683 683
684 read_lock(&GlobalSMBSeslock); 684 read_lock(&GlobalSMBSeslock);
@@ -702,9 +702,8 @@ multi_t2_fnd:
702 list_for_each(tmp, &GlobalSMBSessionList) { 702 list_for_each(tmp, &GlobalSMBSessionList) {
703 ses = list_entry(tmp, struct cifsSesInfo, 703 ses = list_entry(tmp, struct cifsSesInfo,
704 cifsSessionList); 704 cifsSessionList);
705 if (ses->server == server) { 705 if (ses->server == server)
706 ses->status = CifsExiting; 706 ses->status = CifsExiting;
707 }
708 } 707 }
709 708
710 spin_lock(&GlobalMid_Lock); 709 spin_lock(&GlobalMid_Lock);
@@ -714,9 +713,8 @@ multi_t2_fnd:
714 cFYI(1, ("Clearing Mid 0x%x - waking up ", 713 cFYI(1, ("Clearing Mid 0x%x - waking up ",
715 mid_entry->mid)); 714 mid_entry->mid));
716 task_to_wake = mid_entry->tsk; 715 task_to_wake = mid_entry->tsk;
717 if (task_to_wake) { 716 if (task_to_wake)
718 wake_up_process(task_to_wake); 717 wake_up_process(task_to_wake);
719 }
720 } 718 }
721 } 719 }
722 spin_unlock(&GlobalMid_Lock); 720 spin_unlock(&GlobalMid_Lock);
@@ -749,18 +747,15 @@ multi_t2_fnd:
749 list_for_each(tmp, &GlobalSMBSessionList) { 747 list_for_each(tmp, &GlobalSMBSessionList) {
750 ses = list_entry(tmp, struct cifsSesInfo, 748 ses = list_entry(tmp, struct cifsSesInfo,
751 cifsSessionList); 749 cifsSessionList);
752 if (ses->server == server) { 750 if (ses->server == server)
753 ses->server = NULL; 751 ses->server = NULL;
754 }
755 } 752 }
756 write_unlock(&GlobalSMBSeslock); 753 write_unlock(&GlobalSMBSeslock);
757 754
758 kfree(server); 755 kfree(server);
759 if (length > 0) { 756 if (length > 0)
760 mempool_resize(cifs_req_poolp, 757 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
761 length + cifs_min_rcv, 758 GFP_KERNEL);
762 GFP_KERNEL);
763 }
764 759
765 return 0; 760 return 0;
766} 761}
@@ -1477,7 +1472,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1477 if (psin_server->sin_port) { /* user overrode default port */ 1472 if (psin_server->sin_port) { /* user overrode default port */
1478 rc = (*csocket)->ops->connect(*csocket, 1473 rc = (*csocket)->ops->connect(*csocket,
1479 (struct sockaddr *) psin_server, 1474 (struct sockaddr *) psin_server,
1480 sizeof (struct sockaddr_in), 0); 1475 sizeof(struct sockaddr_in), 0);
1481 if (rc >= 0) 1476 if (rc >= 0)
1482 connected = 1; 1477 connected = 1;
1483 } 1478 }
@@ -1493,7 +1488,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1493 1488
1494 rc = (*csocket)->ops->connect(*csocket, 1489 rc = (*csocket)->ops->connect(*csocket,
1495 (struct sockaddr *) psin_server, 1490 (struct sockaddr *) psin_server,
1496 sizeof (struct sockaddr_in), 0); 1491 sizeof(struct sockaddr_in), 0);
1497 if (rc >= 0) 1492 if (rc >= 0)
1498 connected = 1; 1493 connected = 1;
1499 } 1494 }
@@ -1502,7 +1497,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1502 psin_server->sin_port = htons(RFC1001_PORT); 1497 psin_server->sin_port = htons(RFC1001_PORT);
1503 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) 1498 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1504 psin_server, 1499 psin_server,
1505 sizeof (struct sockaddr_in), 0); 1500 sizeof(struct sockaddr_in), 0);
1506 if (rc >= 0) 1501 if (rc >= 0)
1507 connected = 1; 1502 connected = 1;
1508 } 1503 }
@@ -1610,7 +1605,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1610 if (psin_server->sin6_port) { /* user overrode default port */ 1605 if (psin_server->sin6_port) { /* user overrode default port */
1611 rc = (*csocket)->ops->connect(*csocket, 1606 rc = (*csocket)->ops->connect(*csocket,
1612 (struct sockaddr *) psin_server, 1607 (struct sockaddr *) psin_server,
1613 sizeof (struct sockaddr_in6), 0); 1608 sizeof(struct sockaddr_in6), 0);
1614 if (rc >= 0) 1609 if (rc >= 0)
1615 connected = 1; 1610 connected = 1;
1616 } 1611 }
@@ -1626,7 +1621,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1626 1621
1627 rc = (*csocket)->ops->connect(*csocket, 1622 rc = (*csocket)->ops->connect(*csocket,
1628 (struct sockaddr *) psin_server, 1623 (struct sockaddr *) psin_server,
1629 sizeof (struct sockaddr_in6), 0); 1624 sizeof(struct sockaddr_in6), 0);
1630 if (rc >= 0) 1625 if (rc >= 0)
1631 connected = 1; 1626 connected = 1;
1632 } 1627 }
@@ -1634,7 +1629,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1634 if (!connected) { 1629 if (!connected) {
1635 psin_server->sin6_port = htons(RFC1001_PORT); 1630 psin_server->sin6_port = htons(RFC1001_PORT);
1636 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) 1631 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1637 psin_server, sizeof (struct sockaddr_in6), 0); 1632 psin_server, sizeof(struct sockaddr_in6), 0);
1638 if (rc >= 0) 1633 if (rc >= 0)
1639 connected = 1; 1634 connected = 1;
1640 } 1635 }
@@ -1750,7 +1745,16 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
1750 cFYI(1, ("very large write cap")); 1745 cFYI(1, ("very large write cap"));
1751#endif /* CIFS_DEBUG2 */ 1746#endif /* CIFS_DEBUG2 */
1752 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) { 1747 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
1753 cFYI(1, ("setting capabilities failed")); 1748 if (vol_info == NULL) {
1749 cFYI(1, ("resetting capabilities failed"));
1750 } else
1751 cERROR(1, ("Negotiating Unix capabilities "
1752 "with the server failed. Consider "
1753 "mounting with the Unix Extensions\n"
1754 "disabled, if problems are found, "
1755 "by specifying the nounix mount "
1756 "option."));
1757
1754 } 1758 }
1755 } 1759 }
1756} 1760}
@@ -1909,8 +1913,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1909 return rc; 1913 return rc;
1910 } 1914 }
1911 1915
1912 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL); 1916 srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
1913 if (srvTcp == NULL) { 1917 if (!srvTcp) {
1914 rc = -ENOMEM; 1918 rc = -ENOMEM;
1915 sock_release(csocket); 1919 sock_release(csocket);
1916 kfree(volume_info.UNC); 1920 kfree(volume_info.UNC);
@@ -1919,9 +1923,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1919 FreeXid(xid); 1923 FreeXid(xid);
1920 return rc; 1924 return rc;
1921 } else { 1925 } else {
1922 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1923 memcpy(&srvTcp->addr.sockAddr, &sin_server, 1926 memcpy(&srvTcp->addr.sockAddr, &sin_server,
1924 sizeof (struct sockaddr_in)); 1927 sizeof(struct sockaddr_in));
1925 atomic_set(&srvTcp->inFlight, 0); 1928 atomic_set(&srvTcp->inFlight, 0);
1926 /* BB Add code for ipv6 case too */ 1929 /* BB Add code for ipv6 case too */
1927 srvTcp->ssocket = csocket; 1930 srvTcp->ssocket = csocket;
@@ -2173,8 +2176,18 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2173 if (tsk) 2176 if (tsk)
2174 kthread_stop(tsk); 2177 kthread_stop(tsk);
2175 } 2178 }
2176 } else 2179 } else {
2177 cFYI(1, ("No session or bad tcon")); 2180 cFYI(1, ("No session or bad tcon"));
2181 if ((pSesInfo->server) &&
2182 (pSesInfo->server->tsk)) {
2183 struct task_struct *tsk;
2184 force_sig(SIGKILL,
2185 pSesInfo->server->tsk);
2186 tsk = pSesInfo->server->tsk;
2187 if (tsk)
2188 kthread_stop(tsk);
2189 }
2190 }
2178 sesInfoFree(pSesInfo); 2191 sesInfoFree(pSesInfo);
2179 /* pSesInfo = NULL; */ 2192 /* pSesInfo = NULL; */
2180 } 2193 }
@@ -2185,8 +2198,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2185 tcon->ses = pSesInfo; 2198 tcon->ses = pSesInfo;
2186 2199
2187 /* do not care if following two calls succeed - informational */ 2200 /* do not care if following two calls succeed - informational */
2188 CIFSSMBQFSDeviceInfo(xid, tcon); 2201 if (!tcon->ipc) {
2189 CIFSSMBQFSAttributeInfo(xid, tcon); 2202 CIFSSMBQFSDeviceInfo(xid, tcon);
2203 CIFSSMBQFSAttributeInfo(xid, tcon);
2204 }
2190 2205
2191 /* tell server which Unix caps we support */ 2206 /* tell server which Unix caps we support */
2192 if (tcon->ses->capabilities & CAP_UNIX) 2207 if (tcon->ses->capabilities & CAP_UNIX)
@@ -2526,8 +2541,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2526sesssetup_nomem: /* do not return an error on nomem for the info strings, 2541sesssetup_nomem: /* do not return an error on nomem for the info strings,
2527 since that could make reconnection harder, and 2542 since that could make reconnection harder, and
2528 reconnection might be needed to free memory */ 2543 reconnection might be needed to free memory */
2529 if (smb_buffer) 2544 cifs_buf_release(smb_buffer);
2530 cifs_buf_release(smb_buffer);
2531 2545
2532 return rc; 2546 return rc;
2533} 2547}
@@ -2547,7 +2561,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2547 int remaining_words = 0; 2561 int remaining_words = 0;
2548 int bytes_returned = 0; 2562 int bytes_returned = 0;
2549 int len; 2563 int len;
2550 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE); 2564 int SecurityBlobLength = sizeof(NEGOTIATE_MESSAGE);
2551 PNEGOTIATE_MESSAGE SecurityBlob; 2565 PNEGOTIATE_MESSAGE SecurityBlob;
2552 PCHALLENGE_MESSAGE SecurityBlob2; 2566 PCHALLENGE_MESSAGE SecurityBlob2;
2553 __u32 negotiate_flags, capabilities; 2567 __u32 negotiate_flags, capabilities;
@@ -2865,15 +2879,14 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2865 rc = -EIO; 2879 rc = -EIO;
2866 } 2880 }
2867 2881
2868 if (smb_buffer) 2882 cifs_buf_release(smb_buffer);
2869 cifs_buf_release(smb_buffer);
2870 2883
2871 return rc; 2884 return rc;
2872} 2885}
2873static int 2886static int
2874CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, 2887CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2875 char *ntlm_session_key, int ntlmv2_flag, 2888 char *ntlm_session_key, int ntlmv2_flag,
2876 const struct nls_table *nls_codepage) 2889 const struct nls_table *nls_codepage)
2877{ 2890{
2878 struct smb_hdr *smb_buffer; 2891 struct smb_hdr *smb_buffer;
2879 struct smb_hdr *smb_buffer_response; 2892 struct smb_hdr *smb_buffer_response;
@@ -2886,7 +2899,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2886 int remaining_words = 0; 2899 int remaining_words = 0;
2887 int bytes_returned = 0; 2900 int bytes_returned = 0;
2888 int len; 2901 int len;
2889 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE); 2902 int SecurityBlobLength = sizeof(AUTHENTICATE_MESSAGE);
2890 PAUTHENTICATE_MESSAGE SecurityBlob; 2903 PAUTHENTICATE_MESSAGE SecurityBlob;
2891 __u32 negotiate_flags, capabilities; 2904 __u32 negotiate_flags, capabilities;
2892 __u16 count; 2905 __u16 count;
@@ -2901,8 +2914,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2901 return -ENOMEM; 2914 return -ENOMEM;
2902 } 2915 }
2903 smb_buffer_response = smb_buffer; 2916 smb_buffer_response = smb_buffer;
2904 pSMB = (SESSION_SETUP_ANDX *) smb_buffer; 2917 pSMB = (SESSION_SETUP_ANDX *)smb_buffer;
2905 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response; 2918 pSMBr = (SESSION_SETUP_ANDX *)smb_buffer_response;
2906 2919
2907 /* send SMBsessionSetup here */ 2920 /* send SMBsessionSetup here */
2908 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, 2921 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
@@ -2921,7 +2934,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2921 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; 2934 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2922 2935
2923 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | 2936 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2924 CAP_EXTENDED_SECURITY; 2937 CAP_EXTENDED_SECURITY;
2925 if (ses->capabilities & CAP_UNICODE) { 2938 if (ses->capabilities & CAP_UNICODE) {
2926 smb_buffer->Flags2 |= SMBFLG2_UNICODE; 2939 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2927 capabilities |= CAP_UNICODE; 2940 capabilities |= CAP_UNICODE;
@@ -2936,15 +2949,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2936 } 2949 }
2937 pSMB->req.Capabilities = cpu_to_le32(capabilities); 2950 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2938 2951
2939 bcc_ptr = (char *) &pSMB->req.SecurityBlob; 2952 bcc_ptr = (char *)&pSMB->req.SecurityBlob;
2940 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr; 2953 SecurityBlob = (PAUTHENTICATE_MESSAGE)bcc_ptr;
2941 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8); 2954 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2942 SecurityBlob->MessageType = NtLmAuthenticate; 2955 SecurityBlob->MessageType = NtLmAuthenticate;
2943 bcc_ptr += SecurityBlobLength; 2956 bcc_ptr += SecurityBlobLength;
2944 negotiate_flags = 2957 negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2945 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET | 2958 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2946 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO | 2959 0x80000000 | NTLMSSP_NEGOTIATE_128;
2947 0x80000000 | NTLMSSP_NEGOTIATE_128;
2948 if (sign_CIFS_PDUs) 2960 if (sign_CIFS_PDUs)
2949 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN; 2961 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2950 if (ntlmv2_flag) 2962 if (ntlmv2_flag)
@@ -2979,36 +2991,32 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2979 SecurityBlob->DomainName.Length = 0; 2991 SecurityBlob->DomainName.Length = 0;
2980 SecurityBlob->DomainName.MaximumLength = 0; 2992 SecurityBlob->DomainName.MaximumLength = 0;
2981 } else { 2993 } else {
2982 __u16 len = 2994 __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2983 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2984 nls_codepage); 2995 nls_codepage);
2985 len *= 2; 2996 ln *= 2;
2986 SecurityBlob->DomainName.MaximumLength = 2997 SecurityBlob->DomainName.MaximumLength =
2987 cpu_to_le16(len); 2998 cpu_to_le16(ln);
2988 SecurityBlob->DomainName.Buffer = 2999 SecurityBlob->DomainName.Buffer =
2989 cpu_to_le32(SecurityBlobLength); 3000 cpu_to_le32(SecurityBlobLength);
2990 bcc_ptr += len; 3001 bcc_ptr += ln;
2991 SecurityBlobLength += len; 3002 SecurityBlobLength += ln;
2992 SecurityBlob->DomainName.Length = 3003 SecurityBlob->DomainName.Length = cpu_to_le16(ln);
2993 cpu_to_le16(len);
2994 } 3004 }
2995 if (user == NULL) { 3005 if (user == NULL) {
2996 SecurityBlob->UserName.Buffer = 0; 3006 SecurityBlob->UserName.Buffer = 0;
2997 SecurityBlob->UserName.Length = 0; 3007 SecurityBlob->UserName.Length = 0;
2998 SecurityBlob->UserName.MaximumLength = 0; 3008 SecurityBlob->UserName.MaximumLength = 0;
2999 } else { 3009 } else {
3000 __u16 len = 3010 __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
3001 cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
3002 nls_codepage); 3011 nls_codepage);
3003 len *= 2; 3012 ln *= 2;
3004 SecurityBlob->UserName.MaximumLength = 3013 SecurityBlob->UserName.MaximumLength =
3005 cpu_to_le16(len); 3014 cpu_to_le16(ln);
3006 SecurityBlob->UserName.Buffer = 3015 SecurityBlob->UserName.Buffer =
3007 cpu_to_le32(SecurityBlobLength); 3016 cpu_to_le32(SecurityBlobLength);
3008 bcc_ptr += len; 3017 bcc_ptr += ln;
3009 SecurityBlobLength += len; 3018 SecurityBlobLength += ln;
3010 SecurityBlob->UserName.Length = 3019 SecurityBlob->UserName.Length = cpu_to_le16(ln);
3011 cpu_to_le16(len);
3012 } 3020 }
3013 3021
3014 /* SecurityBlob->WorkstationName.Length = 3022 /* SecurityBlob->WorkstationName.Length =
@@ -3052,33 +3060,32 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3052 SecurityBlob->DomainName.Length = 0; 3060 SecurityBlob->DomainName.Length = 0;
3053 SecurityBlob->DomainName.MaximumLength = 0; 3061 SecurityBlob->DomainName.MaximumLength = 0;
3054 } else { 3062 } else {
3055 __u16 len; 3063 __u16 ln;
3056 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED; 3064 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
3057 strncpy(bcc_ptr, domain, 63); 3065 strncpy(bcc_ptr, domain, 63);
3058 len = strnlen(domain, 64); 3066 ln = strnlen(domain, 64);
3059 SecurityBlob->DomainName.MaximumLength = 3067 SecurityBlob->DomainName.MaximumLength =
3060 cpu_to_le16(len); 3068 cpu_to_le16(ln);
3061 SecurityBlob->DomainName.Buffer = 3069 SecurityBlob->DomainName.Buffer =
3062 cpu_to_le32(SecurityBlobLength); 3070 cpu_to_le32(SecurityBlobLength);
3063 bcc_ptr += len; 3071 bcc_ptr += ln;
3064 SecurityBlobLength += len; 3072 SecurityBlobLength += ln;
3065 SecurityBlob->DomainName.Length = cpu_to_le16(len); 3073 SecurityBlob->DomainName.Length = cpu_to_le16(ln);
3066 } 3074 }
3067 if (user == NULL) { 3075 if (user == NULL) {
3068 SecurityBlob->UserName.Buffer = 0; 3076 SecurityBlob->UserName.Buffer = 0;
3069 SecurityBlob->UserName.Length = 0; 3077 SecurityBlob->UserName.Length = 0;
3070 SecurityBlob->UserName.MaximumLength = 0; 3078 SecurityBlob->UserName.MaximumLength = 0;
3071 } else { 3079 } else {
3072 __u16 len; 3080 __u16 ln;
3073 strncpy(bcc_ptr, user, 63); 3081 strncpy(bcc_ptr, user, 63);
3074 len = strnlen(user, 64); 3082 ln = strnlen(user, 64);
3075 SecurityBlob->UserName.MaximumLength = 3083 SecurityBlob->UserName.MaximumLength = cpu_to_le16(ln);
3076 cpu_to_le16(len);
3077 SecurityBlob->UserName.Buffer = 3084 SecurityBlob->UserName.Buffer =
3078 cpu_to_le32(SecurityBlobLength); 3085 cpu_to_le32(SecurityBlobLength);
3079 bcc_ptr += len; 3086 bcc_ptr += ln;
3080 SecurityBlobLength += len; 3087 SecurityBlobLength += ln;
3081 SecurityBlob->UserName.Length = cpu_to_le16(len); 3088 SecurityBlob->UserName.Length = cpu_to_le16(ln);
3082 } 3089 }
3083 /* BB fill in our workstation name if known BB */ 3090 /* BB fill in our workstation name if known BB */
3084 3091
@@ -3100,12 +3107,11 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3100 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, 3107 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
3101 &bytes_returned, 1); 3108 &bytes_returned, 1);
3102 if (rc) { 3109 if (rc) {
3103/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */ 3110/* rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */
3104 } else if ((smb_buffer_response->WordCount == 3) 3111 } else if ((smb_buffer_response->WordCount == 3) ||
3105 || (smb_buffer_response->WordCount == 4)) { 3112 (smb_buffer_response->WordCount == 4)) {
3106 __u16 action = le16_to_cpu(pSMBr->resp.Action); 3113 __u16 action = le16_to_cpu(pSMBr->resp.Action);
3107 __u16 blob_len = 3114 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
3108 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
3109 if (action & GUEST_LOGIN) 3115 if (action & GUEST_LOGIN)
3110 cFYI(1, (" Guest login")); /* BB Should we set anything 3116 cFYI(1, (" Guest login")); /* BB Should we set anything
3111 in SesInfo struct ? */ 3117 in SesInfo struct ? */
@@ -3145,8 +3151,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3145 } else { 3151 } else {
3146 remaining_words = BCC(smb_buffer_response) / 2; 3152 remaining_words = BCC(smb_buffer_response) / 2;
3147 } 3153 }
3148 len = 3154 len = UniStrnlen((wchar_t *) bcc_ptr,
3149 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1); 3155 remaining_words - 1);
3150/* We look for obvious messed up bcc or strings in response so we do not go off 3156/* We look for obvious messed up bcc or strings in response so we do not go off
3151 the end since (at least) WIN2K and Windows XP have a major bug in not null 3157 the end since (at least) WIN2K and Windows XP have a major bug in not null
3152 terminating last Unicode string in response */ 3158 terminating last Unicode string in response */
@@ -3230,7 +3236,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3230 <= BCC(smb_buffer_response)) { 3236 <= BCC(smb_buffer_response)) {
3231 if (ses->serverOS) 3237 if (ses->serverOS)
3232 kfree(ses->serverOS); 3238 kfree(ses->serverOS);
3233 ses->serverOS = kzalloc(len + 1,GFP_KERNEL); 3239 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
3234 strncpy(ses->serverOS,bcc_ptr, len); 3240 strncpy(ses->serverOS,bcc_ptr, len);
3235 3241
3236 bcc_ptr += len; 3242 bcc_ptr += len;
@@ -3259,28 +3265,24 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3259 bcc_ptr[0] = 0; 3265 bcc_ptr[0] = 0;
3260 bcc_ptr++; 3266 bcc_ptr++;
3261 } else 3267 } else
3262 cFYI(1, 3268 cFYI(1, ("field of length %d "
3263 ("field of length %d "
3264 "extends beyond end of smb ", 3269 "extends beyond end of smb ",
3265 len)); 3270 len));
3266 } 3271 }
3267 } else { 3272 } else {
3268 cERROR(1, 3273 cERROR(1, ("Security Blob extends beyond end "
3269 (" Security Blob extends beyond end "
3270 "of SMB")); 3274 "of SMB"));
3271 } 3275 }
3272 } else { 3276 } else {
3273 cERROR(1, ("No session structure passed in.")); 3277 cERROR(1, ("No session structure passed in."));
3274 } 3278 }
3275 } else { 3279 } else {
3276 cERROR(1, 3280 cERROR(1, ("Invalid Word count %d: ",
3277 (" Invalid Word count %d: ",
3278 smb_buffer_response->WordCount)); 3281 smb_buffer_response->WordCount));
3279 rc = -EIO; 3282 rc = -EIO;
3280 } 3283 }
3281 3284
3282 if (smb_buffer) 3285 cifs_buf_release(smb_buffer);
3283 cifs_buf_release(smb_buffer);
3284 3286
3285 return rc; 3287 return rc;
3286} 3288}
@@ -3389,6 +3391,18 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3389 bcc_ptr = pByteArea(smb_buffer_response); 3391 bcc_ptr = pByteArea(smb_buffer_response);
3390 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2); 3392 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
3391 /* skip service field (NB: this field is always ASCII) */ 3393 /* skip service field (NB: this field is always ASCII) */
3394 if (length == 3) {
3395 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
3396 (bcc_ptr[2] == 'C')) {
3397 cFYI(1, ("IPC connection"));
3398 tcon->ipc = 1;
3399 }
3400 } else if (length == 2) {
3401 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
3402 /* the most common case */
3403 cFYI(1, ("disk share connection"));
3404 }
3405 }
3392 bcc_ptr += length + 1; 3406 bcc_ptr += length + 1;
3393 strncpy(tcon->treeName, tree, MAX_TREE_SIZE); 3407 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3394 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { 3408 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
@@ -3399,9 +3413,11 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3399 kfree(tcon->nativeFileSystem); 3413 kfree(tcon->nativeFileSystem);
3400 tcon->nativeFileSystem = 3414 tcon->nativeFileSystem =
3401 kzalloc(length + 2, GFP_KERNEL); 3415 kzalloc(length + 2, GFP_KERNEL);
3402 cifs_strfromUCS_le(tcon->nativeFileSystem, 3416 if (tcon->nativeFileSystem)
3403 (__le16 *) bcc_ptr, 3417 cifs_strfromUCS_le(
3404 length, nls_codepage); 3418 tcon->nativeFileSystem,
3419 (__le16 *) bcc_ptr,
3420 length, nls_codepage);
3405 bcc_ptr += 2 * length; 3421 bcc_ptr += 2 * length;
3406 bcc_ptr[0] = 0; /* null terminate the string */ 3422 bcc_ptr[0] = 0; /* null terminate the string */
3407 bcc_ptr[1] = 0; 3423 bcc_ptr[1] = 0;
@@ -3416,8 +3432,9 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3416 kfree(tcon->nativeFileSystem); 3432 kfree(tcon->nativeFileSystem);
3417 tcon->nativeFileSystem = 3433 tcon->nativeFileSystem =
3418 kzalloc(length + 1, GFP_KERNEL); 3434 kzalloc(length + 1, GFP_KERNEL);
3419 strncpy(tcon->nativeFileSystem, bcc_ptr, 3435 if (tcon->nativeFileSystem)
3420 length); 3436 strncpy(tcon->nativeFileSystem, bcc_ptr,
3437 length);
3421 } 3438 }
3422 /* else do not bother copying these information fields*/ 3439 /* else do not bother copying these information fields*/
3423 } 3440 }
@@ -3433,8 +3450,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3433 ses->ipc_tid = smb_buffer_response->Tid; 3450 ses->ipc_tid = smb_buffer_response->Tid;
3434 } 3451 }
3435 3452
3436 if (smb_buffer) 3453 cifs_buf_release(smb_buffer);
3437 cifs_buf_release(smb_buffer);
3438 return rc; 3454 return rc;
3439} 3455}
3440 3456