]> granicus.if.org Git - postgresql/blob - src/common/restricted_token.c
Remove vestigial resolveUnknown arguments from transformSortClause etc.
[postgresql] / src / common / restricted_token.c
1 /*-------------------------------------------------------------------------
2  *
3  * restricted_token.c
4  *              helper routine to ensure restricted token on Windows
5  *
6  *
7  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  *
11  * IDENTIFICATION
12  *        src/common/restricted_token.c
13  *
14  *-------------------------------------------------------------------------
15  */
16
17 #ifndef FRONTEND
18 #error "This file is not expected to be compiled for backend code"
19 #endif
20
21 #include "postgres_fe.h"
22
23 #include "common/restricted_token.h"
24
25 #ifdef WIN32
26
27 /* internal vars */
28 char       *restrict_env;
29
30 typedef BOOL (WINAPI * __CreateRestrictedToken) (HANDLE, DWORD, DWORD, PSID_AND_ATTRIBUTES, DWORD, PLUID_AND_ATTRIBUTES, DWORD, PSID_AND_ATTRIBUTES, PHANDLE);
31
32 /* Windows API define missing from some versions of MingW headers */
33 #ifndef  DISABLE_MAX_PRIVILEGE
34 #define DISABLE_MAX_PRIVILEGE   0x1
35 #endif
36
37 /*
38  * Create a restricted token and execute the specified process with it.
39  *
40  * Returns restricted token on success and 0 on failure.
41  *
42  * On NT4, or any other system not containing the required functions, will
43  * NOT execute anything.
44  */
45 HANDLE
46 CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo, const char *progname)
47 {
48         BOOL            b;
49         STARTUPINFO si;
50         HANDLE          origToken;
51         HANDLE          restrictedToken;
52         SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
53         SID_AND_ATTRIBUTES dropSids[2];
54         __CreateRestrictedToken _CreateRestrictedToken = NULL;
55         HANDLE          Advapi32Handle;
56
57         ZeroMemory(&si, sizeof(si));
58         si.cb = sizeof(si);
59
60         Advapi32Handle = LoadLibrary("ADVAPI32.DLL");
61         if (Advapi32Handle != NULL)
62         {
63                 _CreateRestrictedToken = (__CreateRestrictedToken) GetProcAddress(Advapi32Handle, "CreateRestrictedToken");
64         }
65
66         if (_CreateRestrictedToken == NULL)
67         {
68                 fprintf(stderr, _("%s: WARNING: cannot create restricted tokens on this platform\n"), progname);
69                 if (Advapi32Handle != NULL)
70                         FreeLibrary(Advapi32Handle);
71                 return 0;
72         }
73
74         /* Open the current token to use as a base for the restricted one */
75         if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &origToken))
76         {
77                 fprintf(stderr, _("%s: could not open process token: error code %lu\n"), progname, GetLastError());
78                 return 0;
79         }
80
81         /* Allocate list of SIDs to remove */
82         ZeroMemory(&dropSids, sizeof(dropSids));
83         if (!AllocateAndInitializeSid(&NtAuthority, 2,
84                  SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
85                                                                   0, &dropSids[0].Sid) ||
86                 !AllocateAndInitializeSid(&NtAuthority, 2,
87         SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
88                                                                   0, &dropSids[1].Sid))
89         {
90                 fprintf(stderr, _("%s: could not allocate SIDs: error code %lu\n"),
91                                 progname, GetLastError());
92                 return 0;
93         }
94
95         b = _CreateRestrictedToken(origToken,
96                                                            DISABLE_MAX_PRIVILEGE,
97                                                            sizeof(dropSids) / sizeof(dropSids[0]),
98                                                            dropSids,
99                                                            0, NULL,
100                                                            0, NULL,
101                                                            &restrictedToken);
102
103         FreeSid(dropSids[1].Sid);
104         FreeSid(dropSids[0].Sid);
105         CloseHandle(origToken);
106         FreeLibrary(Advapi32Handle);
107
108         if (!b)
109         {
110                 fprintf(stderr, _("%s: could not create restricted token: error code %lu\n"),
111                                 progname, GetLastError());
112                 return 0;
113         }
114
115 #ifndef __CYGWIN__
116         AddUserToTokenDacl(restrictedToken);
117 #endif
118
119         if (!CreateProcessAsUser(restrictedToken,
120                                                          NULL,
121                                                          cmd,
122                                                          NULL,
123                                                          NULL,
124                                                          TRUE,
125                                                          CREATE_SUSPENDED,
126                                                          NULL,
127                                                          NULL,
128                                                          &si,
129                                                          processInfo))
130
131         {
132                 fprintf(stderr, _("%s: could not start process for command \"%s\": error code %lu\n"), progname, cmd, GetLastError());
133                 return 0;
134         }
135
136         ResumeThread(processInfo->hThread);
137         return restrictedToken;
138 }
139 #endif
140
141 /*
142  * On Windows make sure that we are running with a restricted token,
143  * On other platforms do nothing.
144  */
145 void
146 get_restricted_token(const char *progname)
147 {
148 #ifdef WIN32
149         HANDLE          restrictedToken;
150
151         /*
152          * Before we execute another program, make sure that we are running with a
153          * restricted token. If not, re-execute ourselves with one.
154          */
155
156         if ((restrict_env = getenv("PG_RESTRICT_EXEC")) == NULL
157                 || strcmp(restrict_env, "1") != 0)
158         {
159                 PROCESS_INFORMATION pi;
160                 char       *cmdline;
161
162                 ZeroMemory(&pi, sizeof(pi));
163
164                 cmdline = pg_strdup(GetCommandLine());
165
166                 putenv("PG_RESTRICT_EXEC=1");
167
168                 if ((restrictedToken = CreateRestrictedProcess(cmdline, &pi, progname)) == 0)
169                 {
170                         fprintf(stderr, _("%s: could not re-execute with restricted token: error code %lu\n"), progname, GetLastError());
171                 }
172                 else
173                 {
174                         /*
175                          * Successfully re-execed. Now wait for child process to capture
176                          * exitcode.
177                          */
178                         DWORD           x;
179
180                         CloseHandle(restrictedToken);
181                         CloseHandle(pi.hThread);
182                         WaitForSingleObject(pi.hProcess, INFINITE);
183
184                         if (!GetExitCodeProcess(pi.hProcess, &x))
185                         {
186                                 fprintf(stderr, _("%s: could not get exit code from subprocess: error code %lu\n"), progname, GetLastError());
187                                 exit(1);
188                         }
189                         exit(x);
190                 }
191         }
192 #endif
193 }