diff options
Diffstat (limited to 'vchat-ssl.c')
-rwxr-xr-x | vchat-ssl.c | 112 |
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 { \ | 122 | int 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 | |||
133 | BIO * 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 | |||
182 | BIO * 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 | ||
213 | int vc_verify_cert_hostname(X509 *cert, char *host) | 156 | int 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 | ||