I believe I found the smoking gun by breaking out the call
to EVP_get_digestbynid(crypto_nid) and testing its return
value:

--- ntp_crypto.c.orig   2009-12-08 23:36:35.000000000 -0800
+++ ntp_crypto.c        2012-04-30 22:44:46.094602274 -0700
@@ -197,6 +197,7 @@
        )
 {
        EVP_MD_CTX ctx;         /* message digest context */
+       const EVP_MD *type;
        u_char dgst[EVP_MAX_MD_SIZE]; /* message digest */
        keyid_t keyid;          /* key identifer */
        u_int32 header[10];     /* data in network byte order */
@@ -229,7 +230,43 @@
                hdlen = 10 * sizeof(u_int32);
                break;
        }
-       EVP_DigestInit(&ctx, EVP_get_digestbynid(crypto_nid));
+       if ((type = EVP_get_digestbynid(crypto_nid)) == NULL)
+               msyslog(LOG_ERR, "EVP_get_digestbynid(KEY_TYPE_MD5) "
+                                "returned NULL");
+       EVP_DigestInit(&ctx, type);
        EVP_DigestUpdate(&ctx, (u_char *)header, hdlen);
        EVP_DigestFinal(&ctx, dgst, &len);
        memcpy(&keyid, dgst, 4);

Sure enough, this routine returns NULL before the program segfaults.
A web search led me to this:
> http://stackoverflow.com/questions/6762054/evp-get-digestbyname-what-is-this

Indeed, the Debian man page for evp_get_digestbynid(3) has this important information:

EVP_get_digestbyname(), EVP_get_digestbynid() and EVP_get_digestbyobj() return
> an EVP_MD structure when passed a digest name, a digest NID or an ASN1_OBJECT > structure respectively. The digest table must be initialized using, for example,
> OpenSSL_add_all_digests() for these functions to work.

My search of the NTP source code for references to
"OpenSSL_add_all_*" showed the following two locations:

libntp/ssl_init.c:
------------------

#ifdef OPENSSL
#include "openssl/err.h"
#include "openssl/rand.h"


int ssl_init_done;

void
ssl_init(void)
{
        if (ssl_init_done)
                return;

        ERR_load_crypto_strings();
        OpenSSL_add_all_algorithms();

        ssl_init_done = 1;
}


void
ssl_check_version(void)
{
        INIT_SSL();
}
#endif  /* OPENSSL */

include/ntp_stdlib.h:
---------------------

/* ssl_init.c */
#ifdef OPENSSL
extern  void    ssl_init                (void);
extern  void    ssl_check_version       (void);
extern  int     ssl_init_done;
#define INIT_SSL()                              \
        do {                                    \
                if (!ssl_init_done)             \
                        ssl_init();             \
        } while (0)
#else   /* !OPENSSL follows */
#define INIT_SSL()              do {} while (0)
#endif

However, I can't find where the ntpd program ever calls ssl_init()
or the INIT_SSL() macro.  So I'm betting that this problem will go
away once I find the proper place to call this important routine.

Perhaps you can keep this ticket open until I can confirm my hunch.
It shouldn't take too long.

Thanks,
Andris





--
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org

Reply via email to