GNU libmicrohttpd  0.9.29
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
io_openssl.c
Go to the documentation of this file.
1 /*
2  This file is part of libmicrospdy
3  Copyright (C) 2012 Andrey Uzunov
4 
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 3 of the License, or
8  (at your option) any later version.
9 
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.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
26 #include "platform.h"
27 #include "internal.h"
28 #include "session.h"
29 #include "io_openssl.h"
30 
31 
41 static int
42 spdyf_next_protos_advertised_cb (SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg)
43 {
44  (void)ssl;
45  (void)arg;
46  static unsigned char npn_spdy3[] = {0x06, // length of "spdy/3"
47  0x73,0x70,0x64,0x79,0x2f,0x33};// spdy/3
48 
49  *out = npn_spdy3;
50  *outlen = 7; // total length of npn_spdy3
51  return SSL_TLSEXT_ERR_OK;
52 }
53 
54 
55 void
57 {
58  //error strings are now not used by the lib
59  //SSL_load_error_strings();
60  //init libssl
61  SSL_library_init(); //always returns 1
62  //the table for looking up algos is not used now by the lib
63  //OpenSSL_add_all_algorithms();
64 }
65 
66 
67 void
69 {
70  //if SSL_load_error_strings was called
71  //ERR_free_strings();
72  //if OpenSSL_add_all_algorithms was called
73  //EVP_cleanup();
74 }
75 
76 
77 int
79 {
80  int options;
81  //create ssl context. TLSv1 used
82  if(NULL == (daemon->io_context = SSL_CTX_new(TLSv1_server_method())))
83  {
84  SPDYF_DEBUG("Couldn't create ssl context");
85  return SPDY_NO;
86  }
87  //set options for tls
88  //TODO DH is not enabled for easier debugging
89  //SSL_CTX_set_options(daemon->io_context, SSL_OP_SINGLE_DH_USE);
90 
91  //TODO here session tickets are disabled for easier debuging with
92  //wireshark when using Chrome
93  // SSL_OP_NO_COMPRESSION disables TLS compression to avoid CRIME attack
94  options = SSL_OP_NO_TICKET;
95 #ifdef SSL_OP_NO_COMPRESSION
96  options |= SSL_OP_NO_COMPRESSION;
97 #elif OPENSSL_VERSION_NUMBER >= 0x00908000L /* workaround for OpenSSL 0.9.8 */
98  sk_SSL_COMP_zero(SSL_COMP_get_compression_methods());
99 #endif
100 
101  SSL_CTX_set_options(daemon->io_context, options);
102  if(1 != SSL_CTX_use_certificate_file(daemon->io_context, daemon->certfile , SSL_FILETYPE_PEM))
103  {
104  SPDYF_DEBUG("Couldn't load the cert file");
105  SSL_CTX_free(daemon->io_context);
106  return SPDY_NO;
107  }
108  if(1 != SSL_CTX_use_PrivateKey_file(daemon->io_context, daemon->keyfile, SSL_FILETYPE_PEM))
109  {
110  SPDYF_DEBUG("Couldn't load the name file");
111  SSL_CTX_free(daemon->io_context);
112  return SPDY_NO;
113  }
114  SSL_CTX_set_next_protos_advertised_cb(daemon->io_context, &spdyf_next_protos_advertised_cb, NULL);
115  if (1 != SSL_CTX_set_cipher_list(daemon->io_context, "HIGH"))
116  {
117  SPDYF_DEBUG("Couldn't set the desired cipher list");
118  SSL_CTX_free(daemon->io_context);
119  return SPDY_NO;
120  }
121 
122  return SPDY_YES;
123 }
124 
125 
126 void
128 {
129  SSL_CTX_free(daemon->io_context);
130 }
131 
132 
133 int
135 {
136  int ret;
137 
138  if(NULL == (session->io_context = SSL_new(session->daemon->io_context)))
139  {
140  SPDYF_DEBUG("Couldn't create ssl structure");
141  return SPDY_NO;
142  }
143  if(1 != (ret = SSL_set_fd(session->io_context, session->socket_fd)))
144  {
145  SPDYF_DEBUG("SSL_set_fd %i",ret);
146  SSL_free(session->io_context);
147  session->io_context = NULL;
148  return SPDY_NO;
149  }
150 
151  //for non-blocking I/O SSL_accept may return -1
152  //and this function won't work
153  if(1 != (ret = SSL_accept(session->io_context)))
154  {
155  SPDYF_DEBUG("SSL_accept %i",ret);
156  SSL_free(session->io_context);
157  session->io_context = NULL;
158  return SPDY_NO;
159  }
160  /* alternatively
161  SSL_set_accept_state(session->io_context);
162  * may be called and then the negotiation will be done on reading
163  */
164 
165  return SPDY_YES;
166 }
167 
168 
169 void
171 {
172  //SSL_shutdown sends TLS "close notify" as in TLS standard.
173  //The function may fail as it waits for the other party to also close
174  //the TLS session. The lib just sends it and will close the socket
175  //after that because the browsers don't seem to care much about
176  //"close notify"
177  SSL_shutdown(session->io_context);
178 
179  SSL_free(session->io_context);
180 }
181 
182 
183 int
185  void * buffer,
186  size_t size)
187 {
188  int ret;
189  int n = SSL_read(session->io_context,
190  buffer,
191  size);
192  //if(n > 0) SPDYF_DEBUG("recvd: %i",n);
193  if (n <= 0)
194  {
195  ret = SSL_get_error(session->io_context, n);
196  switch(ret)
197  {
198  case SSL_ERROR_ZERO_RETURN:
199  return 0;
200 
201  case SSL_ERROR_WANT_READ:
202  case SSL_ERROR_WANT_WRITE:
203  return SPDY_IO_ERROR_AGAIN;
204 
205  case SSL_ERROR_SYSCALL:
206  if(EINTR == errno)
207  return SPDY_IO_ERROR_AGAIN;
208  return SPDY_IO_ERROR_ERROR;
209  default:
210  return SPDY_IO_ERROR_ERROR;
211  }
212  }
213 
214  return n;
215 }
216 
217 
218 int
220  const void * buffer,
221  size_t size)
222 {
223  int ret;
224 
225  int n = SSL_write(session->io_context,
226  buffer,
227  size);
228  //if(n > 0) SPDYF_DEBUG("sent: %i",n);
229  if (n <= 0)
230  {
231  ret = SSL_get_error(session->io_context, n);
232  switch(ret)
233  {
234  case SSL_ERROR_ZERO_RETURN:
235  return 0;
236 
237  case SSL_ERROR_WANT_READ:
238  case SSL_ERROR_WANT_WRITE:
239  return SPDY_IO_ERROR_AGAIN;
240 
241  case SSL_ERROR_SYSCALL:
242  if(EINTR == errno)
243  return SPDY_IO_ERROR_AGAIN;
244  return SPDY_IO_ERROR_ERROR;
245  default:
246  return SPDY_IO_ERROR_ERROR;
247  }
248  }
249 
250  return n;
251 }
252 
253 
254 int
256 {
257  /* From openssl docs:
258  * BUGS
259 SSL_pending() takes into account only bytes from the TLS/SSL record that is currently being processed (if any). If the SSL object's read_ahead flag is set, additional protocol bytes may have been read containing more TLS/SSL records; these are ignored by SSL_pending().
260  */
261  return SSL_pending(session->io_context) > 0 ? SPDY_YES : SPDY_NO;
262 }
263 
264 
265 int
267 {
268  (void)session;
269 
270  return SPDY_YES;
271 }
272 
273 
274 int
275 SPDYF_openssl_after_write(struct SPDY_Session *session, int was_written)
276 {
277  (void)session;
278 
279  return was_written;
280 }
struct SPDY_Daemon * daemon
Definition: structures.h:633
void SPDYF_openssl_close_session(struct SPDY_Session *session)
Definition: io_openssl.c:170
#define SPDY_YES
Definition: microspdy.h:93
void SPDYF_openssl_deinit(struct SPDY_Daemon *daemon)
Definition: io_openssl.c:127
void * io_context
Definition: structures.h:655
TCP connection/SPDY session handling.
TLS handling. openssl with NPN is used, but as long as the functions conform to this interface file...
internal functions and macros for the framing layer
platform-specific includes for libmicrohttpd
void SPDYF_openssl_global_init()
Definition: io_openssl.c:56
char * keyfile
Definition: structures.h:897
void SPDYF_openssl_global_deinit()
Definition: io_openssl.c:68
#define SPDY_NO
Definition: microspdy.h:98
return NULL
Definition: tsearch.c:32
char * certfile
Definition: structures.h:891
int SPDYF_openssl_new_session(struct SPDY_Session *session)
Definition: io_openssl.c:134
int SPDYF_openssl_before_write(struct SPDY_Session *session)
Definition: io_openssl.c:266
#define SPDYF_DEBUG(fmt,...)
Definition: internal.h:154
int SPDYF_openssl_is_pending(struct SPDY_Session *session)
Definition: io_openssl.c:255
int SPDYF_openssl_recv(struct SPDY_Session *session, void *buffer, size_t size)
Definition: io_openssl.c:184
int SPDYF_openssl_init(struct SPDY_Daemon *daemon)
Definition: io_openssl.c:78
void * io_context
Definition: structures.h:886
int SPDYF_openssl_after_write(struct SPDY_Session *session, int was_written)
Definition: io_openssl.c:275
int SPDYF_openssl_send(struct SPDY_Session *session, const void *buffer, size_t size)
Definition: io_openssl.c:219
static int spdyf_next_protos_advertised_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg)
Definition: io_openssl.c:42