[CIFS] CIFS ACL support part 3
[safe/jmp/linux-2.6] / fs / cifs / cifssmb.c
index b339f5f..eff3226 100644 (file)
 #include <asm/uaccess.h>
 #include "cifspdu.h"
 #include "cifsglob.h"
+#include "cifsacl.h"
 #include "cifsproto.h"
 #include "cifs_unicode.h"
 #include "cifs_debug.h"
-#include "cifsacl.h"
 
 #ifdef CONFIG_CIFS_POSIX
 static struct {
@@ -94,9 +94,8 @@ static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
        write_lock(&GlobalSMBSeslock);
        list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
                open_file = list_entry(tmp, struct cifsFileInfo, tlist);
-               if (open_file) {
+               if (open_file)
                        open_file->invalidHandle = TRUE;
-               }
        }
        write_unlock(&GlobalSMBSeslock);
        /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
@@ -132,10 +131,13 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
                                /* Give Demultiplex thread up to 10 seconds to
                                   reconnect, should be greater than cifs socket
                                   timeout which is 7 seconds */
-                       while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
+                       while (tcon->ses->server->tcpStatus ==
+                                                        CifsNeedReconnect) {
                                wait_event_interruptible_timeout(tcon->ses->server->response_q,
-                                       (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
-                               if (tcon->ses->server->tcpStatus == CifsNeedReconnect) {
+                                       (tcon->ses->server->tcpStatus ==
+                                                       CifsGood), 10 * HZ);
+                               if (tcon->ses->server->tcpStatus ==
+                                                       CifsNeedReconnect) {
                                        /* on "soft" mounts we wait once */
                                        if ((tcon->retry == FALSE) ||
                                           (tcon->ses->status == CifsExiting)) {
@@ -209,7 +211,8 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
                return -ENOMEM;
        }
 
-       header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
+       header_assemble((struct smb_hdr *) *request_buf, smb_command,
+                       tcon, wct);
 
        if (tcon != NULL)
                cifs_stats_inc(&tcon->num_smbs_sent);
@@ -274,9 +277,11 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
                                /* Give Demultiplex thread up to 10 seconds to
                                   reconnect, should be greater than cifs socket
                                   timeout which is 7 seconds */
-                       while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
+                       while (tcon->ses->server->tcpStatus ==
+                                                       CifsNeedReconnect) {
                                wait_event_interruptible_timeout(tcon->ses->server->response_q,
-                                       (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
+                                       (tcon->ses->server->tcpStatus ==
+                                                       CifsGood), 10 * HZ);
                                if (tcon->ses->server->tcpStatus ==
                                                CifsNeedReconnect) {
                                        /* on "soft" mounts we wait once */
@@ -381,7 +386,8 @@ static int validate_t2(struct smb_t2_rsp *pSMB)
                        /* check that bcc is less than negotiated smb buffer */
                        total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
                        if (total_size < 512) {
-                               total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
+                               total_size +=
+                                       le16_to_cpu(pSMB->t2_rsp.DataCount);
                                /* BCC le converted in SendReceive */
                                pBCC = (pSMB->hdr.WordCount * 2) +
                                        sizeof(struct smb_hdr) +
@@ -432,8 +438,13 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
 
        pSMB->hdr.Mid = GetNextMid(server);
        pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
+
        if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
                pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
+       else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
+               cFYI(1, ("Kerberos only mechanism, enable extended security"));
+               pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
+       }
 
        count = 0;
        for (i = 0; i < CIFS_NUM_PROT; i++) {
@@ -506,7 +517,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
                                (int)ts.tv_sec, (int)utc.tv_sec,
                                (int)(utc.tv_sec - ts.tv_sec)));
                        val = (int)(utc.tv_sec - ts.tv_sec);
-                       seconds = val < 0 ? -val : val;
+                       seconds = abs(val);
                        result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
                        remain = seconds % MIN_TZ_ADJ;
                        if (remain >= (MIN_TZ_ADJ / 2))
@@ -567,7 +578,20 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
                server->secType = NTLM;
        else if (secFlags & CIFSSEC_MAY_NTLMV2)
                server->secType = NTLMv2;
-       /* else krb5 ... any others ... */
+       else if (secFlags & CIFSSEC_MAY_KRB5)
+               server->secType = Kerberos;
+       else if (secFlags & CIFSSEC_MAY_LANMAN)
+               server->secType = LANMAN;
+/* #ifdef CONFIG_CIFS_EXPERIMENTAL
+       else if (secFlags & CIFSSEC_MAY_PLNTXT)
+               server->secType = ??
+#endif */
+       else {
+               rc = -EOPNOTSUPP;
+               cERROR(1, ("Invalid security type"));
+               goto neg_err_exit;
+       }
+       /* else ... any others ...? */
 
        /* one byte, so no need to convert this or EncryptionKeyLen from
           little endian */
@@ -1105,7 +1129,7 @@ PsxCreat:
                }
                memcpy((char *) pRetData,
                        (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
-                       sizeof (FILE_UNIX_BASIC_INFO));
+                       sizeof(FILE_UNIX_BASIC_INFO));
        }
 
 psx_create_err:
@@ -1186,9 +1210,9 @@ OldOpenRetry:
        }
        if (*pOplock & REQ_OPLOCK)
                pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
-       else if (*pOplock & REQ_BATCHOPLOCK) {
+       else if (*pOplock & REQ_BATCHOPLOCK)
                pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
-       }
+
        pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
        /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
        /* 0 = read
@@ -1303,9 +1327,8 @@ openRetry:
        }
        if (*pOplock & REQ_OPLOCK)
                pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
-       else if (*pOplock & REQ_BATCHOPLOCK) {
+       else if (*pOplock & REQ_BATCHOPLOCK)
                pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
-       }
        pSMB->DesiredAccess = cpu_to_le32(access_flags);
        pSMB->AllocationSize = 0;
        /* set file as system file if special file such
@@ -1439,11 +1462,11 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
                        *nbytes = 0;
                } else {
                        pReadData = (char *) (&pSMBr->hdr.Protocol) +
-                           le16_to_cpu(pSMBr->DataOffset);
-/*                      if (rc = copy_to_user(buf, pReadData, data_length)) {
+                                       le16_to_cpu(pSMBr->DataOffset);
+/*                     if (rc = copy_to_user(buf, pReadData, data_length)) {
                                cERROR(1,("Faulting on read rc = %d",rc));
                                rc = -EFAULT;
-                        }*/ /* can not use copy_to_user when using page cache*/
+                       }*/ /* can not use copy_to_user when using page cache*/
                        if (*buf)
                                memcpy(*buf, pReadData, data_length);
                }
@@ -2531,7 +2554,7 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata,
                cFYI(1, ("data starts after end of smb"));
                return -EINVAL;
        } else if (data_count + *ppdata > end_of_smb) {
-               cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
+               cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
                        *ppdata, data_count, (data_count + *ppdata),
                        end_of_smb, pSMBr));
                return -EINVAL;
@@ -2608,7 +2631,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
                                        reparse_buf->TargetNameOffset +
                                        reparse_buf->TargetNameLen) >
                                                end_of_smb) {
-                                       cFYI(1,("reparse buf extended beyond SMB"));
+                                       cFYI(1, ("reparse buf beyond SMB"));
                                        rc = -EIO;
                                        goto qreparse_out;
                                }
@@ -2632,7 +2655,8 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
                                }
                        } else {
                                rc = -EIO;
-                               cFYI(1,("Invalid return data count on get reparse info ioctl"));
+                               cFYI(1, ("Invalid return data count on "
+                                        "get reparse info ioctl"));
                        }
                        symlinkinfo[buflen] = 0; /* just in case so the caller
                                        does not go off the end of the buffer */
@@ -2750,7 +2774,8 @@ static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
                return 0;
 
        count = posix_acl_xattr_count((size_t)buflen);
-       cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
+       cFYI(1, ("setting acl with %d entries from buf of length %d and "
+               "version of %d",
                count, buflen, le32_to_cpu(local_acl->a_version)));
        if (le32_to_cpu(local_acl->a_version) != 2) {
                cFYI(1, ("unknown POSIX ACL version %d",
@@ -3033,25 +3058,12 @@ GetExtAttrOut:
 
 #endif /* CONFIG_POSIX */
 
-
-/* security id for everyone */
-static const struct cifs_sid sid_everyone =
-               {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
-/* group users */
-static const struct cifs_sid sid_user =
-               {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
-
-/* Convert CIFS ACL to POSIX form */
-static int parse_sec_desc(struct cifs_sid *psec_desc, int acl_len)
-{
-       return 0;
-}
-
+#ifdef CONFIG_CIFS_EXPERIMENTAL
 /* Get Security Descriptor (by handle) from remote server for a file or dir */
 int
 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
                /* BB fix up return info */ char *acl_inf, const int buflen,
-                 const int acl_type /* ACCESS/DEFAULT not sure implication */)
+                 const int acl_type)
 {
        int rc = 0;
        int buf_type = 0;
@@ -3081,7 +3093,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
        if (rc) {
                cFYI(1, ("Send error in QuerySecDesc = %d", rc));
        } else {                /* decode response */
-               struct cifs_sid *psec_desc;
+               struct cifs_ntsd *psec_desc;
                __le32 * parm;
                int parm_len;
                int data_len;
@@ -3096,8 +3108,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
                        goto qsec_out;
                pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
 
-               cERROR(1, ("smb %p parm %p data %p",
-                         pSMBr, parm, psec_desc));  /* BB removeme BB */
+               cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, psec_desc));
 
                if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
                        rc = -EIO;      /* bad smb */
@@ -3119,6 +3130,7 @@ qsec_out:
 /*     cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
        return rc;
 }
+#endif /* CONFIG_CIFS_EXPERIMENTAL */
 
 /* Legacy Query Path Information call for lookup to old servers such
    as Win9x/WinME */
@@ -3354,6 +3366,9 @@ UnixQPathInfoRetry:
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
                if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
+                       cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
+                                  "Unix Extensions can be disabled on mount "
+                                  "by specifying the nosfu mount option."));
                        rc = -EIO;      /* bad smb */
                } else {
                        __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
@@ -3629,15 +3644,6 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
        pSMB->SearchHandle = searchHandle;      /* always kept as le */
        pSMB->SearchCount =
                cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
-       /* test for Unix extensions */
-/*     if (tcon->ses->capabilities & CAP_UNIX) {
-               pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
-               psrch_inf->info_level = SMB_FIND_FILE_UNIX;
-       } else {
-               pSMB->InformationLevel =
-                  cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
-               psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
-       } */
        pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
        pSMB->ResumeKey = psrch_inf->resume_key;
        pSMB->SearchFlags =
@@ -3883,12 +3889,10 @@ getDFSRetry:
        pSMB->hdr.Mid = GetNextMid(ses->server);
        pSMB->hdr.Tid = ses->ipc_tid;
        pSMB->hdr.Uid = ses->Suid;
-       if (ses->capabilities & CAP_STATUS32) {
+       if (ses->capabilities & CAP_STATUS32)
                pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
-       }
-       if (ses->capabilities & CAP_DFS) {
+       if (ses->capabilities & CAP_DFS)
                pSMB->hdr.Flags2 |= SMBFLG2_DFS;
-       }
 
        if (ses->capabilities & CAP_UNICODE) {
                pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
@@ -3957,7 +3961,9 @@ getDFSRetry:
                                        (8 /* sizeof start of data block */ +
                                        data_offset +
                                        (char *) &pSMBr->hdr.Protocol);
-                       cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x",
+                       cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n"
+                               "for referral one refer size: 0x%x srv "
+                               "type: 0x%x refer flags: 0x%x ttl: 0x%x",
                                le16_to_cpu(pSMBr->NumberOfReferrals),
                                le16_to_cpu(pSMBr->DFSFlags),
                                le16_to_cpu(referrals->ReferralSize),
@@ -4058,10 +4064,6 @@ oldQFSInfoRetry:
                (void **) &pSMBr);
        if (rc)
                return rc;
-       rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
-                     (void **) &pSMBr);
-       if (rc)
-               return rc;
 
        params = 2;     /* level */
        pSMB->TotalDataCount = 0;
@@ -4263,7 +4265,7 @@ QFSAttributeRetry:
                             *) (((char *) &pSMBr->hdr.Protocol) +
                                 data_offset);
                        memcpy(&tcon->fsAttrInfo, response_data,
-                              sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
+                              sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
                }
        }
        cifs_buf_release(pSMB);
@@ -4332,7 +4334,7 @@ QFSDeviceRetry:
                                (((char *) &pSMBr->hdr.Protocol) +
                                 data_offset);
                        memcpy(&tcon->fsDevInfo, response_data,
-                              sizeof (FILE_SYSTEM_DEVICE_INFO));
+                              sizeof(FILE_SYSTEM_DEVICE_INFO));
                }
        }
        cifs_buf_release(pSMB);
@@ -4400,7 +4402,7 @@ QFSUnixRetry:
                             *) (((char *) &pSMBr->hdr.Protocol) +
                                 data_offset);
                        memcpy(&tcon->fsUnixInfo, response_data,
-                              sizeof (FILE_SYSTEM_UNIX_INFO));
+                              sizeof(FILE_SYSTEM_UNIX_INFO));
                }
        }
        cifs_buf_release(pSMB);
@@ -4610,7 +4612,7 @@ SetEOFRetry:
                strncpy(pSMB->FileName, fileName, name_len);
        }
        params = 6 + name_len;
-       data_count = sizeof (struct file_end_of_file_info);
+       data_count = sizeof(struct file_end_of_file_info);
        pSMB->MaxParameterCount = cpu_to_le16(2);
        pSMB->MaxDataCount = cpu_to_le16(4100);
        pSMB->MaxSetupCount = 0;
@@ -4798,7 +4800,7 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
 
        data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
 
-       count = sizeof (FILE_BASIC_INFO);
+       count = sizeof(FILE_BASIC_INFO);
        pSMB->MaxParameterCount = cpu_to_le16(2);
        pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
        pSMB->SetupCount = 1;
@@ -4869,7 +4871,7 @@ SetTimesRetry:
        }
 
        params = 6 + name_len;
-       count = sizeof (FILE_BASIC_INFO);
+       count = sizeof(FILE_BASIC_INFO);
        pSMB->MaxParameterCount = cpu_to_le16(2);
        pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
        pSMB->MaxSetupCount = 0;
@@ -4898,7 +4900,7 @@ SetTimesRetry:
                pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
        pSMB->Reserved4 = 0;
        pSMB->hdr.smb_buf_length += byte_count;
-       memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
+       memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
        pSMB->ByteCount = cpu_to_le16(byte_count);
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -5001,7 +5003,7 @@ setPermsRetry:
        }
 
        params = 6 + name_len;
-       count = sizeof (FILE_UNIX_BASIC_INFO);
+       count = sizeof(FILE_UNIX_BASIC_INFO);
        pSMB->MaxParameterCount = cpu_to_le16(2);
        pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
        pSMB->MaxSetupCount = 0;