summaryrefslogtreecommitdiff
path: root/vchat-ssl.c
diff options
context:
space:
mode:
Diffstat (limited to 'vchat-ssl.c')
-rwxr-xr-xvchat-ssl.c112
1 files changed, 27 insertions, 85 deletions
diff --git a/vchat-ssl.c b/vchat-ssl.c
index 3c191c2..1a1ff16 100755
--- a/vchat-ssl.c
+++ b/vchat-ssl.c
@@ -11,7 +11,7 @@
11 * without even the implied warranty of merchantability or fitness for a 11 * without even the implied warranty of merchantability or fitness for a
12 * particular purpose. In no event shall the copyright holder be liable for 12 * particular purpose. In no event shall the copyright holder be liable for
13 * any direct, indirect, incidental or special damages arising in any way out 13 * any direct, indirect, incidental or special damages arising in any way out
14 * of the use of this software. 14 * of the use of this software.
15 * 15 *
16 */ 16 */
17 17
@@ -111,31 +111,19 @@ SSL_CTX * vc_create_sslctx( vc_x509store_t *vc_store )
111 } else if(vc_store->use_key) 111 } else if(vc_store->use_key)
112 r=SSL_CTX_use_PrivateKey(ctx, vc_store->use_key); 112 r=SSL_CTX_use_PrivateKey(ctx, vc_store->use_key);
113 113
114 if(r!=1) 114 if( r!=1 || !SSL_CTX_check_private_key(ctx))
115 VC_SETCERT_ERR_EXIT(store, ctx, "Load private key failed"); 115 VC_SETCERT_ERR_EXIT(store, ctx, "Load private key failed");
116
117 } 116 }
118 117
119 SSL_CTX_set_app_data(ctx, vc_store); 118 SSL_CTX_set_app_data(ctx, vc_store);
120 return(ctx); 119 return(ctx);
121} 120}
122 121
123#define VC_CONNSSL_ERR_EXIT(_cx, cx, cn) do { \ 122int vc_connect_ssl( BIO **conn, vc_x509store_t *vc_store, SSL_CTX **ctx)
124 snprintf(tmpstr, TMPSTRSIZE, "[SSL ERROR] %s", \
125 ERR_error_string (ERR_get_error (), NULL)); \
126 writecf(FS_ERR, tmpstr); \
127 if(cn) BIO_free_all(cn); \
128 if(*cx) SSL_CTX_free(*cx); \
129 if(_cx) *cx = 0; \
130 return(0); \
131 } while(0)
132
133BIO * vc_connect_ssl(char *host, int port, vc_x509store_t *vc_store,
134 SSL_CTX **ctx)
135{ 123{
136 BIO *conn = NULL; 124 BIO *ssl_conn = NULL;
137 int _ctx = 0; 125 int _ctx = 0;
138 126
139 if(*ctx) { 127 if(*ctx) {
140 CRYPTO_add( &((*ctx)->references), 1, CRYPTO_LOCK_SSL_CTX ); 128 CRYPTO_add( &((*ctx)->references), 1, CRYPTO_LOCK_SSL_CTX );
141 if( vc_store && vc_store != SSL_CTX_get_app_data(*ctx) ) { 129 if( vc_store && vc_store != SSL_CTX_get_app_data(*ctx) ) {
@@ -147,72 +135,26 @@ BIO * vc_connect_ssl(char *host, int port, vc_x509store_t *vc_store,
147 _ctx = 1; 135 _ctx = 1;
148 } 136 }
149 137
150 if( !(conn = BIO_new_ssl_connect(*ctx)) ) 138 ssl_conn = BIO_new_ssl(*ctx, 1);
151 VC_CONNSSL_ERR_EXIT(_ctx, ctx, conn); 139 if(_ctx)
152 140 SSL_CTX_free(*ctx);
153 BIO_set_conn_hostname(conn, host);
154 BIO_set_conn_int_port(conn, &port);
155 141
156 fflush(stdout); 142 if( ssl_conn ) {
157 if(BIO_do_connect(conn) <= 0) 143 BIO_push( ssl_conn, *conn );
158 VC_CONNSSL_ERR_EXIT(_ctx, ctx, conn); 144 *conn = ssl_conn;
145 fflush(stdout);
146 if( BIO_do_handshake( *conn ) > 0 )
147 return 0;
148 }
159 149
160 if(_ctx) 150 snprintf(tmpstr, TMPSTRSIZE, "[SSL ERROR] %s", ERR_error_string (ERR_get_error (), NULL));
161 SSL_CTX_free(*ctx); 151 writecf(FS_ERR, tmpstr);
162 152
163 return(conn); 153 return 1;
164}
165
166#define VC_CONN_ERR_EXIT(cn) do { \
167 snprintf(tmpstr, TMPSTRSIZE, "[SSL ERROR] %s", \
168 ERR_error_string(ERR_get_error(), NULL)); \
169 if(ERR_get_error()) \
170 writecf(FS_ERR, tmpstr); \
171 if(cn) BIO_free_all(cn); \
172 return(NULL); \
173 } while(0)
174
175#define VC_VERIFICATION_ERR_EXIT(cn, err) do { \
176 snprintf(tmpstr, TMPSTRSIZE, \
177 "[SSL ERROR] certificate verify failed: %s", err); \
178 writecf(FS_ERR, tmpstr); \
179 if(cn && !ignore_ssl) { BIO_free_all(cn); return(NULL); } \
180 } while(0)
181
182BIO * vc_connect( char *host, int port, int use_ssl,
183 vc_x509store_t *vc_store, SSL_CTX **ctx)
184{
185 BIO *conn = NULL;
186 SSL *ssl = NULL;
187
188 if(use_ssl) {
189 if( !(conn = vc_connect_ssl(host, port, vc_store, ctx)) )
190 VC_CONN_ERR_EXIT(conn);
191
192
193 BIO_get_ssl(conn, &ssl);
194 if(!vc_verify_cert_hostname(SSL_get_peer_certificate(ssl), host))
195 VC_VERIFICATION_ERR_EXIT(conn, "Hostname does not match!");
196
197 return(conn);
198 }
199
200 *ctx = 0;
201
202 if( !(conn = BIO_new_connect(host)) )
203 VC_CONN_ERR_EXIT(conn);
204
205 BIO_set_conn_int_port(conn, &port);
206
207 if(BIO_do_connect(conn) <= 0)
208 VC_CONN_ERR_EXIT(conn);
209
210 return(conn);
211} 154}
212 155
213int vc_verify_cert_hostname(X509 *cert, char *host) 156int vc_verify_cert_hostname(X509 *cert, char *host)
214{ 157{
215
216 int i = 0; 158 int i = 0;
217 int j = 0; 159 int j = 0;
218 int n = 0; 160 int n = 0;
@@ -231,39 +173,39 @@ int vc_verify_cert_hostname(X509 *cert, char *host)
231 memset(&name, 0, sizeof(name)); 173 memset(&name, 0, sizeof(name));
232 174
233 if((extcount = X509_get_ext_count(cert)) > 0) { 175 if((extcount = X509_get_ext_count(cert)) > 0) {
234 176
235 for(i=0; !ok && i < extcount; i++) { 177 for(i=0; !ok && i < extcount; i++) {
236 178
237 meth = NULL; 179 meth = NULL;
238 180
239 ext = X509_get_ext(cert, i); 181 ext = X509_get_ext(cert, i);
240 extstr = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext))); 182 extstr = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
241 183
242 if(!strcasecmp(extstr, "subjectAltName")) { 184 if(!strcasecmp(extstr, "subjectAltName")) {
243 185
244 if( !(meth = X509V3_EXT_get(ext)) ) 186 if( !(meth = X509V3_EXT_get(ext)) )
245 break; 187 break;
246 188
247 if( !(meth->d2i) ) 189 if( !(meth->d2i) )
248 break; 190 break;
249 191
250 data = ext->value->data; 192 data = ext->value->data;
251 193
252 val = meth->i2v(meth, meth->d2i(0, &data, ext->value->length), 0); 194 val = meth->i2v(meth, meth->d2i(0, &data, ext->value->length), 0);
253 for( j=0, n=sk_CONF_VALUE_num(val); j<n; j++ ) { 195 for( j=0, n=sk_CONF_VALUE_num(val); j<n; j++ ) {
254 nval = sk_CONF_VALUE_value(val, j); 196 nval = sk_CONF_VALUE_value(val, j);
255 if( !strcasecmp(nval->name, "DNS") && 197 if( !strcasecmp(nval->name, "DNS") &&
256 !strcasecmp(nval->value, host) ) { 198 !strcasecmp(nval->value, host) ) {
257 ok = 1; 199 ok = 1;
258 break; 200 break;
259 } 201 }
260 } 202 }
261 } 203 }
262 } 204 }
263 } 205 }
264 206
265 if( !ok && (subj = X509_get_subject_name(cert)) && 207 if( !ok && (subj = X509_get_subject_name(cert)) &&
266 X509_NAME_get_text_by_NID(subj, NID_commonName, 208 X509_NAME_get_text_by_NID(subj, NID_commonName,
267 name, sizeof(name)) > 0 ) { 209 name, sizeof(name)) > 0 ) {
268 name[sizeof(name)-1] = '\0'; 210 name[sizeof(name)-1] = '\0';
269 if(!strcasecmp(name, host)) 211 if(!strcasecmp(name, host))
@@ -331,7 +273,7 @@ X509_STORE *vc_x509store_create(vc_x509store_t *vc_store)
331 X509_STORE_set_flags( store, 273 X509_STORE_set_flags( store,
332 X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL ); 274 X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL );
333 } 275 }
334 276
335 if( !(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir())) ) 277 if( !(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir())) )
336 VC_STORE_ERR_EXIT(store); 278 VC_STORE_ERR_EXIT(store);
337 279