]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/ntp/libntp/ssl_init.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / ntp / libntp / ssl_init.c
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 }