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