PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
win32security.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * win32security.c
4  * Microsoft Windows Win32 Security Support Functions
5  *
6  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7  *
8  * IDENTIFICATION
9  * src/port/win32security.c
10  *
11  *-------------------------------------------------------------------------
12  */
13 
14 #ifndef FRONTEND
15 #include "postgres.h"
16 #else
17 #include "postgres_fe.h"
18 #endif
19 
20 
21 /*
22  * Utility wrapper for frontend and backend when reporting an error
23  * message.
24  */
25 static
27 void
28 log_error(const char *fmt,...)
29 {
30  va_list ap;
31 
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);
39 }
40 
41 /*
42  * Returns nonzero if the current user has administrative privileges,
43  * or zero if not.
44  *
45  * Note: this cannot use ereport() because it's called too early during
46  * startup.
47  */
48 int
50 {
51  PSID AdministratorsSid;
52  PSID PowerUsersSid;
53  SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
54  BOOL IsAdministrators;
55  BOOL IsPowerUsers;
56 
57  if (!AllocateAndInitializeSid(&NtAuthority, 2,
58  SECURITY_BUILTIN_DOMAIN_RID,
59  DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
60  0, &AdministratorsSid))
61  {
62  log_error(_("could not get SID for Administrators group: error code %lu\n"),
63  GetLastError());
64  exit(1);
65  }
66 
67  if (!AllocateAndInitializeSid(&NtAuthority, 2,
68  SECURITY_BUILTIN_DOMAIN_RID,
69  DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
70  0, &PowerUsersSid))
71  {
72  log_error(_("could not get SID for PowerUsers group: error code %lu\n"),
73  GetLastError());
74  exit(1);
75  }
76 
77  if (!CheckTokenMembership(NULL, AdministratorsSid, &IsAdministrators) ||
78  !CheckTokenMembership(NULL, PowerUsersSid, &IsPowerUsers))
79  {
80  log_error(_("could not check access token membership: error code %lu\n"),
81  GetLastError());
82  exit(1);
83  }
84 
85  FreeSid(AdministratorsSid);
86  FreeSid(PowerUsersSid);
87 
88  if (IsAdministrators || IsPowerUsers)
89  return 1;
90  else
91  return 0;
92 }
93 
94 /*
95  * We consider ourselves running as a service if one of the following is
96  * true:
97  *
98  * 1) We are running as LocalSystem (only used by services)
99  * 2) Our token contains SECURITY_SERVICE_RID (automatically added to the
100  * process token by the SCM when starting a service)
101  *
102  * The check for LocalSystem is needed, because surprisingly, if a service
103  * is running as LocalSystem, it does not have SECURITY_SERVICE_RID in its
104  * process token.
105  *
106  * Return values:
107  * 0 = Not service
108  * 1 = Service
109  * -1 = Error
110  *
111  * Note: we can't report errors via either ereport (we're called too early
112  * in the backend) or write_stderr (because that calls this). We are
113  * therefore reduced to writing directly on stderr, which sucks, but we
114  * have few alternatives.
115  */
116 int
118 {
119  static int _is_service = -1;
120  BOOL IsMember;
121  PSID ServiceSid;
122  PSID LocalSystemSid;
123  SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
124 
125  /* Only check the first time */
126  if (_is_service != -1)
127  return _is_service;
128 
129  /* First check for LocalSystem */
130  if (!AllocateAndInitializeSid(&NtAuthority, 1,
131  SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0,
132  &LocalSystemSid))
133  {
134  fprintf(stderr, "could not get SID for local system account\n");
135  return -1;
136  }
137 
138  if (!CheckTokenMembership(NULL, LocalSystemSid, &IsMember))
139  {
140  fprintf(stderr, "could not check access token membership: error code %lu\n",
141  GetLastError());
142  FreeSid(LocalSystemSid);
143  return -1;
144  }
145  FreeSid(LocalSystemSid);
146 
147  if (IsMember)
148  {
149  _is_service = 1;
150  return _is_service;
151  }
152 
153  /* Check for service group membership */
154  if (!AllocateAndInitializeSid(&NtAuthority, 1,
155  SECURITY_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0,
156  &ServiceSid))
157  {
158  fprintf(stderr, "could not get SID for service group: error code %lu\n",
159  GetLastError());
160  return -1;
161  }
162 
163  if (!CheckTokenMembership(NULL, ServiceSid, &IsMember))
164  {
165  fprintf(stderr, "could not check access token membership: error code %lu\n",
166  GetLastError());
167  FreeSid(ServiceSid);
168  return -1;
169  }
170  FreeSid(ServiceSid);
171 
172  if (IsMember)
173  _is_service = 1;
174  else
175  _is_service = 0;
176 
177  return _is_service;
178 }
#define log_error(str, param)
Definition: exec.c:31
int pgwin32_is_service(void)
#define write_stderr(str)
Definition: parallel.c:182
int pgwin32_is_admin(void)
Definition: win32security.c:49
static pg_attribute_printf(1, 2)
Definition: win32security.c:26
typedef BOOL(WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess
#define _(x)
Definition: elog.c:84