1 /* $NetBSD: ssl_init.c,v 1.3 2012/02/01 07:46:22 kardel Exp $ */ 2 3 /* 4 * ssl_init.c Common OpenSSL initialization code for the various 5 * programs which use it. 6 * 7 * Moved from ntpd/ntp_crypto.c crypto_setup() 8 */ 9 #ifdef HAVE_CONFIG_H 10 #include <config.h> 11 #endif 12 #include <ctype.h> 13 #include <ntp.h> 14 #include <ntp_debug.h> 15 #include <lib_strbuf.h> 16 17 #ifdef OPENSSL 18 #include "openssl/err.h" 19 #include "openssl/evp.h" 20 21 22 int ssl_init_done; 23 24 void 25 ssl_init(void) 26 { 27 if (ssl_init_done) 28 return; 29 30 ERR_load_crypto_strings(); 31 OpenSSL_add_all_algorithms(); 32 33 ssl_init_done = 1; 34 } 35 36 37 void 38 ssl_check_version(void) 39 { 40 if ((SSLeay() ^ OPENSSL_VERSION_NUMBER) & ~0xff0L) { 41 msyslog(LOG_WARNING, 42 "OpenSSL version mismatch. Built against %lx, you have %lx", 43 OPENSSL_VERSION_NUMBER, SSLeay()); 44 fprintf(stderr, 45 "OpenSSL version mismatch. Built against %lx, you have %lx\n", 46 OPENSSL_VERSION_NUMBER, SSLeay()); 47 } 48 49 INIT_SSL(); 50 } 51 #endif /* OPENSSL */ 52 53 54 /* 55 * keytype_from_text returns OpenSSL NID for digest by name, and 56 * optionally the associated digest length. 57 * 58 * Used by ntpd authreadkeys(), ntpq and ntpdc keytype() 59 */ 60 int 61 keytype_from_text( 62 const char *text, 63 size_t *pdigest_len 64 ) 65 { 66 const u_long max_digest_len = MAX_MAC_LEN - sizeof(keyid_t); 67 int key_type; 68 u_int digest_len; 69 #ifdef OPENSSL 70 u_char digest[EVP_MAX_MD_SIZE]; 71 char * upcased; 72 char * pch; 73 EVP_MD_CTX ctx; 74 75 /* 76 * OpenSSL digest short names are capitalized, so uppercase the 77 * digest name before passing to OBJ_sn2nid(). If it is not 78 * recognized but begins with 'M' use NID_md5 to be consistent 79 * with past behavior. 80 */ 81 INIT_SSL(); 82 LIB_GETBUF(upcased); 83 strncpy(upcased, text, LIB_BUFLENGTH); 84 for (pch = upcased; '\0' != *pch; pch++) 85 *pch = (char)toupper((unsigned char)*pch); 86 key_type = OBJ_sn2nid(upcased); 87 #else 88 key_type = 0; 89 #endif 90 91 if (!key_type && 'm' == tolower((unsigned char)text[0])) 92 key_type = NID_md5; 93 94 if (!key_type) 95 return 0; 96 97 if (NULL != pdigest_len) { 98 #ifdef OPENSSL 99 EVP_DigestInit(&ctx, EVP_get_digestbynid(key_type)); 100 EVP_DigestFinal(&ctx, digest, &digest_len); 101 if (digest_len + sizeof(keyid_t) > MAX_MAC_LEN) { 102 fprintf(stderr, 103 "key type %s %u octet digests are too big, max %lu\n", 104 keytype_name(key_type), digest_len, 105 max_digest_len); 106 msyslog(LOG_ERR, 107 "key type %s %u octet digests are too big, max %lu\n", 108 keytype_name(key_type), digest_len, 109 max_digest_len); 110 return 0; 111 } 112 #else 113 digest_len = 16; 114 #endif 115 *pdigest_len = digest_len; 116 } 117 118 return key_type; 119 } 120 121 122 /* 123 * keytype_name returns OpenSSL short name for digest by NID. 124 * 125 * Used by ntpq and ntpdc keytype() 126 */ 127 const char * 128 keytype_name( 129 int nid 130 ) 131 { 132 static const char unknown_type[] = "(unknown key type)"; 133 const char *name; 134 135 #ifdef OPENSSL 136 INIT_SSL(); 137 name = OBJ_nid2sn(nid); 138 if (NULL == name) 139 name = unknown_type; 140 #else /* !OPENSSL follows */ 141 if (NID_md5 == nid) 142 name = "MD5"; 143 else 144 name = unknown_type; 145 #endif 146 return name; 147 } 148 149 150 /* 151 * Use getpassphrase() if configure.ac detected it, as Suns that 152 * have it truncate the password in getpass() to 8 characters. 153 */ 154 #ifdef HAVE_GETPASSPHRASE 155 # define getpass(str) getpassphrase(str) 156 #endif 157 158 /* 159 * getpass_keytype() -- shared between ntpq and ntpdc, only vaguely 160 * related to the rest of ssl_init.c. 161 */ 162 char * 163 getpass_keytype( 164 int keytype 165 ) 166 { 167 char pass_prompt[64 + 11 + 1]; /* 11 for " Password: " */ 168 169 snprintf(pass_prompt, sizeof(pass_prompt), 170 "%.64s Password: ", keytype_name(keytype)); 171 172 return getpass(pass_prompt); 173 } 174