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