/* sock_peek is recv(...,MSG_PEEK) with a timeout of SOCKET_TIMEOUT. * Returns length of data read or SOCK_* on error */ int sock_peek(nsocket *sock, char *buffer, size_t count) { int ret; ret = sock_block(sock, SOCKET_READ_TIMEOUT); if (ret < 0) { return ret; } /* Got data */ #ifdef ENABLE_SSL if (sock->ssl) { ret = SSL_peek(sock->ssl, buffer, count); /* TODO: This is the fetchmail fix as in sock_readline. * Do we really need it? */ if (ret == 0) { if (sock->ssl->shutdown) { return SOCK_CLOSED; } if (0 != ERR_get_error()) { sock->error = ERROR_SSL_STRING; return SOCK_ERROR; } } } else { #endif do { #ifndef BEOS_PRE_BONE ret = recv(sock->fd, buffer, count, MSG_PEEK); #else /* we're on BeOS pre-BONE so we need to use the buffer... */ if (sock->peeked_bytes_avail > 0) { /* we've got some from last time!!! */ if (count >= sock->peeked_bytes_avail) { strncpy(buffer, sock->peeked_bytes_curpos, sock->peeked_bytes_avail); ret = sock->peeked_bytes_avail; } else { strncpy(buffer, sock->peeked_bytes_curpos, count); ret = count; } } else { if (count > MAX_PEEK_BUFFER) count = MAX_PEEK_BUFFER; ret = recv(sock->fd, buffer, count, 0); sock->peeked_bytes_avail = ret; strncpy(sock->peeked_bytes, buffer, ret); sock->peeked_bytes_curpos = sock->peeked_bytes; } #endif } while (ret == -1 && errno == EINTR); #ifdef ENABLE_SSL } #endif /* According to the Single Unix Spec, recv() will return * zero if the socket has been closed the other end. */ if (ret == 0) { ret = SOCK_CLOSED; } else if (ret < 0) { sock->error = strerror(errno); ret = SOCK_ERROR; } return ret; }
gint ssl_peek(SSL *ssl, gchar *buf, gint len) { gint err, ret; if (SSL_pending(ssl) == 0) { if (fd_check_io(SSL_get_rfd(ssl), G_IO_IN) < 0) return -1; } ret = SSL_peek(ssl, buf, len); switch ((err = SSL_get_error(ssl, ret))) { case SSL_ERROR_NONE: return ret; case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: errno = EAGAIN; return -1; case SSL_ERROR_ZERO_RETURN: return 0; default: g_warning("SSL_peek() returned error %d, ret = %d\n", err, ret); if (ret == 0) return 0; return -1; } }
int SSLSocket::wait(uint32_t millis, int waitFor) throw(SocketException) { if(ssl && (waitFor & Socket::WAIT_READ)) { /** @todo Take writing into account as well if reading is possible? */ char c; if(SSL_peek(ssl, &c, 1) > 0) return WAIT_READ; } return Socket::wait(millis, waitFor); }
std::pair<bool, bool> SSLSocket::wait(uint64_t millis, bool checkRead, bool checkWrite) { if(ssl && checkRead) { /** @todo Take writing into account as well if reading is possible? */ char c; if(SSL_peek(ssl, &c, 1) > 0) return std::make_pair(true, false); } return Socket::wait(millis, checkRead, checkWrite); }
int ssl_client_peek(ssl_client * cli, void * buffer, size_t length){ socklen_t len = SSL_peek(cli->ssl, buffer, length); int accepted[] = {SSL_ERROR_WANT_READ, SSL_ERROR_ZERO_RETURN}; int code[] = {-1, -2}; int ecode = handle_ssl_error2(cli->ssl, len, accepted, code, array_count(accepted)); if(ecode < 0) return ecode; return len; }
bool GSISocketServer::Peek(int bufsize, std::string& s) { if (!ssl) { SetError("No connection established"); return false; } ERR_clear_error(); int ret = -1, ret2 = -1; char *buffer = (char *)OPENSSL_malloc(bufsize); int fd = BIO_get_fd(SSL_get_rbio(ssl), NULL); time_t starttime, curtime; int error = 0; int expected = 0; starttime = time(NULL); do { ret = do_select(fd, starttime, timeout, expected); curtime = time(NULL); if (ret > 0) { ret2 = SSL_peek(ssl, buffer, bufsize); if (ret2 <= 0) expected = error = SSL_get_error(ssl, ret2); } } while ((ret > 0) && ((ret2 <= 0) && (((timeout == -1) || ((timeout != -1) && (curtime - starttime < timeout))) && ((error == SSL_ERROR_WANT_READ) || (error == SSL_ERROR_WANT_WRITE))))); if (ret <= 0 || ret2 <= 0) { if (timeout != -1 && (curtime - starttime >= timeout)) SetError("Connection stuck during read: timeout reached."); else SetErrorOpenSSL("Error during SSL read:"); OPENSSL_free(buffer); ERR_clear_error(); return false; } s = std::string(buffer, ret2); OPENSSL_free(buffer); ERR_clear_error(); return true; }
int HttpsRetriever::openssl_peek (int fd, char *buf, int bufsize, void *ctx) { int ret; SSL *ssl = (SSL *) ctx; do ret = SSL_peek (ssl, buf, bufsize); while (ret == -1 && SSL_get_error (ssl, ret) == SSL_ERROR_SYSCALL && errno == EINTR); return ret; }
int SSLSocket::wait(uint64_t millis, int waitFor) { #ifdef HEADER_OPENSSLV_H if (ssl && (waitFor & Socket::WAIT_READ)) { /** @todo Take writing into account as well if reading is possible? */ char c; if (SSL_peek(ssl, &c, 1) > 0) return WAIT_READ; } #endif return Socket::wait(millis, waitFor); }
static int openssl_peek (int fd, char *buf, int bufsize, void *arg) { int ret; struct openssl_transport_context *ctx = arg; SSL *conn = ctx->conn; do ret = SSL_peek (conn, buf, bufsize); while (ret == -1 && SSL_get_error (conn, ret) == SSL_ERROR_SYSCALL && errno == EINTR); return ret; }
int rocksock_ssl_peek(rocksock* sock, int *result) { char buf[4]; int ret; ret = SSL_peek(sock->ssl, buf, 1); if(ret >= 0) *result = 1; else { ret = SSL_get_error(sock->ssl, ret); if(ret == SSL_ERROR_WANT_READ) return rocksock_seterror(sock, RS_ET_OWN, RS_E_HIT_READTIMEOUT, ROCKSOCK_FILENAME, __LINE__); return rocksock_seterror(sock, RS_ET_SSL, ret, ROCKSOCK_FILENAME, __LINE__); } return rocksock_seterror(sock, RS_ET_OWN, 0, NULL, 0); }
/* Return value: * >0: the number of bytes actually read from SSL connection * SSL_AGAIN: need to read again * SSL_ERROR: failed, call ossSSLGetError() & ossSSLGetErrorMessage() for reason * SSL_TIMEOUT: only in windows * * NOTE: in constrast to the ossSSLRead(), the data in the SSL buffer is unmodified * after the ossSSLPeek() opertaion */ INT32 ossSSLPeek(SSLHandle* handle, void* buf, INT32 num) { INT32 status; INT32 ret = SSL_OK; SSL_ASSERT(NULL != handle); SSL_ASSERT(NULL != handle->ssl); SSL_ASSERT(NULL != buf); status = SSL_peek(handle->ssl, buf, num); ret = _ossSSLCheckStatus(handle, status); if (SSL_OK != ret) { status = ret; } return status; }
int ssl23_peek(SSL *s, void *buf, int len) { int n; errno = 0; if (SSL_in_init(s) && (!s->in_handshake)) { n = s->handshake_func(s); if (n < 0) return (n); if (n == 0) { SSLerr(SSL_F_SSL23_PEEK, SSL_R_SSL_HANDSHAKE_FAILURE); return (-1); } return (SSL_peek(s, buf, len)); } else { ssl_undefined_function(s); return (-1); } }
static int openssl_ssl_peek(lua_State*L) { SSL* s = CHECK_OBJECT(1, SSL, "openssl.ssl"); int num = luaL_optint(L, 2, SSL_pending(s)); void* buf; int ret; num = num ? num : 4096; buf = malloc(num); ret = SSL_peek(s, buf, num); if (ret > 0) { lua_pushlstring(L, buf, ret); ret = 1; } else { ret = openssl_ssl_pushresult(L, s, ret); } free(buf); return ret; }
bool SSLSocket::checkLiveness() { if (getFd() == -1) { return false; } pollfd p; p.fd = getFd(); p.events = POLLIN | POLLERR | POLLHUP | POLLPRI; p.revents = 0; if (poll(&p, 1, 0) > 0 && p.revents > 0) { char buf; if (m_data->m_ssl_active) { while (true) { int n = SSL_peek(m_data->m_handle, &buf, sizeof(buf)); if (n <= 0) { int err = SSL_get_error(m_data->m_handle, n); if (err == SSL_ERROR_SYSCALL) { return errno == EAGAIN; } if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { /* re-negotiate */ continue; } /* any other problem is a fatal error */ return false; } /* either peek succeeded or there was an error; we * have set the alive flag appropriately */ break; } } else if (0 == recv(getFd(), &buf, sizeof(buf), MSG_PEEK) && errno != EAGAIN) { return false; } } return true; }
/* * This function extracts data from the SSL context and puts * it into a buffer. */ static int est_io_read_raw (SSL *ssl, unsigned char *buf, int buf_max, int *read_cnt, int sock_read_timeout) { int cur_cnt; char peek_read_buf; *read_cnt = 0; cur_cnt = est_ssl_read(ssl, buf, buf_max, sock_read_timeout); if (cur_cnt < 0) { EST_LOG_ERR("TLS read error"); ossl_dump_ssl_errors(); return (EST_ERR_SSL_READ); } *read_cnt += cur_cnt; /* * Multiple calls to SSL_read may be required to get the full * HTTP payload. */ while (cur_cnt > 0 && *read_cnt < buf_max) { cur_cnt = est_ssl_read(ssl, (buf + *read_cnt), (buf_max - *read_cnt), sock_read_timeout); if (cur_cnt < 0) { EST_LOG_ERR("TLS read error"); ossl_dump_ssl_errors(); return (EST_ERR_SSL_READ); } *read_cnt += cur_cnt; } if ((*read_cnt == buf_max) && SSL_peek(ssl, &peek_read_buf, 1)) { EST_LOG_ERR("Buffer too small for received message"); return(EST_ERR_READ_BUFFER_TOO_SMALL); } return (EST_ERR_NONE); }
/** @brief Checks if the socket is still connected to the remote host. * @returns True if the connection is still active, false otherwise. */ bool Jatta::Network::SocketTCP::IsConnected() { # ifdef OpenSSL_FOUND if (connectionSecure) { char data; if (sock == INVALID_SOCKET) { return false; } if (SSL_peek(sslHandle, &data, 1) == 0) { sock = INVALID_SOCKET; return false; } return true; } # endif // Check if we've already determined the connection is dead. If so, we can go ahead and return. if (sock == INVALID_SOCKET) { return false; } // Check if recv is returning 0. In that case, the remote host has disconnected gracefully. // TODO: receive could return non-zero and still fail, certain winsock errors indicate this // add a check for those for a more accurate isConnected() method char data; if (recv(sock, &data, 1, MSG_PEEK) == 0) { sock = INVALID_SOCKET; return false; } return true; }
bool SSLSocket::waitWant(int ret, uint64_t millis) { #ifdef HEADER_OPENSSLV_H int err = SSL_get_error(ssl, ret); switch(err) { case SSL_ERROR_WANT_READ: return wait(millis, Socket::WAIT_READ) == WAIT_READ; case SSL_ERROR_WANT_WRITE: return wait(millis, Socket::WAIT_WRITE) == WAIT_WRITE; #else int err = ssl->last_error; switch(err) { case GNUTLS_E_INTERRUPTED: case GNUTLS_E_AGAIN: { int waitFor = wait(millis, Socket::WAIT_READ | Socket::WAIT_WRITE); return (waitFor & Socket::WAIT_READ) || (waitFor & Socket::WAIT_WRITE); } #endif // Check if this is a fatal error... default: checkSSL(ret); } dcdebug("SSL: Unexpected fallthrough"); // There was no error? return true; } int SSLSocket::read(void* aBuffer, int aBufLen) throw(SocketException) { if(!ssl) { return -1; } int len = checkSSL(SSL_read(ssl, aBuffer, aBufLen)); if(len > 0) { stats.totalDown += len; //dcdebug("In(s): %.*s\n", len, (char*)aBuffer); } return len; } int SSLSocket::write(const void* aBuffer, int aLen) throw(SocketException) { if(!ssl) { return -1; } int ret = checkSSL(SSL_write(ssl, aBuffer, aLen)); if(ret > 0) { stats.totalUp += ret; //dcdebug("Out(s): %.*s\n", ret, (char*)aBuffer); } return ret; } int SSLSocket::checkSSL(int ret) throw(SocketException) { if(!ssl) { return -1; } if(ret <= 0) { int err = SSL_get_error(ssl, ret); switch(err) { case SSL_ERROR_NONE: // Fallthrough - YaSSL doesn't for example return an openssl compatible error on recv fail case SSL_ERROR_WANT_READ: // Fallthrough case SSL_ERROR_WANT_WRITE: return -1; case SSL_ERROR_ZERO_RETURN: #ifndef HEADER_OPENSSLV_H if(ssl->last_error == GNUTLS_E_INTERRUPTED || ssl->last_error == GNUTLS_E_AGAIN) return -1; #endif throw SocketException(STRING(CONNECTION_CLOSED)); default: { ssl.reset(); // @todo replace 80 with MAX_ERROR_SZ or whatever's appropriate for yaSSL in some nice way... char errbuf[80]; /* TODO: better message for SSL_ERROR_SYSCALL * If the error queue is empty (i.e. ERR_get_error() returns 0), ret can be used to find out more about the error: * If ret == 0, an EOF was observed that violates the protocol. If ret == -1, the underlying BIO reported an I/O error * (for socket I/O on Unix systems, consult errno for details). */ int error = ERR_get_error(); sprintf(errbuf, "%s %d: %s", CSTRING(SSL_ERROR), err, (error == 0) ? CSTRING(CONNECTION_CLOSED) : ERR_reason_error_string(error)); throw SSLSocketException(errbuf); } } } return ret; } int SSLSocket::wait(uint64_t millis, int waitFor) throw(SocketException) { #ifdef HEADER_OPENSSLV_H if(ssl && (waitFor & Socket::WAIT_READ)) { /** @todo Take writing into account as well if reading is possible? */ char c; if(SSL_peek(ssl, &c, 1) > 0) return WAIT_READ; } #endif return Socket::wait(millis, waitFor); } bool SSLSocket::isTrusted() throw() { if(!ssl) { return false; } #ifdef HEADER_OPENSSLV_H if(SSL_get_verify_result(ssl) != X509_V_OK) { return false; } #else if(gnutls_certificate_verify_peers(((SSL*)ssl)->gnutls_state) != 0) { return false; } #endif X509* cert = SSL_get_peer_certificate(ssl); if(!cert) { return false; } X509_free(cert); return true; } std::string SSLSocket::getCipherName() throw() { if(!ssl) return Util::emptyString; return SSL_get_cipher_name(ssl); } std::string SSLSocket::getDigest() const throw() { #ifdef HEADER_OPENSSLV_H if(!ssl) return Util::emptyString; X509* x509 = SSL_get_peer_certificate(ssl); if(!x509) return Util::emptyString; return ssl::X509_digest(x509, EVP_sha1()); #else return Util::emptyString; #endif } void SSLSocket::shutdown() throw() { if(ssl) SSL_shutdown(ssl); } void SSLSocket::close() throw() { if(ssl) { ssl.reset(); } Socket::shutdown(); Socket::close(); } } // namespace dcpp
static void net_on_input(peer_t *peer) { int ret = 0; int nbyte = 0; netc_t *netc = NULL; netc = peer->ext_ptr; peer->buffer_data_len = peer->recv(peer); if (netc->security_level > NET_UNSECURE && netc->kconn->status == KRYPT_HANDSHAKE) { ret = krypt_do_handshake(netc->kconn, peer->buffer, peer->buffer_data_len); peer->buffer_data_len = 0; net_do_krypt(netc); if (ret == 0) { // handshake successfull netc->on_secure(netc); // inform upper-layer // Handle the fact that we can receive handshake data // and DNDS Messages at the same time from the underlying // network buffer. char peek; ret = SSL_peek(netc->kconn->ssl, &peek, 1); if (ret == 1) { // There is still data in the SSL object, // continue further to process pending data. } else { return; } } else if (ret == -1) { // handshake failed netc->on_disconnect(netc); // inform upper-layer peer->disconnect(peer); // inform lower-layer net_connection_free(netc); return; } // handshake flow ends here if no more data has to be processed } if (netc->security_level > NET_UNSECURE && netc->kconn->status == KRYPT_SECURE) { int peek = 0; // buffer to hold the byte we are peeking at int state_p = 0; do { nbyte = krypt_push_encrypted_data(netc->kconn, peer->buffer + peer->buffer_offset, peer->buffer_data_len); if (nbyte > 0 && nbyte < peer->buffer_data_len) { peer->buffer_data_len -= nbyte; peer->buffer_offset += nbyte; } else{ peer->buffer_data_len = 0; peer->buffer_offset = 0; } ret = krypt_decrypt_buf(netc->kconn); if (ret == 0) { serialize_buf_in(netc, netc->kconn->buf_decrypt, netc->kconn->buf_decrypt_data_size); netc->kconn->buf_decrypt_data_size = 0; // mark the buffer as empty state_p = SSL_peek(netc->kconn->ssl, &peek, 1); } net_do_krypt(netc); // decryption doesn't fail and (SSL data pending or data to feed to BIO) } while (ret == 0 && (state_p == 1 || peer->buffer_data_len > 0)); } else if (netc->security_level == NET_UNSECURE) { serialize_buf_in(netc, peer->buffer, peer->buffer_data_len); } ret = net_decode_msg(netc); if (ret == -1) { netc->on_disconnect(netc); // inform upper-layer peer->disconnect(peer); // inform lower-layer net_connection_free(netc); } else if (netc->security_level > NET_UNSECURE && netc->kconn->status == KRYPT_SECURE) { /* Catch server renegotiation */ krypt_decrypt_buf(netc->kconn); net_do_krypt(netc); if (mbuf_count(netc->queue_msg) > 0) netc->on_input(netc); } }
/* OS dependent */ Boolean rocs_socket_readpeek( iOSocket inst, char* buf, int size, Boolean peek ) { #ifdef __ROCS_SOCKET__ iOSocketData o = Data(inst); int readed = 0; int treaded = 0; int flags = peek ? MSG_PEEK:0; o->readed = 0; while( treaded < size ) { if( o->ssl ) { #ifdef __OPENSSL__ if( peek ) readed = SSL_peek( o->ssl_sh, buf + treaded, size - treaded ); else readed = SSL_read( o->ssl_sh, buf + treaded, size - treaded ); #endif } else readed = recv( o->sh, buf + treaded, size - treaded, flags ); /* Has otherside closed the connection? */ if( readed == 0 ) { o->rc = errno; o->broken = True; TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "Other side has closed connection." ); TraceOp.trc( name, TRCLEVEL_DEBUG, __LINE__, 9999, "errno=%d, read=%d", errno, readed ); return False; } if( peek ) { o->rc = WSAGetLastError(); o->peeked = readed; if( readed == -1 && o->rc != 0 && o->rc != WSAETIMEDOUT && o->rc != WSAEINTR && o->rc != WSAEWOULDBLOCK ) { if( o->ssl ) { #ifdef __OPENSSL__ ERR_print_errors_fp( (FILE*)TraceOp.getF(NULL) ); fflush( (FILE*)TraceOp.getF(NULL) ); #endif } TraceOp.trc( name, TRCLEVEL_WARNING, __LINE__, 9999, "*broken* errno=%d, rc=%d, readed=%d", errno, o->rc, readed ); o->broken = True; } /* WinSock problems: http://sources.redhat.com/ml/cygwin/2001-08/msg00628.html * MSG_PEEK always returns 1 with Windows NT & 2000; XP returns correct number. */ /* return (readed >= size) ? True:False; */ return (readed >= 1) ? True:False; } if( readed < 0 ) { o->rc = WSAGetLastError(); /* For none blocking... if( !o->blocking && o->rc == WSAEWOULDBLOCK ) { ThreadOp.sleep(10); continue; } */ if( o->rc == WSAEWOULDBLOCK || o->rc == WSAESHUTDOWN || o->rc == WSAENOTSOCK || o->rc == WSAETIMEDOUT || o->rc == WSAECONNRESET ) rocs_socket_close(o); if( o->ssl ) { #ifdef __OPENSSL__ ERR_print_errors_fp( (FILE*)TraceOp.getF(NULL) ); fflush( (FILE*)TraceOp.getF(NULL) ); #endif } TraceOp.trc( name, TRCLEVEL_EXCEPTION, __LINE__, 9999, "recv() failed [%d] size=%d readed=%d", o->rc, size, treaded ); return False; } treaded += readed; } o->readed = treaded; if( treaded > 1 ) TraceOp.trc( name, TRCLEVEL_DEBUG, __LINE__, 9999, "%d bytes read from socket.", treaded ); #endif return True; }
int Jatta::Network::SocketTCP::Peek(void* data, unsigned int size) { # ifdef OpenSSL_FOUND if (connectionSecure) { int amount; if (sock == INVALID_SOCKET) { return false; } while (true) { amount = SSL_peek(sslHandle, (char*)data, size); if (amount == 0) { Close(); return 0; } else if (amount > 0) { return amount; } int error = SSL_get_error(sslHandle, amount); if (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE) { //Handle these errors then try again. //Just waiting it out seems to work. } else { throw NetworkException(NetworkExceptionCode::FAILED_PEEK, NetworkExceptionReason::UNKNOWN); } } } # endif // Check if the socket is valid before we continue. if (sock == INVALID_SOCKET) { throw NetworkException(NetworkExceptionCode::FAILED_PEEK, NetworkExceptionReason::SOCKET_INVALID); } // Pizza delivery! int amount; //Peek normally if ((amount = ::recv(sock, (char*)data, size, MSG_PEEK)) == SOCKET_ERROR) { // Check if recv failed because of a WOULDBLOCK error. This basically means that there was // nothing to be received. In that case, just return 0. Otherwise, there was an error. # ifdef JATTA_WINDOWS if (WSAGetLastError() == WSAEWOULDBLOCK) # else if (errno == EWOULDBLOCK) # endif { return 0; } else { throw NetworkException(NetworkExceptionCode::FAILED_PEEK, NetworkExceptionReason::UNKNOWN); } } // Check if recv returned 0, if so, the remove socket disconnected gracefully. if (amount == 0) { Close(); return 0; } else { return amount; } }
/* This is from from Eric Raymond's fetchmail (SockRead() in socket.c) * since I wouldn't have a clue how to do it properly. * This function is Copyright 1999 (C) Eric Raymond. * Modifications Copyright 2000 (C) Joe Orton */ int sock_readline(nsocket *sock, char *buf, int len) { char *newline, *bp = buf; int n; do { /* * The reason for these gymnastics is that we want two things: * (1) to read \n-terminated lines, * (2) to return the true length of data read, even if the * data coming in has embedded NULS. */ #ifdef ENABLE_SSL if (sock->ssl) { /* Hack alert! */ /* OK... SSL_peek works a little different from MSG_PEEK Problem is that SSL_peek can return 0 if there is no data currently available. If, on the other hand, we loose the socket, we also get a zero, but the SSL_read then SEGFAULTS! To deal with this, we'll check the error code any time we get a return of zero from SSL_peek. If we have an error, we bail. If we don't, we read one character in SSL_read and loop. This should continue to work even if they later change the behavior of SSL_peek to "fix" this problem... :-(*/ DEBUG(DEBUG_SOCKET, "SSL readline... \n"); if ((n = SSL_peek(sock->ssl, bp, len)) < 0) { sock->error = ERROR_SSL_STRING; return(-1); } if (0 == n) { /* SSL_peek says no data... Does he mean no data or did the connection blow up? If we got an error then bail! */ DEBUG(DEBUG_SOCKET, "SSL_Peek says no data!\n"); /* Check properly to see if the connection has closed */ if (sock->ssl->shutdown) { DEBUG(DEBUG_SOCKET, "SSL says shutdown."); return SOCK_CLOSED; } else if (0 != (n = ERR_get_error())) { DEBUG(DEBUG_SOCKET, "SSL error occured.\n"); sock->error = ERROR_SSL_STRING; return -1; } /* We didn't get an error so read at least one character at this point and loop */ n = 1; /* Make sure newline start out NULL! We don't have a * string to pass through the strchr at this point yet * */ newline = NULL; } else if ((newline = memchr(bp, '\n', n)) != NULL) n = newline - bp + 1; n = SSL_read(sock->ssl, bp, n); DEBUG(DEBUG_SOCKET, "SSL_read returned %d\n", n); if (n == -1) { sock->error = ERROR_SSL_STRING; return(-1); } /* Check for case where our single character turned out to * be a newline... (It wasn't going to get caught by * the strchr above if it came from the hack...). */ if (NULL == newline && 1 == n && '\n' == *bp) { /* Got our newline - this will break out of the loop now */ newline = bp; } } else { #endif if ((n = sock_peek(sock, bp, len)) <= 0) return n; if ((newline = memchr(bp, '\n', n)) != NULL) n = newline - bp + 1; if ((n = sock_read(sock, bp, n)) < 0) return n; #ifdef ENABLE_SSL } #endif bp += n; len -= n; if (len < 1) { sock->error = _("Line too long"); return SOCK_FULL; } } while (!newline && len); *bp = '\0'; return bp - buf; }
int dual_tls_recv(rad_listen_t *listener) { RADIUS_PACKET *packet; RAD_REQUEST_FUNP fun = NULL; listen_socket_t *sock = listener->data; RADCLIENT *client = sock->client; BIO *rbio; if (listener->status != RAD_LISTEN_STATUS_KNOWN) return 0; redo: if (!tls_socket_recv(listener)) { return 0; } rad_assert(sock->packet != NULL); rad_assert(sock->ssn != NULL); rad_assert(client != NULL); packet = talloc_steal(NULL, sock->packet); sock->packet = NULL; /* * Some sanity checks, based on the packet code. * * "auth+acct" are marked as "auth", with the "dual" flag * set. */ switch (packet->code) { case PW_CODE_ACCESS_REQUEST: if (listener->type != RAD_LISTEN_AUTH) goto bad_packet; FR_STATS_INC(auth, total_requests); fun = rad_authenticate; break; #ifdef WITH_ACCOUNTING case PW_CODE_ACCOUNTING_REQUEST: if (listener->type != RAD_LISTEN_ACCT) { /* * Allow auth + dual. Disallow * everything else. */ if (!((listener->type == RAD_LISTEN_AUTH) && (listener->dual))) { goto bad_packet; } } FR_STATS_INC(acct, total_requests); fun = rad_accounting; break; #endif case PW_CODE_STATUS_SERVER: if (!main_config.status_server) { FR_STATS_INC(auth, total_unknown_types); WARN("Ignoring Status-Server request due to security configuration"); rad_free(&packet); return 0; } fun = rad_status_server; break; default: bad_packet: FR_STATS_INC(auth, total_unknown_types); DEBUG("Invalid packet code %d sent from client %s port %d : IGNORED", packet->code, client->shortname, packet->src_port); rad_free(&packet); return 0; } /* switch over packet types */ if (!request_receive(NULL, listener, packet, client, fun)) { FR_STATS_INC(auth, total_packets_dropped); rad_free(&packet); return 0; } /* * Check for more application data. * * If there is pending SSL data, "peek" at the * application data. If we get at least one byte of * application data, go back to tls_socket_recv(). * SSL_peek() will set SSL_pending(), and * tls_socket_recv() will read another packet. */ rbio = SSL_get_rbio(sock->ssn->ssl); if (BIO_ctrl_pending(rbio)) { char buf[1]; int peek = SSL_peek(sock->ssn->ssl, buf, 1); if (peek > 0) { DEBUG("more TLS records after dual_tls_recv"); goto redo; } } return 1; }
int MAIN(int argc, char **argv) { int off=0; SSL *con=NULL,*con2=NULL; X509_STORE *store = NULL; int s,k,width,state=0; char *cbuf=NULL,*sbuf=NULL,*mbuf=NULL; int cbuf_len,cbuf_off; int sbuf_len,sbuf_off; fd_set readfds,writefds; short port=PORT; int full_log=1; char *host=SSL_HOST_NAME; char *cert_file=NULL,*key_file=NULL; int cert_format = FORMAT_PEM, key_format = FORMAT_PEM; char *passarg = NULL, *pass = NULL; X509 *cert = NULL; EVP_PKEY *key = NULL; char *CApath=NULL,*CAfile=NULL,*cipher=NULL; int reconnect=0,badop=0,verify=SSL_VERIFY_NONE,bugs=0; int crlf=0; int write_tty,read_tty,write_ssl,read_ssl,tty_on,ssl_pending; SSL_CTX *ctx=NULL; int ret=1,in_init=1,i,nbio_test=0; int starttls_proto = PROTO_OFF; int prexit = 0, vflags = 0; SSL_METHOD *meth=NULL; #ifdef sock_type #undef sock_type #endif int sock_type=SOCK_STREAM; BIO *sbio; char *inrand=NULL; int mbuf_len=0; #ifndef OPENSSL_NO_ENGINE char *engine_id=NULL; ENGINE *e=NULL; #endif #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) struct timeval tv; #endif struct sockaddr peer; int peerlen = sizeof(peer); int enable_timeouts = 0 ; long mtu = 0; #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) meth=SSLv23_client_method(); #elif !defined(OPENSSL_NO_SSL3) meth=SSLv3_client_method(); #elif !defined(OPENSSL_NO_SSL2) meth=SSLv2_client_method(); #endif apps_startup(); c_Pause=0; c_quiet=0; c_ign_eof=0; c_debug=0; c_msg=0; c_showcerts=0; if (bio_err == NULL) bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); if (!load_config(bio_err, NULL)) goto end; if ( ((cbuf=OPENSSL_malloc(BUFSIZZ)) == NULL) || ((sbuf=OPENSSL_malloc(BUFSIZZ)) == NULL) || ((mbuf=OPENSSL_malloc(BUFSIZZ)) == NULL)) { BIO_printf(bio_err,"out of memory\n"); goto end; } verify_depth=0; verify_error=X509_V_OK; #ifdef FIONBIO c_nbio=0; #endif argc--; argv++; while (argc >= 1) { if (strcmp(*argv,"-host") == 0) { if (--argc < 1) goto bad; host= *(++argv); } else if (strcmp(*argv,"-port") == 0) { if (--argc < 1) goto bad; port=atoi(*(++argv)); if (port == 0) goto bad; } else if (strcmp(*argv,"-connect") == 0) { if (--argc < 1) goto bad; if (!extract_host_port(*(++argv),&host,NULL,&port)) goto bad; } else if (strcmp(*argv,"-verify") == 0) { verify=SSL_VERIFY_PEER; if (--argc < 1) goto bad; verify_depth=atoi(*(++argv)); BIO_printf(bio_err,"verify depth is %d\n",verify_depth); } else if (strcmp(*argv,"-cert") == 0) { if (--argc < 1) goto bad; cert_file= *(++argv); } else if (strcmp(*argv,"-certform") == 0) { if (--argc < 1) goto bad; cert_format = str2fmt(*(++argv)); } else if (strcmp(*argv,"-crl_check") == 0) vflags |= X509_V_FLAG_CRL_CHECK; else if (strcmp(*argv,"-crl_check_all") == 0) vflags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL; else if (strcmp(*argv,"-prexit") == 0) prexit=1; else if (strcmp(*argv,"-crlf") == 0) crlf=1; else if (strcmp(*argv,"-quiet") == 0) { c_quiet=1; c_ign_eof=1; } else if (strcmp(*argv,"-ign_eof") == 0) c_ign_eof=1; else if (strcmp(*argv,"-pause") == 0) c_Pause=1; else if (strcmp(*argv,"-debug") == 0) c_debug=1; #ifdef WATT32 else if (strcmp(*argv,"-wdebug") == 0) dbug_init(); #endif else if (strcmp(*argv,"-msg") == 0) c_msg=1; else if (strcmp(*argv,"-showcerts") == 0) c_showcerts=1; else if (strcmp(*argv,"-nbio_test") == 0) nbio_test=1; else if (strcmp(*argv,"-state") == 0) state=1; #ifndef OPENSSL_NO_SSL2 else if (strcmp(*argv,"-ssl2") == 0) meth=SSLv2_client_method(); #endif #ifndef OPENSSL_NO_SSL3 else if (strcmp(*argv,"-ssl3") == 0) meth=SSLv3_client_method(); #endif #ifndef OPENSSL_NO_TLS1 else if (strcmp(*argv,"-tls1") == 0) meth=TLSv1_client_method(); #endif #ifndef OPENSSL_NO_DTLS1 else if (strcmp(*argv,"-dtls1") == 0) { meth=DTLSv1_client_method(); sock_type=SOCK_DGRAM; } else if (strcmp(*argv,"-timeout") == 0) enable_timeouts=1; else if (strcmp(*argv,"-mtu") == 0) { if (--argc < 1) goto bad; mtu = atol(*(++argv)); } #endif else if (strcmp(*argv,"-bugs") == 0) bugs=1; else if (strcmp(*argv,"-keyform") == 0) { if (--argc < 1) goto bad; key_format = str2fmt(*(++argv)); } else if (strcmp(*argv,"-pass") == 0) { if (--argc < 1) goto bad; passarg = *(++argv); } else if (strcmp(*argv,"-key") == 0) { if (--argc < 1) goto bad; key_file= *(++argv); } else if (strcmp(*argv,"-reconnect") == 0) { reconnect=5; } else if (strcmp(*argv,"-CApath") == 0) { if (--argc < 1) goto bad; CApath= *(++argv); } else if (strcmp(*argv,"-CAfile") == 0) { if (--argc < 1) goto bad; CAfile= *(++argv); } else if (strcmp(*argv,"-no_tls1") == 0) off|=SSL_OP_NO_TLSv1; else if (strcmp(*argv,"-no_ssl3") == 0) off|=SSL_OP_NO_SSLv3; else if (strcmp(*argv,"-no_ssl2") == 0) off|=SSL_OP_NO_SSLv2; else if (strcmp(*argv,"-serverpref") == 0) off|=SSL_OP_CIPHER_SERVER_PREFERENCE; else if (strcmp(*argv,"-cipher") == 0) { if (--argc < 1) goto bad; cipher= *(++argv); } #ifdef FIONBIO else if (strcmp(*argv,"-nbio") == 0) { c_nbio=1; } #endif else if (strcmp(*argv,"-starttls") == 0) { if (--argc < 1) goto bad; ++argv; if (strcmp(*argv,"smtp") == 0) starttls_proto = PROTO_SMTP; else if (strcmp(*argv,"pop3") == 0) starttls_proto = PROTO_POP3; else if (strcmp(*argv,"imap") == 0) starttls_proto = PROTO_IMAP; else if (strcmp(*argv,"ftp") == 0) starttls_proto = PROTO_FTP; else goto bad; } #ifndef OPENSSL_NO_ENGINE else if (strcmp(*argv,"-engine") == 0) { if (--argc < 1) goto bad; engine_id = *(++argv); } #endif else if (strcmp(*argv,"-rand") == 0) { if (--argc < 1) goto bad; inrand= *(++argv); } else { BIO_printf(bio_err,"unknown option %s\n",*argv); badop=1; break; } argc--; argv++; } if (badop) { bad: sc_usage(); goto end; } OpenSSL_add_ssl_algorithms(); SSL_load_error_strings(); #ifndef OPENSSL_NO_ENGINE e = setup_engine(bio_err, engine_id, 1); #endif if (!app_passwd(bio_err, passarg, NULL, &pass, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } if (key_file == NULL) key_file = cert_file; if (key_file) { key = load_key(bio_err, key_file, key_format, 0, pass, e, "client certificate private key file"); if (!key) { ERR_print_errors(bio_err); goto end; } } if (cert_file) { cert = load_cert(bio_err,cert_file,cert_format, NULL, e, "client certificate file"); if (!cert) { ERR_print_errors(bio_err); goto end; } } if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL && !RAND_status()) { BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n"); } if (inrand != NULL) BIO_printf(bio_err,"%ld semi-random bytes loaded\n", app_RAND_load_files(inrand)); if (bio_c_out == NULL) { if (c_quiet && !c_debug && !c_msg) { bio_c_out=BIO_new(BIO_s_null()); } else { if (bio_c_out == NULL) bio_c_out=BIO_new_fp(stdout,BIO_NOCLOSE); } } ctx=SSL_CTX_new(meth); if (ctx == NULL) { ERR_print_errors(bio_err); goto end; } if (bugs) SSL_CTX_set_options(ctx,SSL_OP_ALL|off); else SSL_CTX_set_options(ctx,off); /* DTLS: partial reads end up discarding unread UDP bytes :-( * Setting read ahead solves this problem. */ if (sock_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1); if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback); if (cipher != NULL) if(!SSL_CTX_set_cipher_list(ctx,cipher)) { BIO_printf(bio_err,"error setting cipher list\n"); ERR_print_errors(bio_err); goto end; } #if 0 else SSL_CTX_set_cipher_list(ctx,getenv("SSL_CIPHER")); #endif SSL_CTX_set_verify(ctx,verify,verify_callback); if (!set_cert_key_stuff(ctx,cert,key)) goto end; if ((!SSL_CTX_load_verify_locations(ctx,CAfile,CApath)) || (!SSL_CTX_set_default_verify_paths(ctx))) { /* BIO_printf(bio_err,"error setting default verify locations\n"); */ ERR_print_errors(bio_err); /* goto end; */ } store = SSL_CTX_get_cert_store(ctx); X509_STORE_set_flags(store, vflags); con=SSL_new(ctx); #ifndef OPENSSL_NO_KRB5 if (con && (con->kssl_ctx = kssl_ctx_new()) != NULL) { kssl_ctx_setstring(con->kssl_ctx, KSSL_SERVER, host); } #endif /* OPENSSL_NO_KRB5 */ /* SSL_set_cipher_list(con,"RC4-MD5"); */ re_start: if (init_client(&s,host,port,sock_type) == 0) { BIO_printf(bio_err,"connect:errno=%d\n",get_last_socket_error()); SHUTDOWN(s); goto end; } BIO_printf(bio_c_out,"CONNECTED(%08X)\n",s); #ifdef FIONBIO if (c_nbio) { unsigned long l=1; BIO_printf(bio_c_out,"turning on non blocking io\n"); if (BIO_socket_ioctl(s,FIONBIO,&l) < 0) { ERR_print_errors(bio_err); goto end; } } #endif if (c_Pause & 0x01) con->debug=1; if ( SSL_version(con) == DTLS1_VERSION) { struct timeval timeout; sbio=BIO_new_dgram(s,BIO_NOCLOSE); if (getsockname(s, &peer, (void *)&peerlen) < 0) { BIO_printf(bio_err, "getsockname:errno=%d\n", get_last_socket_error()); SHUTDOWN(s); goto end; } (void)BIO_ctrl_set_connected(sbio, 1, &peer); if ( enable_timeouts) { timeout.tv_sec = 0; timeout.tv_usec = DGRAM_RCV_TIMEOUT; BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); timeout.tv_sec = 0; timeout.tv_usec = DGRAM_SND_TIMEOUT; BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout); } if ( mtu > 0) { SSL_set_options(con, SSL_OP_NO_QUERY_MTU); SSL_set_mtu(con, mtu); } else /* want to do MTU discovery */ BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); } else sbio=BIO_new_socket(s,BIO_NOCLOSE); if (nbio_test) { BIO *test; test=BIO_new(BIO_f_nbio_test()); sbio=BIO_push(test,sbio); } if (c_debug) { con->debug=1; BIO_set_callback(sbio,bio_dump_callback); BIO_set_callback_arg(sbio,(char *)bio_c_out); } if (c_msg) { SSL_set_msg_callback(con, msg_cb); SSL_set_msg_callback_arg(con, bio_c_out); } SSL_set_bio(con,sbio,sbio); SSL_set_connect_state(con); /* ok, lets connect */ width=SSL_get_fd(con)+1; read_tty=1; write_tty=0; tty_on=0; read_ssl=1; write_ssl=1; cbuf_len=0; cbuf_off=0; sbuf_len=0; sbuf_off=0; /* This is an ugly hack that does a lot of assumptions */ /* We do have to handle multi-line responses which may come in a single packet or not. We therefore have to use BIO_gets() which does need a buffering BIO. So during the initial chitchat we do push a buffering BIO into the chain that is removed again later on to not disturb the rest of the s_client operation. */ if (starttls_proto == PROTO_SMTP) { int foundit=0; BIO *fbio = BIO_new(BIO_f_buffer()); BIO_push(fbio, sbio); /* wait for multi-line response to end from SMTP */ do { mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); } while (mbuf_len>3 && mbuf[3]=='-'); /* STARTTLS command requires EHLO... */ BIO_printf(fbio,"EHLO openssl.client.net\r\n"); (void)BIO_flush(fbio); /* wait for multi-line response to end EHLO SMTP response */ do { mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); if (strstr(mbuf,"STARTTLS")) foundit=1; } while (mbuf_len>3 && mbuf[3]=='-'); (void)BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); if (!foundit) BIO_printf(bio_err, "didn't found starttls in server response," " try anyway...\n"); BIO_printf(sbio,"STARTTLS\r\n"); BIO_read(sbio,sbuf,BUFSIZZ); } else if (starttls_proto == PROTO_POP3) { BIO_read(sbio,mbuf,BUFSIZZ); BIO_printf(sbio,"STLS\r\n"); BIO_read(sbio,sbuf,BUFSIZZ); } else if (starttls_proto == PROTO_IMAP) { int foundit=0; BIO *fbio = BIO_new(BIO_f_buffer()); BIO_push(fbio, sbio); BIO_gets(fbio,mbuf,BUFSIZZ); /* STARTTLS command requires CAPABILITY... */ BIO_printf(fbio,". CAPABILITY\r\n"); (void)BIO_flush(fbio); /* wait for multi-line CAPABILITY response */ do { mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); if (strstr(mbuf,"STARTTLS")) foundit=1; } while (mbuf_len>3 && mbuf[0]!='.'); (void)BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); if (!foundit) BIO_printf(bio_err, "didn't found STARTTLS in server response," " try anyway...\n"); BIO_printf(sbio,". STARTTLS\r\n"); BIO_read(sbio,sbuf,BUFSIZZ); } else if (starttls_proto == PROTO_FTP) { BIO *fbio = BIO_new(BIO_f_buffer()); BIO_push(fbio, sbio); /* wait for multi-line response to end from FTP */ do { mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); } while (mbuf_len>3 && mbuf[3]=='-'); (void)BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); BIO_printf(sbio,"AUTH TLS\r\n"); BIO_read(sbio,sbuf,BUFSIZZ); } for (;;) { FD_ZERO(&readfds); FD_ZERO(&writefds); if (SSL_in_init(con) && !SSL_total_renegotiations(con)) { in_init=1; tty_on=0; } else { tty_on=1; if (in_init) { in_init=0; print_stuff(bio_c_out,con,full_log); if (full_log > 0) full_log--; if (starttls_proto) { BIO_printf(bio_err,"%s",mbuf); /* We don't need to know any more */ starttls_proto = PROTO_OFF; } if (reconnect) { reconnect--; BIO_printf(bio_c_out,"drop connection and then reconnect\n"); SSL_shutdown(con); SSL_set_connect_state(con); SHUTDOWN(SSL_get_fd(con)); goto re_start; } } } ssl_pending = read_ssl && SSL_pending(con); if (!ssl_pending) { #if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_NETWARE) if (tty_on) { if (read_tty) FD_SET(fileno(stdin),&readfds); if (write_tty) FD_SET(fileno(stdout),&writefds); } if (read_ssl) FD_SET(SSL_get_fd(con),&readfds); if (write_ssl) FD_SET(SSL_get_fd(con),&writefds); #else if(!tty_on || !write_tty) { if (read_ssl) FD_SET(SSL_get_fd(con),&readfds); if (write_ssl) FD_SET(SSL_get_fd(con),&writefds); } #endif /* printf("mode tty(%d %d%d) ssl(%d%d)\n", tty_on,read_tty,write_tty,read_ssl,write_ssl);*/ /* Note: under VMS with SOCKETSHR the second parameter * is currently of type (int *) whereas under other * systems it is (void *) if you don't have a cast it * will choke the compiler: if you do have a cast then * you can either go for (int *) or (void *). */ #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) /* Under Windows/DOS we make the assumption that we can * always write to the tty: therefore if we need to * write to the tty we just fall through. Otherwise * we timeout the select every second and see if there * are any keypresses. Note: this is a hack, in a proper * Windows application we wouldn't do this. */ i=0; if(!write_tty) { if(read_tty) { tv.tv_sec = 1; tv.tv_usec = 0; i=select(width,(void *)&readfds,(void *)&writefds, NULL,&tv); #if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS) if(!i && (!_kbhit() || !read_tty) ) continue; #else if(!i && (!((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) || !read_tty) ) continue; #endif } else i=select(width,(void *)&readfds,(void *)&writefds, NULL,NULL); } #elif defined(OPENSSL_SYS_NETWARE) if(!write_tty) { if(read_tty) { tv.tv_sec = 1; tv.tv_usec = 0; i=select(width,(void *)&readfds,(void *)&writefds, NULL,&tv); } else i=select(width,(void *)&readfds,(void *)&writefds, NULL,NULL); } #else i=select(width,(void *)&readfds,(void *)&writefds, NULL,NULL); #endif if ( i < 0) { BIO_printf(bio_err,"bad select %d\n", get_last_socket_error()); goto shut; /* goto end; */ } } if (!ssl_pending && FD_ISSET(SSL_get_fd(con),&writefds)) { k=SSL_write(con,&(cbuf[cbuf_off]), (unsigned int)cbuf_len); switch (SSL_get_error(con,k)) { case SSL_ERROR_NONE: cbuf_off+=k; cbuf_len-=k; if (k <= 0) goto end; /* we have done a write(con,NULL,0); */ if (cbuf_len <= 0) { read_tty=1; write_ssl=0; } else /* if (cbuf_len > 0) */ { read_tty=0; write_ssl=1; } break; case SSL_ERROR_WANT_WRITE: BIO_printf(bio_c_out,"write W BLOCK\n"); write_ssl=1; read_tty=0; break; case SSL_ERROR_WANT_READ: BIO_printf(bio_c_out,"write R BLOCK\n"); write_tty=0; read_ssl=1; write_ssl=0; break; case SSL_ERROR_WANT_X509_LOOKUP: BIO_printf(bio_c_out,"write X BLOCK\n"); break; case SSL_ERROR_ZERO_RETURN: if (cbuf_len != 0) { BIO_printf(bio_c_out,"shutdown\n"); goto shut; } else { read_tty=1; write_ssl=0; break; } case SSL_ERROR_SYSCALL: if ((k != 0) || (cbuf_len != 0)) { BIO_printf(bio_err,"write:errno=%d\n", get_last_socket_error()); goto shut; } else { read_tty=1; write_ssl=0; } break; case SSL_ERROR_SSL: ERR_print_errors(bio_err); goto shut; } } #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) /* Assume Windows/DOS can always write */ else if (!ssl_pending && write_tty) #else else if (!ssl_pending && FD_ISSET(fileno(stdout),&writefds)) #endif { #ifdef CHARSET_EBCDIC ascii2ebcdic(&(sbuf[sbuf_off]),&(sbuf[sbuf_off]),sbuf_len); #endif i=write(fileno(stdout),&(sbuf[sbuf_off]),sbuf_len); if (i <= 0) { BIO_printf(bio_c_out,"DONE\n"); goto shut; /* goto end; */ } sbuf_len-=i;; sbuf_off+=i; if (sbuf_len <= 0) { read_ssl=1; write_tty=0; } } else if (ssl_pending || FD_ISSET(SSL_get_fd(con),&readfds)) { #ifdef RENEG { static int iiii; if (++iiii == 52) { SSL_renegotiate(con); iiii=0; } } #endif #if 1 k=SSL_read(con,sbuf,1024 /* BUFSIZZ */ ); #else /* Demo for pending and peek :-) */ k=SSL_read(con,sbuf,16); { char zbuf[10240]; printf("read=%d pending=%d peek=%d\n",k,SSL_pending(con),SSL_peek(con,zbuf,10240)); } #endif switch (SSL_get_error(con,k)) { case SSL_ERROR_NONE: if (k <= 0) goto end; sbuf_off=0; sbuf_len=k; read_ssl=0; write_tty=1; break; case SSL_ERROR_WANT_WRITE: BIO_printf(bio_c_out,"read W BLOCK\n"); write_ssl=1; read_tty=0; break; case SSL_ERROR_WANT_READ: BIO_printf(bio_c_out,"read R BLOCK\n"); write_tty=0; read_ssl=1; if ((read_tty == 0) && (write_ssl == 0)) write_ssl=1; break; case SSL_ERROR_WANT_X509_LOOKUP: BIO_printf(bio_c_out,"read X BLOCK\n"); break; case SSL_ERROR_SYSCALL: BIO_printf(bio_err,"read:errno=%d\n",get_last_socket_error()); goto shut; case SSL_ERROR_ZERO_RETURN: BIO_printf(bio_c_out,"closed\n"); goto shut; case SSL_ERROR_SSL: ERR_print_errors(bio_err); goto shut; /* break; */ } } #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) #if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS) else if (_kbhit()) #else else if ((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) #endif #elif defined (OPENSSL_SYS_NETWARE) else if (_kbhit()) #else else if (FD_ISSET(fileno(stdin),&readfds)) #endif { if (crlf) { int j, lf_num; i=read(fileno(stdin),cbuf,BUFSIZZ/2); lf_num = 0; /* both loops are skipped when i <= 0 */ for (j = 0; j < i; j++) if (cbuf[j] == '\n') lf_num++; for (j = i-1; j >= 0; j--) { cbuf[j+lf_num] = cbuf[j]; if (cbuf[j] == '\n') { lf_num--; i++; cbuf[j+lf_num] = '\r'; } } assert(lf_num == 0); } else i=read(fileno(stdin),cbuf,BUFSIZZ); if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q'))) { BIO_printf(bio_err,"DONE\n"); goto shut; } if ((!c_ign_eof) && (cbuf[0] == 'R')) { BIO_printf(bio_err,"RENEGOTIATING\n"); SSL_renegotiate(con); cbuf_len=0; } else { cbuf_len=i; cbuf_off=0; #ifdef CHARSET_EBCDIC ebcdic2ascii(cbuf, cbuf, i); #endif } write_ssl=1; read_tty=0; } } shut: SSL_shutdown(con); SHUTDOWN(SSL_get_fd(con)); ret=0; end: if(prexit) print_stuff(bio_c_out,con,1); if (con != NULL) SSL_free(con); if (con2 != NULL) SSL_free(con2); if (ctx != NULL) SSL_CTX_free(ctx); if (cert) X509_free(cert); if (key) EVP_PKEY_free(key); if (pass) OPENSSL_free(pass); if (cbuf != NULL) { OPENSSL_cleanse(cbuf,BUFSIZZ); OPENSSL_free(cbuf); } if (sbuf != NULL) { OPENSSL_cleanse(sbuf,BUFSIZZ); OPENSSL_free(sbuf); } if (mbuf != NULL) { OPENSSL_cleanse(mbuf,BUFSIZZ); OPENSSL_free(mbuf); } if (bio_c_out != NULL) { BIO_free(bio_c_out); bio_c_out=NULL; } apps_shutdown(); OPENSSL_EXIT(ret); }
int ssl_server_peek(ssl_server_con * con, void * buffer, size_t buffer_size){ return SSL_peek(con->ssl, buffer, buffer_size); }