diff options
| author | Shirish Pargaonkar <shirishp@us.ibm.com> | 2007-10-03 14:22:19 -0400 |
|---|---|---|
| committer | Steve French <sfrench@us.ibm.com> | 2007-10-03 14:22:19 -0400 |
| commit | d0d66c443aefa51d5dbdd6a1d9b135a2a0e469cc (patch) | |
| tree | e30ee8cac1bef527cbf9610a82c493e0002fd9c1 /fs | |
| parent | a8a11d399fc3c70f2aa645c7472235a06e8b8efa (diff) | |
[CIFS] CIFS ACL support (part 2)
Signed-off-by: Shirish Pargaonkar <shirishp@us.ibm.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/cifs/cifsacl.c | 203 | ||||
| -rw-r--r-- | fs/cifs/cifsacl.h | 4 | ||||
| -rw-r--r-- | fs/cifs/cifsproto.h | 2 | ||||
| -rw-r--r-- | fs/cifs/cifssmb.c | 2 |
4 files changed, 151 insertions, 60 deletions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 9b84f373af19..23bff0128e2a 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
| @@ -24,48 +24,178 @@ | |||
| 24 | #include <linux/fs.h> | 24 | #include <linux/fs.h> |
| 25 | #include "cifspdu.h" | 25 | #include "cifspdu.h" |
| 26 | #include "cifsglob.h" | 26 | #include "cifsglob.h" |
| 27 | #include "cifsacl.h" | ||
| 27 | #include "cifsproto.h" | 28 | #include "cifsproto.h" |
| 28 | #include "cifs_debug.h" | 29 | #include "cifs_debug.h" |
| 29 | #include "cifsacl.h" | ||
| 30 | 30 | ||
| 31 | /* security id for everyone */ | 31 | /* security id for everyone */ |
| 32 | static const struct cifs_sid sid_everyone = | 32 | static const struct cifs_sid sid_everyone = |
| 33 | {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}}; | 33 | {1, 1, {0, 0, 0, 0, 0, 0}, {}}; |
| 34 | /* group users */ | 34 | /* group users */ |
| 35 | static const struct cifs_sid sid_user = | 35 | static const struct cifs_sid sid_user = |
| 36 | {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}}; | 36 | {1, 2 , {0, 0, 0, 0, 0, 5}, {}}; |
| 37 | |||
| 38 | static void parse_ace(struct cifs_ace * pace, char * end_of_acl) | ||
| 39 | { | ||
| 40 | int i; | ||
| 41 | int num_subauth; | ||
| 42 | __u32 *psub_auth; | ||
| 43 | |||
| 44 | /* validate that we do not go past end of acl */ | ||
| 45 | if (end_of_acl < (char *)pace + sizeof(struct cifs_ace)) { | ||
| 46 | cERROR(1, ("ACL too small to parse ACE")); | ||
| 47 | return; | ||
| 48 | } | ||
| 49 | |||
| 50 | num_subauth = cpu_to_le32(pace->num_subauth); | ||
| 51 | if (num_subauth) { | ||
| 52 | psub_auth = (__u32 *)((char *)pace + sizeof(struct cifs_ace)); | ||
| 53 | #ifdef CONFIG_CIFS_DEBUG2 | ||
| 54 | cFYI(1, ("ACE revision %d num_subauth %d", | ||
| 55 | pace->revision, pace->num_subauth)); | ||
| 56 | for (i = 0; i < num_subauth; ++i) { | ||
| 57 | cFYI(1, ("ACE sub_auth[%d]: 0x%x", i, | ||
| 58 | le32_to_cpu(psub_auth[i]))); | ||
| 59 | } | ||
| 60 | |||
| 61 | /* BB add length check to make sure that we do not have huge | ||
| 62 | num auths and therefore go off the end */ | ||
| 63 | |||
| 64 | cFYI(1, ("RID %d", le32_to_cpu(psub_auth[num_subauth-1]))); | ||
| 65 | #endif | ||
| 66 | } | ||
| 67 | |||
| 68 | return; | ||
| 69 | } | ||
| 70 | |||
| 71 | static void parse_ntace(struct cifs_ntace * pntace, char * end_of_acl) | ||
| 72 | { | ||
| 73 | /* validate that we do not go past end of acl */ | ||
| 74 | if (end_of_acl < (char *)pntace + sizeof(struct cifs_ntace)) { | ||
| 75 | cERROR(1, ("ACL too small to parse NT ACE")); | ||
| 76 | return; | ||
| 77 | } | ||
| 78 | |||
| 79 | #ifdef CONFIG_CIFS_DEBUG2 | ||
| 80 | cFYI(1, ("NTACE type %d flags 0x%x size %d, access Req 0x%x", | ||
| 81 | pntace->type, pntace->flags, pntace->size, | ||
| 82 | pntace->access_req)); | ||
| 83 | #endif | ||
| 84 | return; | ||
| 85 | } | ||
| 86 | |||
| 87 | |||
| 88 | |||
| 89 | static void parse_dacl(struct cifs_acl * pdacl, char * end_of_acl) | ||
| 90 | { | ||
| 91 | int i; | ||
| 92 | int num_aces = 0; | ||
| 93 | int acl_size; | ||
| 94 | char *acl_base; | ||
| 95 | struct cifs_ntace **ppntace; | ||
| 96 | struct cifs_ace **ppace; | ||
| 97 | |||
| 98 | /* BB need to add parm so we can store the SID BB */ | ||
| 99 | |||
| 100 | /* validate that we do not go past end of acl */ | ||
| 101 | if (end_of_acl < (char *)pdacl + pdacl->size) { | ||
| 102 | cERROR(1, ("ACL too small to parse DACL")); | ||
| 103 | return; | ||
| 104 | } | ||
| 105 | |||
| 106 | #ifdef CONFIG_CIFS_DEBUG2 | ||
| 107 | cFYI(1, ("DACL revision %d size %d num aces %d", | ||
| 108 | pdacl->revision, pdacl->size, pdacl->num_aces)); | ||
| 109 | #endif | ||
| 110 | |||
| 111 | acl_base = (char *)pdacl; | ||
| 112 | acl_size = sizeof(struct cifs_acl); | ||
| 113 | |||
| 114 | num_aces = cpu_to_le32(pdacl->num_aces); | ||
| 115 | if (num_aces > 0) { | ||
| 116 | ppntace = kmalloc(num_aces * sizeof(struct cifs_ntace *), | ||
| 117 | GFP_KERNEL); | ||
| 118 | ppace = kmalloc(num_aces * sizeof(struct cifs_ace *), | ||
| 119 | GFP_KERNEL); | ||
| 120 | |||
| 121 | /* cifscred->cecount = pdacl->num_aces; | ||
| 122 | cifscred->ntaces = kmalloc(num_aces * | ||
| 123 | sizeof(struct cifs_ntace *), GFP_KERNEL); | ||
| 124 | cifscred->aces = kmalloc(num_aces * | ||
| 125 | sizeof(struct cifs_ace *), GFP_KERNEL);*/ | ||
| 126 | |||
| 127 | |||
| 128 | for (i = 0; i < num_aces; ++i) { | ||
| 129 | ppntace[i] = (struct cifs_ntace *) | ||
| 130 | (acl_base + acl_size); | ||
| 131 | ppace[i] = (struct cifs_ace *) ((char *)ppntace[i] + | ||
| 132 | sizeof(struct cifs_ntace)); | ||
| 133 | |||
| 134 | parse_ntace(ppntace[i], end_of_acl); | ||
| 135 | parse_ace(ppace[i], end_of_acl); | ||
| 136 | |||
| 137 | /* memcpy((void *)(&(cifscred->ntaces[i])), | ||
| 138 | (void *)ppntace[i], | ||
| 139 | sizeof(struct cifs_ntace)); | ||
| 140 | memcpy((void *)(&(cifscred->aces[i])), | ||
| 141 | (void *)ppace[i], | ||
| 142 | sizeof(struct cifs_ace)); */ | ||
| 143 | |||
| 144 | acl_base = (char *)ppntace[i]; | ||
| 145 | acl_size = cpu_to_le32(ppntace[i]->size); | ||
| 146 | } | ||
| 147 | |||
| 148 | kfree(ppace); | ||
| 149 | kfree(ppntace); | ||
| 150 | } | ||
| 151 | |||
| 152 | return; | ||
| 153 | } | ||
| 154 | |||
| 37 | 155 | ||
| 38 | static int parse_sid(struct cifs_sid *psid, char *end_of_acl) | 156 | static int parse_sid(struct cifs_sid *psid, char *end_of_acl) |
| 39 | { | 157 | { |
| 158 | int i; | ||
| 159 | int num_subauth; | ||
| 160 | __u32 *psub_auth; | ||
| 161 | |||
| 40 | /* BB need to add parm so we can store the SID BB */ | 162 | /* BB need to add parm so we can store the SID BB */ |
| 41 | 163 | ||
| 42 | /* validate that we do not go past end of acl */ | 164 | /* validate that we do not go past end of acl */ |
| 43 | if (end_of_acl < (char *)psid + sizeof(struct cifs_sid)) { | 165 | if (end_of_acl < (char *)psid + sizeof(struct cifs_sid)) { |
| 44 | cERROR(1, ("ACL to small to parse SID")); | 166 | cERROR(1, ("ACL too small to parse SID")); |
| 45 | return -EINVAL; | 167 | return -EINVAL; |
| 46 | } | 168 | } |
| 169 | |||
| 170 | num_subauth = cpu_to_le32(psid->num_subauth); | ||
| 171 | if (num_subauth) { | ||
| 172 | psub_auth = (__u32 *)((char *)psid + sizeof(struct cifs_sid)); | ||
| 47 | #ifdef CONFIG_CIFS_DEBUG2 | 173 | #ifdef CONFIG_CIFS_DEBUG2 |
| 48 | cFYI(1, ("revision %d num_auth %d First subauth 0x%x", | 174 | cFYI(1, ("SID revision %d num_auth %d First subauth 0x%x", |
| 49 | psid->revision, psid->num_subauth, psid->sub_auth[0])); | 175 | psid->revision, psid->num_subauth, psid->sub_auth[0])); |
| 50 | 176 | ||
| 51 | /* BB add length check to make sure that we do not have huge num auths | 177 | for (i = 0; i < num_subauth; ++i) { |
| 52 | and therefore go off the end */ | 178 | cFYI(1, ("SID sub_auth[%d]: 0x%x ", i, |
| 53 | cFYI(1, ("RID 0x%x", le32_to_cpu(psid->sub_auth[psid->num_subauth]))); | 179 | le32_to_cpu(psub_auth[i]))); |
| 180 | } | ||
| 181 | |||
| 182 | /* BB add length check to make sure that we do not have huge | ||
| 183 | num auths and therefore go off the end */ | ||
| 184 | cFYI(1, ("RID 0x%x", | ||
| 185 | le32_to_cpu(psid->sub_auth[psid->num_subauth]))); | ||
| 54 | #endif | 186 | #endif |
| 187 | } | ||
| 188 | |||
| 55 | return 0; | 189 | return 0; |
| 56 | } | 190 | } |
| 57 | 191 | ||
| 192 | |||
| 58 | /* Convert CIFS ACL to POSIX form */ | 193 | /* Convert CIFS ACL to POSIX form */ |
| 59 | int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len) | 194 | int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len) |
| 60 | { | 195 | { |
| 61 | int i, rc; | 196 | int rc; |
| 62 | int num_aces = 0; | ||
| 63 | int acl_size; | ||
| 64 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; | 197 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; |
| 65 | struct cifs_acl *dacl_ptr; /* no need for SACL ptr */ | 198 | struct cifs_acl *dacl_ptr; /* no need for SACL ptr */ |
| 66 | struct cifs_ntace **ppntace; | ||
| 67 | struct cifs_ace **ppace; | ||
| 68 | char *acl_base; | ||
| 69 | char *end_of_acl = ((char *)pntsd) + acl_len; | 199 | char *end_of_acl = ((char *)pntsd) + acl_len; |
| 70 | 200 | ||
| 71 | owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + | 201 | owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + |
| @@ -89,6 +219,8 @@ int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len) | |||
| 89 | if (rc) | 219 | if (rc) |
| 90 | return rc; | 220 | return rc; |
| 91 | 221 | ||
| 222 | parse_dacl(dacl_ptr, end_of_acl); | ||
| 223 | |||
| 92 | /* cifscred->uid = owner_sid_ptr->rid; | 224 | /* cifscred->uid = owner_sid_ptr->rid; |
| 93 | cifscred->gid = group_sid_ptr->rid; | 225 | cifscred->gid = group_sid_ptr->rid; |
| 94 | memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr, | 226 | memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr, |
| @@ -96,46 +228,5 @@ int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len) | |||
| 96 | memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, | 228 | memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, |
| 97 | sizeof (struct cifs_sid)); */ | 229 | sizeof (struct cifs_sid)); */ |
| 98 | 230 | ||
| 99 | num_aces = cpu_to_le32(dacl_ptr->num_aces); | ||
| 100 | cFYI(1, ("num aces %d", num_aces)); | ||
| 101 | if (num_aces > 0) { | ||
| 102 | ppntace = kmalloc(num_aces * sizeof(struct cifs_ntace *), | ||
| 103 | GFP_KERNEL); | ||
| 104 | ppace = kmalloc(num_aces * sizeof(struct cifs_ace *), | ||
| 105 | GFP_KERNEL); | ||
| 106 | |||
| 107 | /* cifscred->cecount = dacl_ptr->num_aces; | ||
| 108 | cifscred->ntaces = kmalloc(num_aces * | ||
| 109 | sizeof(struct cifs_ntace *), GFP_KERNEL); | ||
| 110 | cifscred->aces = kmalloc(num_aces * | ||
| 111 | sizeof(struct cifs_ace *), GFP_KERNEL);*/ | ||
| 112 | |||
| 113 | acl_base = (char *)dacl_ptr; | ||
| 114 | acl_size = sizeof(struct cifs_acl); | ||
| 115 | |||
| 116 | for (i = 0; i < num_aces; ++i) { | ||
| 117 | ppntace[i] = (struct cifs_ntace *) | ||
| 118 | (acl_base + acl_size); | ||
| 119 | ppace[i] = (struct cifs_ace *) | ||
| 120 | ((char *)ppntace[i] + | ||
| 121 | sizeof(struct cifs_ntace)); | ||
| 122 | |||
| 123 | /* memcpy((void *)(&(cifscred->ntaces[i])), | ||
| 124 | (void *)ntace_ptrptr[i], | ||
| 125 | sizeof(struct cifs_ntace)); | ||
| 126 | memcpy((void *)(&(cifscred->aces[i])), | ||
| 127 | (void *)ace_ptrptr[i], | ||
| 128 | sizeof(struct cifs_ace)); */ | ||
| 129 | |||
| 130 | acl_base = (char *)ppntace[i]; | ||
| 131 | acl_size = cpu_to_le32(ppntace[i]->size); | ||
| 132 | #ifdef CONFIG_CIFS_DEBUG2 | ||
| 133 | cFYI(1, ("ACE revision:%d", ppace[i]->revision)); | ||
| 134 | #endif | ||
| 135 | } | ||
| 136 | kfree(ppace); | ||
| 137 | kfree(ppntace); | ||
| 138 | } | ||
| 139 | |||
| 140 | return (0); | 231 | return (0); |
| 141 | } | 232 | } |
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h index 5e7b56738cc5..bf297ea1905a 100644 --- a/fs/cifs/cifsacl.h +++ b/fs/cifs/cifsacl.h | |||
| @@ -44,14 +44,14 @@ struct cifs_acl { | |||
| 44 | __u32 num_aces; | 44 | __u32 num_aces; |
| 45 | } __attribute__((packed)); | 45 | } __attribute__((packed)); |
| 46 | 46 | ||
| 47 | struct cifs_ntace { | 47 | struct cifs_ntace { /* first part of ACE which contains perms */ |
| 48 | __u8 type; | 48 | __u8 type; |
| 49 | __u8 flags; | 49 | __u8 flags; |
| 50 | __u16 size; | 50 | __u16 size; |
| 51 | __u32 access_req; | 51 | __u32 access_req; |
| 52 | } __attribute__((packed)); | 52 | } __attribute__((packed)); |
| 53 | 53 | ||
| 54 | struct cifs_ace { | 54 | struct cifs_ace { /* last part of ACE which includes user info */ |
| 55 | __u8 revision; /* revision level */ | 55 | __u8 revision; /* revision level */ |
| 56 | __u8 num_subauth; | 56 | __u8 num_subauth; |
| 57 | __u8 authority[6]; | 57 | __u8 authority[6]; |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 7dbb79b8dd50..001f0dc7e60d 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
| @@ -310,7 +310,7 @@ extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *, | |||
| 310 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 310 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
| 311 | extern void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key); | 311 | extern void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key); |
| 312 | #endif /* CIFS_WEAK_PW_HASH */ | 312 | #endif /* CIFS_WEAK_PW_HASH */ |
| 313 | extern int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len); | 313 | extern int parse_sec_desc(struct cifs_ntsd *, int); |
| 314 | extern int CIFSSMBCopy(int xid, | 314 | extern int CIFSSMBCopy(int xid, |
| 315 | struct cifsTconInfo *source_tcon, | 315 | struct cifsTconInfo *source_tcon, |
| 316 | const char *fromName, | 316 | const char *fromName, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index a6ff324bc135..90b8f8d64d6e 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
| @@ -34,10 +34,10 @@ | |||
| 34 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
| 35 | #include "cifspdu.h" | 35 | #include "cifspdu.h" |
| 36 | #include "cifsglob.h" | 36 | #include "cifsglob.h" |
| 37 | #include "cifsacl.h" | ||
| 37 | #include "cifsproto.h" | 38 | #include "cifsproto.h" |
| 38 | #include "cifs_unicode.h" | 39 | #include "cifs_unicode.h" |
| 39 | #include "cifs_debug.h" | 40 | #include "cifs_debug.h" |
| 40 | #include "cifsacl.h" | ||
| 41 | 41 | ||
| 42 | #ifdef CONFIG_CIFS_POSIX | 42 | #ifdef CONFIG_CIFS_POSIX |
| 43 | static struct { | 43 | static struct { |
