ssl_init.c revision 290001
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
19void	atexit_ssl_cleanup(void);
20
21int ssl_init_done;
22
23void
24ssl_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
39void
40atexit_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
51void
52ssl_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 */
74int
75keytype_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 */
141const char *
142keytype_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 */
176char *
177getpass_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