]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/ntp/libntp/ssl_init.c
Fix multiple vulnerabilities of ntp.
[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 #include "libssl_compat.h"
19
20 void    atexit_ssl_cleanup(void);
21
22 int ssl_init_done;
23
24 void
25 ssl_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
40 void
41 atexit_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
52 void
53 ssl_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  */
76 int
77 keytype_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  */
146 const char *
147 keytype_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  */
181 char *
182 getpass_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 }