int get_config_handler(worker_st *ws, unsigned http_ver) { int ret; struct stat st; oclog(ws, LOG_HTTP_DEBUG, "requested config: %s", ws->req.url); if (ws->config->xml_config_file == NULL) { oclog(ws, LOG_INFO, "requested config but no config file is set"); tls_printf(ws->session, "HTTP/1.%u 404 Not found\r\n", http_ver); return -1; } ret = stat( ws->config->xml_config_file, &st); if (ret == -1) { oclog(ws, LOG_INFO, "cannot load config file '%s'", ws->config->xml_config_file); tls_printf(ws->session, "HTTP/1.%u 404 Not found\r\n", http_ver); return -1; } tls_cork(ws->session); ret = tls_printf(ws->session, "HTTP/1.%u 200 OK\r\n", http_ver); if (ret < 0) return -1; ret = tls_puts(ws->session, "Connection: Keep-Alive\r\n"); if (ret < 0) return -1; ret = tls_puts(ws->session, "Content-Type: text/xml\r\n"); if (ret < 0) return -1; ret = tls_puts(ws->session, "X-Transcend-Version: 1\r\n"); if (ret < 0) return -1; ret = tls_printf(ws->session, "Content-Length: %u\r\n", (unsigned)st.st_size); if (ret < 0) return -1; ret = tls_puts(ws->session, "\r\n"); if (ret < 0) return -1; ret = tls_uncork(ws->session); if (ret < 0) return -1; ret = tls_send_file(ws->session, ws->config->xml_config_file); if (ret < 0) { oclog(ws, LOG_ERR, "error sending file '%s': %s", ws->config->xml_config_file, gnutls_strerror(ret)); return -1; } return 0; }
/* Read data over TLS connection */ int tls_read(SSL *ssl, char* b, int length) { int status; while (True) { status = SSL_read(ssl, b, length); switch (SSL_get_error(ssl, status)) { case SSL_ERROR_NONE: return status; break; case SSL_ERROR_WANT_READ: break; default: tls_printf("SSL_read", ssl, status); return -1; break; } } return 0; }
/* Write data over TLS connection */ int tls_write(rdpTls * tls, char* b, int length) { int write_status; int bytesWritten = 0; while (bytesWritten < length) { write_status = SSL_write(tls->ssl, b, length); switch (SSL_get_error(tls->ssl, write_status)) { case SSL_ERROR_NONE: bytesWritten += write_status; break; case SSL_ERROR_WANT_WRITE: break; default: tls_printf("SSL_write", tls->ssl, write_status); return -1; break; } } return bytesWritten; }
int get_string_handler(worker_st *ws, unsigned http_ver) { int ret; const char *data; int len; oclog(ws, LOG_HTTP_DEBUG, "requested fixed string: %s", ws->req.url); if (!strcmp(ws->req.url, "/2/binaries/update.txt")) { data = VPN_VERSION; len = sizeof(VPN_VERSION)-1; } else { data = XML_START; len = sizeof(XML_START)-1; } tls_cork(ws->session); ret = tls_printf(ws->session, "HTTP/1.%u 200 OK\r\n", http_ver); if (ret < 0) return -1; ret = tls_puts(ws->session, "Connection: Keep-Alive\r\n"); if (ret < 0) return -1; ret = tls_puts(ws->session, "Content-Type: text/xml\r\n"); if (ret < 0) return -1; ret = tls_puts(ws->session, "X-Transcend-Version: 1\r\n"); if (ret < 0) return -1; ret = tls_printf(ws->session, "Content-Length: %d\r\n\r\n", len); if (ret < 0) return -1; ret = tls_send(ws->session, data, len); if (ret < 0) return -1; ret = tls_uncork(ws->session); if (ret < 0) return -1; return 0; }
int get_dl_handler(worker_st *ws, unsigned http_ver) { int ret; const char *data; int len; oclog(ws, LOG_HTTP_DEBUG, "requested downloader: %s", ws->req.url); data = SH_SCRIPT; len = sizeof(SH_SCRIPT)-1; tls_cork(ws->session); ret = tls_printf(ws->session, "HTTP/1.%u 200 OK\r\n", http_ver); if (ret < 0) return -1; ret = tls_puts(ws->session, "Connection: Keep-Alive\r\n"); if (ret < 0) return -1; ret = tls_puts(ws->session, "Content-Type: application/x-shellscript\r\n"); if (ret < 0) return -1; ret = tls_puts(ws->session, "X-Transcend-Version: 1\r\n"); if (ret < 0) return -1; ret = tls_printf(ws->session, "Content-Length: %d\r\n\r\n", len); if (ret < 0) return -1; ret = tls_send(ws->session, data, len); if (ret < 0) return -1; ret = tls_uncork(ws->session); if (ret < 0) return -1; return 0; }
int get_empty_handler(worker_st *ws, unsigned http_ver) { int ret; tls_cork(ws->session); ret = tls_printf(ws->session, "HTTP/1.%u 200 OK\r\n", http_ver); if (ret < 0) return -1; ret = tls_puts(ws->session, "Connection: Keep-Alive\r\n"); if (ret < 0) return -1; ret = tls_puts(ws->session, "Content-Type: text/html\r\n"); if (ret < 0) return -1; ret = tls_printf(ws->session, "Content-Length: %u\r\n", (unsigned int)sizeof(empty_msg)-1); if (ret < 0) return -1; ret = tls_puts(ws->session, "X-Transcend-Version: 1\r\n"); if (ret < 0) return -1; ret = tls_puts(ws->session, "\r\n"); if (ret < 0) return -1; ret = tls_send(ws->session, empty_msg, sizeof(empty_msg)-1); if (ret < 0) return -1; ret = tls_uncork(ws->session); if (ret < 0) return -1; return 0; }
/* Free TLS resources */ void tls_disconnect(SSL *ssl) { int ret; if (!ssl) return; while (True) { ret = SSL_shutdown(ssl); if (ret >= 0) break; if (tls_printf("ssl_disconnect", ssl, ret)) break; } SSL_free(ssl); ssl = NULL; }
/* Free TLS resources */ void tls_disconnect(rdpTls * tls) { int ret; if (!tls->ssl) return; while (True) { ret = SSL_shutdown(tls->ssl); if (ret >= 0) break; if (tls_printf("ssl_disconnect", tls->ssl, ret)) break; } SSL_free(tls->ssl); tls->ssl = NULL; }
/* Initiate TLS handshake on socket */ SSL* tls_connect(SSL_CTX *ctx, int sockfd, char *server) { SSL *ssl; int connection_status; ssl = SSL_new(ctx); if (ssl == NULL) { printf("SSL_new failed\n"); return NULL; } if (SSL_set_fd(ssl, sockfd) < 1) { printf("SSL_set_fd failed\n"); return NULL; } do { /* SSL_WANT_READ errors are normal, just try again if it happens */ connection_status = SSL_connect(ssl); } while (SSL_get_error(ssl, connection_status) == SSL_ERROR_WANT_READ); if (connection_status < 0) { if (tls_printf("SSL_connect", ssl, connection_status)) return NULL; } tls_verify(ssl, server); printf("TLS connection established\n"); return ssl; }
/* Write data over TLS connection */ int tls_write(SSL *ssl, char* b, int length) { int write_status; int bytesWritten = 0; write_status = SSL_write(ssl, b, length); switch (SSL_get_error(ssl, write_status)) { case SSL_ERROR_NONE: bytesWritten += write_status; break; default: tls_printf("SSL_write", ssl, write_status); break; } if (bytesWritten < length) return bytesWritten += tls_write(ssl, &b[bytesWritten], length - bytesWritten); else return bytesWritten; }
/* Initiate TLS handshake on socket */ RD_BOOL tls_connect(rdpTls * tls, int sockfd) { int connection_status; tls->ssl = SSL_new(tls->ctx); if (tls->ssl == NULL) { printf("SSL_new failed\n"); return False; } if (SSL_set_fd(tls->ssl, sockfd) < 1) { printf("SSL_set_fd failed\n"); return False; } do { /* SSL_WANT_READ errors are normal, just try again if it happens */ connection_status = SSL_connect(tls->ssl); } while (SSL_get_error(tls->ssl, connection_status) == SSL_ERROR_WANT_READ); if (connection_status < 0) { if (tls_printf("SSL_connect", tls->ssl, connection_status)) return False; } printf("TLS connection established\n"); return True; }