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