aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2012-12-10 06:10:44 -0500
committerSteve French <smfrench@gmail.com>2012-12-11 12:48:49 -0500
commit193cdd8a293007d1a1ad252cf66b2dc5b793d2d0 (patch)
tree2bfefe36dd1c6ca0d42fc35b00bf323b8d41e5b3 /fs/cifs
parent6d8b59d712e95d257ee16f80b579677e5e1bf33c (diff)
cifs: fix SID binary to string conversion
The authority fields are supposed to be represented by a single 48-bit value. It's also supposed to represent the value as hex if it's equal to or greater than 2^32. This is documented in MS-DTYP, section 2.4.2.1. Also, fix up the max string length to account for this fix. Acked-by: Pavel Shilovsky <piastry@etersoft.ru> Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsacl.c25
-rw-r--r--fs/cifs/cifsacl.h8
2 files changed, 24 insertions, 9 deletions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 8dd9212ffef5..75c1ee699143 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -94,6 +94,7 @@ sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
94 int i, len; 94 int i, len;
95 unsigned int saval; 95 unsigned int saval;
96 char *sidstr, *strptr; 96 char *sidstr, *strptr;
97 unsigned long long id_auth_val;
97 98
98 /* 3 bytes for prefix */ 99 /* 3 bytes for prefix */
99 sidstr = kmalloc(3 + SID_STRING_BASE_SIZE + 100 sidstr = kmalloc(3 + SID_STRING_BASE_SIZE +
@@ -107,12 +108,24 @@ sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
107 sidptr->revision); 108 sidptr->revision);
108 strptr += len; 109 strptr += len;
109 110
110 for (i = 0; i < NUM_AUTHS; ++i) { 111 /* The authority field is a single 48-bit number */
111 if (sidptr->authority[i]) { 112 id_auth_val = (unsigned long long)sidptr->authority[5];
112 len = sprintf(strptr, "-%hhu", sidptr->authority[i]); 113 id_auth_val |= (unsigned long long)sidptr->authority[4] << 8;
113 strptr += len; 114 id_auth_val |= (unsigned long long)sidptr->authority[3] << 16;
114 } 115 id_auth_val |= (unsigned long long)sidptr->authority[2] << 24;
115 } 116 id_auth_val |= (unsigned long long)sidptr->authority[1] << 32;
117 id_auth_val |= (unsigned long long)sidptr->authority[0] << 48;
118
119 /*
120 * MS-DTYP states that if the authority is >= 2^32, then it should be
121 * expressed as a hex value.
122 */
123 if (id_auth_val <= UINT_MAX)
124 len = sprintf(strptr, "-%llu", id_auth_val);
125 else
126 len = sprintf(strptr, "-0x%llx", id_auth_val);
127
128 strptr += len;
116 129
117 for (i = 0; i < sidptr->num_subauth; ++i) { 130 for (i = 0; i < sidptr->num_subauth; ++i) {
118 saval = le32_to_cpu(sidptr->sub_auth[i]); 131 saval = le32_to_cpu(sidptr->sub_auth[i]);
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h
index a445405f80d0..4f3884835267 100644
--- a/fs/cifs/cifsacl.h
+++ b/fs/cifs/cifsacl.h
@@ -55,12 +55,14 @@
55 * u8: max 3 bytes in decimal 55 * u8: max 3 bytes in decimal
56 * u32: max 10 bytes in decimal 56 * u32: max 10 bytes in decimal
57 * 57 *
58 * "S-" + 3 bytes for version field + 4 bytes for each authority field (3 bytes 58 * "S-" + 3 bytes for version field + 15 for authority field + NULL terminator
59 * per number + 1 for '-') + NULL terminator. 59 *
60 * For authority field, max is when all 6 values are non-zero and it must be
61 * represented in hex. So "-0x" + 12 hex digits.
60 * 62 *
61 * Add 11 bytes for each subauthority field (10 bytes each + 1 for '-') 63 * Add 11 bytes for each subauthority field (10 bytes each + 1 for '-')
62 */ 64 */
63#define SID_STRING_BASE_SIZE (2 + 3 + (4 * NUM_AUTHS) + 1) 65#define SID_STRING_BASE_SIZE (2 + 3 + 15 + 1)
64#define SID_STRING_SUBAUTH_SIZE (11) /* size of a single subauth string */ 66#define SID_STRING_SUBAUTH_SIZE (11) /* size of a single subauth string */
65 67
66struct cifs_ntsd { 68struct cifs_ntsd {