ssl_init.c revision 309007
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
20void	atexit_ssl_cleanup(void);
21
22int ssl_init_done;
23
24void
25ssl_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
40void
41atexit_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
52void
53ssl_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 */
76int
77keytype_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 */
146const char *
147keytype_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 */
181char *
182getpass_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