Skip to content

Commit 2764d5d

Browse files
committed
Make be-secure-common.c more consistent for future SSL implementations
Recent commit 8a3d942 has introduced be-secure-common.c, which is aimed at including backend-side APIs that can be used by any SSL implementation. The purpose is similar to fe-secure-common.c for the frontend-side APIs. However, this has forgotten to include check_ssl_key_file_permissions() in the move, which causes a double dependency between be-secure.c and be-secure-openssl.c. Refactor the code in a more logical way. This also puts into light an API which is usable by future SSL implementations for permissions on SSL key files. Author: Michael Paquier <[email protected]>
1 parent 7e0d64c commit 2764d5d

File tree

3 files changed

+76
-70
lines changed

3 files changed

+76
-70
lines changed

src/backend/libpq/be-secure-common.c

+74
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919

2020
#include "postgres.h"
2121

22+
#include <sys/stat.h>
23+
#include <unistd.h>
24+
2225
#include "libpq/libpq.h"
2326
#include "storage/fd.h"
2427

@@ -118,3 +121,74 @@ run_ssl_passphrase_command(const char *prompt, bool is_server_start, char *buf,
118121
pfree(command.data);
119122
return len;
120123
}
124+
125+
126+
/*
127+
* Check permissions for SSL key files.
128+
*/
129+
bool
130+
check_ssl_key_file_permissions(const char *ssl_key_file, bool isServerStart)
131+
{
132+
int loglevel = isServerStart ? FATAL : LOG;
133+
struct stat buf;
134+
135+
if (stat(ssl_key_file, &buf) != 0)
136+
{
137+
ereport(loglevel,
138+
(errcode_for_file_access(),
139+
errmsg("could not access private key file \"%s\": %m",
140+
ssl_key_file)));
141+
return false;
142+
}
143+
144+
if (!S_ISREG(buf.st_mode))
145+
{
146+
ereport(loglevel,
147+
(errcode(ERRCODE_CONFIG_FILE_ERROR),
148+
errmsg("private key file \"%s\" is not a regular file",
149+
ssl_key_file)));
150+
return false;
151+
}
152+
153+
/*
154+
* Refuse to load key files owned by users other than us or root.
155+
*
156+
* XXX surely we can check this on Windows somehow, too.
157+
*/
158+
#if !defined(WIN32) && !defined(__CYGWIN__)
159+
if (buf.st_uid != geteuid() && buf.st_uid != 0)
160+
{
161+
ereport(loglevel,
162+
(errcode(ERRCODE_CONFIG_FILE_ERROR),
163+
errmsg("private key file \"%s\" must be owned by the database user or root",
164+
ssl_key_file)));
165+
return false;
166+
}
167+
#endif
168+
169+
/*
170+
* Require no public access to key file. If the file is owned by us,
171+
* require mode 0600 or less. If owned by root, require 0640 or less to
172+
* allow read access through our gid, or a supplementary gid that allows
173+
* to read system-wide certificates.
174+
*
175+
* XXX temporarily suppress check when on Windows, because there may not
176+
* be proper support for Unix-y file permissions. Need to think of a
177+
* reasonable check to apply on Windows. (See also the data directory
178+
* permission check in postmaster.c)
179+
*/
180+
#if !defined(WIN32) && !defined(__CYGWIN__)
181+
if ((buf.st_uid == geteuid() && buf.st_mode & (S_IRWXG | S_IRWXO)) ||
182+
(buf.st_uid == 0 && buf.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)))
183+
{
184+
ereport(loglevel,
185+
(errcode(ERRCODE_CONFIG_FILE_ERROR),
186+
errmsg("private key file \"%s\" has group or world access",
187+
ssl_key_file),
188+
errdetail("File must have permissions u=rw (0600) or less if owned by the database user, or permissions u=rw,g=r (0640) or less if owned by root.")));
189+
return false;
190+
}
191+
#endif
192+
193+
return true;
194+
}

src/backend/libpq/be-secure.c

-69
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,10 @@
1818

1919
#include "postgres.h"
2020

21-
#include <sys/stat.h>
2221
#include <signal.h>
2322
#include <fcntl.h>
2423
#include <ctype.h>
2524
#include <sys/socket.h>
26-
#include <unistd.h>
2725
#include <netdb.h>
2826
#include <netinet/in.h>
2927
#ifdef HAVE_NETINET_TCP_H
@@ -320,70 +318,3 @@ secure_raw_write(Port *port, const void *ptr, size_t len)
320318

321319
return n;
322320
}
323-
324-
bool
325-
check_ssl_key_file_permissions(const char *ssl_key_file, bool isServerStart)
326-
{
327-
int loglevel = isServerStart ? FATAL : LOG;
328-
struct stat buf;
329-
330-
if (stat(ssl_key_file, &buf) != 0)
331-
{
332-
ereport(loglevel,
333-
(errcode_for_file_access(),
334-
errmsg("could not access private key file \"%s\": %m",
335-
ssl_key_file)));
336-
return false;
337-
}
338-
339-
if (!S_ISREG(buf.st_mode))
340-
{
341-
ereport(loglevel,
342-
(errcode(ERRCODE_CONFIG_FILE_ERROR),
343-
errmsg("private key file \"%s\" is not a regular file",
344-
ssl_key_file)));
345-
return false;
346-
}
347-
348-
/*
349-
* Refuse to load key files owned by users other than us or root.
350-
*
351-
* XXX surely we can check this on Windows somehow, too.
352-
*/
353-
#if !defined(WIN32) && !defined(__CYGWIN__)
354-
if (buf.st_uid != geteuid() && buf.st_uid != 0)
355-
{
356-
ereport(loglevel,
357-
(errcode(ERRCODE_CONFIG_FILE_ERROR),
358-
errmsg("private key file \"%s\" must be owned by the database user or root",
359-
ssl_key_file)));
360-
return false;
361-
}
362-
#endif
363-
364-
/*
365-
* Require no public access to key file. If the file is owned by us,
366-
* require mode 0600 or less. If owned by root, require 0640 or less to
367-
* allow read access through our gid, or a supplementary gid that allows
368-
* to read system-wide certificates.
369-
*
370-
* XXX temporarily suppress check when on Windows, because there may not
371-
* be proper support for Unix-y file permissions. Need to think of a
372-
* reasonable check to apply on Windows. (See also the data directory
373-
* permission check in postmaster.c)
374-
*/
375-
#if !defined(WIN32) && !defined(__CYGWIN__)
376-
if ((buf.st_uid == geteuid() && buf.st_mode & (S_IRWXG | S_IRWXO)) ||
377-
(buf.st_uid == 0 && buf.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)))
378-
{
379-
ereport(loglevel,
380-
(errcode(ERRCODE_CONFIG_FILE_ERROR),
381-
errmsg("private key file \"%s\" has group or world access",
382-
ssl_key_file),
383-
errdetail("File must have permissions u=rw (0600) or less if owned by the database user, or permissions u=rw,g=r (0640) or less if owned by root.")));
384-
return false;
385-
}
386-
#endif
387-
388-
return true;
389-
}

src/include/libpq/libpq.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ extern ssize_t secure_read(Port *port, void *ptr, size_t len);
9292
extern ssize_t secure_write(Port *port, void *ptr, size_t len);
9393
extern ssize_t secure_raw_read(Port *port, void *ptr, size_t len);
9494
extern ssize_t secure_raw_write(Port *port, const void *ptr, size_t len);
95-
extern bool check_ssl_key_file_permissions(const char *ssl_key_file, bool isServerStart);
9695

9796
extern bool ssl_loaded_verify_locations;
9897

@@ -108,5 +107,7 @@ extern bool SSLPreferServerCiphers;
108107
*/
109108
extern int run_ssl_passphrase_command(const char *prompt, bool is_server_start,
110109
char *buf, int size);
110+
extern bool check_ssl_key_file_permissions(const char *ssl_key_file,
111+
bool isServerStart);
111112

112113
#endif /* LIBPQ_H */

0 commit comments

Comments
 (0)