Re: new libpq SSL connection option - Mailing list pgsql-hackers

From Magnus Hagander
Subject Re: new libpq SSL connection option
Date
Msg-id 495DE8B6.4040505@hagander.net
Whole thread Raw
In response to Re: new libpq SSL connection option  (Andrew Chernow <ac@esilo.com>)
Responses Re: new libpq SSL connection option  (Andrew Chernow <ac@esilo.com>)
Re: new libpq SSL connection option  ("Alex Hunsaker" <badalex@gmail.com>)
List pgsql-hackers
Andrew Chernow wrote:
> Magnus Hagander wrote:
>> Alex Hunsaker wrote:
>>> On Sat, Dec 27, 2008 at 11:50, Andrew Chernow <ac@esilo.com> wrote:
>>>> Why does pqGetHomeDirectory have to succeed to use
>>>> conn->sslrootcert. Maybe
>>>> this should be an OR of the two since sslrootcert is not dependent on
>>>> homedir?
>>>>
>>>> around line 970 src/interfaces/libpq/fe-secure.c
>>>>
>>>> if (conn->sslrootcert || pqGetHomeDirectory(homedir, sizeof(homedir)))
>>>
>>> Certainly, did we miss anywhere else?
>>>
>
> Yes, the homedir variable is used again later in the function.  homedir
> could be invalid since pqGetHomeDirectory might not get called.  Maybe
> something like below would do the trick:
>
> /* when used, it can't be an empty string. */
> *homedir = 0;
>
> /* If either are NULL, homedir is needed */
> if (!conn->sslrootcert || !conn->sslcrl)
>   pqGetHomeDirectory(homedir, sizeof(homedir));
>
> /* one of them must be valid */
> if (conn->sslrootcert || *homedir)

How about this patch?

There's a lot of whitespace change due to indentation change, so I've
included a version without it for reference.


Also, it looks like we have the same problem with the private key, in
client_cert_cb(), agreed?


//Magnus
diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c
index ca2d33e..6957542 100644
--- a/src/interfaces/libpq/fe-secure.c
+++ b/src/interfaces/libpq/fe-secure.c
@@ -964,76 +964,85 @@ initialize_SSL(PGconn *conn)
      * If sslverify is set to anything other than "none", perform certificate
      * verification. If set to "cn" we will also do further verifications after
      * the connection has been completed.
+     *
+     * If we are going to look for either root certificate or CRL in the home directory,
+     * we need pqGetHomeDirectory() to succeed. In other cases, we don't need to
+     * get the home directory explicitly.
      */
-
-    /* Set up to verify server cert, if root.crt is present */
-    if (pqGetHomeDirectory(homedir, sizeof(homedir)))
+    if (!conn->sslrootcert || !conn->sslcrl)
     {
-        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)
+        if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
         {
-            X509_STORE *cvstore;
-
-            if (!SSL_CTX_load_verify_locations(SSL_context, fnbuf, NULL))
+            if (strcmp(conn->sslverify, "none") != 0)
             {
-                char       *err = SSLerrmessage();
-
                 printfPQExpBuffer(&conn->errorMessage,
-                                  libpq_gettext("could not read root certificate file \"%s\": %s\n"),
-                                  fnbuf, err);
-                SSLerrfree(err);
+                                  libpq_gettext("cannot find home directory to locate root certificate file"));
                 return -1;
             }
+        }
+    }
+    else
+    {
+        homedir[0] = '\0';
+    }

-            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, 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,
-                          X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
-                /* if not found, silently ignore;  we do not require CRL */
-#else
-                {
-                    char       *err = SSLerrmessage();

-                    printfPQExpBuffer(&conn->errorMessage,
-                                      libpq_gettext("SSL library does not support CRL certificates (file \"%s\")\n"),
-                                      fnbuf);
-                    SSLerrfree(err);
-                    return -1;
-                }
-#endif
-            }
+    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;
+
+        if (!SSL_CTX_load_verify_locations(SSL_context, fnbuf, NULL))
+        {
+            char       *err = SSLerrmessage();

-            SSL_CTX_set_verify(SSL_context, SSL_VERIFY_PEER, verify_cb);
+            printfPQExpBuffer(&conn->errorMessage,
+                              libpq_gettext("could not read root certificate file \"%s\": %s\n"),
+                              fnbuf, err);
+            SSLerrfree(err);
+            return -1;
         }
-        else
+
+        if ((cvstore = SSL_CTX_get_cert_store(SSL_context)) != NULL)
         {
-            if (strcmp(conn->sslverify, "none") != 0)
+            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, 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,
+                      X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
+            /* if not found, silently ignore;  we do not require CRL */
+#else
             {
+                char       *err = SSLerrmessage();
+
                 printfPQExpBuffer(&conn->errorMessage,
-                                  libpq_gettext("root certificate file (%s) not found"), fnbuf);
+                                  libpq_gettext("SSL library does not support CRL certificates (file \"%s\")\n"),
+                                  fnbuf);
+                SSLerrfree(err);
                 return -1;
             }
+#endif
         }
-    }
+
+        SSL_CTX_set_verify(SSL_context, SSL_VERIFY_PEER, verify_cb);
+    } /* root certificate exists */
     else
     {
         if (strcmp(conn->sslverify, "none") != 0)
         {
             printfPQExpBuffer(&conn->errorMessage,
-                              libpq_gettext("cannot find home directory to locate root certificate file"));
+                              libpq_gettext("root certificate file (%s) not found"), fnbuf);
             return -1;
         }
     }
diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c
index ca2d33e..6957542 100644
--- a/src/interfaces/libpq/fe-secure.c
+++ b/src/interfaces/libpq/fe-secure.c
@@ -964,11 +964,30 @@ initialize_SSL(PGconn *conn)
      * If sslverify is set to anything other than "none", perform certificate
      * verification. If set to "cn" we will also do further verifications after
      * the connection has been completed.
+     *
+     * If we are going to look for either root certificate or CRL in the home directory,
+     * we need pqGetHomeDirectory() to succeed. In other cases, we don't need to
+     * get the home directory explicitly.
      */
-
-    /* Set up to verify server cert, if root.crt is present */
-    if (pqGetHomeDirectory(homedir, sizeof(homedir)))
+    if (!conn->sslrootcert || !conn->sslcrl)
+    {
+        if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
     {
+            if (strcmp(conn->sslverify, "none") != 0)
+            {
+                printfPQExpBuffer(&conn->errorMessage,
+                                  libpq_gettext("cannot find home directory to locate root certificate file"));
+                return -1;
+            }
+        }
+    }
+    else
+    {
+        homedir[0] = '\0';
+    }
+
+
+
         if (conn->sslrootcert)
             strncpy(fnbuf, conn->sslrootcert, sizeof(fnbuf));
         else
@@ -1017,7 +1036,7 @@ initialize_SSL(PGconn *conn)
             }

             SSL_CTX_set_verify(SSL_context, SSL_VERIFY_PEER, verify_cb);
-        }
+    } /* root certificate exists */
         else
         {
             if (strcmp(conn->sslverify, "none") != 0)
@@ -1027,16 +1046,6 @@ initialize_SSL(PGconn *conn)
                 return -1;
             }
         }
-    }
-    else
-    {
-        if (strcmp(conn->sslverify, "none") != 0)
-        {
-            printfPQExpBuffer(&conn->errorMessage,
-                              libpq_gettext("cannot find home directory to locate root certificate file"));
-            return -1;
-        }
-    }

     /* set up mechanism to provide client certificate, if available */
     SSL_CTX_set_client_cert_cb(SSL_context, client_cert_cb);

pgsql-hackers by date:

Previous
From: Greg Smith
Date:
Subject: Re: posix_fadvise v22
Next
From: Greg Smith
Date:
Subject: Re: benchmarking the query planner