int modssl_smart_shutdown(SSL *ssl) { int i; int rc; int flush; /* * Repeat the calls, because SSL_shutdown internally dispatches through a * little state machine. Usually only one or two interation should be * needed, so we restrict the total number of restrictions in order to * avoid process hangs in case the client played bad with the socket * connection and OpenSSL cannot recognize it. */ rc = 0; flush = !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN); for (i = 0; i < 4 /* max 2x pending + 2x data = 4 */; i++) { rc = SSL_shutdown(ssl); if (rc >= 0 && flush && (SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) { /* Once the close notity is sent through the output filters, * ensure it is flushed through the socket. */ if (BIO_flush(SSL_get_wbio(ssl)) <= 0) { rc = -1; break; } flush = 0; } if (rc != 0) break; } return rc; }
static int ssl_read_common(struct vsf_session* p_sess, SSL* p_void_ssl, char* p_buf, unsigned int len, int (*p_ssl_func)(SSL*, void*, int)) { int retval; int err; SSL* p_ssl = (SSL*) p_void_ssl; do { retval = (*p_ssl_func)(p_ssl, p_buf, len); err = SSL_get_error(p_ssl, retval); } while (retval < 0 && (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)); /* If we hit an EOF, make sure it was from the peer, not injected by the * attacker. */ if (retval == 0 && SSL_get_shutdown(p_ssl) != SSL_RECEIVED_SHUTDOWN) { str_alloc_text(&debug_str, "Connection terminated without SSL shutdown " "- buggy client?"); vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); if (tunable_strict_ssl_read_eof) { return -1; } } return retval; }
int SslConnection::read(void* dst, int max) { int res = SSL_read(mSession, dst, max); if(res == 0) if(SSL_get_shutdown(mSession)) return CONNERR_CLOSED; TSSLLTZ(res); return res; }
static void process(SSL* ssl) { char buf[1024]; int sd, bytes; strcpy(buf, "Hello World\n"); if (SSL_connect(ssl) != 1) { ERR_print_errors_fp(stderr); goto out; } show_certificates(ssl); while (1) { bytes = SSL_write(ssl, buf, sizeof(buf)); if (bytes > 0) { printf("received from client: \"%s\"\n", buf); SSL_write(ssl, buf, bytes); } else { ERR_print_errors_fp(stderr); break; } if (SSL_get_shutdown(ssl) == SSL_RECEIVED_SHUTDOWN) { SSL_shutdown(ssl); break; } } out: sd = SSL_get_fd(ssl); SSL_free(ssl); close(sd); }
static void maybe_log_shutdown_state(struct vsf_session* p_sess) { if (tunable_debug_ssl) { int ret = SSL_get_shutdown(p_sess->p_data_ssl); str_alloc_text(&debug_str, "SSL shutdown state is: "); if (ret == 0) { str_append_text(&debug_str, "NONE"); } else if (ret == SSL_SENT_SHUTDOWN) { str_append_text(&debug_str, "SSL_SENT_SHUTDOWN"); } else if (ret == SSL_RECEIVED_SHUTDOWN) { str_append_text(&debug_str, "SSL_RECEIVED_SHUTDOWN"); } else { str_append_ulong(&debug_str, ret); } vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); } }
/* checks if ssl object was closed and can be removed */ int check_close(SSL *ssl) { int res, err, idx; struct sockaddr_storage peer; memset(&peer, 0, sizeof(peer)); (void)BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer); res = 0; if (SSL_get_shutdown(ssl) & SSL_RECEIVED_SHUTDOWN) { printf("SSL_RECEIVED_SHUTDOWN\n"); res = SSL_shutdown(ssl); if (res == 0) { printf("must call SSL_shutdown again\n"); res = SSL_shutdown(ssl); } if (res < 0) { err = SSL_get_error(ssl,res); fprintf(stderr, "shutdown: SSL error %d: %s\n", err, ERR_error_string(err, NULL)); } /* we can close the SSL object anyway */ /* FIXME: need to get ifindex from somewhere */ idx = get_index_of_peer((struct sockaddr *)&peer, 0); OPENSSL_assert(idx < 0 || ssl == ssl_peer_storage[idx]->ssl); if (idx >= 0) { ssl_peer_storage[idx]->state = PEER_ST_CLOSED; printf("moved SSL object %d to CLOSED\n",idx); } } return res; }
bool Connection::isShutdown() const { int state = SSL_get_shutdown(_ssl); log_debug("SSL_get_shutdown() = " << state); return state != 0; }
/* TLSClose(NULL,0) 全TLSセッションのキャッシュをクリアとCTXインスタンスの解放 TLSClose(NULL,1) 全TLSセッションのキャッシュをクリア TLSClose(SSL,0) 指定されたSSLのシャットダウン TLSClose(SSL,1) 指定されたSSLのシャットダウンかつTLSセッションのキャッシュをクリア */ static void TLSClose(SSL *ssl,int clr) { int ret1,ret2,ret3=0; if(ssl){ ret1=SSL_get_shutdown(ssl); ret2=SSL_shutdown(ssl); if(!TLSSessionMode || clr){ ret3=SSL_clear(ssl); SSL_free(ssl); kSocketTLSClose(ssl); } kLogWrite(L_TLS,"%s: SSL[%x] SSL_get_shutdown[%d] SSL_shutdown[%d] SSL_clear[%d]",__FUNCTION__,ssl,ret1,ret2,ret3); } else{ extern SocketInfo *g_socket_start_ptr; SocketInfo *current_position = g_socket_start_ptr; while(current_position){ if(current_position->si_tls_ssl_ptr) { ret3=SSL_clear((SSL*)current_position->si_tls_ssl_ptr); SSL_free((SSL*)current_position->si_tls_ssl_ptr); current_position->si_tls_ssl_ptr=NULL; kLogWrite(L_TLS,"%s: SSL[%x] SSL_clear[%d]",__FUNCTION__,ssl,ret3); } current_position = current_position->si_next_socket_info_ptr; } if(!clr){ if(!TLSctx) return; SSL_CTX_free(TLSctx); ERR_free_strings(); TLSctx=NULL; } } }
static int ssl_socket_close(conn_t * conn) { int ret; SSL *ssl = (SSL *) conn->ssl; if (ssl) { /* * due to the bidirectional shutdown */ if(((ret = SSL_shutdown(ssl)) == 0) && (SSL_get_shutdown(ssl) & SSL_RECEIVED_SHUTDOWN)) ret = SSL_shutdown(ssl); if (ret < 0) { switch (SSL_get_error(ssl, ret)) { case SSL_ERROR_ZERO_RETURN: /* Ah, well */ break; case SSL_ERROR_SYSCALL: case SSL_ERROR_SSL: break; } } SSL_free(ssl); conn->ssl = 0; } return close(conn->fd); }
void Connection::writeData(char* pData, unsigned int len) { int r = 0; // Write data to the wire r = SSL_write(m_ssl, pData, len); // Check to see if the connection was closed or there was a problem sending the data. Either way, DC if((r <= 0) || (SSL_get_shutdown(m_ssl) != 0)) { std::cout << "Client closed the connection or there was a write error\n"; m_runMutex.lock(); m_connected = false; m_runMutex.unlock(); } // If data was written, print it out if(r > 0) { std::cout << "Wrote " << len << " bytes to client:\n"; for(unsigned int i = 0; i < len; i++) { printf("0x%X ", pData[i]); } std::cout << "\n"; for(unsigned int i = 0; i < len; i++) { printf("%c", pData[i]); } std::cout << "\n"; } }
void SecureSocketImpl::shutdown() { if (_pSSL) { // Don't shut down the socket more than once. int shutdownState = SSL_get_shutdown(_pSSL); bool shutdownSent = (shutdownState & SSL_SENT_SHUTDOWN) == SSL_SENT_SHUTDOWN; if (!shutdownSent) { // A proper clean shutdown would require us to // retry the shutdown if we get a zero return // value, until SSL_shutdown() returns 1. // However, this will lead to problems with // most web browsers, so we just set the shutdown // flag by calling SSL_shutdown() once and be // done with it. int rc = SSL_shutdown(_pSSL); if (rc < 0) handleError(rc); if (_pSocket->getBlocking()) { _pSocket->shutdown(); } } } }
int _ssl_close(nsp_state *N, TCP_SOCKET *sock) { #define __FN__ __FILE__ ":_ssl_close()" #if defined HAVE_OPENSSL if (sock->ssl != NULL) { if (SSL_get_shutdown(sock->ssl)&SSL_RECEIVED_SHUTDOWN) { SSL_shutdown(sock->ssl); } else { SSL_clear(sock->ssl); } } if (sock->socket > -1) { shutdown(sock->socket, 2); closesocket(sock->socket); sock->socket = -1; } if (sock->ssl != NULL) { SSL_free(sock->ssl); sock->ssl = NULL; } return 0; #elif defined HAVE_MBEDTLS mbedtls_ssl_close_notify(&sock->ssl); if (sock->socket > -1) { shutdown(sock->socket, 2); closesocket(sock->socket); sock->socket = -1; } return 0; #endif #undef __FN__ }
static ioa_socket_handle dtls_server_input_handler(dtls_listener_relay_server_type* server, ioa_socket_handle s, ioa_network_buffer_handle nbh) { FUNCSTART; if (!server || !nbh) { return NULL; } SSL* connecting_ssl = NULL; BIO *wbio = NULL; struct timeval timeout; /* Create BIO */ wbio = BIO_new_dgram(s->fd, BIO_NOCLOSE); (void)BIO_dgram_set_peer(wbio, (struct sockaddr*) &(server->sm.m.sm.nd.src_addr)); /* Set and activate timeouts */ timeout.tv_sec = DTLS_MAX_RECV_TIMEOUT; timeout.tv_usec = 0; BIO_ctrl(wbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); #if DTLSv1_2_SUPPORTED if(get_dtls_version(ioa_network_buffer_data(nbh), (int)ioa_network_buffer_get_size(nbh)) == 1) { connecting_ssl = SSL_NEW(server->dtls_ctx_v1_2); } else { connecting_ssl = SSL_NEW(server->dtls_ctx); } #else { connecting_ssl = SSL_NEW(server->dtls_ctx); } #endif SSL_set_accept_state(connecting_ssl); SSL_set_bio(connecting_ssl, NULL, wbio); SSL_set_options(connecting_ssl, SSL_OP_COOKIE_EXCHANGE); SSL_set_max_cert_list(connecting_ssl, 655350); ioa_socket_handle rc = dtls_accept_client_connection(server, s, connecting_ssl, &(server->sm.m.sm.nd.src_addr), &(server->addr), nbh); if (!rc) { if (!(SSL_get_shutdown(connecting_ssl) & SSL_SENT_SHUTDOWN)) { SSL_set_shutdown(connecting_ssl, SSL_RECEIVED_SHUTDOWN); SSL_shutdown(connecting_ssl); } SSL_FREE(connecting_ssl); } return rc; }
static PyObject * ssl_Connection_get_shutdown(ssl_ConnectionObj *self, PyObject *args) { if (!PyArg_ParseTuple(args, ":get_shutdown")) return NULL; return PyLong_FromLong((long)SSL_get_shutdown(self->ssl)); }
int SSL_isOpen(SSL *ssl) { if(SSL_get_shutdown(ssl) != 0) { return 0; } #ifdef WIN32 return SSL_get_wfd(ssl) != INVALID_SOCKET ? 1 : 0; #else return SSL_get_wfd(ssl) > -1 ? 1 : 0; #endif }
int vc_CLOSING_loop(struct vContext *C) { struct VC_CTX *vc_ctx = CTX_client_ctx(C); struct VDgramConn *dgram_conn = CTX_current_dgram_conn(C); int ret; /* CLOSING state */ if(is_log_level(VRS_PRINT_DEBUG_MSG)) { printf("%c[%d;%dm", 27, 1, 31); v_print_log(VRS_PRINT_DEBUG_MSG, "Client state: CLOSING\n"); printf("%c[%dm", 27, 0); } dgram_conn->state[UDP_CLIENT_STATE_CLOSING].attempts = 0; while(dgram_conn->state[UDP_CLIENT_STATE_CLOSING].attempts < vc_ctx->max_connection_attempts) { /* Send closing packet */ if( vc_CLOSING_send_packet(C) == SEND_PACKET_ERROR) { return STATE_EXIT_ERROR; } /* Try to receive packet and handle received packet */ ret = vc_receive_and_handle_packet(C, vc_CLOSING_handle_packet); if(ret == RECEIVE_PACKET_SUCCESS) { break; /* Break loop and receive to the next state */ } else if(ret == RECEIVE_PACKET_TIMEOUT) { dgram_conn->state[UDP_CLIENT_STATE_CLOSING].attempts++; /* No packet receive ... try it again */ } else if(ret == RECEIVE_PACKET_CORRUPTED) { dgram_conn->state[UDP_CLIENT_STATE_CLOSING].attempts++; /* Corrupted packet received ... try it again */ } else if(ret == RECEIVE_PACKET_FAKED) { continue; /* Packet wasn't received from the server (should not happen, because connect()) */ } else if(ret == RECEIVE_PACKET_ERROR) { return STATE_EXIT_ERROR; } #ifdef WITH_OPENSSL if(dgram_conn->io_ctx.flags & SOCKET_SECURED) { /* Did server close DTLS connection? */ if((SSL_get_shutdown(dgram_conn->io_ctx.ssl) & SSL_RECEIVED_SHUTDOWN)) { return STATE_EXIT_ERROR; } } #endif } if(dgram_conn->host_state == UDP_CLIENT_STATE_CLOSING) { if(is_log_level(VRS_PRINT_ERROR)) v_print_log(VRS_PRINT_ERROR, "Maximum count of teardown attempts reached %d.\n", vc_ctx->max_connection_attempts); return STATE_EXIT_ERROR; } return STATE_EXIT_SUCCESS; }
SslBox_t::~SslBox_t() { // Freeing pSSL will also free the associated BIOs, so DON'T free them separately. if (pSSL) { if (SSL_get_shutdown (pSSL) & SSL_RECEIVED_SHUTDOWN) SSL_shutdown (pSSL); else SSL_clear (pSSL); SSL_free (pSSL); } delete Context; }
int __ssl_recv2(void *handle, char *buffer, int *length, int timeout) { ABSTRACT_SOCKET *so = handle; _SSLO *sslo = so->sslo; int ret; struct timeval to; fd_set sockSet; if (sslo == NULL) { return ERR_TR50_BADHANDLE; } if (timeout < -1) { //so->err = GETNETERR(); return ERR_TR50_SOCK_OTHER; } if (SSL_pending(sslo->ssl) == 0 && timeout > 0) { to.tv_usec = (timeout % 1000) * 1000; to.tv_sec = timeout / 1000; FD_ZERO(&sockSet); FD_SET(so->s, &sockSet); if ((ret = select(so->s + 1, &sockSet, NULL, NULL, &to)) == 0) { so->err = ERR_TR50_SOCK_TIMEOUT; return ERR_TR50_SOCK_TIMEOUT; } else if (ret == -1) { //so->err = GETNETERR(); return ERR_TR50_SOCK_OTHER; } } ret = SSL_read(sslo->ssl, buffer, *length); if (ret == -1) { *length = 0; if ((SSL_get_shutdown(sslo->ssl) & SSL_RECEIVED_SHUTDOWN)) { so->err = ERR_TR50_SOCK_SHUTDOWN; return ERR_TR50_SOCK_SHUTDOWN; } sslo->errcode = SSL_get_error(sslo->ssl, ret); //ERR_error_string_n(sslo->errcode, sslo->errmsg, SSL_ERR_STR_LEN); return ERR_TR50_SSL_GENERIC; } else if (ret == 0) { *length = 0; so->err = ERR_TR50_SOCK_SHUTDOWN; return ERR_TR50_SOCK_SHUTDOWN; } else { *length = ret; log_hexdump(LOG_TYPE_LOW_LEVEL, "_ssl_recv2()", buffer, ret); return 0; } }
bool finalize_tls_session( SSL *ssl ) { debug( "Finalizing TLS session ( ssl = %p, ctx = %p ).", ssl, ctx ); assert( ssl != NULL ); if ( SSL_get_shutdown( ssl ) != SSL_SENT_SHUTDOWN ) { // FIXME: SSL_shutdown() may return an error if underlying socket is non-blocking. SSL_shutdown( ssl ); } SSL_free( ssl ); return true; }
CAMLprim value ocaml_ssl_get_shutdown(value socket) { CAMLparam1(socket); CAMLlocal3(rcvd,sent,ret); int r; ssl_socket_t *ssl = ssl_socket_of_block(socket); r = SSL_get_shutdown(ssl->handler); rcvd = Val_bool(r & SSL_RECEIVED_SHUTDOWN); sent = Val_bool(r & SSL_SENT_SHUTDOWN); ret = alloc_tuple(2); Store_field(ret, 0, rcvd); Store_field(ret, 1, sent); CAMLreturn(ret); }
/* Return values: * 1 Success * 0 Failure. Remove this connection */ int IpfixReceiverDtlsSctpIpV4::DtlsConnection::fdready() { int ret, error; boost::shared_array<uint8_t> data(new uint8_t[MAX_MSG_LEN]); if (socket < 0) return 0; ret = SSL_read(ssl,data.get(),MAX_MSG_LEN); error = SSL_get_error(ssl,ret); #ifdef DEBUG msg_openssl_return_code(MSG_DEBUG,"SSL_read()",ret,error); DPRINTF("Error: %s",strerror(errno)); DPRINTF("Received shutdown: %s",SSL_get_shutdown(ssl) & SSL_RECEIVED_SHUTDOWN ? "yes":"no"); #endif if (ret<0) { if (error == SSL_ERROR_WANT_READ) { FD_SET(socket,&parent.readfds); FD_CLR(socket,&parent.writefds); return 1; } else if (error == SSL_ERROR_WANT_WRITE) { FD_SET(socket,&parent.writefds); FD_CLR(socket,&parent.readfds); return 1; } msg_openssl_return_code(MSG_ERROR,"SSL_read()",ret,error); msg_openssl_errors(); shutdown(); return 0; } else if (ret==0) { if (error == SSL_ERROR_ZERO_RETURN) { // remote side closed connection DPRINTF("remote side closed connection."); } else { msg_openssl_return_code(MSG_ERROR,"SSL_read()",ret,error); msg_openssl_errors(); } shutdown(); return 0; } else { DPRINTF("SSL_read() returned %d bytes.",ret); } parent.statReceivedPackets++; parent.mutex.lock(); for (std::list<IpfixPacketProcessor*>::iterator i = parent.packetProcessors.begin(); i != parent.packetProcessors.end(); ++i) { (*i)->processPacket(data, ret, sourceID); } parent.mutex.unlock(); return 1; }
int do_server_loop(SSL *ssl) { int err, nread; char buf[80]; for (;;) { for (nread = 0; nread < sizeof(buf); nread += err) { err = SSL_read(ssl, buf + nread, sizeof(buf) - nread); if (err <= 0) break; } fwrite(buf, 1, nread, stdout); } return (SSL_get_shutdown(ssl) & SSL_RECEIVED_SHUTDOWN) ? 1 : 0; }
static ioa_socket_handle dtls_server_input_handler(dtls_listener_relay_server_type* server, u08bits *buf, int len) { FUNCSTART; if (!server || !buf || len<1) { return NULL; } SSL* connecting_ssl = NULL; BIO *wbio = NULL; struct timeval timeout; /* Create BIO */ wbio = BIO_new_dgram(server->udp_listen_s->fd, BIO_NOCLOSE); (void)BIO_dgram_set_peer(wbio, (struct sockaddr*) &(server->sm.m.sm.nd.src_addr)); /* Set and activate timeouts */ timeout.tv_sec = DTLS_MAX_RECV_TIMEOUT; timeout.tv_usec = 0; BIO_ctrl(wbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); connecting_ssl = SSL_new(server->dtls_ctx); SSL_set_accept_state(connecting_ssl); SSL_set_bio(connecting_ssl, NULL, wbio); SSL_set_options(connecting_ssl, SSL_OP_COOKIE_EXCHANGE); SSL_set_max_cert_list(connecting_ssl, 655350); ioa_socket_handle rc = dtls_accept_client_connection(server, connecting_ssl, &(server->sm.m.sm.nd.src_addr), &(server->addr), buf, len); if (!rc) { if (!(SSL_get_shutdown(connecting_ssl) & SSL_SENT_SHUTDOWN)) { SSL_set_shutdown(connecting_ssl, SSL_RECEIVED_SHUTDOWN); SSL_shutdown(connecting_ssl); } SSL_free(connecting_ssl); } return rc; }
static int openssl_ssl_shutdown(lua_State*L) { SSL* s = CHECK_OBJECT(1, SSL, "openssl.ssl"); int ret = 0; if (lua_isnoneornil(L, 2)) { ret = SSL_shutdown(s); return openssl_ssl_pushresult(L, s, ret); } else if (lua_isstring(L, 2)) { const static char* sMode[] = {"read", "write", "quiet", "noquiet", NULL}; int mode = luaL_checkoption(L, 2, NULL, sMode); if (mode == 0) SSL_set_shutdown(s, SSL_RECEIVED_SHUTDOWN); else if (mode == 1) SSL_set_shutdown(s, SSL_SENT_SHUTDOWN); else if (mode == 2) SSL_set_quiet_shutdown(s, 1); else if (mode == 3) SSL_set_quiet_shutdown(s, 0); } else if (lua_isboolean(L, 2)) { int quiet = lua_toboolean(L, 2); if (quiet) lua_pushboolean(L, SSL_get_quiet_shutdown(s)); else { int shut = SSL_get_shutdown(s); if (shut == SSL_RECEIVED_SHUTDOWN) lua_pushstring(L, "read"); else if (shut == SSL_SENT_SHUTDOWN) lua_pushstring(L, "write"); else if (shut == 0) lua_pushnil(L); else luaL_error(L, "Can't understand SSL_get_shutdown result"); } return 1; } else luaL_argerror(L, 2, "should be boolean or string[read|write|quiet|noquite]"); return 0; };
int do_server_loop(SSL *ssl) { int err, nread; char buf[80]; do { for (nread = 0; nread < sizeof(buf); nread += err) { err = SSL_read(ssl, buf + nread, sizeof(buf) - nread); if (err <= 0) break; } fprintf(stdout, "%s", buf); } while (err > 0); return (SSL_get_shutdown(ssl) & SSL_RECEIVED_SHUTDOWN) ? 1 : 0; }
//void do_server(BIO *conn) int do_server(SSL *ssl) { int err, rd; char buf[80]; do { for(rd = 0; rd < sizeof(buf); rd += err) { err = SSL_read(ssl, buf+rd, sizeof(buf) - rd); if(err <= 0) break; } fwrite(buf, 1, rd, stdout); } while(err > 0); if(SSL_get_shutdown(ssl) & SSL_RECEIVED_SHUTDOWN) return 1; else return 0; }
static int tls_error(tls_t *tls, int ret, char const *who, void *buf, int size) { int events = 0; int err = SSL_get_error(tls->con, ret); switch (err) { case SSL_ERROR_WANT_WRITE: events = SU_WAIT_OUT; break; case SSL_ERROR_WANT_READ: events = SU_WAIT_IN; break; case SSL_ERROR_ZERO_RETURN: return 0; case SSL_ERROR_SYSCALL: if (SSL_get_shutdown(tls->con) & SSL_RECEIVED_SHUTDOWN) return 0; /* EOS */ if (errno == 0) return 0; /* EOS */ return -1; default: tls_log_errors(1, who, err); errno = EIO; return -1; } if (buf) { tls->write_events = events; tls->write_buffer = buf, tls->write_buffer_len = size; } else { tls->read_events = events; } errno = EAGAIN; return -1; }
int doServerSSL (SSL* ssl) { char msg[128]; // this is the buffer that will be executed int bytes_read = 0; memset (msg, '\0', 128); //printf ("Waiting for msg\n"); putchar ('3'); putchar ('\n'); if ((bytes_read = SSL_read (ssl, msg, sizeof (msg) - 1) ) <= 0) { int err = SSL_get_error (ssl, bytes_read); if (bytes_read == 0) { //The read operation was not successful. if (SSL_get_shutdown (ssl) == SSL_RECEIVED_SHUTDOWN) { // The reason was a clean shutdown due to a ``close notify'' alert sent by the peer return 0; } if (err == SSL_ERROR_ZERO_RETURN) { // The reason was an incomplete shutdown return 0; } } if (bytes_read < 0) { //The read operation was not successful, because either an error occurred or action must be taken by the calling process. SSL_errmsg (ssl, err); } fprintf (stderr, "Bytes_read: %d, SSL_get_error: %d\n", bytes_read, err); errmesg ("SSL_read error"); } //printf ("Msg recv'd\n"); putchar ('4'); putchar ('\n'); if (bytes_read == 1 && msg[0] == '\n') { return 0; } msg[bytes_read] = 0; putchar ('5'); putchar ('\n'); logMsg (msg); putchar ('7'); putchar ('\n'); memset (msg, '\0', 128); sprintf (msg, "Msg of %uB recv'd and logged, secret: 0x%08x\n", bytes_read, (unsigned int) msg); if (SSL_write (ssl, msg, strlen (msg) ) < 0) { return -1; } return bytes_read; } // end fn doServer
int do_server_loop(SSL *ssl) { int err, nread; char buf[80]; do { for (nread = 0; nread < sizeof(buf); nread += err) { err = SSL_read(ssl, buf + nread, sizeof(buf) - nread); if (err <= 0) break; } fprintf(stdout, "%s", buf); } while (err > 0); // use a call to SSL_get_shutdown to check into the error status // of the SSL object. This allows us to differentiate normal // client terminations from actual errors. // If SSL_RECEIVERD_SHUTDOWN flag is set, we knowthe session // hasn't had an error and it's safe to cache. In other words, // we can call SSL_shutdown rather simply clear the connection. return (SSL_get_shutdown(ssl) & SSL_RECEIVED_SHUTDOWN) ? 1 : 0; }
void SSLAdapter::shutdown() { TraceLS(this) << "Shutdown" << endl; if (_ssl) { TraceLS(this) << "Shutdown SSL" << endl; // Don't shut down the socket more than once. int shutdownState = SSL_get_shutdown(_ssl); bool shutdownSent = (shutdownState & SSL_SENT_SHUTDOWN) == SSL_SENT_SHUTDOWN; if (!shutdownSent) { // A proper clean shutdown would require us to // retry the shutdown if we get a zero return // value, until SSL_shutdown() returns 1. // However, this will lead to problems with // most web browsers, so we just set the shutdown // flag by calling SSL_shutdown() once and be // done with it. int rc = SSL_shutdown(_ssl); if (rc < 0) handleError(rc); } } }