void ERR_clear_error(void) { ERR_STATE *es; es=ERR_get_state(); #if 0 /* hmm... is this needed */ for (i=0; i<ERR_NUM_ERRORS; i++) { es->err_buffer[i]=0; es->err_file[i]=NULL; es->err_line[i]= -1; err_clear_data(es,i); } #endif es->top=es->bottom=0; }
int ERR_pop_to_mark(void) { ERR_STATE *es; es=ERR_get_state(); while(es->bottom != es->top && (es->err_flags[es->top] & ERR_FLAG_MARK) == 0) { err_clear(es,es->top); es->top-=1; if (es->top == -1) es->top=ERR_NUM_ERRORS-1; } if (es->bottom == es->top) return 0; es->err_flags[es->top]&=~ERR_FLAG_MARK; return 1; }
void err_clear_last_constant_time(int clear) { ERR_STATE *es; int top; es = ERR_get_state(); if (es == NULL) return; top = es->top; /* * Flag error as cleared but remove it elsewhere to avoid two errors * accessing the same error stack location, revealing timing information. */ clear = constant_time_select_int(constant_time_eq_int(clear, 0), 0, ERR_FLAG_CLEAR); es->err_flags[top] |= clear; }
int ERR_clear_last_mark(void) { ERR_STATE *es; int top; es = ERR_get_state(); if (es == NULL) return 0; top = es->top; while (es->bottom != top && (es->err_flags[top] & ERR_FLAG_MARK) == 0) { top = top > 0 ? top - 1 : ERR_NUM_ERRORS - 1; } if (es->bottom == top) return 0; es->err_flags[top] &= ~ERR_FLAG_MARK; return 1; }
void ERR_put_error(int lib, int func, int reason, const char *file, int line) { ERR_STATE *es; #ifdef _OSD_POSIX /* * In the BS2000-OSD POSIX subsystem, the compiler generates path names * in the form "*POSIX(/etc/passwd)". This dirty hack strips them to * something sensible. @@@ We shouldn't modify a const string, though. */ if (strncmp(file, "*POSIX(", sizeof("*POSIX(") - 1) == 0) { char *end; /* Skip the "*POSIX(" prefix */ file += sizeof("*POSIX(") - 1; end = &file[strlen(file) - 1]; if (*end == ')') *end = '\0'; /* Optional: use the basename of the path only. */ if ((end = strrchr(file, '/')) != NULL) file = &end[1]; } #endif es = ERR_get_state(); if (es == NULL) return; es->top = (es->top + 1) % ERR_NUM_ERRORS; if (es->top == es->bottom) es->bottom = (es->bottom + 1) % ERR_NUM_ERRORS; es->err_flags[es->top] = 0; es->err_buffer[es->top] = ERR_PACK(lib, func, reason); es->err_file[es->top] = file; es->err_line[es->top] = line; err_clear_data(es, es->top); }
static unsigned long get_error_values(int inc, int top, const char **file, int *line, const char **data, int *flags) { int i=0; ERR_STATE *es; unsigned long ret; es=ERR_get_state(); if (inc && top) { if (file) *file = ""; if (line) *line = 0; if (data) *data = ""; if (flags) *flags = 0; return ERR_R_INTERNAL_ERROR; } if (es->bottom == es->top) return 0; if (top) i=es->top; /* last error */ else i=(es->bottom+1)%ERR_NUM_ERRORS; /* first error */ ret=es->err_buffer[i]; if (inc) { es->bottom=i; es->err_buffer[i]=0; } if ((file != NULL) && (line != NULL)) { if (es->err_file[i] == NULL) { *file="NA"; if (line != NULL) *line=0; } else { *file=es->err_file[i]; if (line != NULL) *line=es->err_line[i]; } } if (data == NULL) { if (inc) { err_clear_data(es, i); } } else { if (es->err_data[i] == NULL) { *data=""; if (flags != NULL) *flags=0; } else { *data=es->err_data[i]; if (flags != NULL) *flags=es->err_data_flags[i]; } } return ret; }
int zc_socket_ssl(zcSocket *s, char *key_file, char *cert_file, zcSSLCertRequire certreq, zcSSLVer ver, char *cacerts_file, bool isclient) { char *errstr = NULL; int ret; //int err; //int sockstate; if (!isclient && (key_file == NULL || cert_file == NULL)) { ZCERROR("both key and cert files must be specified for server"); goto zc_socket_ssl_fail; } memset(s->server, '\0', sizeof(char) * X509_NAME_MAXLEN); memset(s->issuer, '\0', sizeof(char) * X509_NAME_MAXLEN); s->peer_cert = NULL; s->ssl = NULL; s->ctx = NULL; //s->Socket = NULL; /* Init OpenSSL */ SSL_load_error_strings(); SSL_library_init(); OpenSSL_add_all_algorithms(); (void) ERR_get_state(); ERR_clear_error(); if ((key_file && !cert_file) || (!key_file && cert_file)) { errstr = "Both the key & certificate files must be specified"; goto zc_socket_ssl_fail; } //SSL_load_error_strings(); //SSLeay_add_ssl_algorithms(); if (s->sslver == ZC_SSL_VER_TLS1) s->ctx = SSL_CTX_new(TLSv1_method()); /* Set up context */ else if (ver == ZC_SSL_VER_SSL3) s->ctx = SSL_CTX_new(SSLv3_method()); /* Set up context */ else if (ver == ZC_SSL_VER_SSL2) s->ctx = SSL_CTX_new(SSLv2_method()); /* Set up context */ else if (ver == ZC_SSL_VER_SSL23) s->ctx = SSL_CTX_new(SSLv23_method()); /* Set up context */ //s->ctx = SSL_CTX_new(SSLv23_method()); /* Set up context */ if (s->ctx == NULL) { errstr = "SSL_CTX_new error"; goto zc_socket_ssl_fail; } if (certreq != ZC_SSL_CERT_NONE) { if (cacerts_file == NULL) { errstr = "No root certificates specified for verification of other-side certificates."; goto zc_socket_ssl_fail; } else { ret = SSL_CTX_load_verify_locations(s->ctx, cacerts_file, NULL); if (ret != 1) { //_setSSLError(NULL, 0, __FILE__, __LINE__); ZCERROR("load verify locations error: %d", ret); goto zc_socket_ssl_fail; } } } if (key_file) { ret = SSL_CTX_use_PrivateKey_file(s->ctx, key_file, SSL_FILETYPE_PEM); if (ret != 1) { //_setSSLError(NULL, ret, __FILE__, __LINE__); ZCERROR("use privatekey file error:%d", ret); goto zc_socket_ssl_fail; } ret = SSL_CTX_use_certificate_chain_file(s->ctx, cert_file); if (ret != 1) { /* fprintf(stderr, "ret is %d, errcode is %lu, %lu, with file \"%s\"\n", ret, ERR_peek_error(), ERR_peek_last_error(), cert_file); */ if (ERR_peek_last_error() != 0) { //_setSSLError(NULL, ret, __FILE__, __LINE__); ZCERROR("peek last error failed:%d", ret); goto zc_socket_ssl_fail; } } } /* ssl compatibility */ SSL_CTX_set_options(s->ctx, SSL_OP_ALL); int verification_mode = SSL_VERIFY_NONE; if (certreq == ZC_SSL_CERT_OPTIONAL) verification_mode = SSL_VERIFY_PEER; else if (certreq == ZC_SSL_CERT_REQUIRED) verification_mode = (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT); SSL_CTX_set_verify(s->ctx, verification_mode, NULL); /* set verify lvl */ s->ssl = SSL_new(s->ctx); /* New ssl struct */ SSL_set_fd(s->ssl, s->fd); /* Set the socket for SSL */ #ifdef SSL_MODE_AUTO_RETRY SSL_set_mode(s->ssl, SSL_MODE_AUTO_RETRY); #endif /* If the socket is in non-blocking mode or timeout mode, set the BIO * to non-blocking mode (blocking is the default) */ if (!s->blocked) { /* Set both the read and write BIO's to non-blocking mode */ BIO_set_nbio(SSL_get_rbio(s->ssl), 1); BIO_set_nbio(SSL_get_wbio(s->ssl), 1); } if (isclient) { SSL_set_connect_state(s->ssl); }else{ SSL_set_accept_state(s->ssl); } if (isclient) { ret = zc_socket_ssl_handshake(s); if (ret != ZC_OK) { ZCERROR("ssl handshake error: %d", ret); goto zc_socket_ssl_fail; } } return ZC_OK; zc_socket_ssl_fail: if (errstr) { ZCERROR("ssl error: %s\n", errstr); } return -1; }
static PySSLObject * newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file, enum py_ssl_server_or_client socket_type, enum py_ssl_cert_requirements certreq, enum py_ssl_version proto_version, char *cacerts_file) { PySSLObject *self; char *errstr = NULL; int ret; int verification_mode; self = PyObject_New(PySSLObject, &PySSL_Type); /* Create new object */ if (self == NULL) return NULL; self->peer_cert = NULL; self->ssl = NULL; self->ctx = NULL; self->Socket = NULL; /* Make sure the SSL error state is initialized */ (void) ERR_get_state(); ERR_clear_error(); if ((key_file && !cert_file) || (!key_file && cert_file)) { errstr = ERRSTR("Both the key & certificate files " "must be specified"); goto fail; } if ((socket_type == PY_SSL_SERVER) && ((key_file == NULL) || (cert_file == NULL))) { errstr = ERRSTR("Both the key & certificate files " "must be specified for server-side operation"); goto fail; } PySSL_BEGIN_ALLOW_THREADS if (proto_version == PY_SSL_VERSION_TLS1) self->ctx = SSL_CTX_new(TLSv1_method()); /* Set up context */ else if (proto_version == PY_SSL_VERSION_SSL3) self->ctx = SSL_CTX_new(SSLv3_method()); /* Set up context */ else if (proto_version == PY_SSL_VERSION_SSL2) self->ctx = SSL_CTX_new(SSLv2_method()); /* Set up context */ else if (proto_version == PY_SSL_VERSION_SSL23) self->ctx = SSL_CTX_new(SSLv23_method()); /* Set up context */ PySSL_END_ALLOW_THREADS if (self->ctx == NULL) { errstr = ERRSTR("Invalid SSL protocol variant specified."); goto fail; } if (certreq != PY_SSL_CERT_NONE) { if (cacerts_file == NULL) { errstr = ERRSTR("No root certificates specified for " "verification of other-side certificates."); goto fail; } else { PySSL_BEGIN_ALLOW_THREADS ret = SSL_CTX_load_verify_locations(self->ctx, cacerts_file, NULL); PySSL_END_ALLOW_THREADS if (ret != 1) { _setSSLError(NULL, 0, __FILE__, __LINE__); goto fail; } } } if (key_file) { PySSL_BEGIN_ALLOW_THREADS ret = SSL_CTX_use_PrivateKey_file(self->ctx, key_file, SSL_FILETYPE_PEM); PySSL_END_ALLOW_THREADS if (ret != 1) { _setSSLError(NULL, ret, __FILE__, __LINE__); goto fail; } PySSL_BEGIN_ALLOW_THREADS ret = SSL_CTX_use_certificate_chain_file(self->ctx, cert_file); PySSL_END_ALLOW_THREADS if (ret != 1) { /* fprintf(stderr, "ret is %d, errcode is %lu, %lu, with file \"%s\"\n", ret, ERR_peek_error(), ERR_peek_last_error(), cert_file); */ if (ERR_peek_last_error() != 0) { _setSSLError(NULL, ret, __FILE__, __LINE__); goto fail; } } } /* ssl compatibility */ SSL_CTX_set_options(self->ctx, SSL_OP_ALL); verification_mode = SSL_VERIFY_NONE; if (certreq == PY_SSL_CERT_OPTIONAL) verification_mode = SSL_VERIFY_PEER; else if (certreq == PY_SSL_CERT_REQUIRED) verification_mode = (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT); SSL_CTX_set_verify(self->ctx, verification_mode, NULL); /* set verify lvl */ PySSL_BEGIN_ALLOW_THREADS self->ssl = SSL_new(self->ctx); /* New ssl struct */ PySSL_END_ALLOW_THREADS SSL_set_fd(self->ssl, Sock->sock_fd); /* Set the socket for SSL */ /* If the socket is in non-blocking mode or timeout mode, set the BIO * to non-blocking mode (blocking is the default) */ if (Sock->sock_timeout >= 0.0) { /* Set both the read and write BIO's to non-blocking mode */ BIO_set_nbio(SSL_get_rbio(self->ssl), 1); BIO_set_nbio(SSL_get_wbio(self->ssl), 1); } PySSL_BEGIN_ALLOW_THREADS if (socket_type == PY_SSL_CLIENT) SSL_set_connect_state(self->ssl); else SSL_set_accept_state(self->ssl); PySSL_END_ALLOW_THREADS self->Socket = PyWeakref_NewRef((PyObject *) Sock, Py_None); return self; fail: if (errstr) PyErr_SetString(PySSLErrorObject, errstr); Py_DECREF(self); return NULL; }
static unsigned long get_error_values(int inc, int top, const char **file, int *line, const char **data, int *flags) { int i = 0; ERR_STATE *es; unsigned long ret; es = ERR_get_state(); if (es == NULL) return 0; if (inc && top) { if (file) *file = ""; if (line) *line = 0; if (data) *data = ""; if (flags) *flags = 0; return ERR_R_INTERNAL_ERROR; } while (es->bottom != es->top) { if (es->err_flags[es->top] & ERR_FLAG_CLEAR) { err_clear(es, es->top); es->top = es->top > 0 ? es->top - 1 : ERR_NUM_ERRORS - 1; continue; } i = (es->bottom + 1) % ERR_NUM_ERRORS; if (es->err_flags[i] & ERR_FLAG_CLEAR) { es->bottom = i; err_clear(es, es->bottom); continue; } break; } if (es->bottom == es->top) return 0; if (top) i = es->top; /* last error */ else i = (es->bottom + 1) % ERR_NUM_ERRORS; /* first error */ ret = es->err_buffer[i]; if (inc) { es->bottom = i; es->err_buffer[i] = 0; } if (file != NULL && line != NULL) { if (es->err_file[i] == NULL) { *file = "NA"; *line = 0; } else { *file = es->err_file[i]; *line = es->err_line[i]; } } if (data == NULL) { if (inc) { err_clear_data(es, i); } } else { if (es->err_data[i] == NULL) { *data = ""; if (flags != NULL) *flags = 0; } else { *data = es->err_data[i]; if (flags != NULL) *flags = es->err_data_flags[i]; } } return ret; }
int main(int argc, char *argv[]) { // default paths currently point to my test certificates char *m_caCertPath; char *m_serverCert; char *m_serverKey; char *stoparg; m_caCertPath= argv[1]; fprintf(stdout, "phase1\n"); m_serverCert = strchr(m_caCertPath, ';'); fprintf(stdout, "phase2\n"); *m_serverCert++ ='\0'; m_serverKey = strchr(m_serverCert, ';'); fprintf(stdout, "phase3\n"); *m_serverKey++ ='\0'; stoparg = strchr(m_serverKey, ';'); fprintf(stdout, "phase4\n"); *stoparg++ = '\0'; fprintf(stdout, "ca:%s\ncert:%s\nkey:%s\nstop:%s\n", m_caCertPath, m_serverCert, m_serverKey, stoparg); SSL_CTX *m_sslCtx = NULL; // Initializing OpenSSL // FIXME should this only be called once? OpenSSL_add_all_algorithms(); SSLeay_add_all_algorithms(); SSL_load_error_strings(); ERR_load_crypto_strings(); ERR_load_BIO_strings(); SSL_library_init(); m_sslCtx = SSL_CTX_new( SSLv23_method() ); if (!m_sslCtx) { ERR_print_errors_fp( stdout ); printf("error1\n"); } SSL_CTX_set_options(m_sslCtx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); /* SSL_CTX_set_cipher_list(m_sslCtx, "ALL:!LOW:!EXP:!MD5:!MD2"); */ SSL_CTX_set_purpose(m_sslCtx, X509_PURPOSE_ANY); /* SSL_CTX_set_mode(m_sslCtx, SSL_MODE_AUTO_RETRY); */ printf("test\n"); // load server certificate if ( SSL_CTX_use_certificate_file( m_sslCtx, m_serverCert, SSL_FILETYPE_PEM ) <= 0 ) { ERR_print_errors_fp( stdout ); printf("error1\n"); } // load private key if ( SSL_CTX_use_PrivateKey_file( m_sslCtx, m_serverKey, SSL_FILETYPE_PEM) <= 0 ) { ERR_print_errors_fp( stdout ); printf("error2\n"); } // load trusted Certificate Authority if ( !SSL_CTX_load_verify_locations( m_sslCtx, 0, m_caCertPath ) ) { ERR_print_errors_fp( stdout ); printf("error3\n"); } // require peer (client) certificate verification SSL_CTX_set_verify( m_sslCtx, SSL_VERIFY_PEER, 0 ); // Set the verification depth to 1 SSL_CTX_set_verify_depth( m_sslCtx, 100 ); // set the verify call back to girdsite, which understands // proxy certificates SSL_CTX_set_cert_verify_callback( m_sslCtx, proxy_verify_callback_server, 0); // create new ssl structure and pass the fd to it SSL *m_sslCon = SSL_new( m_sslCtx ); BIO *bio = BIO_new_accept("33334"); if (BIO_do_accept(bio) <= 0) fprintf(stdout, "BIO_do_accept failed\n"); fprintf(stdout, "now accepting\n"); fprintf(stdout, "bio=%ld\n", bio); BIO_do_accept(bio); fprintf(stdout, "part1\n"); BIO *client= BIO_pop(bio); fprintf(stdout, "part2\n"); SSL_set_bio(m_sslCon, client, client); fprintf(stdout,"bio set\n"); // initiate the handshake int error; if ( (error = SSL_accept( m_sslCon )) <= 0 ) { unsigned long l; char buf[256]; #if SSLEAY_VERSION_NUMBER >= 0x00904100L const char *file; #else char *file; #endif char *dat; int line; /* WIN32 does not have the ERR_get_error_line_data */ /* exported, so simulate it till it is fixed */ /* in SSLeay-0.9.0 */ while ( ERR_peek_error() != 0 ) { int i; ERR_STATE *es; es = ERR_get_state(); i = (es->bottom+1)%ERR_NUM_ERRORS; if (es->err_data[i] == NULL) dat = (char*)""; else dat = es->err_data[i]; if (dat) { l = ERR_get_error_line(&file, &line); // if (debug) fprintf(stdout, "%s:%s,%d,%s\n", ERR_error_string(l, buf), file, line, dat); // error += std::string(ERR_reason_error_string(l)) + ":" + std::string(ERR_func_error_string(l)) + "\n"; } } /* fprintf(stdout, "%s\n", */ /* ERR_reason_error_string( ERR_get_error() )); */ fprintf(stdout, "ERROR\n"); exit(1); } fprintf(stdout, "Handshake done!\n"); /* connected */ sleep(100); exit(0); }