Re: [PATCH setup 06/11] Enable SeCreateSymbolicLink privilege

2021-09-14 Thread Jon Turney

On 11/08/2021 09:46, Corinna Vinschen via Cygwin-apps wrote:

On Aug 10 18:02, Jon Turney wrote:

I'm not sure if SeCreateSymbolicLink privilege can get removed by UAC
filtering, but to make sure to enable it, if we can.


I'm not sure this is required.  This is one of the privileges which is
enabled automatically on usage if it's present in the token and not
marked as "deny only".  UAC removes the privilege entirely from the
token, so you can't enable it in that case.


Yes, looking into this nonsense a bit more, that's correct.

I'll change this to just log the availability of that privilege.



Re: [PATCH setup 06/11] Enable SeCreateSymbolicLink privilege

2021-08-11 Thread Corinna Vinschen via Cygwin-apps
On Aug 10 18:02, Jon Turney wrote:
> I'm not sure if SeCreateSymbolicLink privilege can get removed by UAC
> filtering, but to make sure to enable it, if we can.

I'm not sure this is required.  This is one of the privileges which is
enabled automatically on usage if it's present in the token and not
marked as "deny only".  UAC removes the privilege entirely from the
token, so you can't enable it in that case.


Corinna


[PATCH setup 06/11] Enable SeCreateSymbolicLink privilege

2021-08-10 Thread Jon Turney
I'm not sure if SeCreateSymbolicLink privilege can get removed by UAC
filtering, but to make sure to enable it, if we can.

Also report if it's available to log.
---
 win32.cc | 58 
 win32.h  |  2 ++
 2 files changed, 60 insertions(+)

diff --git a/win32.cc b/win32.cc
index 8ee424f..6455384 100644
--- a/win32.cc
+++ b/win32.cc
@@ -280,6 +280,28 @@ NTSecurity::setBackupPrivileges ()
 }
 }
 
+void
+NTSecurity::setSymlinkPrivilege ()
+{
+  LUID symlink;
+  if (!LookupPrivilegeValue (NULL, SE_CREATE_SYMBOLIC_LINK_NAME, ))
+NoteFailedAPI ("LookupPrivilegeValue");
+
+  PTOKEN_PRIVILEGES new_priv;
+  new_priv = (PTOKEN_PRIVILEGES) alloca (sizeof (TOKEN_PRIVILEGES));
+  new_priv->PrivilegeCount = 1;
+  new_priv->Privileges[0].Luid = symlink;
+  new_priv->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+  if (!AdjustTokenPrivileges (token.theHANDLE (), FALSE, new_priv,
+  0, NULL, NULL))
+NoteFailedAPI ("AdjustTokenPrivileges");
+  else if (GetLastError () == ERROR_NOT_ALL_ASSIGNED)
+Log (LOG_TIMESTAMP) << "User has NO symlink creation right" << endLog;
+  else
+Log (LOG_TIMESTAMP) << "User has symlink creation right" << endLog;
+}
+
 void
 NTSecurity::resetPrimaryGroup ()
 {
@@ -321,6 +343,9 @@ NTSecurity::setDefaultSecurity (bool isAdmin)
   /* Set backup and restore privileges if available. */
   setBackupPrivileges ();
 
+  /* Set symlink creation privilege, if available. */
+  setSymlinkPrivilege ();
+
   /* If initializing the well-known SIDs didn't work, we're finished here. */
   if (!wellKnownSIDsinitialized ())
 return;
@@ -371,6 +396,39 @@ NTSecurity::isRunAsAdmin ()
   return (is_run_as_admin == TRUE);
 }
 
+bool
+NTSecurity::hasSymlinkCreationRights ()
+{
+  LUID symlink;
+  if (!LookupPrivilegeValue (NULL, SE_CREATE_SYMBOLIC_LINK_NAME, ))
+{
+  NoteFailedAPI ("LookupPrivilegeValue");
+  return FALSE;
+}
+
+  DWORD size;
+  GetTokenInformation (token.theHANDLE (), TokenPrivileges, NULL, 0, );
+  /* Will fail ERROR_INSUFFICIENT_BUFFER, but updates size */
+
+  TOKEN_PRIVILEGES *privileges = (TOKEN_PRIVILEGES *)alloca(size);
+  if (!GetTokenInformation (token.theHANDLE (), TokenPrivileges, privileges,
+size, ))
+{
+  NoteFailedAPI ("GetTokenInformation(privileges)");
+  return FALSE;
+}
+
+  unsigned int i;
+  for (i = 0; i < privileges->PrivilegeCount; i++)
+{
+  if (memcmp(>Privileges[i].Luid, , sizeof(LUID)) == 0)
+{
+  return (privileges->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED);
+}
+}
+
+  return FALSE;
+}
 
 VersionInfo::VersionInfo ()
 {
diff --git a/win32.h b/win32.h
index daebf2e..e498077 100644
--- a/win32.h
+++ b/win32.h
@@ -132,12 +132,14 @@ public:
   void initialiseWellKnownSIDs ();
   void setDefaultSecurity(bool isAdmin);
   bool isRunAsAdmin ();
+  bool hasSymlinkCreationRights ();
 private:
   void NoteFailedAPI (const std::string &);
   bool wellKnownSIDsinitialized () const { return _wellKnownSIDsinitialized; }
   void wellKnownSIDsinitialized (bool b) { _wellKnownSIDsinitialized = b; }
   void setDefaultDACL ();
   void setBackupPrivileges ();
+  void setSymlinkPrivilege ();
 
   SIDWrapper nullSID, everyOneSID, administratorsSID, usersSID,
 cr_ownerSID, cr_groupSID;
-- 
2.32.0