diff options
| author | erdgeist <> | 2010-07-30 21:41:50 +0000 |
|---|---|---|
| committer | erdgeist <> | 2010-07-30 21:41:50 +0000 |
| commit | 6dac4efa6181e2696ea112c3f1826f529160ceef (patch) | |
| tree | 0f081ca75b0f35d727314c78c4b0f33fdf93af25 /vchat-ssl.c | |
| parent | a4b65f17eb73100a3fd4ec1f4de7cee56aa5131b (diff) | |
Can do v6 and reconnect.
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 | ||
