aboutsummaryrefslogtreecommitdiff
path: root/contrib/ntp/libntp/ssl_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/ntp/libntp/ssl_init.c')
-rw-r--r--contrib/ntp/libntp/ssl_init.c252
1 files changed, 252 insertions, 0 deletions
diff --git a/contrib/ntp/libntp/ssl_init.c b/contrib/ntp/libntp/ssl_init.c
new file mode 100644
index 000000000000..6de8a0b5fccc
--- /dev/null
+++ b/contrib/ntp/libntp/ssl_init.c
@@ -0,0 +1,252 @@
+/*
+ * ssl_init.c Common OpenSSL initialization code for the various
+ * programs which use it.
+ *
+ * Moved from ntpd/ntp_crypto.c crypto_setup()
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <ctype.h>
+#include <ntp.h>
+#include <ntp_debug.h>
+#include <lib_strbuf.h>
+
+#ifdef OPENSSL
+# include <openssl/crypto.h>
+# include <openssl/err.h>
+# include <openssl/evp.h>
+# include <openssl/opensslv.h>
+# include "libssl_compat.h"
+# ifdef HAVE_OPENSSL_CMAC_H
+# include <openssl/cmac.h>
+# define CMAC_LENGTH 16
+# define CMAC "AES128CMAC"
+# endif /*HAVE_OPENSSL_CMAC_H*/
+
+EVP_MD_CTX *digest_ctx;
+
+
+static void
+atexit_ssl_cleanup(void)
+{
+ if (NULL == digest_ctx) {
+ return;
+ }
+ EVP_MD_CTX_free(digest_ctx);
+ digest_ctx = NULL;
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+ EVP_cleanup();
+ ERR_free_strings();
+#endif /* OpenSSL < 1.1 */
+}
+
+
+void
+ssl_init(void)
+{
+ init_lib();
+
+ if (NULL == digest_ctx) {
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+ ERR_load_crypto_strings();
+ OpenSSL_add_all_algorithms();
+#endif /* OpenSSL < 1.1 */
+ digest_ctx = EVP_MD_CTX_new();
+ INSIST(digest_ctx != NULL);
+ atexit(&atexit_ssl_cleanup);
+ }
+}
+
+
+void
+ssl_check_version(void)
+{
+ u_long v;
+ char * buf;
+
+ v = OpenSSL_version_num();
+ if ((v ^ OPENSSL_VERSION_NUMBER) & ~0xff0L) {
+ LIB_GETBUF(buf);
+ snprintf(buf, LIB_BUFLENGTH,
+ "OpenSSL version mismatch."
+ "Built against %lx, you have %lx\n",
+ (u_long)OPENSSL_VERSION_NUMBER, v);
+ msyslog(LOG_WARNING, "%s", buf);
+ fputs(buf, stderr);
+ }
+ INIT_SSL();
+}
+#endif /* OPENSSL */
+
+
+/*
+ * keytype_from_text returns OpenSSL NID for digest by name, and
+ * optionally the associated digest length.
+ *
+ * Used by ntpd authreadkeys(), ntpq and ntpdc keytype()
+ */
+int
+keytype_from_text(
+ const char * text,
+ size_t * pdigest_len
+ )
+{
+ int key_type;
+ u_int digest_len;
+#ifdef OPENSSL /* --*-- OpenSSL code --*-- */
+ const u_long max_digest_len = MAX_MDG_LEN;
+ char * upcased;
+ char * pch;
+ EVP_MD const * md;
+
+ /*
+ * OpenSSL digest short names are capitalized, so uppercase the
+ * digest name before passing to OBJ_sn2nid(). If it is not
+ * recognized but matches our CMAC string use NID_cmac, or if
+ * it begins with 'M' or 'm' use NID_md5 to be consistent with
+ * past behavior.
+ */
+ INIT_SSL();
+
+ /* get name in uppercase */
+ LIB_GETBUF(upcased);
+ strlcpy(upcased, text, LIB_BUFLENGTH);
+
+ for (pch = upcased; '\0' != *pch; pch++) {
+ *pch = (char)toupper((unsigned char)*pch);
+ }
+
+ key_type = OBJ_sn2nid(upcased);
+
+# ifdef ENABLE_CMAC
+ if (!key_type && !strncmp(CMAC, upcased, strlen(CMAC) + 1)) {
+ key_type = NID_cmac;
+
+ if (debug) {
+ fprintf(stderr, "%s:%d:%s():%s:key\n",
+ __FILE__, __LINE__, __func__, CMAC);
+ }
+ }
+# endif /*ENABLE_CMAC*/
+#else
+
+ key_type = 0;
+#endif
+
+ if (!key_type && 'm' == tolower((unsigned char)text[0])) {
+ key_type = NID_md5;
+ }
+
+ if (!key_type) {
+ return 0;
+ }
+
+ if (NULL != pdigest_len) {
+#ifdef OPENSSL
+ md = EVP_get_digestbynid(key_type);
+ digest_len = (md) ? EVP_MD_size(md) : 0;
+
+ if (!md || digest_len <= 0) {
+# ifdef ENABLE_CMAC
+ if (key_type == NID_cmac) {
+ digest_len = CMAC_LENGTH;
+
+ if (debug) {
+ fprintf(stderr, "%s:%d:%s():%s:len\n",
+ __FILE__, __LINE__, __func__, CMAC);
+ }
+ } else
+# endif /*ENABLE_CMAC*/
+ {
+ fprintf(stderr,
+ "key type %s is not supported by OpenSSL\n",
+ keytype_name(key_type));
+ msyslog(LOG_ERR,
+ "key type %s is not supported by OpenSSL\n",
+ keytype_name(key_type));
+ return 0;
+ }
+ }
+
+ if (digest_len > max_digest_len) {
+ fprintf(stderr,
+ "key type %s %u octet digests are too big, max %lu\n",
+ keytype_name(key_type), digest_len,
+ max_digest_len);
+ msyslog(LOG_ERR,
+ "key type %s %u octet digests are too big, max %lu",
+ keytype_name(key_type), digest_len,
+ max_digest_len);
+ return 0;
+ }
+#else
+ digest_len = MD5_LENGTH;
+#endif
+ *pdigest_len = digest_len;
+ }
+
+ return key_type;
+}
+
+
+/*
+ * keytype_name returns OpenSSL short name for digest by NID.
+ *
+ * Used by ntpq and ntpdc keytype()
+ */
+const char *
+keytype_name(
+ int type
+ )
+{
+ static const char unknown_type[] = "(unknown key type)";
+ const char *name;
+
+#ifdef OPENSSL
+ INIT_SSL();
+ name = OBJ_nid2sn(type);
+
+# ifdef ENABLE_CMAC
+ if (NID_cmac == type) {
+ name = CMAC;
+ } else
+# endif /*ENABLE_CMAC*/
+ if (NULL == name) {
+ name = unknown_type;
+ }
+#else /* !OPENSSL follows */
+ if (NID_md5 == type)
+ name = "MD5";
+ else
+ name = unknown_type;
+#endif
+ return name;
+}
+
+
+/*
+ * Use getpassphrase() if configure.ac detected it, as Suns that
+ * have it truncate the password in getpass() to 8 characters.
+ */
+#ifdef HAVE_GETPASSPHRASE
+# define getpass(str) getpassphrase(str)
+#endif
+
+/*
+ * getpass_keytype() -- shared between ntpq and ntpdc, only vaguely
+ * related to the rest of ssl_init.c.
+ */
+char *
+getpass_keytype(
+ int type
+ )
+{
+ char pass_prompt[64 + 11 + 1]; /* 11 for " Password: " */
+
+ snprintf(pass_prompt, sizeof(pass_prompt),
+ "%.64s Password: ", keytype_name(type));
+
+ return getpass(pass_prompt);
+}
+