Skip to content

Commit b15f9b0

Browse files
committed
Replace direct fprintf(stderr) calls by write_stderr(), and cause this
routine to do something appropriate on Win32. Also, add a security check on Win32 that parallels the can't-run-as-root check on Unix. Magnus Hagander
1 parent b5b9e33 commit b15f9b0

File tree

13 files changed

+319
-102
lines changed

13 files changed

+319
-102
lines changed

src/backend/bootstrap/bootstrap.c

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.184 2004/06/06 00:41:26 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.185 2004/06/24 21:02:24 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -328,12 +328,11 @@ BootstrapMain(int argc, char *argv[])
328328
{
329329
if (!potential_DataDir)
330330
{
331-
fprintf(stderr,
332-
gettext("%s does not know where to find the database system data.\n"
333-
"You must specify the directory that contains the database system\n"
334-
"either by specifying the -D invocation option or by setting the\n"
335-
"PGDATA environment variable.\n"),
336-
argv[0]);
331+
write_stderr("%s does not know where to find the database system data.\n"
332+
"You must specify the directory that contains the database system\n"
333+
"either by specifying the -D invocation option or by setting the\n"
334+
"PGDATA environment variable.\n",
335+
argv[0]);
337336
proc_exit(1);
338337
}
339338
SetDataDir(potential_DataDir);
@@ -503,15 +502,14 @@ BootstrapMain(int argc, char *argv[])
503502
static void
504503
usage(void)
505504
{
506-
fprintf(stderr,
507-
gettext("Usage:\n"
505+
write_stderr("Usage:\n"
508506
" postgres -boot [OPTION]... DBNAME\n"
509507
" -c NAME=VALUE set run-time parameter\n"
510508
" -d 1-5 debug level\n"
511509
" -D datadir data directory\n"
512510
" -F turn off fsync\n"
513511
" -o file send debug output to file\n"
514-
" -x num internal use\n"));
512+
" -x num internal use\n");
515513

516514
proc_exit(1);
517515
}

src/backend/main/main.c

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*
1414
*
1515
* IDENTIFICATION
16-
* $PostgreSQL: pgsql/src/backend/main/main.c,v 1.86 2004/06/03 00:07:36 momjian Exp $
16+
* $PostgreSQL: pgsql/src/backend/main/main.c,v 1.87 2004/06/24 21:02:33 tgl Exp $
1717
*
1818
*-------------------------------------------------------------------------
1919
*/
@@ -91,8 +91,8 @@ main(int argc, char *argv[])
9191
#if defined(__alpha) /* no __alpha__ ? */
9292
if (setsysinfo(SSI_NVPAIRS, buffer, 1, (caddr_t) NULL,
9393
(unsigned long) NULL) < 0)
94-
fprintf(stderr, gettext("%s: setsysinfo failed: %s\n"),
95-
argv[0], strerror(errno));
94+
write_stderr("%s: setsysinfo failed: %s\n",
95+
argv[0], strerror(errno));
9696
#endif
9797
#endif /* NOFIXADE || NOPRINTADE */
9898

@@ -109,7 +109,7 @@ main(int argc, char *argv[])
109109
err = WSAStartup(MAKEWORD(2, 2), &wsaData);
110110
if (err != 0)
111111
{
112-
fprintf(stderr, "%s: WSAStartup failed: %d\n",
112+
write_stderr("%s: WSAStartup failed: %d\n",
113113
argv[0], err);
114114
exit(1);
115115
}
@@ -212,12 +212,10 @@ main(int argc, char *argv[])
212212
*/
213213
if (geteuid() == 0)
214214
{
215-
fprintf(stderr,
216-
gettext("\"root\" execution of the PostgreSQL server is not permitted.\n"
217-
"The server must be started under an unprivileged user ID to prevent\n"
218-
"possible system security compromise. See the documentation for\n"
219-
"more information on how to properly start the server.\n"
220-
));
215+
write_stderr("\"root\" execution of the PostgreSQL server is not permitted.\n"
216+
"The server must be started under an unprivileged user ID to prevent\n"
217+
"possible system security compromise. See the documentation for\n"
218+
"more information on how to properly start the server.\n");
221219
exit(1);
222220
}
223221
#endif /* !__BEOS__ */
@@ -233,9 +231,17 @@ main(int argc, char *argv[])
233231
*/
234232
if (getuid() != geteuid())
235233
{
236-
fprintf(stderr,
237-
gettext("%s: real and effective user IDs must match\n"),
238-
argv[0]);
234+
write_stderr("%s: real and effective user IDs must match\n",
235+
argv[0]);
236+
exit(1);
237+
}
238+
#else /* WIN32 */
239+
if (pgwin32_is_admin())
240+
{
241+
write_stderr("execution of PostgreSQL by a user with administrative permissions is not permitted.\n"
242+
"The server must be started under an unprivileged user ID to prevent\n"
243+
"possible system security compromise. See the documentation for\n"
244+
"more information on how to properly start the server.\n");
239245
exit(1);
240246
}
241247
#endif /* !WIN32 */
@@ -292,8 +298,8 @@ main(int argc, char *argv[])
292298
pw = getpwuid(geteuid());
293299
if (pw == NULL)
294300
{
295-
fprintf(stderr, gettext("%s: invalid effective UID: %d\n"),
296-
argv[0], (int) geteuid());
301+
write_stderr("%s: invalid effective UID: %d\n",
302+
argv[0], (int) geteuid());
297303
exit(1);
298304
}
299305
/* Allocate new memory because later getpwuid() calls can overwrite it */
@@ -305,7 +311,7 @@ main(int argc, char *argv[])
305311
pw_name_persist = malloc(namesize);
306312
if (!GetUserName(pw_name_persist, &namesize))
307313
{
308-
fprintf(stderr, gettext("%s: could not determine user name (GetUserName failed)\n"),
314+
write_stderr("%s: could not determine user name (GetUserName failed)\n",
309315
argv[0]);
310316
exit(1);
311317
}

src/backend/nls.mk

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
# $PostgreSQL: pgsql/src/backend/nls.mk,v 1.12 2004/06/10 17:10:24 petere Exp $
1+
# $PostgreSQL: pgsql/src/backend/nls.mk,v 1.13 2004/06/24 21:02:40 tgl Exp $
22
CATALOG_NAME := postgres
33
AVAIL_LANGUAGES := af cs de es hr hu it nb pt_BR ru sv tr zh_CN zh_TW
44
GETTEXT_FILES := + gettext-files
55
# you can add "elog:2" and "errmsg_internal" to this list if you want to
66
# include internal messages in the translation list.
7-
GETTEXT_TRIGGERS:= errmsg errdetail errhint errcontext postmaster_error yyerror
7+
GETTEXT_TRIGGERS:= errmsg errdetail errhint errcontext write_stderr yyerror
88

99
gettext-files: distprep
1010
find $(srcdir)/ -name '*.c' -print >$@

src/backend/port/win32/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
# Makefile for port/win32
55
#
66
# IDENTIFICATION
7-
# $PostgreSQL: pgsql/src/backend/port/win32/Makefile,v 1.4 2004/04/12 16:19:18 momjian Exp $
7+
# $PostgreSQL: pgsql/src/backend/port/win32/Makefile,v 1.5 2004/06/24 21:02:42 tgl Exp $
88
#
99
#-------------------------------------------------------------------------
1010

1111
subdir = src/backend/port/win32
1212
top_builddir = ../../../..
1313
include $(top_builddir)/src/Makefile.global
1414

15-
OBJS = sema.o shmem.o timer.o socket.o signal.o
15+
OBJS = sema.o shmem.o timer.o socket.o signal.o security.o
1616

1717
all: SUBSYS.o
1818

src/backend/port/win32/security.c

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* security.c
4+
* Microsoft Windows Win32 Security Support Functions
5+
*
6+
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
7+
*
8+
* IDENTIFICATION
9+
* $PostgreSQL: pgsql/src/backend/port/win32/security.c,v 1.1 2004/06/24 21:02:42 tgl Exp $
10+
*
11+
*-------------------------------------------------------------------------
12+
*/
13+
14+
#include "postgres.h"
15+
16+
17+
/*
18+
* Returns nonzero if the current user has administrative privileges,
19+
* or zero if not.
20+
*
21+
* Note: this cannot use ereport() because it's called too early during
22+
* startup.
23+
*/
24+
int
25+
pgwin32_is_admin(void)
26+
{
27+
HANDLE AccessToken;
28+
UCHAR InfoBuffer[1024];
29+
PTOKEN_GROUPS Groups = (PTOKEN_GROUPS)InfoBuffer;
30+
DWORD InfoBufferSize;
31+
PSID AdministratorsSid;
32+
PSID PowerUsersSid;
33+
SID_IDENTIFIER_AUTHORITY NtAuthority = { SECURITY_NT_AUTHORITY };
34+
UINT x;
35+
BOOL success;
36+
37+
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_READ,&AccessToken))
38+
{
39+
write_stderr("failed to open process token: %d\n",
40+
(int)GetLastError());
41+
exit(1);
42+
}
43+
44+
if (!GetTokenInformation(AccessToken,TokenGroups,InfoBuffer,
45+
1024, &InfoBufferSize))
46+
{
47+
write_stderr("failed to get token information: %d\n",
48+
(int)GetLastError());
49+
exit(1);
50+
}
51+
52+
CloseHandle(AccessToken);
53+
54+
if(!AllocateAndInitializeSid(&NtAuthority, 2,
55+
SECURITY_BUILTIN_DOMAIN_RID,DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
56+
0,&AdministratorsSid))
57+
{
58+
write_stderr("failed to get SID for Administrators group: %d\n",
59+
(int)GetLastError());
60+
exit(1);
61+
}
62+
63+
if (!AllocateAndInitializeSid(&NtAuthority, 2,
64+
SECURITY_BUILTIN_DOMAIN_RID,DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
65+
0, &PowerUsersSid))
66+
{
67+
write_stderr("failed to get SID for PowerUsers group: %d\n",
68+
(int)GetLastError());
69+
exit(1);
70+
}
71+
72+
success = FALSE;
73+
74+
for (x=0; x<Groups->GroupCount; x++)
75+
{
76+
if (EqualSid(AdministratorsSid, Groups->Groups[x].Sid) ||
77+
EqualSid(PowerUsersSid, Groups->Groups[x].Sid))
78+
{
79+
success = TRUE;
80+
break;
81+
}
82+
}
83+
84+
FreeSid(AdministratorsSid);
85+
FreeSid(PowerUsersSid);
86+
return success;
87+
}
88+
89+
/*
90+
* We consider ourselves running as a service if one of the following is
91+
* true:
92+
*
93+
* 1) We are running as Local System (only used by services)
94+
* 2) Our token contains SECURITY_SERVICE_RID (automatically added to the
95+
* process token by the SCM when starting a service)
96+
*
97+
* Return values:
98+
* 0 = Not service
99+
* 1 = Service
100+
* -1 = Error
101+
*
102+
* Note: we can't report errors via either ereport (we're called too early)
103+
* or write_stderr (because that calls this). We are therefore reduced to
104+
* writing directly on stderr, which sucks, but we have few alternatives.
105+
*/
106+
int
107+
pgwin32_is_service(void)
108+
{
109+
static int _is_service = -1;
110+
HANDLE AccessToken;
111+
UCHAR InfoBuffer[1024];
112+
PTOKEN_GROUPS Groups = (PTOKEN_GROUPS)InfoBuffer;
113+
PTOKEN_USER User = (PTOKEN_USER)InfoBuffer;
114+
DWORD InfoBufferSize;
115+
PSID ServiceSid;
116+
PSID LocalSystemSid;
117+
SID_IDENTIFIER_AUTHORITY NtAuthority = { SECURITY_NT_AUTHORITY };
118+
UINT x;
119+
120+
/* Only check the first time */
121+
if (_is_service != -1)
122+
return _is_service;
123+
124+
if (!OpenProcessToken(GetCurrentProcess(),TOKEN_READ,&AccessToken)) {
125+
fprintf(stderr,"failed to open process token: %d\n",
126+
(int)GetLastError());
127+
return -1;
128+
}
129+
130+
/* First check for local system */
131+
if (!GetTokenInformation(AccessToken,TokenUser,InfoBuffer,1024,&InfoBufferSize)) {
132+
fprintf(stderr,"failed to get token information: %d\n",
133+
(int)GetLastError());
134+
return -1;
135+
}
136+
137+
if (!AllocateAndInitializeSid(&NtAuthority,1,
138+
SECURITY_LOCAL_SYSTEM_RID,0,0,0,0,0,0,0,
139+
&LocalSystemSid)) {
140+
fprintf(stderr,"failed to get SID for local system account\n");
141+
CloseHandle(AccessToken);
142+
return -1;
143+
}
144+
145+
if (EqualSid(LocalSystemSid, User->User.Sid)) {
146+
FreeSid(LocalSystemSid);
147+
CloseHandle(AccessToken);
148+
_is_service = 1;
149+
return _is_service;
150+
}
151+
152+
FreeSid(LocalSystemSid);
153+
154+
/* Now check for group SID */
155+
if (!GetTokenInformation(AccessToken,TokenGroups,InfoBuffer,1024,&InfoBufferSize)) {
156+
fprintf(stderr,"failed to get token information: %d\n",
157+
(int)GetLastError());
158+
return -1;
159+
}
160+
161+
if (!AllocateAndInitializeSid(&NtAuthority,1,
162+
SECURITY_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0,
163+
&ServiceSid)) {
164+
fprintf(stderr,"failed to get SID for service group\n");
165+
CloseHandle(AccessToken);
166+
return -1;
167+
}
168+
169+
_is_service = 0;
170+
for (x = 0; x < Groups->GroupCount; x++)
171+
{
172+
if (EqualSid(ServiceSid, Groups->Groups[x].Sid))
173+
{
174+
_is_service = 1;
175+
break;
176+
}
177+
}
178+
179+
FreeSid(ServiceSid);
180+
181+
CloseHandle(AccessToken);
182+
183+
return _is_service;
184+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy