This is the mail archive of the
cygwin-patches
mailing list for the Cygwin project.
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;
}