1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

Add ssl_passphrase_command setting

This allows specifying an external command for prompting for or
otherwise obtaining passphrases for SSL key files.  This is useful
because in many cases there is no TTY easily available during service
startup.

Also add a setting ssl_passphrase_command_supports_reload, which allows
supporting SSL configuration reload even if SSL files need passphrases.

Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
This commit is contained in:
Peter Eisentraut
2018-02-26 13:28:38 -05:00
parent 7a50bb690b
commit 8a3d942529
13 changed files with 313 additions and 20 deletions

View File

@ -0,0 +1,120 @@
/*-------------------------------------------------------------------------
*
* be-secure-common.c
*
* common implementation-independent SSL support code
*
* While be-secure.c contains the interfaces that the rest of the
* communications code calls, this file contains support routines that are
* used by the library-specific implementations such as be-secure-openssl.c.
*
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* src/backend/libpq/be-secure-common.c
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "libpq/libpq.h"
#include "storage/fd.h"
/*
* Run ssl_passphrase_command
*
* prompt will be substituted for %p. is_server_start determines the loglevel
* of error messages.
*
* The result will be put in buffer buf, which is of size size. The return
* value is the length of the actual result.
*/
int
run_ssl_passphrase_command(const char *prompt, bool is_server_start, char *buf, int size)
{
int loglevel = is_server_start ? ERROR : LOG;
StringInfoData command;
char *p;
FILE *fh;
int pclose_rc;
size_t len = 0;
Assert(prompt);
Assert(size > 0);
buf[0] = '\0';
initStringInfo(&command);
for (p = ssl_passphrase_command; *p; p++)
{
if (p[0] == '%')
{
switch (p[1])
{
case 'p':
appendStringInfoString(&command, prompt);
p++;
break;
case '%':
appendStringInfoChar(&command, '%');
p++;
break;
default:
appendStringInfoChar(&command, p[0]);
}
}
else
appendStringInfoChar(&command, p[0]);
}
fh = OpenPipeStream(command.data, "r");
if (fh == NULL)
{
ereport(loglevel,
(errcode_for_file_access(),
errmsg("could not execute command \"%s\": %m",
command.data)));
goto error;
}
if (!fgets(buf, size, fh))
{
if (ferror(fh))
{
ereport(loglevel,
(errcode_for_file_access(),
errmsg("could not read from command \"%s\": %m",
command.data)));
goto error;
}
}
pclose_rc = ClosePipeStream(fh);
if (pclose_rc == -1)
{
ereport(loglevel,
(errcode_for_file_access(),
errmsg("could not close pipe to external command: %m")));
goto error;
}
else if (pclose_rc != 0)
{
ereport(loglevel,
(errcode_for_file_access(),
errmsg("command \"%s\" failed",
command.data),
errdetail_internal("%s", wait_result_to_str(pclose_rc))));
goto error;
}
/* strip trailing newline */
len = strlen(buf);
if (buf[len - 1] == '\n')
buf[len-- -1] = '\0';
error:
pfree(command.data);
return len;
}