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