int rfbConnect(rfbScreenInfoPtr rfbScreen, char *host, int port) { int sock; int one = 1; rfbLog("Making connection to client on host %s port %d\n", host,port); if ((sock = rfbConnectToTcpAddr(host, port)) < 0) { rfbLogPerror("connection failed"); return -1; } if(!rfbSetNonBlocking(sock)) { closesocket(sock); return -1; } if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) { rfbLogPerror("setsockopt failed"); closesocket(sock); return -1; } /* AddEnabledDevice(sock); */ FD_SET(sock, &rfbScreen->allFds); rfbScreen->maxFd = max(sock,rfbScreen->maxFd); return sock; }
int main(int argc,char** argv) { char *repeaterHost; int repeaterPort, sock; char id[250]; int idlen; rfbClientPtr cl; int i,j; uint16_t* f; /* Parse command-line arguments */ if (argc < 3) { fprintf(stderr, "Usage: %s <id> <repeater-host> [<repeater-port>]\n", argv[0]); exit(1); } idlen = snprintf(id, sizeof(id) - 1, "ID:%s", argv[1]); if(idlen < 0 || idlen >= (int)sizeof(id)) { fprintf(stderr, "Error, given ID is probably too long.\n"); return 1; } repeaterHost = argv[2]; repeaterPort = argc < 4 ? 5500 : atoi(argv[3]); /* The initialization is identical to simple15.c */ rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,400,300,5,3,2); if(!server) return 0; server->frameBuffer=(char*)malloc(400*300*2); f=(uint16_t*)server->frameBuffer; for(j=0;j<300;j++) for(i=0;i<400;i++) f[j*400+i]=/* red */ ((j*32/300) << 10) | /* green */ (((j+400-i)*32/700) << 5) | /* blue */ ((i*32/400)); /* Now for the repeater-specific part: */ server->port = -1; /* do not listen on any port */ server->ipv6port = -1; /* do not listen on any port */ sock = rfbConnectToTcpAddr(repeaterHost, repeaterPort); if (sock < 0) { perror("connect to repeater"); return 1; } if (write(sock, id, idlen+1) != idlen+1) { perror("writing id"); return 1; } cl = rfbNewClient(server, sock); if (!cl) { perror("new client"); return 1; } cl->reverseConnection = 0; cl->clientGoneHook = clientGone; /* Run the server */ rfbInitServer(server); rfbRunEventLoop(server,-1,FALSE); return 0; }
int connect_tcp(char *host, int port) { double t0 = dnow(); int fd = -1; int fail4 = noipv4; if (getenv("IPV4_FAILS")) { fail4 = 2; } rfbLog("connect_tcp: trying: %s %d\n", host, port); if (fail4) { if (fail4 > 1) { rfbLog("TESTING: IPV4_FAILS for connect_tcp.\n"); } } else { fd = rfbConnectToTcpAddr(host, port); } if (fd >= 0) { return fd; } rfbLogPerror("connect_tcp: connection failed"); if (dnow() - t0 < 4.0) { rfbLog("connect_tcp: re-trying %s %d\n", host, port); usleep (100 * 1000); if (!fail4) { fd = rfbConnectToTcpAddr(host, port); } if (fd < 0) { rfbLogPerror("connect_tcp: connection failed"); } } if (fd < 0 && !noipv6) { #if X11VNC_IPV6 int err; struct addrinfo *ai; struct addrinfo hints; char service[32], *host2, *q; rfbLog("connect_tcp: trying IPv6 %s %d\n", host, port); memset(&hints, 0, sizeof(hints)); sprintf(service, "%d", port); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; #ifdef AI_ADDRCONFIG hints.ai_flags |= AI_ADDRCONFIG; #endif if(ipv6_ip(host)) { #ifdef AI_NUMERICHOST rfbLog("connect_tcp[ipv6]: setting AI_NUMERICHOST for %s\n", host); hints.ai_flags |= AI_NUMERICHOST; #endif } #ifdef AI_NUMERICSERV hints.ai_flags |= AI_NUMERICSERV; #endif if (!strcmp(host, "127.0.0.1")) { host2 = strdup("::1"); } else if (host[0] == '[') { host2 = strdup(host+1); } else { host2 = strdup(host); } q = strrchr(host2, ']'); if (q) { *q = '\0'; } err = getaddrinfo(host2, service, &hints, &ai); if (err != 0) { rfbLog("connect_tcp[ipv6]: getaddrinfo[%d]: %s\n", err, gai_strerror(err)); usleep(100 * 1000); err = getaddrinfo(host2, service, &hints, &ai); } free(host2); if (err != 0) { rfbLog("connect_tcp[ipv6]: getaddrinfo[%d]: %s\n", err, gai_strerror(err)); } else { struct addrinfo *ap = ai; while (ap != NULL) { int sock; if (fail4) { struct sockaddr_in6 *s6ptr; if (ap->ai_family != AF_INET6) { rfbLog("connect_tcp[ipv6]: skipping AF_INET address under -noipv4\n"); ap = ap->ai_next; continue; } #ifdef IN6_IS_ADDR_V4MAPPED s6ptr = (struct sockaddr_in6 *) ap->ai_addr; if (IN6_IS_ADDR_V4MAPPED(&(s6ptr->sin6_addr))) { rfbLog("connect_tcp[ipv6]: skipping V4MAPPED address under -noipv4\n"); ap = ap->ai_next; continue; } #endif } sock = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol); if (sock == -1) { rfbLogPerror("connect_tcp[ipv6]: socket"); if (0) rfbLog("(Ignore the above error if this system is IPv4-only.)\n"); } else { int res = -1, dmsg = 0; char *s = ipv6_getipaddr(ap->ai_addr, ap->ai_addrlen); if (!s) s = strdup("unknown"); rfbLog("connect_tcp[ipv6]: trying sock=%d fam=%d proto=%d using %s\n", sock, ap->ai_family, ap->ai_protocol, s); res = connect(sock, ap->ai_addr, ap->ai_addrlen); #if defined(SOL_IPV6) && defined(IPV6_V6ONLY) if (res != 0) { int zero = 0; rfbLogPerror("connect_tcp[ipv6]: connect"); dmsg = 1; if (setsockopt(sock, SOL_IPV6, IPV6_V6ONLY, (char *)&zero, sizeof(zero)) == 0) { rfbLog("connect_tcp[ipv6]: trying again with IPV6_V6ONLY=0\n"); res = connect(sock, ap->ai_addr, ap->ai_addrlen); dmsg = 0; } else { rfbLogPerror("connect_tcp[ipv6]: setsockopt IPV6_V6ONLY"); } } #endif if (res == 0) { rfbLog("connect_tcp[ipv6]: connect OK\n"); fd = sock; if (!ipv6_client_ip_str) { ipv6_client_ip_str = strdup(s); } free(s); break; } else { if (!dmsg) rfbLogPerror("connect_tcp[ipv6]: connect"); close(sock); } free(s); } ap = ap->ai_next; } freeaddrinfo(ai); } #endif } if (fd < 0 && !fail4) { /* this is a kludge for IPv4-only machines getting v4mapped string. */ char *q, *host2; if (host[0] == '[') { host2 = strdup(host+1); } else { host2 = strdup(host); } q = strrchr(host2, ']'); if (q) { *q = '\0'; } if (strstr(host2, "::ffff:") == host2 || strstr(host2, "::FFFF:") == host2) { char *host3 = host2 + strlen("::ffff:"); if (dotted_ip(host3, 0)) { rfbLog("connect_tcp[ipv4]: trying fallback to IPv4 for %s\n", host2); fd = rfbConnectToTcpAddr(host3, port); if (fd < 0) { rfbLogPerror("connect_tcp[ipv4]: connection failed"); } } } free(host2); } return fd; }
PresentationServer::PresentationServer(const std::string & conferenceUrl, const std::string & managerHost, unsigned short managerPort, int screenWidth, int screenHeight, const std::string & caCertificate, const std::string & managerPath, const std::string & managerParam) : _server(0), _fps(5) { if (caCertificate.empty()) { throw std::invalid_argument("no CA Certificate provided!"); } //Erstmal d�rfte jetzt die Authorisierung und die Anfrage an den Manager geschehen //Dazu einfach �ber nen Socket ne primitive http anfrage senden und die Antwort auswerten //Achtung momentan ist BUF_SIZE auch die maximale Nachrichtengr��e die Empfangen werden kann!! //@TODO Dringend ne bessere HTTP Implementation verwenden oder selber bauen. const int BUF_SIZE = 2048; char tmpBuffer[BUF_SIZE]; SOCKET httpSocket = rfbConnectToTcpAddr(const_cast<char*> (managerHost.c_str()), managerPort); std::string httpResponse; if (httpSocket == INVALID_SOCKET) { std::cerr << "Failed to connect to " << managerHost << ":" << managerPort << std::endl; throw std::runtime_error(STR_ERR_WEBHOST_UNREACHABLE); return; } //HTTPS Verbindung mit GnuTLS und handkodierter HTTP Nachricht :) gnutls_session_t session = 0; gnutls_certificate_credentials_t credentials = 0; gnutls_datum_t data; int gtlsRet = GNUTLS_E_SUCCESS; try { //Zertifikat if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_certificate_allocate_credentials(&credentials))) { std::cerr << "failed to allocate credentials." << std::endl; throw std::runtime_error("failed to allocate credentials."); } data.size = caCertificate.size(); data.data = (unsigned char*) caCertificate.data(); gnutls_certificate_set_x509_trust_mem(credentials, &data, GNUTLS_X509_FMT_PEM); // Verifizierung des Zertifikats in der übergebenen Callback Funktion, Ausführung erfolgt als Teil des Handshakes gnutls_certificate_set_verify_function(credentials, [] (gnutls_session_t session) throw () -> int { std::cout << "verifying certificate..."; //Server Zertifikat prüfen: unsigned int verify = 0; if (GNUTLS_E_SUCCESS != gnutls_certificate_verify_peers3(session, (const char*) gnutls_session_get_ptr(session), &verify)) { std::cerr << "certficate verification failed." << std::endl; return -1; } if (verify != 0) { gnutls_datum_t pr; std::cout << "no" << std::endl; gnutls_certificate_verification_status_print(verify, GNUTLS_CRT_X509, &pr, 0); std::cerr << pr.data << std::endl; free(pr.data); return -2; } std::cout << "yes" << std::endl; return 0; }); //Session if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_init(&session, GNUTLS_CLIENT))) { std::cerr << "failed to init session." << std::endl; throw std::runtime_error("failed to init session."); } gnutls_server_name_set(session, GNUTLS_NAME_DNS, managerHost.data(), managerHost.length()); gnutls_session_set_ptr(session, (void*) managerHost.c_str()); if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_priority_set_direct(session, CIPHERSUITE_PRIORITIES, 0))) { std::cerr << "failed to set priority." << std::endl; throw std::runtime_error("failed to set priority."); } gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, credentials); gnutls_transport_set_int(session, httpSocket); gnutls_handshake_set_timeout(session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); if (GNUTLS_E_SUCCESS != ((gtlsRet = gnutls_handshake(session)))) { std::cerr << "handshake failed." << std::endl; throw std::runtime_error("handshake failed."); } //Ciphersuite std::cout << "ciphersuite: " << gnutls_cipher_suite_get_name(gnutls_kx_get(session), gnutls_cipher_get(session), gnutls_mac_get(session)) << std::endl; //Prepare HTTP Request std::string httpRequest; std::string httpRequestBody = managerParam + "=" + urlencode(conferenceUrl) + "&version=" + std::to_string(TOOL_VERSION); httpRequest += "POST "; httpRequest += managerPath; httpRequest += " HTTP/1.1\r\n"; httpRequest += "Host: "; httpRequest += managerHost + "\r\n"; httpRequest += "Content-Type: application/x-www-form-urlencoded\r\n"; //< Beachte der Webserver kann auf der Zielroute momentan auch nichts anderes httpRequest += "Connection: close\r\n"; sprintf(tmpBuffer, "%d", httpRequestBody.length()); httpRequest += "Content-Length: " + std::string(tmpBuffer) + "\r\n"; httpRequest += "\r\n"; httpRequest += httpRequestBody; std::cout << "SEND >>" << std::endl << httpRequest << std::endl << "<<" << std::endl; gnutls_record_send(session, httpRequest.data(), httpRequest.length()); std::cout << "WAITING TO RECEIVE.." << std::endl; //Alles lesen und hoffen dass sich der Webserver dran h�lt und die Verbindung schlie�t //wenn er fertig mit Senden ist int c = 0, r = 0; do { r = gnutls_record_recv(session, tmpBuffer + c, BUF_SIZE - c); if (r > 0) c += r; } while (r > 0 && c < BUF_SIZE); if (c > 1024 || c <= 0) { std::cout << "received " << c << " bytes" << std::endl; std::cout << std::string(tmpBuffer, c) << std::endl; std::cerr << "Couldn't receive answer." << std::endl; throw std::runtime_error(STR_ERR_WRONG_ANSWER); } httpResponse = std::string(tmpBuffer, c); //Und fertig Verbindung beenden gnutls_bye(session, GNUTLS_SHUT_RDWR); gnutls_deinit(session); gnutls_certificate_free_credentials(credentials); closesocket(httpSocket); } catch (...) { //Irgendein Fehler trat auf, dann schließen. std::cerr << gtlsRet << ' ' << gnutls_error_is_fatal(gtlsRet) << std::endl; std::cerr << gnutls_strerror(gtlsRet) << std::endl; std::cerr << gnutls_alert_get_name(gnutls_alert_get(session)) << std::endl; if (session) gnutls_deinit(session); if (credentials) gnutls_certificate_free_credentials(credentials); closesocket(httpSocket); throw std::runtime_error(STR_ERR_TLS_FAILED); //weiterschmeißen } std::cout << "RECV >>" << std::endl << httpResponse << std::endl << "<<" << std::endl; /** Antwort sollte jetzt der typische HTTP Antwortquark sein und als Inhalt sollte ein Text der folgenden Form sein: PresentationServerUseHost: <host>\n PresentationServerUsePort: <port>\n */ unsigned short port; std::string host; int lifetime; try { _messageBox = utf8_to_ucs2(getParameter(httpResponse, "MessageBox", "")); port = atoi(getParameter(httpResponse, "PresentationServerUsePort").c_str()); host = getParameter(httpResponse, "PresentationServerUseHost"); _demo = atoi(getParameter(httpResponse, "Demo", "0").c_str()) ? true : false; lifetime = atoi(getParameter(httpResponse, "RuntimeSec", "0").c_str()); _serverPassword = getParameter(httpResponse, "PresentationServerPassword"); } catch (std::runtime_error e) { if (!_messageBox.empty()) throw runtime_error_with_extra_msg(_messageBox, getParameter(httpResponse, "Message")); throw std::runtime_error(getParameter(httpResponse, "Message")); } //Wenn die erfolgreich war dann den Server erstellen, Gr��e = Desktopgr��e _initRfbServer(screenWidth, screenHeight, _serverPassword, managerHost, caCertificate, host, port); if (lifetime > 0) { _timeOfDeath = std::chrono::system_clock::now() + std::chrono::seconds(lifetime); _useTimeOfDeath = true; } else { _useTimeOfDeath = false; } }
char *ident_username(rfbClientPtr client) { ClientData *cd = (ClientData *) client->clientData; char *str, *newhost, *user = NULL, *newuser = NULL; int len; if (cd) { user = cd->username; } if (!user || *user == '\0') { char msg[128]; int n, sock, ok = 0; int block = 0; /* * need to check to see if the operation will block for * a long time: a firewall may just ignore our packets. */ #if LIBVNCSERVER_HAVE_FORK { pid_t pid, pidw; int rc; if ((pid = fork()) > 0) { usleep(100 * 1000); /* 0.1 sec */ pidw = waitpid(pid, &rc, WNOHANG); if (pidw <= 0) { usleep(1000 * 1000); /* 1.0 sec */ pidw = waitpid(pid, &rc, WNOHANG); if (pidw <= 0) { block = 1; kill(pid, SIGTERM); } } } else if (pid == -1) { ; } else { /* child */ signal(SIGHUP, SIG_DFL); signal(SIGINT, SIG_DFL); signal(SIGQUIT, SIG_DFL); signal(SIGTERM, SIG_DFL); if ((sock = rfbConnectToTcpAddr(client->host, 113)) < 0) { exit(1); } else { close(sock); exit(0); } } } #endif if (block) { ; } else if ((sock = rfbConnectToTcpAddr(client->host, 113)) < 0) { rfbLog("could not connect to ident: %s:%d\n", client->host, 113); } else { int ret; fd_set rfds; struct timeval tv; int rport = get_remote_port(client->sock); int lport = get_local_port(client->sock); sprintf(msg, "%d, %d\r\n", rport, lport); n = write(sock, msg, strlen(msg)); FD_ZERO(&rfds); FD_SET(sock, &rfds); tv.tv_sec = 4; tv.tv_usec = 0; ret = select(sock+1, &rfds, NULL, NULL, &tv); if (ret > 0) { int i; char *q, *p; for (i=0; i<128; i++) { msg[i] = '\0'; } usleep(250*1000); n = read(sock, msg, 127); close(sock); if (n <= 0) goto badreply; /* 32782 , 6000 : USERID : UNIX :runge */ q = strstr(msg, "USERID"); if (!q) goto badreply; q = strstr(q, ":"); if (!q) goto badreply; q++; q = strstr(q, ":"); if (!q) goto badreply; q++; q = lblanks(q); p = q; while (*p) { if (*p == '\r' || *p == '\n') { *p = '\0'; } p++; } ok = 1; if (strlen(q) > 24) { *(q+24) = '\0'; } newuser = strdup(q); badreply: n = 0; /* avoid syntax error */ } else { close(sock); } } if (! ok || !newuser) { newuser = strdup("unknown-user"); } if (cd) { if (cd->username) { free(cd->username); } cd->username = newuser; } user = newuser; } if (!strcmp(user, "unknown-user") && cd && cd->unixname[0] != '\0') { user = cd->unixname; } if (unixpw && openssl_last_ip && strstr("UNIX:", user) != user) { newhost = ip2host(openssl_last_ip); } else { newhost = ip2host(client->host); } len = strlen(user) + 1 + strlen(newhost) + 1; str = (char *) malloc(len); sprintf(str, "%s@%s", user, newhost); free(newhost); return str; }