annotate extern/libircclient/src/ssl.c @ 0:1158cffe5a5e

Initial import
author David Demelier <markand@malikania.fr>
date Mon, 08 Feb 2016 16:43:14 +0100
parents
children f67540addf5a
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
1 /*
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
2 * Copyright (C) 2004-2012 George Yunaev gyunaev@ulduzsoft.com
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
3 *
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
4 * This library is free software; you can redistribute it and/or modify it
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
5 * under the terms of the GNU Lesser General Public License as published by
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
6 * the Free Software Foundation; either version 3 of the License, or (at your
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
7 * option) any later version.
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
8 *
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
9 * This library is distributed in the hope that it will be useful, but WITHOUT
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
12 * License for more details.
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
13 */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
14
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
15
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
16 #if defined (ENABLE_SSL)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
17
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
18 // Nonzero if OpenSSL has been initialized
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
19 static SSL_CTX * ssl_context = 0;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
20
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
21 #if defined (_WIN32)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
22 #include <windows.h>
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
23 // This array will store all of the mutexes available to OpenSSL
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
24 static CRITICAL_SECTION * mutex_buf = 0;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
25
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
26 // OpenSSL callback to utilize static locks
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
27 static void cb_openssl_locking_function( int mode, int n, const char * file, int line )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
28 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
29 if ( mode & CRYPTO_LOCK)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
30 EnterCriticalSection( &mutex_buf[n] );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
31 else
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
32 LeaveCriticalSection( &mutex_buf[n] );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
33 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
34
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
35 // OpenSSL callback to get the thread ID
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
36 static unsigned long cb_openssl_id_function(void)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
37 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
38 return ((unsigned long) GetCurrentThreadId() );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
39 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
40
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
41 static int alloc_mutexes( unsigned int total )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
42 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
43 unsigned int i;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
44
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
45 // Enable thread safety in OpenSSL
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
46 mutex_buf = (CRITICAL_SECTION*) malloc( total * sizeof(CRITICAL_SECTION) );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
47
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
48 if ( !mutex_buf )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
49 return -1;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
50
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
51 for ( i = 0; i < total; i++)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
52 InitializeCriticalSection( &(mutex_buf[i]) );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
53
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
54 return 0;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
55 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
56
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
57
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
58 #else
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
59
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
60 // This array will store all of the mutexes available to OpenSSL
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
61 static pthread_mutex_t * mutex_buf = 0;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
62
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
63 // OpenSSL callback to utilize static locks
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
64 static void cb_openssl_locking_function( int mode, int n, const char * file, int line )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
65 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
66 (void)file;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
67 (void)line;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
68
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
69 if ( mode & CRYPTO_LOCK)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
70 pthread_mutex_lock( &mutex_buf[n] );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
71 else
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
72 pthread_mutex_unlock( &mutex_buf[n] );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
73 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
74
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
75 // OpenSSL callback to get the thread ID
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
76 static unsigned long cb_openssl_id_function()
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
77 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
78 return ((unsigned long) pthread_self() );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
79 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
80
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
81 static int alloc_mutexes( unsigned int total )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
82 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
83 unsigned i;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
84
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
85 // Enable thread safety in OpenSSL
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
86 mutex_buf = (pthread_mutex_t*) malloc( total * sizeof(pthread_mutex_t) );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
87
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
88 if ( !mutex_buf )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
89 return -1;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
90
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
91 for ( i = 0; i < total; i++)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
92 pthread_mutex_init( &(mutex_buf[i]), 0 );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
93
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
94 return 0;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
95 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
96
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
97 #endif
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
98
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
99 static int ssl_init_context( irc_session_t * session )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
100 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
101 // Load the strings and init the library
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
102 SSL_load_error_strings();
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
103
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
104 // Enable thread safety in OpenSSL
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
105 if ( alloc_mutexes( CRYPTO_num_locks() ) )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
106 return LIBIRC_ERR_NOMEM;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
107
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
108 // Register our callbacks
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
109 CRYPTO_set_id_callback( cb_openssl_id_function );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
110 CRYPTO_set_locking_callback( cb_openssl_locking_function );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
111
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
112 // Init it
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
113 if ( !SSL_library_init() )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
114 return LIBIRC_ERR_SSL_INIT_FAILED;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
115
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
116 if ( RAND_status() == 0 )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
117 return LIBIRC_ERR_SSL_INIT_FAILED;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
118
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
119 // Create an SSL context; currently a single context is used for all connections
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
120 ssl_context = SSL_CTX_new( SSLv23_method() );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
121
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
122 if ( !ssl_context )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
123 return LIBIRC_ERR_SSL_INIT_FAILED;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
124
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
125 // Disable SSLv2 as it is unsecure
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
126 if ( (SSL_CTX_set_options( ssl_context, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2) == 0 )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
127 return LIBIRC_ERR_SSL_INIT_FAILED;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
128
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
129 // Enable only strong ciphers
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
130 if ( SSL_CTX_set_cipher_list( ssl_context, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH" ) != 1 )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
131 return LIBIRC_ERR_SSL_INIT_FAILED;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
132
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
133 // Set the verification
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
134 if ( session->options & LIBIRC_OPTION_SSL_NO_VERIFY )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
135 SSL_CTX_set_verify( ssl_context, SSL_VERIFY_NONE, 0 );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
136 else
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
137 SSL_CTX_set_verify( ssl_context, SSL_VERIFY_PEER, 0 );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
138
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
139 // Disable session caching
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
140 SSL_CTX_set_session_cache_mode( ssl_context, SSL_SESS_CACHE_OFF );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
141
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
142 // Enable SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER so we can move the buffer during sending
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
143 SSL_CTX_set_mode( ssl_context, SSL_CTX_get_mode(ssl_context) | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
144
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
145 return 0;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
146 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
147
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
148
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
149 #if defined (_WIN32)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
150 #define SSLINIT_LOCK_MUTEX(a) WaitForSingleObject( a, INFINITE )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
151 #define SSLINIT_UNLOCK_MUTEX(a) ReleaseMutex( a )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
152 #else
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
153 #define SSLINIT_LOCK_MUTEX(a) pthread_mutex_lock( &a )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
154 #define SSLINIT_UNLOCK_MUTEX(a) pthread_mutex_unlock( &a )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
155 #endif
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
156
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
157 // Initializes the SSL context. Must be called after the socket is created.
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
158 static int ssl_init( irc_session_t * session )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
159 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
160 static int ssl_context_initialized = 0;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
161
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
162 #if defined (_WIN32)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
163 static HANDLE initmutex = 0;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
164
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
165 // First time run? Create the mutex
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
166 if ( initmutex == 0 )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
167 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
168 HANDLE m = CreateMutex( 0, FALSE, 0 );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
169
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
170 // Now we check if the mutex has already been created by another thread performing the init concurrently.
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
171 // If it was, we close our mutex and use the original one. This could be done synchronously by using the
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
172 // InterlockedCompareExchangePointer function.
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
173 if ( InterlockedCompareExchangePointer( &m, m, 0 ) != 0 )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
174 CloseHandle( m );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
175 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
176 #else
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
177 static pthread_mutex_t initmutex = PTHREAD_MUTEX_INITIALIZER;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
178 #endif
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
179
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
180 // This initialization needs to be performed only once. The problem is that it is called from
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
181 // irc_connect() and this function may be called simultaneously from different threads. So we have
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
182 // to use mutex on Linux because it allows static mutex initialization. Windows doesn't, so here
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
183 // we do the sabre dance around it.
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
184 SSLINIT_LOCK_MUTEX( initmutex );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
185
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
186 if ( ssl_context_initialized == 0 )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
187 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
188 int res = ssl_init_context( session );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
189
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
190 if ( res )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
191 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
192 SSLINIT_UNLOCK_MUTEX( initmutex );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
193 return res;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
194 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
195
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
196 ssl_context_initialized = 1;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
197 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
198
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
199 SSLINIT_UNLOCK_MUTEX( initmutex );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
200
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
201 // Get the SSL context
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
202 session->ssl = SSL_new( ssl_context );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
203
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
204 if ( !session->ssl )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
205 return LIBIRC_ERR_SSL_INIT_FAILED;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
206
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
207 // Let OpenSSL use our socket
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
208 if ( SSL_set_fd( session->ssl, session->sock) != 1 )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
209 return LIBIRC_ERR_SSL_INIT_FAILED;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
210
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
211 // Since we're connecting on our own, tell openssl about it
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
212 SSL_set_connect_state( session->ssl );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
213
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
214 return 0;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
215 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
216
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
217 static void ssl_handle_error( irc_session_t * session, int ssl_error )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
218 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
219 if ( ERR_GET_LIB(ssl_error) == ERR_LIB_SSL )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
220 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
221 if ( ERR_GET_REASON(ssl_error) == SSL_R_CERTIFICATE_VERIFY_FAILED )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
222 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
223 session->lasterror = LIBIRC_ERR_SSL_CERT_VERIFY_FAILED;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
224 return;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
225 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
226
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
227 if ( ERR_GET_REASON(ssl_error) == SSL_R_UNKNOWN_PROTOCOL )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
228 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
229 session->lasterror = LIBIRC_ERR_CONNECT_SSL_FAILED;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
230 return;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
231 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
232 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
233
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
234 #if defined (ENABLE_DEBUG)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
235 if ( IS_DEBUG_ENABLED(session) )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
236 fprintf (stderr, "[DEBUG] SSL error: %s\n\t(%d, %d)\n",
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
237 ERR_error_string( ssl_error, NULL), ERR_GET_LIB( ssl_error), ERR_GET_REASON(ssl_error) );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
238 #endif
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
239 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
240
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
241 static int ssl_recv( irc_session_t * session )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
242 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
243 int count;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
244 unsigned int amount = (sizeof (session->incoming_buf) - 1) - session->incoming_offset;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
245
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
246 ERR_clear_error();
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
247
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
248 // Read up to m_bufferLength bytes
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
249 count = SSL_read( session->ssl, session->incoming_buf + session->incoming_offset, amount );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
250
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
251 if ( count > 0 )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
252 return count;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
253 else if ( count == 0 )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
254 return -1; // remote connection closed
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
255 else
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
256 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
257 int ssl_error = SSL_get_error( session->ssl, count );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
258
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
259 // Handle SSL error since not all of them are actually errors
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
260 switch ( ssl_error )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
261 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
262 case SSL_ERROR_WANT_READ:
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
263 // This is not really an error. We received something, but
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
264 // OpenSSL gave nothing to us because all it read was
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
265 // internal data. Repeat the same read.
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
266 return 0;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
267
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
268 case SSL_ERROR_WANT_WRITE:
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
269 // This is not really an error. We received something, but
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
270 // now OpenSSL needs to send the data before returning any
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
271 // data to us (like negotiations). This means we'd need
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
272 // to wait for WRITE event, but call SSL_read() again.
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
273 session->flags |= SESSIONFL_SSL_READ_WANTS_WRITE;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
274 return 0;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
275 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
276
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
277 // This is an SSL error, handle it
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
278 ssl_handle_error( session, ERR_get_error() );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
279 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
280
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
281 return -1;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
282 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
283
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
284
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
285 static int ssl_send( irc_session_t * session )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
286 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
287 int count;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
288 ERR_clear_error();
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
289
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
290 count = SSL_write( session->ssl, session->outgoing_buf, session->outgoing_offset );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
291
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
292 if ( count > 0 )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
293 return count;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
294 else if ( count == 0 )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
295 return -1;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
296 else
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
297 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
298 int ssl_error = SSL_get_error( session->ssl, count );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
299
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
300 switch ( ssl_error )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
301 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
302 case SSL_ERROR_WANT_READ:
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
303 // This is not really an error. We sent some internal OpenSSL data,
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
304 // but now it needs to read more data before it can send anything.
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
305 // Thus we wait for READ event, but will call SSL_write() again.
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
306 session->flags |= SESSIONFL_SSL_WRITE_WANTS_READ;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
307 return 0;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
308
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
309 case SSL_ERROR_WANT_WRITE:
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
310 // This is not really an error. We sent some data, but now OpenSSL
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
311 // wants to send some internal data before sending ours.
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
312 // Repeat the same write.
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
313 return 0;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
314 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
315
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
316 // This is an SSL error, handle it
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
317 ssl_handle_error( session, ERR_get_error() );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
318 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
319
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
320 return -1;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
321 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
322
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
323 #endif
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
324
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
325
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
326 // Handles both SSL and non-SSL reads.
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
327 // Returns -1 in case there is an error and socket should be closed/connection terminated
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
328 // Returns 0 in case there is a temporary error and the call should be retried (SSL_WANTS_WRITE case)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
329 // Returns a positive number if we actually read something
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
330 static int session_socket_read( irc_session_t * session )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
331 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
332 int length;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
333
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
334 #if defined (ENABLE_SSL)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
335 if ( session->ssl )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
336 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
337 // Yes, I know this is tricky
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
338 if ( session->flags & SESSIONFL_SSL_READ_WANTS_WRITE )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
339 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
340 session->flags &= ~SESSIONFL_SSL_READ_WANTS_WRITE;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
341 ssl_send( session );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
342 return 0;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
343 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
344
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
345 return ssl_recv( session );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
346 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
347 #endif
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
348
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
349 length = socket_recv( &session->sock,
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
350 session->incoming_buf + session->incoming_offset,
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
351 (sizeof (session->incoming_buf) - 1) - session->incoming_offset );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
352
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
353 // There is no "retry" errors for regular sockets
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
354 if ( length <= 0 )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
355 return -1;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
356
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
357 return length;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
358 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
359
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
360 // Handles both SSL and non-SSL writes.
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
361 // Returns -1 in case there is an error and socket should be closed/connection terminated
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
362 // Returns 0 in case there is a temporary error and the call should be retried (SSL_WANTS_WRITE case)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
363 // Returns a positive number if we actually sent something
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
364 static int session_socket_write( irc_session_t * session )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
365 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
366 int length;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
367
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
368 #if defined (ENABLE_SSL)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
369 if ( session->ssl )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
370 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
371 // Yep
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
372 if ( session->flags & SESSIONFL_SSL_WRITE_WANTS_READ )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
373 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
374 session->flags &= ~SESSIONFL_SSL_WRITE_WANTS_READ;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
375 ssl_recv( session );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
376 return 0;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
377 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
378
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
379 return ssl_send( session );
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
380 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
381 #endif
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
382
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
383 length = socket_send (&session->sock, session->outgoing_buf, session->outgoing_offset);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
384
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
385 // There is no "retry" errors for regular sockets
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
386 if ( length <= 0 )
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
387 return -1;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
388
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
389 return length;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
390 }