cifs: fix SID binary to string conversion
authorJeff Layton <jlayton@redhat.com>
Mon, 10 Dec 2012 11:10:44 +0000 (06:10 -0500)
committerSteve French <smfrench@gmail.com>
Tue, 11 Dec 2012 17:48:49 +0000 (11:48 -0600)
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>
fs/cifs/cifsacl.c
fs/cifs/cifsacl.h

index 8dd9212ffef58fb003f6745d5a850669ac1d9969..75c1ee6991433d90886f5d88dcb239f8ba2cafd6 100644 (file)
@@ -94,6 +94,7 @@ sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
        int i, len;
        unsigned int saval;
        char *sidstr, *strptr;
+       unsigned long long id_auth_val;
 
        /* 3 bytes for prefix */
        sidstr = kmalloc(3 + SID_STRING_BASE_SIZE +
@@ -107,12 +108,24 @@ sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
                        sidptr->revision);
        strptr += len;
 
-       for (i = 0; i < NUM_AUTHS; ++i) {
-               if (sidptr->authority[i]) {
-                       len = sprintf(strptr, "-%hhu", sidptr->authority[i]);
-                       strptr += len;
-               }
-       }
+       /* The authority field is a single 48-bit number */
+       id_auth_val = (unsigned long long)sidptr->authority[5];
+       id_auth_val |= (unsigned long long)sidptr->authority[4] << 8;
+       id_auth_val |= (unsigned long long)sidptr->authority[3] << 16;
+       id_auth_val |= (unsigned long long)sidptr->authority[2] << 24;
+       id_auth_val |= (unsigned long long)sidptr->authority[1] << 32;
+       id_auth_val |= (unsigned long long)sidptr->authority[0] << 48;
+
+       /*
+        * MS-DTYP states that if the authority is >= 2^32, then it should be
+        * expressed as a hex value.
+        */
+       if (id_auth_val <= UINT_MAX)
+               len = sprintf(strptr, "-%llu", id_auth_val);
+       else
+               len = sprintf(strptr, "-0x%llx", id_auth_val);
+
+       strptr += len;
 
        for (i = 0; i < sidptr->num_subauth; ++i) {
                saval = le32_to_cpu(sidptr->sub_auth[i]);
index a445405f80d0fb0bc0a4c90543e02c6d4e981ffe..4f3884835267162a55224921f20fd70a7ef2dd5d 100644 (file)
  * u8:  max 3 bytes in decimal
  * u32: max 10 bytes in decimal
  *
- * "S-" + 3 bytes for version field + 4 bytes for each authority field (3 bytes
- * per number + 1 for '-') + NULL terminator.
+ * "S-" + 3 bytes for version field + 15 for authority field + NULL terminator
+ *
+ * For authority field, max is when all 6 values are non-zero and it must be
+ * represented in hex. So "-0x" + 12 hex digits.
  *
  * Add 11 bytes for each subauthority field (10 bytes each + 1 for '-')
  */
-#define SID_STRING_BASE_SIZE (2 + 3 + (4 * NUM_AUTHS) + 1)
+#define SID_STRING_BASE_SIZE (2 + 3 + 15 + 1)
 #define SID_STRING_SUBAUTH_SIZE (11) /* size of a single subauth string */
 
 struct cifs_ntsd {