Re: Connection to PostgreSQL Using Certificate: Wrong Permissions on Private Key File

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Kevin Hunter <hunteke(at)earlham(dot)edu>
Cc: Angus Black Atkins-Trimnell <trimnell(at)uic(dot)edu>, Postgres General List <pgsql-general(at)postgresql(dot)org>, pgsql-hackers(at)postgresql(dot)org
Subject: Re: Connection to PostgreSQL Using Certificate: Wrong Permissions on Private Key File
Date: 2008-03-30 21:34:21
Message-ID: 29213.1206912861@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general pgsql-hackers

Kevin Hunter <hunteke(at)earlham(dot)edu> writes:
> At 3:50p -0400 on Sat, 29 Mar 2008, Tom Lane wrote:
>> The code appears to want 700 and ownership equal to that of the
>> process executing libpq, ie, the apache server.

> I just checked the 8.3 documentation and didn't see any mention of
> the private key file requirements. Modulo the fact that I don't know
> the docs /that/ well, would a HINT be helpful here? Or a pointer to
> the correct doc section?

Hmm. The quality of the error message does seem to be fairly far short
of what we expect for user-facing messages. We've got this:

if (!S_ISREG(buf.st_mode) || (buf.st_mode & 0077) ||
buf.st_uid != geteuid())
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("private key file \"%s\" has wrong permissions\n"),
fnbuf);
ERR_pop_to_mark();
return 0;
}

versus this coding in the exactly parallel place on the backend side:

if (!S_ISREG(buf.st_mode) || (buf.st_mode & (S_IRWXG | S_IRWXO)) ||
buf.st_uid != geteuid())
ereport(FATAL,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("unsafe permissions on private key file \"%s\"",
SERVER_PRIVATE_KEY_FILE),
errdetail("File must be owned by the database user and must have no permissions for \"group\" or \"other\".")));

Now libpq doesn't have any provision for DETAIL or HINT in its
locally-generated messages at the moment, so we can't just duplicate
the backend message, but we could do something like this example
from elsewhere in libpq:

if (stat_buf.st_mode & (S_IRWXG | S_IRWXO))
{
fprintf(stderr,
libpq_gettext("WARNING: password file \"%s\" has world or group read access; permission should be u=rw (0600)\n"),
pgpassfile);
return NULL;
}

I also wonder why we are bothering with explicit tests of the file
ownership in these places. If it's mode 700 or less, and not owned by
us, the subsequent attempt to read the file will fail anyway, no?
That would give us two different failure messages (the explicit one
versus "open failed: permission denied") for the two separate cases.
That seems better than one error message covering two types of mistake.

Lastly, I see that the libpq docs don't cover this very well:
http://developer.postgresql.org/pgdocs/postgres/libpq-ssl.html
says "The private key file must not be world-readable." which is
true but fails to mention that it also mustn't be world-writable,
world-executable, group-readable, group-writable, or group-executable.

Barring objections I'll go make this nicer in HEAD. Back-patching
is probably inappropriate because it'd change translated strings.

regards, tom lane

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Ross Boylan 2008-03-30 21:43:26 Re: database 1.2G, pg_dump 73M?!
Previous Message Vismaster46 2008-03-30 21:12:37 PostgreSQL and Java on WindowsXP

Browse pgsql-hackers by date

  From Date Subject
Next Message Douglas McNaught 2008-03-30 21:37:43 Re: Submission of Feature Request : RFC- for Implementing Transparent Data Encryption in Postgres
Previous Message Tom Lane 2008-03-30 21:09:17 Re: first time hacker ;) messing with prepared statements