restructure configure so pkg-config derived SSL flags get used
[rofl0r-ixchat.git] / src / common / ssl.c
blob7586114823d7ccb390aebd04738e5ad016252cbc
1 /*
2 * ssl.c v0.0.3
3 * Copyright (C) 2000 -- DaP <profeta@freemail.c3.hu>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 #include <openssl/ssl.h> /* SSL_() */
21 #include <openssl/err.h> /* ERR_() */
22 #include <time.h> /* asctime() */
23 #include <string.h> /* strncpy() */
24 #include "ssl.h" /* struct cert_info */
25 #include "inet.h"
26 #include "util.h"
28 #ifndef MIN
29 #define MIN(a, b) (a < b ? a : b)
30 #endif
32 /* If openssl was built without ec */
33 #ifndef SSL_OP_SINGLE_ECDH_USE
34 #define SSL_OP_SINGLE_ECDH_USE 0
35 #endif
37 #ifndef HAVE_SSL_CTX_get_ssl_method
38 #define SSL_CTX_get_ssl_method(CTX) CTX->method
39 #endif
41 /* globals */
42 static struct chiper_info chiper_info; /* static buffer for _SSL_get_cipher_info() */
43 static char err_buf[256]; /* generic error buffer */
46 /* +++++ Internal functions +++++ */
48 static void
49 __SSL_fill_err_buf (char *funcname)
51 int err;
52 char buf[256];
55 err = ERR_get_error ();
56 ERR_error_string (err, buf);
57 snprintf (err_buf, sizeof (err_buf), "%s: %s (%d)\n", funcname, buf, err);
61 static void
62 __SSL_critical_error (char *funcname)
64 __SSL_fill_err_buf (funcname);
65 fprintf (stderr, "%s\n", err_buf);
67 exit (1);
70 /* +++++ SSL functions +++++ */
72 SSL_CTX *
73 _SSL_context_init (void (*info_cb_func))
75 SSL_CTX *ctx;
77 SSLeay_add_ssl_algorithms ();
78 SSL_load_error_strings ();
79 ctx = SSL_CTX_new (SSLv23_client_method ());
81 SSL_CTX_set_session_cache_mode (ctx, SSL_SESS_CACHE_BOTH);
82 SSL_CTX_set_timeout (ctx, 300);
83 SSL_CTX_set_options (ctx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3
84 |SSL_OP_NO_COMPRESSION
85 |SSL_OP_SINGLE_DH_USE|SSL_OP_SINGLE_ECDH_USE
86 |SSL_OP_NO_TICKET
87 |SSL_OP_CIPHER_SERVER_PREFERENCE);
89 /* used in SSL_connect(), SSL_accept() */
90 SSL_CTX_set_info_callback (ctx, info_cb_func);
92 return(ctx);
95 static void
96 ASN1_TIME_snprintf (char *buf, int buf_len, ASN1_TIME * tm)
98 char *expires = NULL;
99 BIO *inMem = BIO_new (BIO_s_mem ());
101 ASN1_TIME_print (inMem, tm);
102 BIO_get_mem_data (inMem, &expires);
103 buf[0] = 0;
104 if (expires != NULL)
106 /* expires is not \0 terminated */
107 safe_strcpy (buf, expires, MIN(24, buf_len));
109 BIO_free (inMem);
113 static void
114 broke_oneline (char *oneline, char *parray[])
116 char *pt, *ppt;
117 int i;
120 i = 0;
121 ppt = pt = oneline + 1;
122 while ((pt = strchr (pt, '/')))
124 *pt = 0;
125 parray[i++] = ppt;
126 ppt = ++pt;
128 parray[i++] = ppt;
129 parray[i] = NULL;
134 FIXME: Master-Key, Extensions, CA bits
135 (openssl x509 -text -in servcert.pem)
138 _SSL_get_cert_info (struct cert_info *cert_info, SSL * ssl)
140 X509 *peer_cert;
141 X509_PUBKEY *peer_pub_key;
142 ASN1_OBJECT *algorithm;
143 EVP_PKEY *peer_pkey;
144 /* EVP_PKEY *ca_pkey; */
145 /* EVP_PKEY *tmp_pkey; */
146 char notBefore[64];
147 char notAfter[64];
148 int alg;
149 int sign_alg;
152 if (!(peer_cert = SSL_get_peer_certificate (ssl)))
153 return (1); /* FATAL? */
155 X509_NAME_oneline (X509_get_subject_name (peer_cert), cert_info->subject,
156 sizeof (cert_info->subject));
157 X509_NAME_oneline (X509_get_issuer_name (peer_cert), cert_info->issuer,
158 sizeof (cert_info->issuer));
159 broke_oneline (cert_info->subject, cert_info->subject_word);
160 broke_oneline (cert_info->issuer, cert_info->issuer_word);
162 peer_pub_key = X509_get_X509_PUBKEY (peer_cert);
163 X509_PUBKEY_get0_param (&algorithm, NULL, NULL, NULL, peer_pub_key);
164 alg = OBJ_obj2nid (algorithm);
165 sign_alg = X509_get_signature_type (peer_cert);
166 ASN1_TIME_snprintf (notBefore, sizeof (notBefore),
167 X509_get_notBefore (peer_cert));
168 ASN1_TIME_snprintf (notAfter, sizeof (notAfter),
169 X509_get_notAfter (peer_cert));
171 peer_pkey = X509_get_pubkey (peer_cert);
173 safe_strcpy (cert_info->algorithm,
174 (alg == NID_undef) ? "Unknown" : OBJ_nid2ln (alg),
175 sizeof (cert_info->algorithm));
176 cert_info->algorithm_bits = EVP_PKEY_bits (peer_pkey);
177 safe_strcpy (cert_info->sign_algorithm,
178 (sign_alg == NID_undef) ? "Unknown" : OBJ_nid2ln (sign_alg),
179 sizeof (cert_info->sign_algorithm));
180 /* EVP_PKEY_bits(ca_pkey)); */
181 cert_info->sign_algorithm_bits = 0;
182 safe_strcpy (cert_info->notbefore, notBefore, sizeof (cert_info->notbefore));
183 safe_strcpy (cert_info->notafter, notAfter, sizeof (cert_info->notafter));
185 EVP_PKEY_free (peer_pkey);
187 /* SSL_SESSION_print_fp(stdout, SSL_get_session(ssl)); */
189 if (ssl->session->sess_cert->peer_rsa_tmp) {
190 tmp_pkey = EVP_PKEY_new();
191 EVP_PKEY_assign_RSA(tmp_pkey, ssl->session->sess_cert->peer_rsa_tmp);
192 cert_info->rsa_tmp_bits = EVP_PKEY_bits (tmp_pkey);
193 EVP_PKEY_free(tmp_pkey);
194 } else
195 fprintf(stderr, "REMOTE SIDE DOESN'T PROVIDES ->peer_rsa_tmp\n");
197 cert_info->rsa_tmp_bits = 0;
199 X509_free (peer_cert);
201 return (0);
205 struct chiper_info *
206 _SSL_get_cipher_info (SSL * ssl)
208 const SSL_CIPHER *c;
211 c = SSL_get_current_cipher (ssl);
212 safe_strcpy (chiper_info.version, SSL_CIPHER_get_version (c),
213 sizeof (chiper_info.version));
214 safe_strcpy (chiper_info.chiper, SSL_CIPHER_get_name (c),
215 sizeof (chiper_info.chiper));
216 SSL_CIPHER_get_bits (c, &chiper_info.chiper_bits);
218 return (&chiper_info);
223 _SSL_send (SSL * ssl, char *buf, int len)
225 int num;
228 num = SSL_write (ssl, buf, len);
230 switch (SSL_get_error (ssl, num))
232 case SSL_ERROR_SSL: /* setup errno! */
233 /* ??? */
234 __SSL_fill_err_buf ("SSL_write");
235 fprintf (stderr, "%s\n", err_buf);
236 break;
237 case SSL_ERROR_SYSCALL:
238 /* ??? */
239 perror ("SSL_write/write");
240 break;
241 case SSL_ERROR_ZERO_RETURN:
242 /* fprintf(stderr, "SSL closed on write\n"); */
243 break;
246 return (num);
251 _SSL_recv (SSL * ssl, char *buf, int len)
253 int num;
256 num = SSL_read (ssl, buf, len);
258 switch (SSL_get_error (ssl, num))
260 case SSL_ERROR_SSL:
261 /* ??? */
262 __SSL_fill_err_buf ("SSL_read");
263 fprintf (stderr, "%s\n", err_buf);
264 break;
265 case SSL_ERROR_SYSCALL:
266 /* ??? */
267 if (!would_block ())
268 perror ("SSL_read/read");
269 break;
270 case SSL_ERROR_ZERO_RETURN:
271 /* fprintf(stdeerr, "SSL closed on read\n"); */
272 break;
275 return (num);
279 SSL *
280 _SSL_socket (SSL_CTX *ctx, int sd)
282 SSL *ssl;
283 SSL_METHOD *method;
286 if (!(ssl = SSL_new (ctx)))
287 /* FATAL */
288 __SSL_critical_error ("SSL_new");
290 SSL_set_fd (ssl, sd);
292 method = SSL_CTX_get_ssl_method (ctx);
293 if (method == SSLv23_client_method())
294 SSL_set_connect_state (ssl);
295 else
296 SSL_set_accept_state(ssl);
298 return (ssl);
302 char *
303 _SSL_set_verify (SSL_CTX *ctx, void *verify_callback, char *cacert)
305 if (!SSL_CTX_set_default_verify_paths (ctx))
307 __SSL_fill_err_buf ("SSL_CTX_set_default_verify_paths");
308 return (err_buf);
311 if (cacert)
313 if (!SSL_CTX_load_verify_locations (ctx, cacert, NULL))
315 __SSL_fill_err_buf ("SSL_CTX_load_verify_locations");
316 return (err_buf);
320 SSL_CTX_set_verify (ctx, SSL_VERIFY_PEER, verify_callback);
322 return (NULL);
326 void
327 _SSL_close (SSL * ssl)
329 SSL_set_shutdown (ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
330 SSL_free (ssl);
331 ERR_remove_state (0); /* free state buffer */