2004-06-24 23:03:42 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
2016-01-07 15:59:08 +01:00
|
|
|
* win32security.c
|
2004-08-29 07:07:03 +02:00
|
|
|
* Microsoft Windows Win32 Security Support Functions
|
2004-06-24 23:03:42 +02:00
|
|
|
*
|
2017-01-03 19:48:53 +01:00
|
|
|
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
|
2004-06-24 23:03:42 +02:00
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2016-01-07 15:59:08 +01:00
|
|
|
* src/port/win32security.c
|
2004-06-24 23:03:42 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
2016-01-07 15:59:08 +01:00
|
|
|
#ifndef FRONTEND
|
2004-06-24 23:03:42 +02:00
|
|
|
#include "postgres.h"
|
2016-01-07 15:59:08 +01:00
|
|
|
#else
|
|
|
|
#include "postgres_fe.h"
|
|
|
|
#endif
|
2004-06-24 23:03:42 +02:00
|
|
|
|
|
|
|
|
2016-01-07 15:59:08 +01:00
|
|
|
/*
|
|
|
|
* Utility wrapper for frontend and backend when reporting an error
|
|
|
|
* message.
|
|
|
|
*/
|
|
|
|
static
|
|
|
|
pg_attribute_printf(1, 2)
|
|
|
|
void
|
|
|
|
log_error(const char *fmt,...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
2016-01-08 00:32:14 +01:00
|
|
|
va_start(ap, fmt);
|
2016-01-07 15:59:08 +01:00
|
|
|
#ifndef FRONTEND
|
|
|
|
write_stderr(fmt, ap);
|
|
|
|
#else
|
|
|
|
fprintf(stderr, fmt, ap);
|
|
|
|
#endif
|
|
|
|
va_end(ap);
|
|
|
|
}
|
2004-11-16 20:52:22 +01:00
|
|
|
|
2004-06-24 23:03:42 +02:00
|
|
|
/*
|
|
|
|
* Returns nonzero if the current user has administrative privileges,
|
|
|
|
* or zero if not.
|
|
|
|
*
|
|
|
|
* Note: this cannot use ereport() because it's called too early during
|
|
|
|
* startup.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
pgwin32_is_admin(void)
|
|
|
|
{
|
2004-08-29 07:07:03 +02:00
|
|
|
PSID AdministratorsSid;
|
|
|
|
PSID PowerUsersSid;
|
|
|
|
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
|
2017-03-17 10:14:01 +01:00
|
|
|
BOOL IsAdministrators;
|
|
|
|
BOOL IsPowerUsers;
|
2004-06-24 23:03:42 +02:00
|
|
|
|
2004-08-29 07:07:03 +02:00
|
|
|
if (!AllocateAndInitializeSid(&NtAuthority, 2,
|
2016-01-07 15:59:08 +01:00
|
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
|
|
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
|
2004-08-29 07:07:03 +02:00
|
|
|
0, &AdministratorsSid))
|
2004-06-24 23:03:42 +02:00
|
|
|
{
|
2016-09-20 18:00:00 +02:00
|
|
|
log_error(_("could not get SID for Administrators group: error code %lu\n"),
|
2016-01-07 15:59:08 +01:00
|
|
|
GetLastError());
|
2004-06-24 23:03:42 +02:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!AllocateAndInitializeSid(&NtAuthority, 2,
|
2016-01-07 15:59:08 +01:00
|
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
|
|
DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
|
2004-06-24 23:03:42 +02:00
|
|
|
0, &PowerUsersSid))
|
|
|
|
{
|
2016-09-20 18:00:00 +02:00
|
|
|
log_error(_("could not get SID for PowerUsers group: error code %lu\n"),
|
2016-01-07 15:59:08 +01:00
|
|
|
GetLastError());
|
2004-06-24 23:03:42 +02:00
|
|
|
exit(1);
|
|
|
|
}
|
2004-08-29 07:07:03 +02:00
|
|
|
|
2017-03-17 10:14:01 +01:00
|
|
|
if (!CheckTokenMembership(NULL, AdministratorsSid, &IsAdministrators) ||
|
|
|
|
!CheckTokenMembership(NULL, PowerUsersSid, &IsPowerUsers))
|
2004-06-24 23:03:42 +02:00
|
|
|
{
|
2017-03-17 10:14:01 +01:00
|
|
|
log_error(_("could not check access token membership: error code %lu\n"),
|
|
|
|
GetLastError());
|
|
|
|
exit(1);
|
2004-06-24 23:03:42 +02:00
|
|
|
}
|
2004-08-29 07:07:03 +02:00
|
|
|
|
2004-06-24 23:03:42 +02:00
|
|
|
FreeSid(AdministratorsSid);
|
|
|
|
FreeSid(PowerUsersSid);
|
2017-03-17 10:14:01 +01:00
|
|
|
|
|
|
|
if (IsAdministrators || IsPowerUsers)
|
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return 0;
|
2004-06-24 23:03:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We consider ourselves running as a service if one of the following is
|
|
|
|
* true:
|
|
|
|
*
|
2017-03-17 10:14:01 +01:00
|
|
|
* 1) We are running as LocalSystem (only used by services)
|
2004-06-24 23:03:42 +02:00
|
|
|
* 2) Our token contains SECURITY_SERVICE_RID (automatically added to the
|
2004-08-29 07:07:03 +02:00
|
|
|
* process token by the SCM when starting a service)
|
2004-06-24 23:03:42 +02:00
|
|
|
*
|
2017-03-17 10:14:01 +01:00
|
|
|
* The check for LocalSystem is needed, because surprisingly, if a service
|
|
|
|
* is running as LocalSystem, it does not have SECURITY_SERVICE_RID in its
|
|
|
|
* process token.
|
|
|
|
*
|
2004-06-24 23:03:42 +02:00
|
|
|
* Return values:
|
2004-08-29 07:07:03 +02:00
|
|
|
* 0 = Not service
|
|
|
|
* 1 = Service
|
|
|
|
* -1 = Error
|
2004-06-24 23:03:42 +02:00
|
|
|
*
|
2016-01-07 15:59:08 +01:00
|
|
|
* Note: we can't report errors via either ereport (we're called too early
|
|
|
|
* in the backend) or write_stderr (because that calls this). We are
|
|
|
|
* therefore reduced to writing directly on stderr, which sucks, but we
|
|
|
|
* have few alternatives.
|
2004-06-24 23:03:42 +02:00
|
|
|
*/
|
|
|
|
int
|
|
|
|
pgwin32_is_service(void)
|
|
|
|
{
|
2004-08-29 07:07:03 +02:00
|
|
|
static int _is_service = -1;
|
2017-03-17 10:14:01 +01:00
|
|
|
BOOL IsMember;
|
2004-08-29 07:07:03 +02:00
|
|
|
PSID ServiceSid;
|
|
|
|
PSID LocalSystemSid;
|
|
|
|
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
|
2004-06-24 23:03:42 +02:00
|
|
|
|
|
|
|
/* Only check the first time */
|
|
|
|
if (_is_service != -1)
|
|
|
|
return _is_service;
|
2004-08-29 07:07:03 +02:00
|
|
|
|
2017-03-17 10:14:01 +01:00
|
|
|
/* First check for LocalSystem */
|
2004-08-29 07:07:03 +02:00
|
|
|
if (!AllocateAndInitializeSid(&NtAuthority, 1,
|
2005-10-15 04:49:52 +02:00
|
|
|
SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0,
|
2004-08-29 07:07:03 +02:00
|
|
|
&LocalSystemSid))
|
|
|
|
{
|
2004-10-12 23:54:45 +02:00
|
|
|
fprintf(stderr, "could not get SID for local system account\n");
|
2004-06-24 23:03:42 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2017-03-17 10:14:01 +01:00
|
|
|
if (!CheckTokenMembership(NULL, LocalSystemSid, &IsMember))
|
2004-08-29 07:07:03 +02:00
|
|
|
{
|
2017-03-17 10:14:01 +01:00
|
|
|
fprintf(stderr, "could not check access token membership: error code %lu\n",
|
|
|
|
GetLastError());
|
2004-06-24 23:03:42 +02:00
|
|
|
FreeSid(LocalSystemSid);
|
2017-03-17 10:14:01 +01:00
|
|
|
return -1;
|
2004-06-24 23:03:42 +02:00
|
|
|
}
|
|
|
|
FreeSid(LocalSystemSid);
|
|
|
|
|
2017-03-17 10:14:01 +01:00
|
|
|
if (IsMember)
|
2004-08-29 07:07:03 +02:00
|
|
|
{
|
2017-03-17 10:14:01 +01:00
|
|
|
_is_service = 1;
|
|
|
|
return _is_service;
|
2004-06-24 23:03:42 +02:00
|
|
|
}
|
|
|
|
|
2017-03-17 10:14:01 +01:00
|
|
|
/* Check for service group membership */
|
2004-08-29 07:07:03 +02:00
|
|
|
if (!AllocateAndInitializeSid(&NtAuthority, 1,
|
2005-10-15 04:49:52 +02:00
|
|
|
SECURITY_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0,
|
2004-08-29 07:07:03 +02:00
|
|
|
&ServiceSid))
|
|
|
|
{
|
2017-03-17 10:14:01 +01:00
|
|
|
fprintf(stderr, "could not get SID for service group: error code %lu\n",
|
|
|
|
GetLastError());
|
2004-06-24 23:03:42 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2017-03-17 10:14:01 +01:00
|
|
|
if (!CheckTokenMembership(NULL, ServiceSid, &IsMember))
|
2004-06-24 23:03:42 +02:00
|
|
|
{
|
2017-03-17 10:14:01 +01:00
|
|
|
fprintf(stderr, "could not check access token membership: error code %lu\n",
|
|
|
|
GetLastError());
|
|
|
|
FreeSid(ServiceSid);
|
|
|
|
return -1;
|
2004-06-24 23:03:42 +02:00
|
|
|
}
|
|
|
|
FreeSid(ServiceSid);
|
|
|
|
|
2017-03-17 10:14:01 +01:00
|
|
|
if (IsMember)
|
|
|
|
_is_service = 1;
|
|
|
|
else
|
|
|
|
_is_service = 0;
|
2004-06-24 23:03:42 +02:00
|
|
|
|
|
|
|
return _is_service;
|
|
|
|
}
|