Fix hash function in acl_xattr to be SHA256, make
authorJeremy Allison <jra@samba.org>
Fri, 24 Jul 2009 21:09:42 +0000 (14:09 -0700)
committerJeremy Allison <jra@samba.org>
Fri, 24 Jul 2009 21:09:42 +0000 (14:09 -0700)
the hash function selectable. Upgrade version.
Compiles but not fully tested yet (coming). Make
vfs_acl_tdb.c compile - this needs updating to
match acl_xattr (also coming soon).
Jeremy.

librpc/gen_ndr/ndr_xattr.c
librpc/gen_ndr/ndr_xattr.h
librpc/gen_ndr/xattr.h
librpc/idl/xattr.idl
source3/modules/vfs_acl_tdb.c
source3/modules/vfs_acl_xattr.c

index d217a00228dd688cc2cb1621205edde571bbde2b..3d09f008644b1bd5b93dff97c511b5ee1735ff93 100644 (file)
@@ -546,7 +546,7 @@ _PUBLIC_ void ndr_print_xattr_DosStreams(struct ndr_print *ndr, const char *name
        ndr->depth--;
 }
 
-_PUBLIC_ enum ndr_err_code ndr_push_security_descriptor_hash(struct ndr_push *ndr, int ndr_flags, const struct security_descriptor_hash *r)
+_PUBLIC_ enum ndr_err_code ndr_push_security_descriptor_hash_v2(struct ndr_push *ndr, int ndr_flags, const struct security_descriptor_hash_v2 *r)
 {
        if (ndr_flags & NDR_SCALARS) {
                NDR_CHECK(ndr_push_align(ndr, 4));
@@ -561,7 +561,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_security_descriptor_hash(struct ndr_push *nd
        return NDR_ERR_SUCCESS;
 }
 
-_PUBLIC_ enum ndr_err_code ndr_pull_security_descriptor_hash(struct ndr_pull *ndr, int ndr_flags, struct security_descriptor_hash *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_security_descriptor_hash_v2(struct ndr_pull *ndr, int ndr_flags, struct security_descriptor_hash_v2 *r)
 {
        uint32_t _ptr_sd;
        TALLOC_CTX *_mem_save_sd_0;
@@ -586,9 +586,9 @@ _PUBLIC_ enum ndr_err_code ndr_pull_security_descriptor_hash(struct ndr_pull *nd
        return NDR_ERR_SUCCESS;
 }
 
-_PUBLIC_ void ndr_print_security_descriptor_hash(struct ndr_print *ndr, const char *name, const struct security_descriptor_hash *r)
+_PUBLIC_ void ndr_print_security_descriptor_hash_v2(struct ndr_print *ndr, const char *name, const struct security_descriptor_hash_v2 *r)
 {
-       ndr_print_struct(ndr, name, "security_descriptor_hash");
+       ndr_print_struct(ndr, name, "security_descriptor_hash_v2");
        ndr->depth++;
        ndr_print_ptr(ndr, "sd", r->sd);
        ndr->depth++;
@@ -600,6 +600,64 @@ _PUBLIC_ void ndr_print_security_descriptor_hash(struct ndr_print *ndr, const ch
        ndr->depth--;
 }
 
+_PUBLIC_ enum ndr_err_code ndr_push_security_descriptor_hash_v3(struct ndr_push *ndr, int ndr_flags, const struct security_descriptor_hash_v3 *r)
+{
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_push_align(ndr, 4));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->sd));
+               NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->hash_type));
+               NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->hash, XATTR_SD_HASH_SIZE));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               if (r->sd) {
+                       NDR_CHECK(ndr_push_security_descriptor(ndr, NDR_SCALARS|NDR_BUFFERS, r->sd));
+               }
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_security_descriptor_hash_v3(struct ndr_pull *ndr, int ndr_flags, struct security_descriptor_hash_v3 *r)
+{
+       uint32_t _ptr_sd;
+       TALLOC_CTX *_mem_save_sd_0;
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_pull_align(ndr, 4));
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_sd));
+               if (_ptr_sd) {
+                       NDR_PULL_ALLOC(ndr, r->sd);
+               } else {
+                       r->sd = NULL;
+               }
+               NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->hash_type));
+               NDR_PULL_ALLOC_N(ndr, r->hash, XATTR_SD_HASH_SIZE);
+               NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->hash, XATTR_SD_HASH_SIZE));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               if (r->sd) {
+                       _mem_save_sd_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->sd, 0);
+                       NDR_CHECK(ndr_pull_security_descriptor(ndr, NDR_SCALARS|NDR_BUFFERS, r->sd));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_sd_0, 0);
+               }
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_security_descriptor_hash_v3(struct ndr_print *ndr, const char *name, const struct security_descriptor_hash_v3 *r)
+{
+       ndr_print_struct(ndr, name, "security_descriptor_hash_v3");
+       ndr->depth++;
+       ndr_print_ptr(ndr, "sd", r->sd);
+       ndr->depth++;
+       if (r->sd) {
+               ndr_print_security_descriptor(ndr, "sd", r->sd);
+       }
+       ndr->depth--;
+       ndr_print_uint16(ndr, "hash_type", r->hash_type);
+       ndr_print_array_uint8(ndr, "hash", r->hash, XATTR_SD_HASH_SIZE);
+       ndr->depth--;
+}
+
 static enum ndr_err_code ndr_push_xattr_NTACL_Info(struct ndr_push *ndr, int ndr_flags, const union xattr_NTACL_Info *r)
 {
        if (ndr_flags & NDR_SCALARS) {
@@ -611,7 +669,11 @@ static enum ndr_err_code ndr_push_xattr_NTACL_Info(struct ndr_push *ndr, int ndr
                        break; }
 
                        case 2: {
-                               NDR_CHECK(ndr_push_unique_ptr(ndr, r->sd_hs));
+                               NDR_CHECK(ndr_push_unique_ptr(ndr, r->sd_hs2));
+                       break; }
+
+                       case 3: {
+                               NDR_CHECK(ndr_push_unique_ptr(ndr, r->sd_hs3));
                        break; }
 
                        default:
@@ -628,8 +690,14 @@ static enum ndr_err_code ndr_push_xattr_NTACL_Info(struct ndr_push *ndr, int ndr
                        break;
 
                        case 2:
-                               if (r->sd_hs) {
-                                       NDR_CHECK(ndr_push_security_descriptor_hash(ndr, NDR_SCALARS|NDR_BUFFERS, r->sd_hs));
+                               if (r->sd_hs2) {
+                                       NDR_CHECK(ndr_push_security_descriptor_hash_v2(ndr, NDR_SCALARS|NDR_BUFFERS, r->sd_hs2));
+                               }
+                       break;
+
+                       case 3:
+                               if (r->sd_hs3) {
+                                       NDR_CHECK(ndr_push_security_descriptor_hash_v3(ndr, NDR_SCALARS|NDR_BUFFERS, r->sd_hs3));
                                }
                        break;
 
@@ -645,7 +713,8 @@ static enum ndr_err_code ndr_pull_xattr_NTACL_Info(struct ndr_pull *ndr, int ndr
        int level;
        uint16_t _level;
        TALLOC_CTX *_mem_save_sd_0;
-       TALLOC_CTX *_mem_save_sd_hs_0;
+       TALLOC_CTX *_mem_save_sd_hs2_0;
+       TALLOC_CTX *_mem_save_sd_hs3_0;
        level = ndr_pull_get_switch_value(ndr, r);
        if (ndr_flags & NDR_SCALARS) {
                NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &_level));
@@ -664,12 +733,22 @@ static enum ndr_err_code ndr_pull_xattr_NTACL_Info(struct ndr_pull *ndr, int ndr
                        break; }
 
                        case 2: {
-                               uint32_t _ptr_sd_hs;
-                               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_sd_hs));
-                               if (_ptr_sd_hs) {
-                                       NDR_PULL_ALLOC(ndr, r->sd_hs);
+                               uint32_t _ptr_sd_hs2;
+                               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_sd_hs2));
+                               if (_ptr_sd_hs2) {
+                                       NDR_PULL_ALLOC(ndr, r->sd_hs2);
+                               } else {
+                                       r->sd_hs2 = NULL;
+                               }
+                       break; }
+
+                       case 3: {
+                               uint32_t _ptr_sd_hs3;
+                               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_sd_hs3));
+                               if (_ptr_sd_hs3) {
+                                       NDR_PULL_ALLOC(ndr, r->sd_hs3);
                                } else {
-                                       r->sd_hs = NULL;
+                                       r->sd_hs3 = NULL;
                                }
                        break; }
 
@@ -689,11 +768,20 @@ static enum ndr_err_code ndr_pull_xattr_NTACL_Info(struct ndr_pull *ndr, int ndr
                        break;
 
                        case 2:
-                               if (r->sd_hs) {
-                                       _mem_save_sd_hs_0 = NDR_PULL_GET_MEM_CTX(ndr);
-                                       NDR_PULL_SET_MEM_CTX(ndr, r->sd_hs, 0);
-                                       NDR_CHECK(ndr_pull_security_descriptor_hash(ndr, NDR_SCALARS|NDR_BUFFERS, r->sd_hs));
-                                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_sd_hs_0, 0);
+                               if (r->sd_hs2) {
+                                       _mem_save_sd_hs2_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                                       NDR_PULL_SET_MEM_CTX(ndr, r->sd_hs2, 0);
+                                       NDR_CHECK(ndr_pull_security_descriptor_hash_v2(ndr, NDR_SCALARS|NDR_BUFFERS, r->sd_hs2));
+                                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_sd_hs2_0, 0);
+                               }
+                       break;
+
+                       case 3:
+                               if (r->sd_hs3) {
+                                       _mem_save_sd_hs3_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                                       NDR_PULL_SET_MEM_CTX(ndr, r->sd_hs3, 0);
+                                       NDR_CHECK(ndr_pull_security_descriptor_hash_v3(ndr, NDR_SCALARS|NDR_BUFFERS, r->sd_hs3));
+                                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_sd_hs3_0, 0);
                                }
                        break;
 
@@ -720,10 +808,19 @@ _PUBLIC_ void ndr_print_xattr_NTACL_Info(struct ndr_print *ndr, const char *name
                break;
 
                case 2:
-                       ndr_print_ptr(ndr, "sd_hs", r->sd_hs);
+                       ndr_print_ptr(ndr, "sd_hs2", r->sd_hs2);
+                       ndr->depth++;
+                       if (r->sd_hs2) {
+                               ndr_print_security_descriptor_hash_v2(ndr, "sd_hs2", r->sd_hs2);
+                       }
+                       ndr->depth--;
+               break;
+
+               case 3:
+                       ndr_print_ptr(ndr, "sd_hs3", r->sd_hs3);
                        ndr->depth++;
-                       if (r->sd_hs) {
-                               ndr_print_security_descriptor_hash(ndr, "sd_hs", r->sd_hs);
+                       if (r->sd_hs3) {
+                               ndr_print_security_descriptor_hash_v3(ndr, "sd_hs3", r->sd_hs3);
                        }
                        ndr->depth--;
                break;
index 610d4b32960298850e5e92aac288506f3c640085..9bf49d00efa1a3d5adf338102a046a14302a0b96 100644 (file)
@@ -24,9 +24,12 @@ void ndr_print_xattr_DosStream(struct ndr_print *ndr, const char *name, const st
 enum ndr_err_code ndr_push_xattr_DosStreams(struct ndr_push *ndr, int ndr_flags, const struct xattr_DosStreams *r);
 enum ndr_err_code ndr_pull_xattr_DosStreams(struct ndr_pull *ndr, int ndr_flags, struct xattr_DosStreams *r);
 void ndr_print_xattr_DosStreams(struct ndr_print *ndr, const char *name, const struct xattr_DosStreams *r);
-enum ndr_err_code ndr_push_security_descriptor_hash(struct ndr_push *ndr, int ndr_flags, const struct security_descriptor_hash *r);
-enum ndr_err_code ndr_pull_security_descriptor_hash(struct ndr_pull *ndr, int ndr_flags, struct security_descriptor_hash *r);
-void ndr_print_security_descriptor_hash(struct ndr_print *ndr, const char *name, const struct security_descriptor_hash *r);
+enum ndr_err_code ndr_push_security_descriptor_hash_v2(struct ndr_push *ndr, int ndr_flags, const struct security_descriptor_hash_v2 *r);
+enum ndr_err_code ndr_pull_security_descriptor_hash_v2(struct ndr_pull *ndr, int ndr_flags, struct security_descriptor_hash_v2 *r);
+void ndr_print_security_descriptor_hash_v2(struct ndr_print *ndr, const char *name, const struct security_descriptor_hash_v2 *r);
+enum ndr_err_code ndr_push_security_descriptor_hash_v3(struct ndr_push *ndr, int ndr_flags, const struct security_descriptor_hash_v3 *r);
+enum ndr_err_code ndr_pull_security_descriptor_hash_v3(struct ndr_pull *ndr, int ndr_flags, struct security_descriptor_hash_v3 *r);
+void ndr_print_security_descriptor_hash_v3(struct ndr_print *ndr, const char *name, const struct security_descriptor_hash_v3 *r);
 void ndr_print_xattr_NTACL_Info(struct ndr_print *ndr, const char *name, const union xattr_NTACL_Info *r);
 enum ndr_err_code ndr_push_xattr_NTACL(struct ndr_push *ndr, int ndr_flags, const struct xattr_NTACL *r);
 enum ndr_err_code ndr_pull_xattr_NTACL(struct ndr_pull *ndr, int ndr_flags, struct xattr_NTACL *r);
index 1ce58f7ec685e04e0cd202a9ac97a55bdd43d550..39f1cb088432de38367444c31d270e445b3e246f 100644 (file)
@@ -17,6 +17,9 @@
 #define XATTR_MAX_STREAM_SIZE  ( 0x4000 )
 #define XATTR_MAX_STREAM_SIZE_TDB      ( 0x100000 )
 #define XATTR_NTACL_NAME       ( "security.NTACL" )
+#define XATTR_SD_HASH_SIZE     ( 64 )
+#define XATTR_SD_HASH_TYPE_NONE        ( 0x0 )
+#define XATTR_SD_HASH_TYPE_SHA256      ( 0x1 )
 struct xattr_DosInfo1 {
        uint32_t attrib;
        uint32_t ea_size;
@@ -75,14 +78,21 @@ struct xattr_DosStreams {
        struct xattr_DosStream *streams;/* [unique,size_is(num_streams)] */
 }/* [public] */;
 
-struct security_descriptor_hash {
+struct security_descriptor_hash_v2 {
        struct security_descriptor *sd;/* [unique] */
        uint8_t hash[16];
 }/* [public] */;
 
+struct security_descriptor_hash_v3 {
+       struct security_descriptor *sd;/* [unique] */
+       uint16_t hash_type;
+       uint8_t *hash;
+}/* [public] */;
+
 union xattr_NTACL_Info {
        struct security_descriptor *sd;/* [unique,case] */
-       struct security_descriptor_hash *sd_hs;/* [unique,case(2)] */
+       struct security_descriptor_hash_v2 *sd_hs2;/* [unique,case(2)] */
+       struct security_descriptor_hash_v3 *sd_hs3;/* [unique,case(3)] */
 }/* [switch_type(uint16)] */;
 
 struct xattr_NTACL {
index 4191ea67ceb7ff0fc9fe08752996dcbb8aa5c8bb..c2b8bb0cc208d0285dbd857ec9bd2469cc65e9c3 100644 (file)
@@ -123,14 +123,25 @@ interface xattr
 
        const char *XATTR_NTACL_NAME = "security.NTACL";
 
+       const int XATTR_SD_HASH_SIZE = 64;
+       const int XATTR_SD_HASH_TYPE_NONE = 0x0;
+       const int XATTR_SD_HASH_TYPE_SHA256 = 0x1;
+
        typedef [public] struct {
                security_descriptor *sd;
                uint8 hash[16];
-       } security_descriptor_hash;
+       } security_descriptor_hash_v2; /* Hash never used in this version. */
+
+       typedef [public] struct {
+               security_descriptor *sd;
+               uint16 hash_type;
+               uint8 hash[XATTR_SD_HASH_SIZE]; /* 64 bytes hash. */
+       } security_descriptor_hash_v3;
 
        typedef [switch_type(uint16)] union {
                [case(1)] security_descriptor *sd;
-               [case(2)] security_descriptor_hash *sd_hs;
+               [case(2)] security_descriptor_hash_v2 *sd_hs2;
+               [case(3)] security_descriptor_hash_v3 *sd_hs3;
        } xattr_NTACL_Info;
 
        typedef [public] struct {
index 5d1bb8728c9851fbea9470860944a507d448da0b..026c5226efad12aa7901861eff387a88e7e2c690 100644 (file)
@@ -156,15 +156,15 @@ static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
                return NT_STATUS_REVISION_MISMATCH;
        }
 
-       *ppdesc = make_sec_desc(ctx, SEC_DESC_REVISION, xacl.info.sd_hs->sd->type | SEC_DESC_SELF_RELATIVE,
+       *ppdesc = make_sec_desc(ctx, SEC_DESC_REVISION, xacl.info.sd_hs2->sd->type | SEC_DESC_SELF_RELATIVE,
                        (security_info & OWNER_SECURITY_INFORMATION)
-                       ? xacl.info.sd_hs->sd->owner_sid : NULL,
+                       ? xacl.info.sd_hs2->sd->owner_sid : NULL,
                        (security_info & GROUP_SECURITY_INFORMATION)
-                       ? xacl.info.sd_hs->sd->group_sid : NULL,
+                       ? xacl.info.sd_hs2->sd->group_sid : NULL,
                        (security_info & SACL_SECURITY_INFORMATION)
-                       ? xacl.info.sd_hs->sd->sacl : NULL,
+                       ? xacl.info.sd_hs2->sd->sacl : NULL,
                        (security_info & DACL_SECURITY_INFORMATION)
-                       ? xacl.info.sd_hs->sd->dacl : NULL,
+                       ? xacl.info.sd_hs2->sd->dacl : NULL,
                        &sd_size);
 
        TALLOC_FREE(xacl.info.sd);
@@ -237,17 +237,17 @@ static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
 static NTSTATUS create_acl_blob(const struct security_descriptor *psd, DATA_BLOB *pblob)
 {
        struct xattr_NTACL xacl;
-       struct security_descriptor_hash sd_hs;
+       struct security_descriptor_hash_v2 sd_hs2;
        enum ndr_err_code ndr_err;
        TALLOC_CTX *ctx = talloc_tos();
 
        ZERO_STRUCT(xacl);
-       ZERO_STRUCT(sd_hs);
+       ZERO_STRUCT(sd_hs2);
 
        xacl.version = 2;
-       xacl.info.sd_hs = &sd_hs;
-       xacl.info.sd_hs->sd = CONST_DISCARD(struct security_descriptor *, psd);
-       memset(&xacl.info.sd_hs->hash[0], '\0', 16);
+       xacl.info.sd_hs2 = &sd_hs2;
+       xacl.info.sd_hs2->sd = CONST_DISCARD(struct security_descriptor *, psd);
+       memset(&xacl.info.sd_hs2->hash[0], '\0', 16);
 
        ndr_err = ndr_push_struct_blob(
                        pblob, ctx, NULL, &xacl,
index 3646b659dcd9929c2cb71d481410edd4403b3173..381c374decbc0d4362987cdb1a6eac3a2c9d110e 100644 (file)
 #include "includes.h"
 #include "librpc/gen_ndr/xattr.h"
 #include "librpc/gen_ndr/ndr_xattr.h"
+#include "../lib/crypto/crypto.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_VFS
 
 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
                        DATA_BLOB *pblob,
-                       uint8_t hash[16]);
+                       uint16_t hash_type,
+                       uint8_t hash[XATTR_SD_HASH_SIZE]);
 
 #define HASH_SECURITY_INFO (OWNER_SECURITY_INFORMATION | \
                                GROUP_SECURITY_INFORMATION | \
@@ -40,21 +42,23 @@ static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
  Hash a security descriptor.
 *******************************************************************/
 
-static NTSTATUS hash_sd(struct security_descriptor *psd,
-                       uint8_t hash[16])
+static NTSTATUS hash_sd_sha256(struct security_descriptor *psd,
+                       uint8_t hash[XATTR_SD_HASH_SIZE])
 {
        DATA_BLOB blob;
-       struct MD5Context tctx;
+       SHA256_CTX tctx;
        NTSTATUS status;
 
-       memset(hash, '\0', 16);
-       status = create_acl_blob(psd, &blob, hash);
+       memset(hash, '\0', XATTR_SD_HASH_SIZE);
+       status = create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
-       MD5Init(&tctx);
-       MD5Update(&tctx, blob.data, blob.length);
-       MD5Final(hash, &tctx);
+
+       SHA256_Init(&tctx);
+       SHA256_Update(&tctx, blob.data, blob.length);
+       SHA256_Final(hash, &tctx);
+
        return NT_STATUS_OK;
 }
 
@@ -63,9 +67,9 @@ static NTSTATUS hash_sd(struct security_descriptor *psd,
 *******************************************************************/
 
 static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
-                               uint32 security_info,
                                struct security_descriptor **ppdesc,
-                               uint8_t hash[16])
+                               uint16_t *p_hash_type,
+                               uint8_t hash[XATTR_SD_HASH_SIZE])
 {
        TALLOC_CTX *ctx = talloc_tos();
        struct xattr_NTACL xacl;
@@ -81,22 +85,35 @@ static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
                return ndr_map_error2ntstatus(ndr_err);;
        }
 
-       if (xacl.version != 2) {
-               return NT_STATUS_REVISION_MISMATCH;
+       switch (xacl.version) {
+               case 2:
+                       *ppdesc = make_sec_desc(ctx, SEC_DESC_REVISION,
+                                       xacl.info.sd_hs2->sd->type | SEC_DESC_SELF_RELATIVE,
+                                       xacl.info.sd_hs2->sd->owner_sid,
+                                       xacl.info.sd_hs2->sd->group_sid,
+                                       xacl.info.sd_hs2->sd->sacl,
+                                       xacl.info.sd_hs2->sd->dacl,
+                                       &sd_size);
+                       /* No hash - null out. */
+                       *p_hash_type = XATTR_SD_HASH_TYPE_NONE;
+                       memset(hash, '\0', XATTR_SD_HASH_SIZE);
+                       break;
+               case 3:
+                       *ppdesc = make_sec_desc(ctx, SEC_DESC_REVISION,
+                                       xacl.info.sd_hs3->sd->type | SEC_DESC_SELF_RELATIVE,
+                                       xacl.info.sd_hs3->sd->owner_sid,
+                                       xacl.info.sd_hs3->sd->group_sid,
+                                       xacl.info.sd_hs3->sd->sacl,
+                                       xacl.info.sd_hs3->sd->dacl,
+                                       &sd_size);
+                       *p_hash_type = xacl.info.sd_hs3->hash_type;
+                       /* Current version 3. */
+                       memcpy(hash, xacl.info.sd_hs3->hash, XATTR_SD_HASH_SIZE);
+                       break;
+               default:
+                       return NT_STATUS_REVISION_MISMATCH;
        }
 
-       *ppdesc = make_sec_desc(ctx, SEC_DESC_REVISION, xacl.info.sd_hs->sd->type | SEC_DESC_SELF_RELATIVE,
-                       (security_info & OWNER_SECURITY_INFORMATION)
-                       ? xacl.info.sd_hs->sd->owner_sid : NULL,
-                       (security_info & GROUP_SECURITY_INFORMATION)
-                       ? xacl.info.sd_hs->sd->group_sid : NULL,
-                       (security_info & SACL_SECURITY_INFORMATION)
-                       ? xacl.info.sd_hs->sd->sacl : NULL,
-                       (security_info & DACL_SECURITY_INFORMATION)
-                       ? xacl.info.sd_hs->sd->dacl : NULL,
-                       &sd_size);
-
-       memcpy(hash, xacl.info.sd_hs->hash, 16);
        TALLOC_FREE(xacl.info.sd);
 
        return (*ppdesc != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
@@ -166,20 +183,22 @@ static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
 
 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
                        DATA_BLOB *pblob,
-                       uint8_t hash[16])
+                       uint16_t hash_type,
+                       uint8_t hash[XATTR_SD_HASH_SIZE])
 {
        struct xattr_NTACL xacl;
-       struct security_descriptor_hash sd_hs;
+       struct security_descriptor_hash_v3 sd_hs3;
        enum ndr_err_code ndr_err;
        TALLOC_CTX *ctx = talloc_tos();
 
        ZERO_STRUCT(xacl);
-       ZERO_STRUCT(sd_hs);
+       ZERO_STRUCT(sd_hs3);
 
-       xacl.version = 2;
-       xacl.info.sd_hs = &sd_hs;
-       xacl.info.sd_hs->sd = CONST_DISCARD(struct security_descriptor *, psd);
-       memcpy(&xacl.info.sd_hs->hash[0], hash, 16);
+       xacl.version = 3;
+       xacl.info.sd_hs3 = &sd_hs3;
+       xacl.info.sd_hs3->sd = CONST_DISCARD(struct security_descriptor *, psd);
+       xacl.info.sd_hs3->hash_type = hash_type;
+       memcpy(&xacl.info.sd_hs3->hash[0], hash, XATTR_SD_HASH_SIZE);
 
        ndr_err = ndr_push_struct_blob(
                        pblob, ctx, NULL, &xacl,
@@ -274,13 +293,14 @@ static NTSTATUS store_acl_blob_pathname(vfs_handle_struct *handle,
 static NTSTATUS get_nt_acl_xattr_internal(vfs_handle_struct *handle,
                                        files_struct *fsp,
                                        const char *name,
-                                       uint32 security_info,
+                                       uint32_t security_info,
                                        struct security_descriptor **ppdesc)
 {
        DATA_BLOB blob;
        NTSTATUS status;
-       uint8_t hash[16];
-       uint8_t hash_tmp[16];
+       uint16_t hash_type;
+       uint8_t hash[XATTR_SD_HASH_SIZE];
+       uint8_t hash_tmp[XATTR_SD_HASH_SIZE];
        struct security_descriptor *pdesc_next = NULL;
 
        if (fsp && name == NULL) {
@@ -295,18 +315,23 @@ static NTSTATUS get_nt_acl_xattr_internal(vfs_handle_struct *handle,
                return status;
        }
 
-       status = parse_acl_blob(&blob, security_info, ppdesc, &hash[0]);
+       status = parse_acl_blob(&blob, ppdesc,
+                               &hash_type, &hash[0]);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(10, ("parse_acl_blob returned %s\n",
                                nt_errstr(status)));
                return status;
        }
 
-       /* If there was no stored hash, don't check. */
-       memset(&hash_tmp[0], '\0', 16);
-       if (memcmp(&hash[0], &hash_tmp[0], 16) == 0) {
-               /* No hash, goto return blob sd. */
-               goto out;
+       /* Ensure the hash type is one we know. */
+       switch (hash_type) {
+               case XATTR_SD_HASH_TYPE_NONE:
+                       /* No hash, goto return blob sd. */
+                       goto out;
+               case XATTR_SD_HASH_TYPE_SHA256:
+                       break;
+               default:
+                       return NT_STATUS_REVISION_MISMATCH;
        }
 
        /* Get the full underlying sd, then hash. */
@@ -326,12 +351,12 @@ static NTSTATUS get_nt_acl_xattr_internal(vfs_handle_struct *handle,
                goto out;
        }
 
-       status = hash_sd(pdesc_next, hash_tmp);
+       status = hash_sd_sha256(pdesc_next, hash_tmp);
        if (!NT_STATUS_IS_OK(status)) {
                goto out;
        }
 
-       if (memcmp(&hash[0], &hash_tmp[0], 16) == 0) {
+       if (memcmp(&hash[0], &hash_tmp[0], XATTR_SD_HASH_SIZE) == 0) {
                TALLOC_FREE(pdesc_next);
                /* Hash matches, return blob sd. */
                goto out;
@@ -357,6 +382,19 @@ static NTSTATUS get_nt_acl_xattr_internal(vfs_handle_struct *handle,
 
   out:
 
+       if (!(security_info & OWNER_SECURITY_INFORMATION)) {
+               (*ppdesc)->owner_sid = NULL;
+       }
+       if (!(security_info & GROUP_SECURITY_INFORMATION)) {
+               (*ppdesc)->group_sid = NULL;
+       }
+       if (!(security_info & DACL_SECURITY_INFORMATION)) {
+               (*ppdesc)->dacl = NULL;
+       }
+       if (!(security_info & SACL_SECURITY_INFORMATION)) {
+               (*ppdesc)->sacl = NULL;
+       }
+
        TALLOC_FREE(blob.data);
        return status;
 }
@@ -420,7 +458,7 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
        DATA_BLOB blob;
        size_t size;
        char *parent_name;
-       uint8_t hash[16];
+       uint8_t hash[XATTR_SD_HASH_SIZE];
 
        if (!parent_dirname(ctx, smb_fname->base_name, &parent_name, NULL)) {
                return NT_STATUS_NO_MEMORY;
@@ -511,11 +549,11 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
                return status;
        }
 
-       status = hash_sd(pdesc_next, hash);
+       status = hash_sd_sha256(pdesc_next, hash);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
-       status = create_acl_blob(psd, &blob, hash);
+       status = create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -630,7 +668,7 @@ static int mkdir_acl_xattr(vfs_handle_struct *handle, const char *path, mode_t m
 *********************************************************************/
 
 static NTSTATUS fget_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
-        uint32 security_info, struct security_descriptor **ppdesc)
+        uint32_t security_info, struct security_descriptor **ppdesc)
 {
        return get_nt_acl_xattr_internal(handle, fsp,
                                NULL, security_info, ppdesc);
@@ -641,7 +679,7 @@ static NTSTATUS fget_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
 *********************************************************************/
 
 static NTSTATUS get_nt_acl_xattr(vfs_handle_struct *handle,
-        const char *name, uint32 security_info, struct security_descriptor **ppdesc)
+        const char *name, uint32_t security_info, struct security_descriptor **ppdesc)
 {
        return get_nt_acl_xattr_internal(handle, NULL,
                                name, security_info, ppdesc);
@@ -652,12 +690,12 @@ static NTSTATUS get_nt_acl_xattr(vfs_handle_struct *handle,
 *********************************************************************/
 
 static NTSTATUS fset_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
-        uint32 security_info_sent, const struct security_descriptor *psd)
+        uint32_t security_info_sent, const struct security_descriptor *psd)
 {
        NTSTATUS status;
        DATA_BLOB blob;
        struct security_descriptor *pdesc_next = NULL;
-       uint8_t hash[16];
+       uint8_t hash[XATTR_SD_HASH_SIZE];
 
        if (DEBUGLEVEL >= 10) {
                DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n",
@@ -712,7 +750,7 @@ static NTSTATUS fset_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
                return status;
        }
 
-       status = hash_sd(pdesc_next, hash);
+       status = hash_sd_sha256(pdesc_next, hash);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -741,7 +779,7 @@ static NTSTATUS fset_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
                NDR_PRINT_DEBUG(security_descriptor,
                        CONST_DISCARD(struct security_descriptor *,psd));
        }
-       create_acl_blob(psd, &blob, hash);
+       create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
        store_acl_blob_fsp(handle, fsp, &blob);
 
        return NT_STATUS_OK;