From 6dc1b7d9e533379133857629bb9c09e1045a9020 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Mon, 7 Aug 2017 02:28:35 +0200
Subject: [PATCH] server: Implement token integrity level.

---
 dlls/ntdll/unix/security.c | 23 ++++++++++++++---------
 server/protocol.def        |  7 +++++++
 server/token.c             | 30 +++++++++++++++++++++++++++---
 3 files changed, 48 insertions(+), 12 deletions(-)

diff --git a/dlls/ntdll/unix/security.c b/dlls/ntdll/unix/security.c
index 03a81afa46e..f0057116dee 100644
--- a/dlls/ntdll/unix/security.c
+++ b/dlls/ntdll/unix/security.c
@@ -172,7 +172,7 @@ NTSTATUS WINAPI NtQueryInformationToken( HANDLE token, TOKEN_INFORMATION_CLASS c
         0,    /* TokenAccessInformation */
         0,    /* TokenVirtualizationAllowed */
         sizeof(DWORD), /* TokenVirtualizationEnabled */
-        sizeof(TOKEN_MANDATORY_LABEL) + sizeof(SID), /* TokenIntegrityLevel [sizeof(SID) includes one SubAuthority] */
+        0,    /* TokenIntegrityLevel */
         0,    /* TokenUIAccess */
         0,    /* TokenMandatoryPolicy */
         0,    /* TokenLogonSid */
@@ -428,18 +428,23 @@ NTSTATUS WINAPI NtQueryInformationToken( HANDLE token, TOKEN_INFORMATION_CLASS c
         break;
 
     case TokenIntegrityLevel:
+        SERVER_START_REQ( get_token_integrity )
         {
-            /* report always "S-1-16-12288" (high mandatory level) for now */
-            static const SID high_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
-                                                            {SECURITY_MANDATORY_HIGH_RID}};
-
             TOKEN_MANDATORY_LABEL *tml = info;
-            PSID psid = tml + 1;
+            PSID sid = tml + 1;
+            DWORD sid_len = length < sizeof(*tml) ? 0 : length - sizeof(*tml);
 
-            tml->Label.Sid = psid;
-            tml->Label.Attributes = SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED;
-            memcpy( psid, &high_level, sizeof(SID) );
+            req->handle = wine_server_obj_handle( token );
+            wine_server_set_reply( req, sid, sid_len );
+            status = wine_server_call( req );
+            if (retlen) *retlen = reply->sid_len + sizeof(*tml);
+            if (status == STATUS_SUCCESS)
+            {
+                tml->Label.Sid = sid;
+                tml->Label.Attributes = SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED;
+            }
         }
+        SERVER_END_REQ;
         break;
 
     case TokenAppContainerSid:
diff --git a/server/protocol.def b/server/protocol.def
index 84f0b577d72..4d37a0df348 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3296,6 +3296,13 @@ enum caret_state
     VARARG(sid,SID);              /* the sid specified by which_sid from the token */
 @END
 
+@REQ(get_token_integrity)
+    obj_handle_t    handle;       /* handle to the token */
+@REPLY
+    data_size_t     sid_len;      /* length needed to store sid */
+    VARARG(sid,SID);              /* the integrity sid */
+@END
+
 @REQ(get_token_groups)
     obj_handle_t    handle;       /* handle to the token */
 @REPLY
diff --git a/server/token.c b/server/token.c
index 7c510fbdad9..d267991f751 100644
--- a/server/token.c
+++ b/server/token.c
@@ -111,6 +111,7 @@ struct token
     TOKEN_SOURCE   source;          /* source of the token */
     int            impersonation_level; /* impersonation level this token is capable of if non-primary token */
     TOKEN_ELEVATION_TYPE elevation; /* elevation level */
+    const SID     *integrity;       /* token integrity */
 };
 
 struct privilege
@@ -553,7 +554,8 @@ static struct token *create_token( unsigned primary, const SID *user,
                                    const LUID_AND_ATTRIBUTES *privs, unsigned int priv_count,
                                    const ACL *default_dacl, TOKEN_SOURCE source,
                                    const luid_t *modified_id,
-                                   int impersonation_level, TOKEN_ELEVATION_TYPE elevation )
+                                   int impersonation_level, TOKEN_ELEVATION_TYPE elevation,
+                                   const SID *integrity )
 {
     struct token *token = alloc_object( &token_ops );
     if (token)
@@ -637,6 +639,7 @@ static struct token *create_token( unsigned primary, const SID *user,
         }
 
         token->source = source;
+        token->integrity = integrity;
     }
     return token;
 }
@@ -692,7 +695,8 @@ struct token *token_duplicate( struct token *src_token, unsigned primary,
                           NULL, 0, src_token->default_dacl,
                           src_token->source, modified_id,
                           impersonation_level,
-                          src_token->elevation );
+                          src_token->elevation,
+                          src_token->integrity );
     if (!token) return token;
 
     /* copy groups */
@@ -898,7 +902,7 @@ struct token *token_create_admin( void )
         static const TOKEN_SOURCE admin_source = {"SeMgr", {0, 0}};
         token = create_token( TRUE, user_sid, admin_groups, ARRAY_SIZE( admin_groups ),
                               admin_privs, ARRAY_SIZE( admin_privs ), default_dacl,
-                              admin_source, NULL, -1, TokenElevationTypeFull );
+                              admin_source, NULL, -1, TokenElevationTypeFull, &high_label_sid );
         /* we really need a primary group */
         assert( token->primary_group );
     }
@@ -1532,6 +1536,26 @@ DECL_HANDLER(get_token_sid)
     }
 }
 
+/* retrieves the integrity sid */
+DECL_HANDLER(get_token_integrity)
+{
+    struct token *token;
+
+    reply->sid_len = 0;
+
+    if ((token = (struct token *)get_handle_obj( current->process, req->handle,
+                                                 TOKEN_QUERY,
+                                                 &token_ops )))
+    {
+        reply->sid_len = security_sid_len( token->integrity );
+        if (reply->sid_len <= get_reply_max_size())
+            set_reply_data( token->integrity, reply->sid_len );
+        else
+            set_error( STATUS_BUFFER_TOO_SMALL );
+        release_object( token );
+    }
+}
+
 /* retrieves the groups that the user represented by the token belongs to */
 DECL_HANDLER(get_token_groups)
 {
-- 
2.27.0

