bool SSLClient::sslConnect(int fd, std::string &hostname, short port) { GNASH_REPORT_FUNCTION; int ret; if (!_ctx) { if (!sslSetupCTX()) { return false; } } _ssl.reset(SSL_new(_ctx.get())); // // Make a tcp/ip connect to the server // if (createClient(hostname, getPort()) == false) { // log_error("Can't connect to server %s", hostname); // return false; // } // Handshake the server ERR_clear_error(); #if 0 _bio.reset(BIO_new_socket(fd, BIO_NOCLOSE)); #else // BIO_set_conn_hostname(_bio.get(), _hostname.c_str()); _bio.reset(BIO_new_connect(const_cast<char *>(_hostname.c_str()))); BIO_set_conn_int_port(_bio.get(), &port); log_debug("PORT is: %d", BIO_get_conn_port(_bio.get())); if (BIO_do_connect(_bio.get()) <= 0) { log_error("Error connecting to remote machine: %s", ERR_reason_error_string(ERR_get_error())); } #endif SSL_set_bio(_ssl.get(), _bio.get(), _bio.get()); SSL_set_connect_state(_ssl.get()); if ((ret = SSL_connect(_ssl.get())) < 0) { log_error("Can't connect to SSL server %s", hostname); log_error("Error was: \"%s\"!", ERR_reason_error_string(ERR_get_error())); return false; } else { log_debug("Connected to SSL server %s", hostname); } ERR_clear_error(); #if 0 if (_need_server_auth) { checkCert(hostname); } #endif return true; }
static BIO * my_connect_ssl(char *host, int port, SSL_CTX **ctx) { BIO *conn = 0; if (!(conn = BIO_new_ssl_connect(*ctx))) goto error_exit; BIO_set_conn_hostname(conn, host); BIO_set_conn_int_port(conn, &port); if (BIO_do_connect(conn) <= 0) goto error_exit; return conn; error_exit: if (conn) BIO_free_all(conn); return 0; }
static BIO * my_connect(char *host, int port, int ssl, SSL_CTX **ctx) { BIO *conn; SSL *ssl_ptr; if (ssl) { if (!(conn = my_connect_ssl(host, port, ctx))) goto error_exit; BIO_get_ssl(conn, &ssl_ptr); if (!verify_cert_hostname(SSL_get_peer_certificate(ssl_ptr), host)) goto error_exit; if (SSL_get_verify_result(ssl_ptr) != X509_V_OK) goto error_exit; return conn; } if (!(conn = BIO_new_connect(host))) goto error_exit; BIO_set_conn_int_port(conn, &port); if (BIO_do_connect(conn) <= 0) goto error_exit; return conn; error_exit: if (conn) BIO_free_all(conn); return 0; }
BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeout) { int status; UINT32 option_value; socklen_t option_len; if (!hostname) return FALSE; if (hostname[0] == '/') { tcp->sockfd = freerdp_uds_connect(hostname); if (tcp->sockfd < 0) return FALSE; tcp->socketBio = BIO_new_fd(tcp->sockfd, 1); if (!tcp->socketBio) return FALSE; } else { fd_set cfds; struct timeval tv; tcp->socketBio = BIO_new(BIO_s_connect()); if (!tcp->socketBio) return FALSE; if (BIO_set_conn_hostname(tcp->socketBio, hostname) < 0 || BIO_set_conn_int_port(tcp->socketBio, &port) < 0) return FALSE; BIO_set_nbio(tcp->socketBio, 1); status = BIO_do_connect(tcp->socketBio); if ((status <= 0) && !BIO_should_retry(tcp->socketBio)) return FALSE; tcp->sockfd = BIO_get_fd(tcp->socketBio, NULL); if (tcp->sockfd < 0) return FALSE; if (status <= 0) { FD_ZERO(&cfds); FD_SET(tcp->sockfd, &cfds); tv.tv_sec = timeout; tv.tv_usec = 0; status = select(tcp->sockfd + 1, NULL, &cfds, NULL, &tv); if (status == 0) { return FALSE; /* timeout */ } } BIO_set_close(tcp->socketBio, BIO_NOCLOSE); BIO_free(tcp->socketBio); tcp->socketBio = BIO_new(BIO_s_simple_socket()); if (!tcp->socketBio) return -1; BIO_set_fd(tcp->socketBio, tcp->sockfd, BIO_CLOSE); } SetEventFileDescriptor(tcp->event, tcp->sockfd); tcp_get_ip_address(tcp); tcp_get_mac_address(tcp); option_value = 1; option_len = sizeof(option_value); if (setsockopt(tcp->sockfd, IPPROTO_TCP, TCP_NODELAY, (void*) &option_value, option_len) < 0) fprintf(stderr, "%s: unable to set TCP_NODELAY\n", __FUNCTION__); /* receive buffer must be a least 32 K */ if (getsockopt(tcp->sockfd, SOL_SOCKET, SO_RCVBUF, (void*) &option_value, &option_len) == 0) { if (option_value < (1024 * 32)) { option_value = 1024 * 32; option_len = sizeof(option_value); if (setsockopt(tcp->sockfd, SOL_SOCKET, SO_RCVBUF, (void*) &option_value, option_len) < 0) { fprintf(stderr, "%s: unable to set receive buffer len\n", __FUNCTION__); return FALSE; } } } if (!tcp_set_keep_alive_mode(tcp)) return FALSE; tcp->bufferedBio = BIO_new(BIO_s_buffered_socket()); if (!tcp->bufferedBio) return FALSE; tcp->bufferedBio->ptr = tcp; tcp->bufferedBio = BIO_push(tcp->bufferedBio, tcp->socketBio); return TRUE; }
static int context_connect(lua_State *T) { struct lem_ssl_context *c; const char *hostname; int port; BIO *bio; SSL *ssl; int ret; const char *msg; struct lem_ssl_stream *s; luaL_checktype(T, 1, LUA_TUSERDATA); c = lua_touserdata(T, 1); hostname = luaL_checkstring(T, 2); port = (int)luaL_optnumber(T, 3, -1); if (c->ctx == NULL) { lua_pushnil(T); lua_pushliteral(T, "closed"); return 2; } bio = BIO_new(BIO_s_connect()); if (bio == NULL) { lua_pushnil(T); lua_pushfstring(T, "error creating BIO: %s", ERR_reason_error_string(ERR_get_error())); return 2; } BIO_set_conn_hostname(bio, hostname); if (port > 0) BIO_set_conn_int_port(bio, (char *)&port); BIO_set_nbio(bio, 1); ssl = SSL_new(c->ctx); if (ssl == NULL) { lua_pushnil(T); lua_pushfstring(T, "error creating SSL connection: %s", ERR_reason_error_string(ERR_get_error())); return 2; } SSL_set_bio(ssl, bio, bio); ret = SSL_connect(ssl); switch (SSL_get_error(ssl, ret)) { case SSL_ERROR_NONE: lem_debug("SSL_ERROR_NONE"); s = stream_new(T, ssl, NULL, 0); return 1; case SSL_ERROR_ZERO_RETURN: lem_debug("SSL_ERROR_ZERO_RETURN"); msg = "connection closed unexpectedly"; break; case SSL_ERROR_WANT_READ: lem_debug("SSL_ERROR_WANT_READ"); lua_settop(T, 0); s = stream_new(T, ssl, connect_handler, EV_READ); s->T = T; ev_io_start(EV_G_ &s->w); return lua_yield(T, 1); case SSL_ERROR_WANT_WRITE: lem_debug("SSL_ERROR_WANT_WRITE"); case SSL_ERROR_WANT_CONNECT: lem_debug("SSL_ERROR_WANT_CONNECT"); lua_settop(T, 0); s = stream_new(T, ssl, connect_handler, EV_WRITE); s->T = T; ev_io_start(EV_G_ &s->w); return lua_yield(T, 1); case SSL_ERROR_SYSCALL: lem_debug("SSL_ERROR_SYSCALL"); { long e = ERR_get_error(); if (e) msg = ERR_reason_error_string(e); else if (ret == 0) msg = "connection closed unexpectedly"; else msg = strerror(errno); } break; case SSL_ERROR_SSL: lem_debug("SSL_ERROR_SSL"); msg = ERR_reason_error_string(ERR_get_error()); break; default: lem_debug("SSL_ERROR_* (default)"); msg = "unexpected error from SSL library"; } lua_pushnil(T); lua_pushfstring(T, "error establishing SSL connection: %s", msg); SSL_free(ssl); return 2; }
int getPageFromURL(char *rurl, char *usrname, char *password, char **buff) { int port; char *host, *bitbucket, *url, *foo; BIO *bio; SSL_CTX *ctx; SSL *ssl; if (rurl == NULL) { return NET_ERROR_NO_SUCH_HOST; } if ((url = malloc(strlen(rurl) + 1)) == NULL) { fprintf(stderr, "Error: Out of RAM.\n"); return NET_ERROR_GENERAL_LOCAL_ERROR; } sprintf(url, "%s", rurl); if (strstr(url, "https://") != url) { fprintf(stderr, "Error: unhandled protocol in URL: %s\n", url); free(url); return NET_ERROR_BAD_PROTOCOL; } url += 8; if (strstr(url, "/") != NULL) { bitbucket = strstr(url, "/"); *bitbucket = '\0'; } else bitbucket = NULL; if ((host = malloc(strlen(url) + 1)) == NULL) { url -= 8; free(url); fprintf(stderr, "Error: Out of RAM.\n"); return NET_ERROR_GENERAL_LOCAL_ERROR; } sprintf(host, "%s", url); if ((foo = strstr(host, ":")) != NULL) { *foo = 0; } if (strstr(url, ":") != NULL) { port = atoi(1 + strstr(url, ":")); } else { port = 443; } if (bitbucket != NULL) *bitbucket = '/'; ctx = SSL_CTX_new(SSLv23_client_method()); if (!(bio = BIO_new_ssl_connect(ctx))) { fprintf(stderr, "Unable to allocate a BIO\n"); return NET_ERROR_GENERAL_LOCAL_ERROR; } BIO_get_ssl(bio, &ssl); SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); BIO_set_conn_hostname(bio, host); BIO_set_conn_int_port(bio, &port); if (BIO_do_connect(bio) < 0) return NET_ERROR_NO_SUCH_HOST; BIO_write(bio, "GET ", 4); fprintf(stderr, "Contacting %s port %i url %s\n", host, port, bitbucket); if (bitbucket != NULL) BIO_write(bio, bitbucket, strlen(bitbucket)); else BIO_write(bio, "/", 1); BIO_write(bio, " HTTP/1.0\r\n", 11); BIO_write(bio, NET_USER_AGENT, strlen(NET_USER_AGENT)); BIO_write(bio, "Host: ", 6); BIO_write(bio, host, strlen(host)); BIO_write(bio, "\r\n", 2); BIO_write(bio, "\r\n\r\n", 4); *buff = getURLData(bio, host); url -= 8; free(url); free(host); BIO_free_all(bio); SSL_CTX_free(ctx); if (*buff == NULL) return NET_ERROR_NO_DATA_FROM_SERVER; return NET_NO_ERROR; }
BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeout) { int status; UINT32 option_value; socklen_t option_len; if (!hostname) return FALSE; if (hostname[0] == '/') tcp->ipcSocket = TRUE; if (tcp->ipcSocket) { tcp->sockfd = freerdp_uds_connect(hostname); if (tcp->sockfd < 0) return FALSE; tcp->socketBio = BIO_new(BIO_s_simple_socket()); if (!tcp->socketBio) return FALSE; BIO_set_fd(tcp->socketBio, tcp->sockfd, BIO_CLOSE); } else { #ifdef HAVE_POLL_H struct pollfd pollfds; #else fd_set cfds; struct timeval tv; #endif #ifdef NO_IPV6 tcp->socketBio = BIO_new(BIO_s_connect()); if (!tcp->socketBio) return FALSE; if (BIO_set_conn_hostname(tcp->socketBio, hostname) < 0 || BIO_set_conn_int_port(tcp->socketBio, &port) < 0) return FALSE; BIO_set_nbio(tcp->socketBio, 1); status = BIO_do_connect(tcp->socketBio); if ((status <= 0) && !BIO_should_retry(tcp->socketBio)) return FALSE; tcp->sockfd = BIO_get_fd(tcp->socketBio, NULL); if (tcp->sockfd < 0) return FALSE; #else /* NO_IPV6 */ struct addrinfo hints = {0}; struct addrinfo *result; struct addrinfo *tmp; char port_str[11]; //ZeroMemory(&hints, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ hints.ai_socktype = SOCK_STREAM; /* * FIXME: the following is a nasty workaround. Find a cleaner way: * Either set port manually afterwards or get it passed as string? */ sprintf_s(port_str, 11, "%u", port); status = getaddrinfo(hostname, port_str, &hints, &result); if (status) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); return FALSE; } /* For now prefer IPv4 over IPv6. */ tmp = result; if (tmp->ai_family == AF_INET6 && tmp->ai_next != 0) { while ((tmp = tmp->ai_next)) { if (tmp->ai_family == AF_INET) break; } if (!tmp) tmp = result; } tcp->sockfd = socket(tmp->ai_family, tmp->ai_socktype, tmp->ai_protocol); if (tcp->sockfd < 0) { freeaddrinfo(result); return FALSE; } if (connect(tcp->sockfd, tmp->ai_addr, tmp->ai_addrlen) < 0) { fprintf(stderr, "connect: %s\n", strerror(errno)); freeaddrinfo(result); return FALSE; } freeaddrinfo(result); tcp->socketBio = BIO_new_socket(tcp->sockfd, BIO_NOCLOSE); /* TODO: make sure the handshake is done by querying the bio */ // if (BIO_should_retry(tcp->socketBio)) // return FALSE; #endif /* NO_IPV6 */ if (status <= 0) { #ifdef HAVE_POLL_H pollfds.fd = tcp->sockfd; pollfds.events = POLLOUT; pollfds.revents = 0; do { status = poll(&pollfds, 1, timeout * 1000); } while ((status < 0) && (errno == EINTR)); #else FD_ZERO(&cfds); FD_SET(tcp->sockfd, &cfds); tv.tv_sec = timeout; tv.tv_usec = 0; status = _select(tcp->sockfd + 1, NULL, &cfds, NULL, &tv); #endif if (status == 0) { return FALSE; /* timeout */ } } (void)BIO_set_close(tcp->socketBio, BIO_NOCLOSE); BIO_free(tcp->socketBio); tcp->socketBio = BIO_new(BIO_s_simple_socket()); if (!tcp->socketBio) return FALSE; BIO_set_fd(tcp->socketBio, tcp->sockfd, BIO_CLOSE); } SetEventFileDescriptor(tcp->event, tcp->sockfd); tcp_get_ip_address(tcp); tcp_get_mac_address(tcp); option_value = 1; option_len = sizeof(option_value); if (!tcp->ipcSocket) { if (setsockopt(tcp->sockfd, IPPROTO_TCP, TCP_NODELAY, (void*) &option_value, option_len) < 0) WLog_ERR(TAG, "unable to set TCP_NODELAY"); } /* receive buffer must be a least 32 K */ if (getsockopt(tcp->sockfd, SOL_SOCKET, SO_RCVBUF, (void*) &option_value, &option_len) == 0) { if (option_value < (1024 * 32)) { option_value = 1024 * 32; option_len = sizeof(option_value); if (setsockopt(tcp->sockfd, SOL_SOCKET, SO_RCVBUF, (void*) &option_value, option_len) < 0) { WLog_ERR(TAG, "unable to set receive buffer len"); return FALSE; } } } if (!tcp->ipcSocket) { if (!tcp_set_keep_alive_mode(tcp)) return FALSE; } tcp->bufferedBio = BIO_new(BIO_s_buffered_socket()); if (!tcp->bufferedBio) return FALSE; tcp->bufferedBio->ptr = tcp; tcp->bufferedBio = BIO_push(tcp->bufferedBio, tcp->socketBio); return TRUE; }