int dns_forward_query_tcp(event_entry_t *general_entry) { struct event_tcp_entry *entry = &general_entry->tcp; if (!ip_tcp_open(&entry->intsock, &global_target_address)) { debug_log(DEBUG_ERROR, "dns_forward_query_tcp(): unable to open TCP socket\n"); goto wrong; } // randomizing port is not really necessary, as TCP is invulnerable to cache poisoning // however, the source IP address is set in ip_bind_random... if (!ip_bind_random(entry->intsock)) { // if this fails, let the kernel handle it (would mean source IP address is not guaranteed...) debug_log(DEBUG_WARN, "dns_forward_query_tcp(): unable to bind to source IP address and/or random port\n"); } if (!ip_connect(entry->intsock, &global_target_address)) { debug_log(DEBUG_ERROR, "dns_forward_query_tcp(): unable to connect to authoritative name server (%s)\n", strerror(errno)); goto wrong; } // Now generate a new TXID to forecome any poisoning: entry->buffer[0] = misc_crypto_random(256); entry->buffer[1] = misc_crypto_random(256); // XXX: do this platform safe (i.e. ntoh) entry->dns.dsttxid = (entry->buffer[0] << 8) + entry->buffer[1]; debug_log(DEBUG_INFO, "dns_forward_query_tcp(): forwarding query to authoritative name server (prev id = %d, new id = %d)\n", entry->dns.srctxid, entry->dns.dsttxid); return 1; wrong: return 0; }
/******************************************************************************* * * Open interface */ int16_t stk500v2_open(const char *interface, int port, int flag) { if (interface[0] == '/') { stk_fsock = serial_open(interface, serial_speed(p.baudrate)); } else { if (flag == STK_CONNECT) { stk_fsock = ip_connect(interface, port); } else { /* STK _LISTEN */ stk_fsock = ip_listen(interface, port); } } return stk_fsock; }
/* Create a socket and connect to host (name or number, ipv6 ok) at one of port-range. Arguments: type SOCK_DGRAM or SOCK_STREAM af AF_INET6 or AF_INET for the socket type address the remote address, in text form portlo,porthi the remote port range timeout a timeout connhost if not NULL, host_item filled in with connection details errstr pointer for allocated string on error Return: socket fd, or -1 on failure (having allocated an error string) */ int ip_connectedsocket(int type, const uschar * hostname, int portlo, int porthi, int timeout, host_item * connhost, uschar ** errstr) { int namelen, port; host_item shost; host_item *h; int af = 0, fd, fd4 = -1, fd6 = -1; shost.next = NULL; shost.address = NULL; shost.port = portlo; shost.mx = -1; namelen = Ustrlen(hostname); /* Anything enclosed in [] must be an IP address. */ if (hostname[0] == '[' && hostname[namelen - 1] == ']') { uschar * host = string_copy(hostname); host[namelen - 1] = 0; host++; if (string_is_ip_address(host, NULL) == 0) { *errstr = string_sprintf("malformed IP address \"%s\"", hostname); return -1; } shost.name = shost.address = host; } /* Otherwise check for an unadorned IP address */ else if (string_is_ip_address(hostname, NULL) != 0) shost.name = shost.address = string_copy(hostname); /* Otherwise lookup IP address(es) from the name */ else { shost.name = string_copy(hostname); if (host_find_byname(&shost, NULL, HOST_FIND_QUALIFY_SINGLE, NULL, FALSE) != HOST_FOUND) { *errstr = string_sprintf("no IP address found for host %s", shost.name); return -1; } } /* Try to connect to the server - test each IP till one works */ for (h = &shost; h != NULL; h = h->next) { fd = (Ustrchr(h->address, ':') != 0) ? (fd6 < 0) ? (fd6 = ip_socket(type, af = AF_INET6)) : fd6 : (fd4 < 0) ? (fd4 = ip_socket(type, af = AF_INET )) : fd4; if (fd < 0) { *errstr = string_sprintf("failed to create socket: %s", strerror(errno)); goto bad; } for(port = portlo; port <= porthi; port++) if (ip_connect(fd, af, h->address, port, timeout) == 0) { if (fd != fd6) close(fd6); if (fd != fd4) close(fd4); if (connhost) { h->port = port; *connhost = *h; connhost->next = NULL; } return fd; } } *errstr = string_sprintf("failed to connect to any address for %s: %s", hostname, strerror(errno)); bad: close(fd4); close(fd6); return -1; }
int initialize_client_stage1(ClientRealm* cr, SSL_CTX* ctx, unsigned char* buff, char wanttoexit, char ignorePublicKeys) { int n, nlen, elen, len, tmp; unsigned int olen; X509* server_cert; const EVP_MD *md; EVP_PKEY* pkey; EVP_MD_CTX md_ctx; unsigned char *encoded = NULL; char b64_encoded[100]; unsigned char *key_buf = NULL; assert((ClientRealm_get_tunnelType(cr) == 0) || (ClientRealm_get_tunnelType(cr) == 1)); switch (ClientRealm_get_tunnelType(cr)) { case 0: { if (ip_connect(&tmp, ClientRealm_get_serverName(cr), ClientRealm_get_managePort(cr), ClientRealm_get_ipFamily(cr), ClientRealm_get_localName(cr), ClientRealm_get_localPort(cr))) { #ifdef AF_INET6 aflog(LOG_T_INIT, LOG_I_CRIT, "tcp_connect_%s error for %s, %s", (ClientRealm_get_ipFamily(cr) & 0x02) ? "ipv4":(ClientRealm_get_ipFamily(cr) & 0x04) ? "ipv6":"unspec", ClientRealm_get_serverName(cr), ClientRealm_get_managePort(cr)); #else aflog(LOG_T_INIT, LOG_I_CRIT, "tcp_connect error for %s, %s", ClientRealm_get_serverName(cr), ClientRealm_get_managePort(cr)); #endif if (wanttoexit) { exit(1); } else { return 1; } } SslFd_set_fd(ClientRealm_get_masterSslFd(cr), tmp); break; } #ifdef HAVE_LIBPTHREAD case 1: { if (initialize_http_proxy_client(&tmp, cr, ctx)) { #ifdef AF_INET6 aflog(LOG_T_INIT, LOG_I_CRIT, "http_proxy_connect_%s error for %s, %s (proxy: %s, %s)", (ClientRealm_get_ipFamily(cr) & 0x02) ? "ipv4":(ClientRealm_get_ipFamily(cr) & 0x04) ? "ipv6":"unspec", ClientRealm_get_serverName(cr), ClientRealm_get_managePort(cr), HttpProxyOptions_get_proxyname(ClientRealm_get_httpProxyOptions(cr)), HttpProxyOptions_get_proxyport(ClientRealm_get_httpProxyOptions(cr))); #else aflog(LOG_T_INIT, LOG_I_CRIT, "http_proxy_connect error for %s, %s (proxy: %s, %s)", ClientRealm_get_serverName(cr), ClientRealm_get_managePort(cr), HttpProxyOptions_get_proxyname(ClientRealm_get_httpProxyOptions(cr)), HttpProxyOptions_get_proxyport(ClientRealm_get_httpProxyOptions(cr))); #endif if (wanttoexit) { exit(1); } else { return 1; } } SslFd_set_fd(ClientRealm_get_masterSslFd(cr), tmp); break; } #endif default: { aflog(LOG_T_INIT, LOG_I_CRIT, "Unknown tunnel type"); if (wanttoexit) { exit(1); } else { return 1; } break; } } SslFd_set_ssl(ClientRealm_get_masterSslFd(cr), SSL_new(ctx)); if (SSL_set_fd(SslFd_get_ssl(ClientRealm_get_masterSslFd(cr)), SslFd_get_fd(ClientRealm_get_masterSslFd(cr))) != 1) { aflog(LOG_T_INIT, LOG_I_CRIT, "Problem with initializing ssl... exiting"); if (wanttoexit) { exit(1); } else { close(SslFd_get_fd(ClientRealm_get_masterSslFd(cr))); return 2; } } alarm(60); aflog(LOG_T_INIT, LOG_I_INFO, "Trying SSL_connect"); if ((n = SSL_connect(SslFd_get_ssl(ClientRealm_get_masterSslFd(cr)))) == 1) { if ((server_cert = SSL_get_peer_certificate(SslFd_get_ssl(ClientRealm_get_masterSslFd(cr)))) == NULL) { aflog(LOG_T_MAIN, LOG_I_CRIT, "Server did not present a certificate... exiting"); exit(1); } /* FIXME: change almost everything here */ pkey = X509_get_pubkey(server_cert); if (pkey == NULL) { aflog(LOG_T_MAIN, LOG_I_CRIT, "Server's public key is invalid... exiting"); exit(1); } nlen = BN_num_bytes(pkey->pkey.rsa->n); elen = BN_num_bytes(pkey->pkey.rsa->e); len = nlen + elen; key_buf = malloc(len); if (key_buf == NULL) { aflog(LOG_T_MAIN, LOG_I_CRIT, "Cannot allocate memory for server's public key checking... exiting"); exit(1); } BN_bn2bin(pkey->pkey.rsa->n, key_buf); BN_bn2bin(pkey->pkey.rsa->e, key_buf + nlen); md = EVP_md5(); EVP_DigestInit(&md_ctx, md); EVP_DigestUpdate(&md_ctx, key_buf, len); encoded = calloc(1, EVP_MAX_MD_SIZE+1); if (encoded == NULL) { aflog(LOG_T_MAIN, LOG_I_CRIT, "Cannot allocate memory for server's public key checking... exiting"); exit(1); } EVP_DigestFinal(&md_ctx, encoded, &olen); if (b64_ntop(encoded, olen, b64_encoded, 100) == -1) { aflog(LOG_T_MAIN, LOG_I_CRIT, "Problem with base64 encoding... exiting"); exit(1); } switch (check_public_key(get_store_filename(), ClientRealm_get_serverName(cr), b64_encoded)) { case SSL_PUBLIC_KEY_VALID: /* public key is ok - do nothing */ break; case SSL_PUBLIC_KEY_NOT_KNOWN: aflog(LOG_T_MAIN, LOG_I_WARNING, "WARNING: implicitly added new server's public key to the list of known hosts"); add_public_key(get_store_filename(), ClientRealm_get_serverName(cr), b64_encoded); break; default: if (ignorePublicKeys) { aflog(LOG_T_MAIN, LOG_I_WARNING, "WARNING: Invalid server's public key... ignoring"); } else { aflog(LOG_T_MAIN, LOG_I_CRIT, "Invalid server's public key... exiting"); aflog(LOG_T_MAIN, LOG_I_CRIT, "Please delete conflicting entry in %s or use '--ignorepkeys' option", get_store_filename()); exit(1); } } memset(key_buf, 0, len); free(key_buf); free(encoded); aflog(LOG_T_INIT, LOG_I_INFO, "SSL_connect successful"); } else { alarm(0); aflog(LOG_T_INIT, LOG_I_CRIT, "SSL_connect has failed (%d | %d)... exiting", n, SSL_get_error(SslFd_get_ssl(ClientRealm_get_masterSslFd(cr)), n)); if (wanttoexit) { exit(1); } else { close(SslFd_get_fd(ClientRealm_get_masterSslFd(cr))); return 3; } } alarm(0); buff[0] = AF_S_LOGIN; buff[1] = ClientRealm_get_password(cr)[0]; buff[2] = ClientRealm_get_password(cr)[1]; buff[3] = ClientRealm_get_password(cr)[2]; buff[4] = ClientRealm_get_password(cr)[3]; return 0; }
int main(int argc, char * argv[]) { openlog("transparent", LOG_CONS | LOG_PERROR, LOG_USER); const char * copyright_notice = "\n" "ReDemPtion Transparent Proxy " VERSION ".\n" "Copyright (C) Wallix 2010-2015.\n" "Christophe Grosjean, Raphael Zhou.\n" "\n" ; std::string input_filename; std::string output_filename; std::string target_device; uint32_t target_port; std::string username; std::string password; std::string record_filename; std::string play_filename; std::string persistent_key_list_filename; persistent_key_list_filename = "./PersistentKeyList.bin"; target_port = 3389; program_options::options_description desc({ {'h', "help", "produce help message"}, {'v', "version", "show software version"}, {'i', "input-file", &input_filename, "input ini file name"}, {'o', "output-file", &output_filename, "output int file name"}, {'t', "target-device", &target_device, "target device[:port]"}, {'u', "username", &username, "username"}, {'p', "password", &password, "password"}, {'k', "key-list-file", &persistent_key_list_filename, "persistent key list file name"}, {'r', "record-file", &record_filename, "record file name"}, {'d', "play-file", &play_filename, "play file name"}, }); auto options = program_options::parse_command_line(argc, argv, desc); if (options.count("help") > 0) { std::cout << copyright_notice; std::cout << "Usage: rdptproxy [options]\n\n"; std::cout << desc << endl; exit(0); } if (options.count("version") > 0) { std::cout << copyright_notice; exit(0); } if ( target_device.empty() && play_filename.empty()) { std::cerr << "Missing target device or play file name: use -t target or -d filename\n\n"; exit(-1); } if ( !target_device.empty() && !play_filename.empty()) { std::cerr << "Use -t target or -d filename\n\n"; exit(-1); } if ( !output_filename.empty() && !play_filename.empty()) { std::cerr << "Use -o filename or -d filename\n\n"; exit(-1); } if ( !record_filename.empty() && !play_filename.empty()) { std::cerr << "Use -r filename or -d filename\n\n"; exit(-1); } if ( !input_filename.empty() && !output_filename.empty()) { std::cerr << "Use -i filename or -o filename\n\n"; exit(-1); } if (!target_device.empty()) { size_t pos = target_device.find(':'); if (pos != string::npos) { target_port = atoi(target_device.substr(pos + 1).c_str()); target_device.resize(pos); } if (username.c_str()[0] == 0) { std::cerr << "Missing username : use -u username\n\n"; exit(-1); } } if (password.empty()) { password = ""; } // This server only support one incoming connection before closing listener class ServerOnce : public Server { public: int sck; char ip_source[256]; ServerOnce() : sck(0) { this->ip_source[0] = 0; } virtual Server_status start(int incoming_sck) { union { struct sockaddr s; struct sockaddr_storage ss; struct sockaddr_in s4; struct sockaddr_in6 s6; } u; unsigned int sin_size = sizeof(u); memset(&u, 0, sin_size); this->sck = accept(incoming_sck, &u.s, &sin_size); strcpy(this->ip_source, inet_ntoa(u.s4.sin_addr)); LOG(LOG_INFO, "Incoming socket to %d (ip=%s)\n", this->sck, this->ip_source); return START_WANT_STOP; } } one_shot_server; Listen listener(one_shot_server, 0, 3389, true, 5); // 25 seconds to connect, or timeout listener.run(); Inifile ini; ConfigurationLoader cfg_loader(ini, CFG_PATH "/" RDPPROXY_INI); int nodelay = 1; if (-1 == setsockopt( one_shot_server.sck, IPPROTO_TCP, TCP_NODELAY, (char *)&nodelay , sizeof(nodelay))) { LOG(LOG_ERR, "Failed to set socket TCP_NODELAY option on client socket"); } SocketTransport front_trans( "RDP Client", one_shot_server.sck, "0.0.0.0", 0 , ini.debug.front, 0); wait_obj front_event; LCGRandom gen(0); // Remove existing Persistent Key List file. unlink(persistent_key_list_filename.c_str()); OutFileTransport * persistent_key_list_oft = NULL; int persistent_key_list_ofd; persistent_key_list_ofd = open(persistent_key_list_filename.c_str(), O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP); if (persistent_key_list_ofd != -1) { persistent_key_list_oft = new OutFileTransport(persistent_key_list_ofd); } else { LOG(LOG_ERR, "Failed to open Persistent Key List file to writing: name=\"%s\"", persistent_key_list_filename.c_str()); } const bool fastpath_support = true; const bool mem3blt_support = true; Front front(front_trans, SHARE_PATH "/" DEFAULT_FONT_NAME, gen, ini, fastpath_support, mem3blt_support, input_filename.c_str(), persistent_key_list_oft); null_mod no_mod(front); while (front.up_and_running == 0) { front.incoming(no_mod); } LOG(LOG_INFO, "hostname=\"%s\"", front.client_info.hostname); try { if (target_device.empty()) { TransparentReplayMod mod(front, play_filename.c_str(), front.client_info.width, front.client_info.height, NULL, ini.font); run_mod(mod, front, front_event, nullptr, &front_trans); } else { OutFileTransport * record_oft = NULL; int record_fd = -1; if (!record_filename.empty()) { record_fd = open(record_filename.c_str(), O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP); if (record_fd != -1) { record_oft = new OutFileTransport(record_fd); } else { LOG(LOG_ERR, "Failed to open record file to writing: name=\"%s\"", record_filename.c_str()); } } InFileTransport * persistent_key_list_ift = NULL; int persistent_key_list_ifd; persistent_key_list_ifd = open(persistent_key_list_filename.c_str(), O_RDONLY); if (persistent_key_list_ifd != -1) { persistent_key_list_ift = new InFileTransport(persistent_key_list_ifd); } else { LOG(LOG_ERR, "Failed to open Persistent Key List file to reading: name=\"%s\"", persistent_key_list_filename.c_str()); } int client_sck = ip_connect(target_device.c_str(), target_port, 3, 1000, ini.debug.mod_rdp); SocketTransport mod_trans( "RDP Server", client_sck, target_device.c_str(), target_port , ini.debug.mod_rdp, &ini.context.auth_error_message); ClientInfo client_info = front.client_info; ModRDPParams mod_rdp_params( username.c_str() , password.c_str() , target_device.c_str() , "0.0.0.0" // client ip is silenced , front.keymap.key_flags , ini.debug.mod_rdp ); //mod_rdp_params.enable_tls = true; mod_rdp_params.enable_nla = ini.mod_rdp.enable_nla; mod_rdp_params.enable_krb = ini.mod_rdp.enable_kerberos; //mod_rdp_params.enable_fastpath = true; //mod_rdp_params.enable_mem3blt = true; mod_rdp_params.enable_bitmap_update = ini.globals.enable_bitmap_update; //mod_rdp_params.enable_new_pointer = true; mod_rdp_params.enable_transparent_mode = true; mod_rdp_params.output_filename = (output_filename.empty() ? "" : output_filename.c_str()); mod_rdp_params.persistent_key_list_transport = persistent_key_list_ift; mod_rdp_params.transparent_recorder_transport = record_oft; mod_rdp_params.auth_channel = ini.globals.auth_channel; mod_rdp_params.alternate_shell = ini.globals.alternate_shell.get_cstr(); mod_rdp_params.shell_working_directory = ini.globals.shell_working_directory.get_cstr(); mod_rdp_params.rdp_compression = ini.mod_rdp.rdp_compression; mod_rdp_params.disconnect_on_logon_user_change = ini.mod_rdp.disconnect_on_logon_user_change; mod_rdp_params.open_session_timeout = ini.mod_rdp.open_session_timeout; mod_rdp_params.certificate_change_action = ini.mod_rdp.certificate_change_action; mod_rdp_params.extra_orders = ini.mod_rdp.extra_orders.c_str(); mod_rdp_params.enable_persistent_disk_bitmap_cache = ini.mod_rdp.persistent_disk_bitmap_cache; mod_rdp_params.enable_cache_waiting_list = ini.mod_rdp.cache_waiting_list; mod_rdp_params.password_printing_mode = ini.debug.password; mod_rdp_params.cache_verbose = ini.debug.cache; mod_rdp_params.allow_channels = &(ini.mod_rdp.allow_channels); mod_rdp_params.deny_channels = &(ini.mod_rdp.deny_channels); mod_rdp mod(mod_trans, front, client_info, ini.mod_rdp.redir_info, gen, mod_rdp_params); run_mod(mod, front, front_event, &mod_trans, &front_trans); if (client_sck != -1) { shutdown(client_sck, 2); close(client_sck); } if (persistent_key_list_ifd != -1) { delete persistent_key_list_ift; close(persistent_key_list_ifd); } if (record_fd != -1) { delete record_oft; close(record_fd); } } } // try catch (Error & e) { LOG(LOG_ERR, "errid = %d", e.id); } front.disconnect(); if (persistent_key_list_ofd != -1) { delete persistent_key_list_oft; close(persistent_key_list_ofd); } shutdown(one_shot_server.sck, 2); close(one_shot_server.sck); LOG(LOG_INFO, "Listener closed\n"); LOG(LOG_INFO, "Incoming socket %d (ip=%s)\n", one_shot_server.sck, one_shot_server.ip_source); return 0; }