diff options
Diffstat (limited to 'src/interfaces/libpq/fe-secure.c')
-rw-r--r-- | src/interfaces/libpq/fe-secure.c | 122 |
1 files changed, 76 insertions, 46 deletions
diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c index 7aa2ca508c1..14f71c74cf4 100644 --- a/src/interfaces/libpq/fe-secure.c +++ b/src/interfaces/libpq/fe-secure.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.113 2008/12/04 14:07:42 mha Exp $ + * $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.114 2008/12/15 10:28:22 mha Exp $ * * NOTES * @@ -568,7 +568,10 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey) } /* read the user certificate */ - snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE); + if (conn->sslcert) + strncpy(fnbuf, conn->sslcert, sizeof(fnbuf)); + else + snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE); /* * OpenSSL <= 0.9.8 lacks error stack handling, which means it's likely to @@ -618,60 +621,78 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey) BIO_free(bio); -#if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE) - if (getenv("PGSSLKEY")) + /* + * Read the SSL key. If a key is specified, treat it as an engine:key combination + * if there is colon present - we don't support files with colon in the name. The + * exception is if the second character is a colon, in which case it can be a Windows + * filename with drive specification. + */ + if (conn->sslkey && strlen(conn->sslkey) > 0) { - /* read the user key from engine */ - char *engine_env = getenv("PGSSLKEY"); - char *engine_colon = strchr(engine_env, ':'); - char *engine_str; - ENGINE *engine_ptr; - - if (!engine_colon) +#if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE) + if (strchr(conn->sslkey, ':') +#ifdef WIN32 + && conn->sslkey[1] != ':' +#endif + ) { - printfPQExpBuffer(&conn->errorMessage, - libpq_gettext("invalid value of PGSSLKEY environment variable\n")); - ERR_pop_to_mark(); - return 0; - } + /* Colon, but not in second character, treat as engine:key */ + ENGINE *engine_ptr; + char *engine_str = strdup(conn->sslkey); + char *engine_colon = strchr(engine_str, ':'); - engine_str = malloc(engine_colon - engine_env + 1); - strlcpy(engine_str, engine_env, engine_colon - engine_env + 1); - engine_ptr = ENGINE_by_id(engine_str); - if (engine_ptr == NULL) - { - char *err = SSLerrmessage(); + *engine_colon = '\0'; /* engine_str now has engine name */ + engine_colon++; /* engine_colon now has key name */ - printfPQExpBuffer(&conn->errorMessage, - libpq_gettext("could not load SSL engine \"%s\": %s\n"), - engine_str, err); - SSLerrfree(err); - free(engine_str); - ERR_pop_to_mark(); - return 0; - } + engine_ptr = ENGINE_by_id(engine_str); + if (engine_ptr == NULL) + { + char *err = SSLerrmessage(); - *pkey = ENGINE_load_private_key(engine_ptr, engine_colon + 1, - NULL, NULL); - if (*pkey == NULL) - { - char *err = SSLerrmessage(); + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext("could not load SSL engine \"%s\": %s\n"), + engine_str, err); + SSLerrfree(err); + free(engine_str); + ERR_pop_to_mark(); + return 0; + } - printfPQExpBuffer(&conn->errorMessage, - libpq_gettext("could not read private SSL key \"%s\" from engine \"%s\": %s\n"), - engine_colon + 1, engine_str, err); - SSLerrfree(err); + *pkey = ENGINE_load_private_key(engine_ptr, engine_colon, + NULL, NULL); + if (*pkey == NULL) + { + char *err = SSLerrmessage(); + + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext("could not read private SSL key \"%s\" from engine \"%s\": %s\n"), + engine_colon, engine_str, err); + SSLerrfree(err); + free(engine_str); + ERR_pop_to_mark(); + return 0; + } free(engine_str); - ERR_pop_to_mark(); - return 0; + + fnbuf[0] = '\0'; /* indicate we're not going to load from a file */ + } + else +#endif /* support for SSL engines */ + { + /* PGSSLKEY is not an engine, treat it as a filename */ + strncpy(fnbuf, conn->sslkey, sizeof(fnbuf)); } - free(engine_str); } else -#endif /* use PGSSLKEY */ { - /* read the user key from file */ + /* No PGSSLKEY specified, load default file */ snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE); + } + + if (fnbuf[0] != '\0') + { + /* read the user key from file */ + if (stat(fnbuf, &buf) != 0) { printfPQExpBuffer(&conn->errorMessage, @@ -948,7 +969,11 @@ initialize_SSL(PGconn *conn) /* Set up to verify server cert, if root.crt is present */ if (pqGetHomeDirectory(homedir, sizeof(homedir))) { - snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CERT_FILE); + if (conn->sslrootcert) + strncpy(fnbuf, conn->sslrootcert, sizeof(fnbuf)); + else + snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CERT_FILE); + if (stat(fnbuf, &buf) == 0) { X509_STORE *cvstore; @@ -966,8 +991,13 @@ initialize_SSL(PGconn *conn) if ((cvstore = SSL_CTX_get_cert_store(SSL_context)) != NULL) { + if (conn->sslcrl) + strncpy(fnbuf, conn->sslcrl, sizeof(fnbuf)); + else + snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CRL_FILE); + /* setting the flags to check against the complete CRL chain */ - if (X509_STORE_load_locations(cvstore, ROOT_CRL_FILE, NULL) != 0) + if (X509_STORE_load_locations(cvstore, fnbuf, NULL) != 0) /* OpenSSL 0.96 does not support X509_V_FLAG_CRL_CHECK */ #ifdef X509_V_FLAG_CRL_CHECK X509_STORE_set_flags(cvstore, |