This is the mail archive of the cygwin-patches mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [Patch] Allow to disable root privileges with CYGWIN=noroot


Corinna Vinschen wrote:
Patch checked in.

Thanks.


Thanks for doing this.  Would you have fun to provide a tool for the
net distro which uses this feature?


A first try is attached.


cygdrop command ... -- Drop admin group and most privileges and run command.
cygdrop -b command ... -- same, but keep SeBackupPrivilege (~ R/O admin :-)

Christian

// Drop admin privileges and exec() a command.

#define WINVER 0x0500
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <windows.h>
#include <sys/cygwin.h>

#define SIDSTRUCT(name, auth, n, subauth...) \
  static struct  { \
    BYTE Revision; \
    BYTE SubAuthorityCount; \
    SID_IDENTIFIER_AUTHORITY IdentifierAuthority; \
    DWORD SubAuthority[n]; \
  } name = {SID_REVISION, n, {auth}, {subauth}}

static int
pwinerror(const char * msg)
{
  fprintf(stderr, "%s: %d\n", msg, (int)GetLastError());
  return 1;
}

int
main(int argc, char **argv)
{
  int ac = 1;
  bool b_flag = false;
  if (ac < argc && !strcmp (argv[ac], "-b"))
    {
      b_flag = true;
      ac++;
    }
  if (ac >= argc || argv[ac][0] == '-')
    {
      printf ("Usage: %s [-b] COMMAND [ARG ...]\n"
	      "Drop admin privileges and exec COMMAND\n"
	      "\n"
	      "    -b    keep SeBackupPrivilege\n",
	      argv[0]);
      return 1;
    }

  // Get token
  HANDLE ptoken;
  if(!OpenProcessToken (GetCurrentProcess (), TOKEN_ALL_ACCESS, &ptoken))
    return pwinerror("OpenProcessToken");

  // Get privileges
  const int max_privs = 100;
  char priv_buf[sizeof (DWORD) + sizeof (LUID_AND_ATTRIBUTES) * max_privs];
  TOKEN_PRIVILEGES * privs = (TOKEN_PRIVILEGES *)priv_buf;
  DWORD size = 0;
  if (!GetTokenInformation (ptoken, TokenPrivileges, privs, sizeof(priv_buf), &size))
    return pwinerror ("GetTokenInformation");

  // Collect luids of privileges to disable
  LUID_AND_ATTRIBUTES disable_privs[max_privs];
  int num_disable_privs = 0;
  for (unsigned i = 0; i < privs->PrivilegeCount; i++)
    {
      char name[100];
      size = sizeof(name);
      if (!LookupPrivilegeName (NULL, &privs->Privileges[i].Luid, name, &size))
	return pwinerror ("LookupPrivilegeName");
      if (!strcmp (name, SE_CHANGE_NOTIFY_NAME))
	continue;
      if (!strcmp (name, SE_CREATE_GLOBAL_NAME))
	continue;
      if (b_flag && !strcmp (name, SE_BACKUP_NAME))
	continue;
      disable_privs[num_disable_privs].Luid = privs->Privileges[i].Luid;
      disable_privs[num_disable_privs].Attributes = 0;
      num_disable_privs++;
    }

  // Set SIDs to disable
  const int num_disable_sids = 1;
  SID_AND_ATTRIBUTES disable_sids[num_disable_sids];

  SIDSTRUCT(admins, SECURITY_NT_AUTHORITY, 2, // S-1-5-32-544
            SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS);
  disable_sids[0].Sid = &admins;
  disable_sids[0].Attributes = 0;

  // Create restricted token
  HANDLE rtoken;
  if (!CreateRestrictedToken (ptoken, 0,
                              num_disable_sids, disable_sids,
                              num_disable_privs, disable_privs,
                              0, 0, &rtoken))
    return pwinerror("CreateRestrictedToken");

  CloseHandle (ptoken);

  // Change to restricted token
  if (cygwin_internal (CW_SET_EXTERNAL_TOKEN, rtoken, CW_TOKEN_RESTRICTED))
    {
      perror ("cygwin_internal (CW_SET_EXTERNAL_TOKEN,...)");
      return 1;
    }

  if (setuid (geteuid ()))
    {
      perror ("setuid");
      return 1;
    }

  execvp (argv[ac], argv+ac);
  perror (argv[ac]);
  return 1;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]