Update copyright for 2022
[pgsql.git] / src / port / win32security.c
blob1235199f2fbc938cfc066259f0d9199f16a13978
1 /*-------------------------------------------------------------------------
3 * win32security.c
4 * Microsoft Windows Win32 Security Support Functions
6 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
8 * IDENTIFICATION
9 * src/port/win32security.c
11 *-------------------------------------------------------------------------
14 #ifndef FRONTEND
15 #include "postgres.h"
16 #else
17 #include "postgres_fe.h"
18 #endif
22 * Utility wrapper for frontend and backend when reporting an error
23 * message.
25 static
26 pg_attribute_printf(1, 2)
27 void
28 log_error(const char *fmt,...)
30 va_list ap;
32 va_start(ap, fmt);
33 #ifndef FRONTEND
34 write_stderr(fmt, ap);
35 #else
36 fprintf(stderr, fmt, ap);
37 #endif
38 va_end(ap);
42 * Returns nonzero if the current user has administrative privileges,
43 * or zero if not.
45 * Note: this cannot use ereport() because it's called too early during
46 * startup.
48 int
49 pgwin32_is_admin(void)
51 PSID AdministratorsSid;
52 PSID PowerUsersSid;
53 SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
54 BOOL IsAdministrators;
55 BOOL IsPowerUsers;
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"),
63 GetLastError());
64 exit(1);
67 if (!AllocateAndInitializeSid(&NtAuthority, 2,
68 SECURITY_BUILTIN_DOMAIN_RID,
69 DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
70 0, &PowerUsersSid))
72 log_error(_("could not get SID for PowerUsers group: error code %lu\n"),
73 GetLastError());
74 exit(1);
77 if (!CheckTokenMembership(NULL, AdministratorsSid, &IsAdministrators) ||
78 !CheckTokenMembership(NULL, PowerUsersSid, &IsPowerUsers))
80 log_error(_("could not check access token membership: error code %lu\n"),
81 GetLastError());
82 exit(1);
85 FreeSid(AdministratorsSid);
86 FreeSid(PowerUsersSid);
88 if (IsAdministrators || IsPowerUsers)
89 return 1;
90 else
91 return 0;
95 * We consider ourselves running as a service if one of the following is
96 * true:
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
107 * process token.
109 * Return values:
110 * 0 = Not service
111 * 1 = Service
112 * -1 = Error
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;
123 BOOL IsMember;
124 PSID ServiceSid;
125 PSID LocalSystemSid;
126 SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
127 HANDLE stderr_handle;
129 /* Only check the first time */
130 if (_is_service != -1)
131 return _is_service;
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)
137 _is_service = 0;
138 return _is_service;
141 /* Check if running as LocalSystem */
142 if (!AllocateAndInitializeSid(&NtAuthority, 1,
143 SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0,
144 &LocalSystemSid))
146 fprintf(stderr, "could not get SID for local system account\n");
147 return -1;
150 if (!CheckTokenMembership(NULL, LocalSystemSid, &IsMember))
152 fprintf(stderr, "could not check access token membership: error code %lu\n",
153 GetLastError());
154 FreeSid(LocalSystemSid);
155 return -1;
157 FreeSid(LocalSystemSid);
159 if (IsMember)
161 _is_service = 1;
162 return _is_service;
165 /* Check for service group membership */
166 if (!AllocateAndInitializeSid(&NtAuthority, 1,
167 SECURITY_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0,
168 &ServiceSid))
170 fprintf(stderr, "could not get SID for service group: error code %lu\n",
171 GetLastError());
172 return -1;
175 if (!CheckTokenMembership(NULL, ServiceSid, &IsMember))
177 fprintf(stderr, "could not check access token membership: error code %lu\n",
178 GetLastError());
179 FreeSid(ServiceSid);
180 return -1;
182 FreeSid(ServiceSid);
184 if (IsMember)
185 _is_service = 1;
186 else
187 _is_service = 0;
189 return _is_service;