1 /*-------------------------------------------------------------------------
4 * Microsoft Windows Win32 Security Support Functions
6 * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
9 * src/port/win32security.c
11 *-------------------------------------------------------------------------
17 #include "postgres_fe.h"
22 * Utility wrapper for frontend and backend when reporting an error
26 pg_attribute_printf(1, 2)
28 log_error(const char *fmt
,...)
34 write_stderr(fmt
, ap
);
36 fprintf(stderr
, fmt
, ap
);
42 * Returns nonzero if the current user has administrative privileges,
45 * Note: this cannot use ereport() because it's called too early during
49 pgwin32_is_admin(void)
51 PSID AdministratorsSid
;
53 SID_IDENTIFIER_AUTHORITY NtAuthority
= {SECURITY_NT_AUTHORITY
};
54 BOOL IsAdministrators
;
57 if (!AllocateAndInitializeSid(&NtAuthority
, 2,
58 SECURITY_BUILTIN_DOMAIN_RID
,
59 DOMAIN_ALIAS_RID_ADMINS
, 0, 0, 0, 0, 0,
60 0, &AdministratorsSid
))
62 log_error(_("could not get SID for Administrators group: error code %lu\n"),
67 if (!AllocateAndInitializeSid(&NtAuthority
, 2,
68 SECURITY_BUILTIN_DOMAIN_RID
,
69 DOMAIN_ALIAS_RID_POWER_USERS
, 0, 0, 0, 0, 0,
72 log_error(_("could not get SID for PowerUsers group: error code %lu\n"),
77 if (!CheckTokenMembership(NULL
, AdministratorsSid
, &IsAdministrators
) ||
78 !CheckTokenMembership(NULL
, PowerUsersSid
, &IsPowerUsers
))
80 log_error(_("could not check access token membership: error code %lu\n"),
85 FreeSid(AdministratorsSid
);
86 FreeSid(PowerUsersSid
);
88 if (IsAdministrators
|| IsPowerUsers
)
95 * We consider ourselves running as a service if one of the following is
98 * 1) Standard error is not valid (always the case for services, and pg_ctl
99 * running as a service "passes" that down to postgres,
100 * c.f. CreateRestrictedProcess())
101 * 2) We are running as LocalSystem (only used by services)
102 * 3) Our token contains SECURITY_SERVICE_RID (automatically added to the
103 * process token by the SCM when starting a service)
105 * The check for LocalSystem is needed, because surprisingly, if a service
106 * is running as LocalSystem, it does not have SECURITY_SERVICE_RID in its
114 * Note: we can't report errors via either ereport (we're called too early
115 * in the backend) or write_stderr (because that calls this). We are
116 * therefore reduced to writing directly on stderr, which sucks, but we
117 * have few alternatives.
120 pgwin32_is_service(void)
122 static int _is_service
= -1;
126 SID_IDENTIFIER_AUTHORITY NtAuthority
= {SECURITY_NT_AUTHORITY
};
127 HANDLE stderr_handle
;
129 /* Only check the first time */
130 if (_is_service
!= -1)
133 /* Check if standard error is not valid */
134 stderr_handle
= GetStdHandle(STD_ERROR_HANDLE
);
135 if (stderr_handle
!= INVALID_HANDLE_VALUE
&& stderr_handle
!= NULL
)
141 /* Check if running as LocalSystem */
142 if (!AllocateAndInitializeSid(&NtAuthority
, 1,
143 SECURITY_LOCAL_SYSTEM_RID
, 0, 0, 0, 0, 0, 0, 0,
146 fprintf(stderr
, "could not get SID for local system account\n");
150 if (!CheckTokenMembership(NULL
, LocalSystemSid
, &IsMember
))
152 fprintf(stderr
, "could not check access token membership: error code %lu\n",
154 FreeSid(LocalSystemSid
);
157 FreeSid(LocalSystemSid
);
165 /* Check for service group membership */
166 if (!AllocateAndInitializeSid(&NtAuthority
, 1,
167 SECURITY_SERVICE_RID
, 0, 0, 0, 0, 0, 0, 0,
170 fprintf(stderr
, "could not get SID for service group: error code %lu\n",
175 if (!CheckTokenMembership(NULL
, ServiceSid
, &IsMember
))
177 fprintf(stderr
, "could not check access token membership: error code %lu\n",