diff --git a/Makefile.in b/Makefile.in index 678899f..6166f20 100644 --- a/Makefile.in +++ b/Makefile.in @@ -10,15 +10,14 @@ LIBS = @CRYPTO_LIBS@ @LIBS@ CFLAGS = @CRYPTO_CPPFLAGS@ @CFLAGS@ @CPPFLAGS@ CFLAGS += -W -Wall -Wno-unused-parameter -pedantic -OBJS = main.o tray.o openvpn.o openvpn_monitor_process.o viewlog.o \ - service.o options.o passphrase.o proxy.o registry.o \ +OBJS = main.o tray.o openvpn.o viewlog.o \ + service.o options.o passphrase.o proxy.o registry.o manage.o \ openvpn_config.o scripts.o localization.o openvpn-gui-res.o SOURCES = main.c main.h openvpn.c openvpn.h localization.c localization.h \ - openvpn_monitor_process.c openvpn_monitor_process.h \ tray.c tray.h viewlog.c viewlog.h service.c service.h \ options.c options.h passphrase.c passphrase.h proxy.c proxy.h \ - registry.c registry.h scripts.c scripts.h \ + registry.c registry.h scripts.c scripts.h manage.c manage.h \ openvpn_config.c openvpn_config.h openvpn-gui.manifest \ chartable.h openvpn-gui-res.h openvpn-gui-res*.rc diff --git a/TODO b/TODO new file mode 100644 index 0000000..8c6f898 --- /dev/null +++ b/TODO @@ -0,0 +1,10 @@ +TODOs for OpenVPN-GUI + +* support usernames and passwords that contain a " character + +* pass string length to IDS_NFO_CONNECTION_XXX +* move registry values below openvpn pregistry key +* convert boolean registry values from string to dword +* maybe parse config and use selected options in command line directly +* have some kind of error log instead of message boxes for low level errors +* user auth dlg box: enable OK button only if username contains something diff --git a/configure.ac b/configure.ac index 96112b1..5a2c5b4 100644 --- a/configure.ac +++ b/configure.ac @@ -39,8 +39,12 @@ AX_ASSERT_LIB([wininet], [wininet.h], [Make sure you have a recent w32api installed.]) AX_ASSERT_LIB([comctl32], [prsht.h], - [PROPSHEETHEADER psh; PropertySheet(&psh)], - [Make sure you have a recent w32api installed.], [#include ]) + [PROPSHEETHEADER psh; PropertySheet(&psh)], + [Make sure you have a recent w32api installed.], [#include ]) + +AX_ASSERT_LIB([Ws2_32], [Winsock2.h], + [WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData)], + [Make sure you have a recent w32api installed.], [#include ]) AX_SEARCH_LIB([crypto], [cryptoeay32 eay32 crypto], [-lgdi32], [openssl/pkcs12.h], [EVP_PKEY *k = EVP_PKEY_new()]) diff --git a/main.c b/main.c index aa8fc59..03ea0b7 100644 --- a/main.c +++ b/main.c @@ -20,6 +20,7 @@ */ #define _WIN32_IE 0x0500 + #include #include #include @@ -37,6 +38,7 @@ #include "registry.h" #include "openvpn-gui-res.h" #include "localization.h" +#include "manage.h" #ifndef DISABLE_CHANGE_PASSWORD #include @@ -56,6 +58,36 @@ TCHAR szTitleText[ ] = _T("OpenVPN"); /* Options structure */ options_t o; +static int +VerifyAutoConnections() +{ + int i; + BOOL match; + + for (i = 0; o.auto_connect[i] != 0 && i < MAX_CONFIGS; i++) + { + int j; + match = FALSE; + for (j = 0; j < MAX_CONFIGS; j++) + { + if (_tcsicmp(o.conn[j].config_file, o.auto_connect[i]) == 0) + { + match = TRUE; + break; + } + } + if (match == FALSE) + { + /* autostart config not found */ + ShowLocalizedMsg(IDS_ERR_AUTOSTART_CONF, o.auto_connect[i]); + return FALSE; + } + } + + return TRUE; +} + + int WINAPI WinMain (HINSTANCE hThisInstance, UNUSED HINSTANCE hPrevInstance, UNUSED LPSTR lpszArgument, @@ -66,6 +98,17 @@ int WINAPI WinMain (HINSTANCE hThisInstance, WNDCLASSEX wincl; /* Data structure for the windowclass */ DWORD shell32_version; + /* Initialize handlers for manangement interface notifications */ + mgmt_rtmsg_handler handler[] = { + { ready, OnReady }, + { hold, OnHold }, + { log, OnLogLine }, + { state, OnStateChange }, + { password, OnPassword }, + { stop, OnStop }, + { 0, NULL } + }; + InitManagement(handler); /* initialize options to default state */ InitOptions(&o); @@ -125,6 +168,7 @@ int WINAPI WinMain (HINSTANCE hThisInstance, if (!CheckVersion()) { exit(1); } + BuildFileList(); if (!VerifyAutoConnections()) { exit(1); @@ -187,6 +231,41 @@ int WINAPI WinMain (HINSTANCE hThisInstance, } +static void +StopAllOpenVPN() +{ + int i; + + for (i = 0; i < o.num_configs; i++) + { + if (o.conn[i].state != disconnected) + StopOpenVPN(&o.conn[i]); + } + + /* Wait for all connections to terminate (Max 5 sec) */ + for (i = 0; i < 20; i++, Sleep(250)) + { + if (CountConnState(disconnected) == o.num_configs) + break; + } +} + + +static int +AutoStartConnections() +{ + int i; + + for (i = 0; i < o.num_configs; i++) + { + if (o.conn[i].auto_connect) + StartOpenVPN(&o.conn[i]); + } + + return TRUE; +} + + /* This function is called by the Windows function DispatchMessage() */ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { @@ -221,13 +300,13 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM case WM_NOTIFYICONTRAY: OnNotifyTray(lParam); // Manages message from tray break; - + case WM_COMMAND: if ( (LOWORD(wParam) >= IDM_CONNECTMENU) && (LOWORD(wParam) < IDM_CONNECTMENU + MAX_CONFIGS) ) { - StartOpenVPN(LOWORD(wParam) - IDM_CONNECTMENU); + StartOpenVPN(&o.conn[LOWORD(wParam) - IDM_CONNECTMENU]); } if ( (LOWORD(wParam) >= IDM_DISCONNECTMENU) && (LOWORD(wParam) < IDM_DISCONNECTMENU + MAX_CONFIGS) ) { - StopOpenVPN(LOWORD(wParam) - IDM_DISCONNECTMENU); + StopOpenVPN(&o.conn[LOWORD(wParam) - IDM_DISCONNECTMENU]); } if ( (LOWORD(wParam) >= IDM_STATUSMENU) && (LOWORD(wParam) < IDM_STATUSMENU + MAX_CONFIGS) ) { ShowWindow(o.conn[LOWORD(wParam) - IDM_STATUSMENU].hwndStatus, SW_SHOW); @@ -303,11 +382,11 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM { /* Restart suspend connections */ if (o.conn[i].state == suspended) - StartOpenVPN(i); + StartOpenVPN(&o.conn[i]); /* If some connection never reached SUSPENDED state */ if (o.conn[i].state == suspending) - StopOpenVPN(i); + StopOpenVPN(&o.conn[i]); } return FALSE; } diff --git a/main.h b/main.h index 4d04cac..227924a 100644 --- a/main.h +++ b/main.h @@ -39,6 +39,7 @@ /* Registry key for Global Settings */ #define GUI_REGKEY_HKLM _T("SOFTWARE\\OpenVPN-GUI") +#define MAX_LOG_LENGTH 1024/* Max number of characters per log line */ #define MAX_LOG_LINES 500 /* Max number of lines in LogWindow */ #define DEL_LOG_LINES 10 /* Number of lines to delete from LogWindow */ diff --git a/manage.c b/manage.c new file mode 100644 index 0000000..c995128 --- /dev/null +++ b/manage.c @@ -0,0 +1,307 @@ +/* + * OpenVPN-GUI -- A Windows GUI for OpenVPN. + * + * Copyright (C) 2010 Heiko Hund + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program (see the file COPYING included with this + * distribution); if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "options.h" +#include "main.h" +#include "manage.h" + +extern options_t o; + +static mgmt_msg_func rtmsg_handler[mgmt_rtmsg_type_max]; + + +/* + * Initialize the real-time notification handlers + */ +void +InitManagement(const mgmt_rtmsg_handler *handler) +{ + int i; + for (i = 0; handler[i].handler; ++i) + { + rtmsg_handler[handler[i].type] = handler[i].handler; + } +} + + +/* + * Connect to the OpenVPN management interface and register + * asynchronous socket event notification for it + */ +BOOL +OpenManagement(connection_t *c, u_long addr, u_short port) +{ + WSADATA wsaData; + SOCKADDR_IN skaddr = { + .sin_family = AF_INET, + .sin_addr.s_addr = addr, + .sin_port = htons(port) + }; + + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) + return FALSE; + + c->manage.sk = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (c->manage.sk == INVALID_SOCKET) + return FALSE; + + if (WSAAsyncSelect(c->manage.sk, c->hwndStatus, WM_MANAGEMENT, + FD_CONNECT|FD_READ|FD_WRITE|FD_CLOSE) != 0) + return FALSE; + + connect(c->manage.sk, (SOCKADDR *)&skaddr, sizeof(skaddr)); + + return TRUE; +} + + +/* + * Send a command to the OpenVPN management interface + */ +BOOL +ManagementCommand(connection_t *c, char *command, mgmt_msg_func handler, mgmt_cmd_type type) +{ + int res = 0; + int size = strlen(command) + 1; + + mgmt_cmd_t *cmd = calloc(1, sizeof(*cmd)); + if (cmd == NULL) + return FALSE; + + cmd->handler = handler; + cmd->type = type; + + if (c->manage.cmd_queue) + { + cmd->next = c->manage.cmd_queue; + cmd->prev = c->manage.cmd_queue->prev; + cmd->next->prev = cmd->prev->next = cmd; + } + else + { + cmd->next = cmd->prev = cmd; + c->manage.cmd_queue = cmd; + } + + if (c->manage.cmd_queue == cmd) + { + *(command + size - 1) = '\n'; + res = send(c->manage.sk, command, size, 0); + *(command + size - 1) = '\0'; + } + + if (res != size) + { + if (res == SOCKET_ERROR) + res = 0; + + size -= res; + cmd->command = malloc(size); + if (cmd->command == NULL) + { + free(cmd); + return FALSE; + } + memcpy(cmd->command, command + res, size); + *(cmd->command + size - 1) = '\n'; + cmd->size = size; + } + + return TRUE; +} + + +/* + * Try to send a queued management command to OpenVPN + */ +static void +SendCommand(connection_t *c) +{ + int res; + mgmt_cmd_t *cmd = c->manage.cmd_queue; + if (cmd == NULL || cmd->size == 0) + return; + + res = send(c->manage.sk, cmd->command, cmd->size, 0); + if (res < 1) + return; + + if (res != cmd->size) + memmove(cmd->command, cmd->command + res, cmd->size - res); + + cmd->size -= res; +} + +/* + * Remove a command from a connection's command queue + */ +static BOOL +UnqueueCommand(connection_t *c) +{ + mgmt_cmd_t *cmd = c->manage.cmd_queue; + if (!cmd) + return FALSE; + + if (cmd->type == combined) + { + cmd->type = regular; + return TRUE; + } + + if (cmd->next == cmd) + { + c->manage.cmd_queue = NULL; + } + else + { + cmd->prev->next = cmd->next; + cmd->next->prev = cmd->prev; + c->manage.cmd_queue = cmd->next; + SendCommand(c); + } + + free(cmd->command); + free(cmd); + + return TRUE; +} + +/* + * Handle management socket events asynchronously + */ +void +OnManagement(SOCKET sk, LPARAM lParam) +{ + int res; + char *pos = NULL; + char data[MAX_LOG_LENGTH]; + connection_t *c = GetConnByManagement(sk); + if (c == NULL) + return; + + switch (WSAGETSELECTEVENT(lParam)) + { + case FD_CONNECT: + if (WSAGETSELECTERROR(lParam)) + SendMessage(c->hwndStatus, WM_CLOSE, 0, 0); + break; + + case FD_READ: + /* Check if there's a complete line to read */ + res = recv(c->manage.sk, data, sizeof(data), MSG_PEEK); + if (res < 1) + return; + + pos = memchr(data, (*c->manage.password ? ':' : '\n'), res); + if (!pos) + return; + + /* There is data available: read it */ + res = recv(c->manage.sk, data, pos - data + 1, 0); + if (res != pos - data + 1) + return; + + /* Reply to a management password request */ + if (*c->manage.password) + { + ManagementCommand(c, c->manage.password, NULL, regular); + *c->manage.password = '\0'; + return; + } + + /* Handle regular management interface output */ + data[pos - data - 1] = '\0'; + if (data[0] == '>') + { + /* Real time notifications */ + pos = data + 1; + if (strncmp(pos, "LOG:", 4) == 0) + { + if (rtmsg_handler[log]) + rtmsg_handler[log](c, pos + 4); + } + else if (strncmp(pos, "STATE:", 6) == 0) + { + if (rtmsg_handler[state]) + rtmsg_handler[state](c, pos + 6); + } + else if (strncmp(pos, "HOLD:", 5) == 0) + { + if (rtmsg_handler[hold]) + rtmsg_handler[hold](c, pos + 5); + } + else if (strncmp(pos, "PASSWORD:", 9) == 0) + { + if (rtmsg_handler[password]) + rtmsg_handler[password](c, pos + 9); + } + else if (strncmp(pos, "INFO:", 5) == 0) + { + /* delay until management interface accepts input */ + Sleep(100); + if (rtmsg_handler[ready]) + rtmsg_handler[ready](c, pos + 5); + } + } + else if (c->manage.cmd_queue) + { + /* Response to commands */ + mgmt_cmd_t *cmd = c->manage.cmd_queue; + if (strncmp(data, "SUCCESS:", 8) == 0) + { + if (cmd->handler) + cmd->handler(c, data + 9); + UnqueueCommand(c); + } + else if (strncmp(data, "ERROR:", 6) == 0) + { + if (cmd->handler) + cmd->handler(c, NULL); + UnqueueCommand(c); + } + else if (strcmp(data, "END") == 0) + { + UnqueueCommand(c); + } + else if (cmd->handler) + { + cmd->handler(c, data); + } + } + break; + + case FD_WRITE: + SendCommand(c); + break; + + case FD_CLOSE: + closesocket(c->manage.sk); + c->manage.sk = INVALID_SOCKET; + while (UnqueueCommand(c)) + ; + WSACleanup(); + if (rtmsg_handler[stop]) + rtmsg_handler[stop](c, ""); + break; + } +} diff --git a/manage.h b/manage.h new file mode 100644 index 0000000..f91a3c0 --- /dev/null +++ b/manage.h @@ -0,0 +1,69 @@ +/* + * OpenVPN-GUI -- A Windows GUI for OpenVPN. + * + * Copyright (C) 2010 Heiko Hund + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program (see the file COPYING included with this + * distribution); if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANAGE_H +#define MANAGE_H + +#define WM_MANAGEMENT (WM_APP + 2) + +typedef enum { + ready, + stop, + bytecount, + echo, + hold, + log, + password, + state, + needok, + needstr, + pkcs11_id_count, + mgmt_rtmsg_type_max +} mgmt_rtmsg_type; + +typedef enum { + regular, + combined +} mgmt_cmd_type; + +typedef void (*mgmt_msg_func)(connection_t *, char *); + +typedef struct { + mgmt_rtmsg_type type; + mgmt_msg_func handler; +} mgmt_rtmsg_handler; + +typedef struct mgmt_cmd { + struct mgmt_cmd *prev, *next; + char *command; + int size; + mgmt_msg_func handler; + mgmt_cmd_type type; +} mgmt_cmd_t; + + +void InitManagement(const mgmt_rtmsg_handler *handler); +BOOL OpenManagement(connection_t *, u_long, u_short); +BOOL ManagementCommand(connection_t *, char *, mgmt_msg_func, mgmt_cmd_type); + +void OnManagement(SOCKET, LPARAM); + +#endif diff --git a/openvpn-gui-res-de.rc b/openvpn-gui-res-de.rc index 619420a..2abc91b 100644 --- a/openvpn-gui-res-de.rc +++ b/openvpn-gui-res-de.rc @@ -199,16 +199,12 @@ BEGIN IDS_ERR_INIT_SEC_DESC "InitializeSecurityDescriptor fehlgeschlagen." IDS_ERR_SET_SEC_DESC_ACL "SetSecurityDescriptorDacl fehlgeschlagen." IDS_ERR_CREATE_PIPE_OUTPUT "CreatePipe an hOutputWrite fehlgeschlagen." - IDS_ERR_DUP_HANDLE_ERR_WRITE "DuplicateHandle an hErrorWrite fehlgeschlagen." IDS_ERR_CREATE_PIPE_INPUT "CreatePipe an hInputRead fehlgeschlagen." IDS_ERR_DUP_HANDLE_OUT_READ "DuplicateHandle an hOutputRead fehlgeschlagen." IDS_ERR_DUP_HANDLE_IN_WRITE "DuplicateHandle an hInputWrite fehlgeschlagen." - IDS_ERR_CLOSE_HANDLE_TMP "CloseHandle an hOutputReadTmp/hInputWriteTmp fehlgeschlagen." IDS_ERR_CREATE_PROCESS "CreateProcess fehlgeschlagen, exe='%s' cmdline='%s' dir='%s'" - IDS_ERR_CLOSE_HANDLE "CloseHandle fehlgeschlagen." IDS_ERR_CREATE_THREAD_STATUS "CreateThread, welcher das Statusfenster zeigt ist fehlgschlagen." IDS_NFO_STATE_WAIT_TERM "Aktueller Status: Wartet bis OpenVPN beendet ist..." - IDS_ERR_OPEN_LOG_WRITE "Fehler beim Schreiben des Logfiles: %s. Sie haben vermutlich keine Administratorenrechte, welche nötig sind um OpenVPN zu starten." IDS_NFO_STATE_CONNECTED "Aktueller Status: Verbunden" IDS_NFO_NOW_CONNECTED "%s ist nun verbunden." IDS_NFO_ASSIGN_IP "Zugewiesene IP: %s" @@ -229,7 +225,6 @@ BEGIN IDS_ERR_CREATE_PIPE_IN_READ "CreatePipe an hInputRead fehlgeschlagen." IDS_NFO_STATE_CONNECTING "Aktueller Status: Verbinden" IDS_NFO_CONNECTION_XXX "OpenVPN Verbindung (%s)" - IDS_ERR_THREAD_READ_STDOUT "CreateThread zum Lesen des OpenVPN Prozess stdout fehlgeschlagen." IDS_NFO_STATE_CONN_SCRIPT "Aktueller Status: Verbindungsscript läuft" IDS_NFO_STATE_DISCONN_SCRIPT "Aktueller Status: Verbindungstrennungsscript läuft" IDS_ERR_RUN_CONN_SCRIPT "Fehler beim Ausführen des Verbindungsscript: %s" @@ -252,11 +247,6 @@ BEGIN IDS_NFO_SERVICE_ACTIVE_EXIT "Der OpenVPN Dienst ist gestartet und verbunden. " \ "Die Verbindung besteht solange bis Sie die OpenVPN GUI beenden.\n\n" \ "\n\nSind sie sicher, dass Sie das Programm beenden möchten?" - IDS_ERR_OPTION_LOG_IN_CONFIG "Sie haben ""log"" oder ""log-append"" in Ihrer OpenVPN Konfigurationsdatei. Diese Optionen " \ - "sollten nicht mit der OpenVPN GUI verwendet werden, denn es verhindert, dass die Ausgaben " \ - "von OpenVPN lesen kann, welche nötig ist, für den korrekten Betrieb des OpenVPN " \ - "GUI. Die Ausgabe wird immer in ein Logfile geschrieben, wenn OpenVPN GUI verwendet wird. " \ - "Deshalb sollten Sie diese Option entfernen.\n\nMöchten Sie dennoch mit dem Verbinden fortfahren? " /* options - Resources */ IDS_NFO_USAGE "--help\t\t\t: Zeigt diese Information.\n" \ diff --git a/openvpn-gui-res-en.rc b/openvpn-gui-res-en.rc index a49f90f..58112ed 100644 --- a/openvpn-gui-res-en.rc +++ b/openvpn-gui-res-en.rc @@ -194,16 +194,12 @@ BEGIN IDS_ERR_INIT_SEC_DESC "InitializeSecurityDescriptor failed." IDS_ERR_SET_SEC_DESC_ACL "SetSecurityDescriptorDacl failed." IDS_ERR_CREATE_PIPE_OUTPUT "CreatePipe on hOutputWrite failed." - IDS_ERR_DUP_HANDLE_ERR_WRITE "DuplicateHandle on hErrorWrite failed." IDS_ERR_CREATE_PIPE_INPUT "CreatePipe on hInputRead failed." IDS_ERR_DUP_HANDLE_OUT_READ "DuplicateHandle on hOutputRead failed." IDS_ERR_DUP_HANDLE_IN_WRITE "DuplicateHandle on hInputWrite failed." - IDS_ERR_CLOSE_HANDLE_TMP "CloseHandle on hOutputReadTmp/hInputWriteTmp failed." IDS_ERR_CREATE_PROCESS "CreateProcess failed, exe='%s' cmdline='%s' dir='%s'" - IDS_ERR_CLOSE_HANDLE "CloseHandle failed." IDS_ERR_CREATE_THREAD_STATUS "CreateThread to show Status window Failed." IDS_NFO_STATE_WAIT_TERM "Current State: Waiting for OpenVPN to terminate..." - IDS_ERR_OPEN_LOG_WRITE "Error opening logfile for writing: %s. You probably don't have administrator privileges, which are necessary to run OpenVPN." IDS_NFO_STATE_CONNECTED "Current State: Connected" IDS_NFO_NOW_CONNECTED "%s is now connected." IDS_NFO_ASSIGN_IP "Assigned IP: %s" @@ -224,7 +220,6 @@ BEGIN IDS_ERR_CREATE_PIPE_IN_READ "CreatePipe on hInputRead failed." IDS_NFO_STATE_CONNECTING "Current State: Connecting" IDS_NFO_CONNECTION_XXX "OpenVPN Connection (%s)" - IDS_ERR_THREAD_READ_STDOUT "CreateThread to read openvpn process stdout failed." IDS_NFO_STATE_CONN_SCRIPT "Current State: Running Connect Script" IDS_NFO_STATE_DISCONN_SCRIPT "Current State: Running Disconnect Script" IDS_ERR_RUN_CONN_SCRIPT "Error running Connect Script: %s" @@ -246,12 +241,6 @@ BEGIN IDS_NFO_SERVICE_ACTIVE_EXIT "You are currently connected (the OpenVPN Service is running). " \ "You will stay connected even if you exit OpenVPN GUI.\n\n" \ "Do you want to proceed and exit OpenVPN GUI?" - IDS_ERR_OPTION_LOG_IN_CONFIG "You have ""log"" or ""log-append"" in your OpenVPN config file. These options " \ - "should not be used with OpenVPN GUI as they prevents OpenVPN GUI from reading " \ - "the log output of OpenVPN which is necessary for correct operation of OpenVPN " \ - "GUI. The log is always written to a logfile when OpenVPN GUI is beeing used " \ - "anyway, so you should remove this option.\n\nDo you want to proceed connecting " \ - "anyway?" /* options - Resources */ IDS_NFO_USAGE "--help\t\t\t: Show this message.\n" \ diff --git a/openvpn-gui-res-es.rc b/openvpn-gui-res-es.rc index 3fbf31c..b1ba9a0 100644 --- a/openvpn-gui-res-es.rc +++ b/openvpn-gui-res-es.rc @@ -181,16 +181,12 @@ BEGIN IDS_ERR_INIT_SEC_DESC "InitializeSecurityDescriptor fallido." IDS_ERR_SET_SEC_DESC_ACL "SetSecurityDescriptorDacl fallido." IDS_ERR_CREATE_PIPE_OUTPUT "CreatePipe on hOutputWrite fallido." - IDS_ERR_DUP_HANDLE_ERR_WRITE "DuplicateHandle on hErrorWrite fallido." IDS_ERR_CREATE_PIPE_INPUT "CreatePipe on hInputRead fallido." IDS_ERR_DUP_HANDLE_OUT_READ "DuplicateHandle on hOutputRead fallido." IDS_ERR_DUP_HANDLE_IN_WRITE "DuplicateHandle on hInputWrite fallido." - IDS_ERR_CLOSE_HANDLE_TMP "CloseHandle on hOutputReadTmp/hInputWriteTmp fallido." IDS_ERR_CREATE_PROCESS "CreateProcess fallido, exe='%s' cmdline='%s' dir='%s'" - IDS_ERR_CLOSE_HANDLE "CloseHandle fallido." IDS_ERR_CREATE_THREAD_STATUS "CreateThread para mostrar la Ventana de Estado fallido." IDS_NFO_STATE_WAIT_TERM "Estado actual: Esperando que OpenVPN termine..." - IDS_ERR_OPEN_LOG_WRITE "Error al abrir el fichero de log para escritura: %s. Probablemente no tiene privilegios de administrador, que son necesarios para ejecutar OpenVPN." IDS_NFO_STATE_CONNECTED "Estado actual: Conectado." IDS_NFO_NOW_CONNECTED "Conectado a %s." IDS_NFO_ASSIGN_IP "IP asignada: %s" @@ -211,7 +207,6 @@ BEGIN IDS_ERR_CREATE_PIPE_IN_READ "CreatePipe on hInputRead falló." IDS_NFO_STATE_CONNECTING "Estado actual: Conectando" IDS_NFO_CONNECTION_XXX "Conexión OpenVPN (%s)" - IDS_ERR_THREAD_READ_STDOUT "CreateThread para leer la salida del proceso de OpenVPN falló." IDS_NFO_STATE_CONN_SCRIPT "Estado actual: Ejecutando el script de conexión" IDS_NFO_STATE_DISCONN_SCRIPT "Estado actual: Ejecutando el script de desconexión" IDS_ERR_RUN_CONN_SCRIPT "Error ejecutando el script de conexión: %s" @@ -233,12 +228,6 @@ BEGIN IDS_NFO_SERVICE_ACTIVE_EXIT "Ahora mismo está conectado (el servicio OpenVPN está corriendo). " \ "Seguriá conectado incluso si sale de OpenVPN GUI.\n\n" \ "¿Quiere proceder y salir de OpenVPN GUI?" - IDS_ERR_OPTION_LOG_IN_CONFIG "Tiene ""log"" ó ""log-append"" en el fichero de configuración de OpenVPN. Dichas opciones " \ - "no deberían usarse con OpenVPN GUI pues impiden que OpenVPN GUI pueda leer " \ - "el log de salida de OpenVPN que es necesario para el correcto funcionamiento de OpenVPN " \ - "GUI. En todo caso, el log siempre se escribe en un fichero cuando OpenVPN GUI está en " \ - "uso, asi que deberia quitar ésta opción.\n\n¿Quiere continuar con la conexión " \ - "de todas formas?" /* options - Resources */ IDS_NFO_USAGE "--help\t\t\t: Mostrar éste mensaje.\n" \ diff --git a/openvpn-gui-res-fi.rc b/openvpn-gui-res-fi.rc index 0638d85..1ffd4ab 100644 --- a/openvpn-gui-res-fi.rc +++ b/openvpn-gui-res-fi.rc @@ -194,16 +194,12 @@ BEGIN IDS_ERR_INIT_SEC_DESC "InitializeSecurityDescriptor failed." IDS_ERR_SET_SEC_DESC_ACL "SetSecurityDescriptorDacl failed." IDS_ERR_CREATE_PIPE_OUTPUT "CreatePipe on hOutputWrite failed." - IDS_ERR_DUP_HANDLE_ERR_WRITE "DuplicateHandle on hErrorWrite failed." IDS_ERR_CREATE_PIPE_INPUT "CreatePipe on hInputRead failed." IDS_ERR_DUP_HANDLE_OUT_READ "DuplicateHandle on hOutputRead failed." IDS_ERR_DUP_HANDLE_IN_WRITE "DuplicateHandle on hInputWrite failed." - IDS_ERR_CLOSE_HANDLE_TMP "CloseHandle on hOutputReadTmp/hInputWriteTmp failed." IDS_ERR_CREATE_PROCESS "CreateProcess failed, exe='%s' cmdline='%s' dir='%s'" - IDS_ERR_CLOSE_HANDLE "CloseHandle failed." IDS_ERR_CREATE_THREAD_STATUS "CreateThread to show Status window Failed." IDS_NFO_STATE_WAIT_TERM "Tila: Odotetaan OpenVPN:n sammumista..." - IDS_ERR_OPEN_LOG_WRITE "Virhe kirjoitettaessa lokitiedostoon: %s. Varmista, että OpenVPN käynnistetään ylläpitäjän oikeuksin." IDS_NFO_STATE_CONNECTED "Tila: Yhdistetty" IDS_NFO_NOW_CONNECTED "%s on nyt yhdistetty." IDS_NFO_ASSIGN_IP "IP-osoite: %s" @@ -224,7 +220,6 @@ BEGIN IDS_ERR_CREATE_PIPE_IN_READ "CreatePipe on hInputRead failed." IDS_NFO_STATE_CONNECTING "Tila: Yhdistetään" IDS_NFO_CONNECTION_XXX "OpenVPN-yhteys (%s)" - IDS_ERR_THREAD_READ_STDOUT "CreateThread to read openvpn process stdout failed." IDS_NFO_STATE_CONN_SCRIPT "Tila: Suoritetaan yhteydenmuodostamisskripti" IDS_NFO_STATE_DISCONN_SCRIPT "Tila: Suoritetaan yhteydenkatkaisemisskripti " IDS_ERR_RUN_CONN_SCRIPT "Virhe suoritettaessa yhteydenmuodostamisskriptiä: %s" @@ -247,11 +242,6 @@ BEGIN IDS_NFO_SERVICE_ACTIVE_EXIT "Yhteys on muodostettu OpenVPN-palvelun avulla. " \ "Yhteydet eivät katkea, vaikka OpenVPN GUI suljettaisiinkin.\n\n" \ "Suljetaanko OpenVPN GUI?" - IDS_ERR_OPTION_LOG_IN_CONFIG "OpenVPN:n asetustiedostossa on käytössä ""log"" tai ""log-append"". " \ - "Nämä asetukset estävät OpenVPN GUI:ta toimimasta oikein eikä niitä " \ - "tulisi käyttää. Vaikka asetukset eivät olisikaan käytössä, OpenVPN " \ - "GUI kirjoittaa silti lokia." \ - "\n\nHaluatko varmasti jatkaa?" /* options - Resources */ IDS_NFO_USAGE "--help\t\t\t: Näytä tämä viesti.\n" \ diff --git a/openvpn-gui-res-fr.rc b/openvpn-gui-res-fr.rc index 79d55de..fda7a2a 100644 --- a/openvpn-gui-res-fr.rc +++ b/openvpn-gui-res-fr.rc @@ -192,16 +192,12 @@ BEGIN IDS_ERR_INIT_SEC_DESC "InitializeSecurityDescriptor échoué." IDS_ERR_SET_SEC_DESC_ACL "SetSecurityDescriptorDacl échoué." IDS_ERR_CREATE_PIPE_OUTPUT "CreatePipe sur hOutputWrite échoué." - IDS_ERR_DUP_HANDLE_ERR_WRITE "DuplicateHandle sur hErrorWrite échoué." IDS_ERR_CREATE_PIPE_INPUT "CreatePipe sur hInputRead échoué." IDS_ERR_DUP_HANDLE_OUT_READ "DuplicateHandle sur hOutputRead échoué." IDS_ERR_DUP_HANDLE_IN_WRITE "DuplicateHandle sur hInputWrite échoué." - IDS_ERR_CLOSE_HANDLE_TMP "CloseHandle sur hOutputReadTmp/hInputWriteTmp échoué." IDS_ERR_CREATE_PROCESS "CreateProcess échoué, exe='%s' cmdline='%s' dir='%s'" - IDS_ERR_CLOSE_HANDLE "CloseHandle échoué." IDS_ERR_CREATE_THREAD_STATUS "CreateThread échoué pour afficher la fenêtre de statut." IDS_NFO_STATE_WAIT_TERM "Etat actuel: Attente que OpenVPN se termine..." - IDS_ERR_OPEN_LOG_WRITE "Erreur pour ouverture du fichier de log pour écriture: %s. Vous n'avez probablement pas les privilèges administrateur, nécessaires pour lancer OpenVPN." IDS_NFO_STATE_CONNECTED "Etat actuel: Connecté" IDS_NFO_NOW_CONNECTED "%s est désormais connecté." IDS_NFO_ASSIGN_IP "Adresse IP assignée: %s" @@ -222,7 +218,6 @@ BEGIN IDS_ERR_CREATE_PIPE_IN_READ "CreatePipe sur hInputRead échoué." IDS_NFO_STATE_CONNECTING "Etat actuel: En cours de connexion" IDS_NFO_CONNECTION_XXX "Connexion OpenVPN (%s)" - IDS_ERR_THREAD_READ_STDOUT "CreateThread pour lecture de la procédure openvpn stdout échoué." IDS_NFO_STATE_CONN_SCRIPT "Etat actuel: Exécution du script de connexion" IDS_NFO_STATE_DISCONN_SCRIPT "Etat actuel: Exécution du script de déconnexion" IDS_ERR_RUN_CONN_SCRIPT "Erreur d'exécution du script de connexion: %s" @@ -244,12 +239,6 @@ BEGIN IDS_NFO_SERVICE_ACTIVE_EXIT "Vous êtes actuellement connecté (Le service OpenVPN est actif). " \ "Vous restez connecté même si vous terminez l'OpenVPN GUI.\n\n" \ "Voulez-vous continuer et fermer l'OpenVPN GUI ?" - IDS_ERR_OPTION_LOG_IN_CONFIG "Vous avez ""log"" ou ""log-append"" dans votre fichier de configuration OpenVPN. Ces options " \ - "ne doivent pas être utilisées avec OpenVPN GUI afin d'éviter la lecture en sortie " \ - "d'OpenVPN ce qui est nécéssaire au fonctionnement correct OpenVPN GUI. " \ - "Les actions sont toujours écrites dans le fichier de log lorsque OpenVPN GUI est utilisé " \ - "donc, vous devez supprimer cette option.\n\nVoulez-vous malgré tout procéder à " \ - "la connexion ?" /* options - Resources */ IDS_NFO_USAGE "--help\t\t\t: Afficher ce message.\n" \ diff --git a/openvpn-gui-res-it.rc b/openvpn-gui-res-it.rc index 3bba596..cc50c08 100644 --- a/openvpn-gui-res-it.rc +++ b/openvpn-gui-res-it.rc @@ -180,16 +180,12 @@ BEGIN IDS_ERR_INIT_SEC_DESC "InitializeSecurityDescriptor fallito." IDS_ERR_SET_SEC_DESC_ACL "SetSecurityDescriptorDacl fallito." IDS_ERR_CREATE_PIPE_OUTPUT "CreatePipe on hOutputWrite fallito." - IDS_ERR_DUP_HANDLE_ERR_WRITE "DuplicateHandle on hErrorWrite fallito." IDS_ERR_CREATE_PIPE_INPUT "CreatePipe on hInputRead fallito." IDS_ERR_DUP_HANDLE_OUT_READ "DuplicateHandle on hOutputRead fallito." IDS_ERR_DUP_HANDLE_IN_WRITE "DuplicateHandle on hInputWrite fallito." - IDS_ERR_CLOSE_HANDLE_TMP "CloseHandle on hOutputReadTmp/hInputWriteTmp fallito." IDS_ERR_CREATE_PROCESS "CreateProcess fallito, exe='%s' cmdline='%s' dir='%s'" - IDS_ERR_CLOSE_HANDLE "CloseHandle fallito." IDS_ERR_CREATE_THREAD_STATUS "CreateThread fallito per visualizzare lo stato." IDS_NFO_STATE_WAIT_TERM "Stato corrente: In attesa che OpenVPN termini..." - IDS_ERR_OPEN_LOG_WRITE "Errore apertura del file di log in scrittura: %s. Probabilmente non hai i privilegi di amministratore, che sono necessari a far funzionare OpenVPN." IDS_NFO_STATE_CONNECTED "Stato corrente: Connesso" IDS_NFO_NOW_CONNECTED "%s è ora connesso." IDS_NFO_ASSIGN_IP "IP asseganto: %s" @@ -210,7 +206,6 @@ BEGIN IDS_ERR_CREATE_PIPE_IN_READ "CreatePipe on hInputRead falito." IDS_NFO_STATE_CONNECTING "Stato corrente: Connessione in corso" IDS_NFO_CONNECTION_XXX "Connessione OpenVPN (%s)" - IDS_ERR_THREAD_READ_STDOUT "CreateThread per leggere il process stdout di openvpn è fallito." IDS_NFO_STATE_CONN_SCRIPT "Stato corrente: Avviato lo script di connessione" IDS_NFO_STATE_DISCONN_SCRIPT "Stato corrente: Avviato lo script di disconnessione" IDS_ERR_RUN_CONN_SCRIPT "Errore durante il funzionamento dello script di connessione: %s" @@ -232,11 +227,6 @@ BEGIN IDS_NFO_SERVICE_ACTIVE_EXIT "Al momento sei connesso (il servizio di OpenVPN è in funzione). " \ "Rimarrai connesso finché non uscirai da OpenVPN GUI.\n\n" \ "Vuoi continuare e uscire da OpenVPN GUI?" - IDS_ERR_OPTION_LOG_IN_CONFIG "Hai ""log"" o ""log-append"" nel tuo file di configurazione OpenVPN . Queste opzioni " \ - "non devono essere usate con OpenVPN GUI in quanto impediscono a OpenVPN GUI la lettura " \ - "del file di log di output di OpenVPN che è necessario per il corretto funzionamento di OpenVPN " \ - "GUI. I log vengono sempre scritti in un file di log quando OpenVPN GUI è in uso, " \ - "quindi devi rimuovere queste opzioni.\n\nVuoi continuare e conntterti comunque?" /* options - Resources */ IDS_NFO_USAGE "--help\t\t\t: Visualizza questo messaggio.\n" \ diff --git a/openvpn-gui-res-nl.rc b/openvpn-gui-res-nl.rc index c11c99b..b494688 100644 --- a/openvpn-gui-res-nl.rc +++ b/openvpn-gui-res-nl.rc @@ -180,16 +180,12 @@ BEGIN IDS_ERR_INIT_SEC_DESC "InitializeSecurityDescriptor mislukt." IDS_ERR_SET_SEC_DESC_ACL "SetSecurityDescriptorDacl mislukt." IDS_ERR_CREATE_PIPE_OUTPUT "CreatePipe on hOutputWrite mislukt." - IDS_ERR_DUP_HANDLE_ERR_WRITE "DuplicateHandle on hErrorWrite mislukt." IDS_ERR_CREATE_PIPE_INPUT "CreatePipe on hInputRead mislukt." IDS_ERR_DUP_HANDLE_OUT_READ "DuplicateHandle on hOutputRead mislukt." IDS_ERR_DUP_HANDLE_IN_WRITE "DuplicateHandle on hInputWrite mislukt." - IDS_ERR_CLOSE_HANDLE_TMP "CloseHandle on hOutputReadTmp/hInputWriteTmp mislukt." IDS_ERR_CREATE_PROCESS "CreateProcess mislukt, exe='%s' cmdline='%s' dir='%s'" - IDS_ERR_CLOSE_HANDLE "CloseHandle mislukt." IDS_ERR_CREATE_THREAD_STATUS "CreateThread om om Status venster te tonen mislukt." IDS_NFO_STATE_WAIT_TERM "Huidige Status: Wachten tot OpenVPN gestopt is..." - IDS_ERR_OPEN_LOG_WRITE "Fout tijdens schrijven naar log-bestand: %s. U heeft waarschijnlijk geen Administrator rechten, deze zijn noodzakelijk om OpenVPN te starten." IDS_NFO_STATE_CONNECTED "Hudige status: Verbonden" IDS_NFO_NOW_CONNECTED "%s is nu verbonden." IDS_NFO_ASSIGN_IP "Toegewezen IP: %s" @@ -210,7 +206,6 @@ BEGIN IDS_ERR_CREATE_PIPE_IN_READ "CreatePipe tijdens hInputRead mislukt." IDS_NFO_STATE_CONNECTING "Huidige Status: Verbinden" IDS_NFO_CONNECTION_XXX "OpenVPN Verbinding (%s)" - IDS_ERR_THREAD_READ_STDOUT "CreateThread naar OpenVPN stdout lees-proces mislukt.." IDS_NFO_STATE_CONN_SCRIPT "Huidige Status: Connect Script Uitvoeren" IDS_NFO_STATE_DISCONN_SCRIPT "Hudige Status: Disconnect Script Uitvoeren" IDS_ERR_RUN_CONN_SCRIPT "Fout tijdens uitvoeren Connect Script: %s" @@ -233,11 +228,6 @@ BEGIN IDS_NFO_SERVICE_ACTIVE_EXIT "Er is momenteel een active verbinding (OpenVPN services is gestart). " \ "De verbinding blijft actief ook als OpenVPN GUI afgesloten wordt.\n\n" \ "OpenVPN GUI afsluiten?" - IDS_ERR_OPTION_LOG_IN_CONFIG "Er is een ""log"" of ""log-append"" parameter in de OpenVPN configuratie. Deze parameters " \ - "kunnen niet samen met OpenVPN GUI gebruikt worden. " \ - "OpenVPN GUI moet via STDOUT toegang hebben tot de log gegevens om correcte te werken. " \ - "OpenVPN GUI maakt automatisch een log bestand aan, ook als deze parameters niet ingesteld zijn. " \ - "Toch verbinding maken? " \ /* options - Resources */ IDS_NFO_USAGE "--help\t\t\t: Toon dit bericht.\n" \ diff --git a/openvpn-gui-res-no.rc b/openvpn-gui-res-no.rc index bb8e4ba..ca032be 100644 --- a/openvpn-gui-res-no.rc +++ b/openvpn-gui-res-no.rc @@ -185,16 +185,12 @@ BEGIN IDS_ERR_INIT_SEC_DESC "InitializeSecurityDescriptor feilet." IDS_ERR_SET_SEC_DESC_ACL "SetSecurityDescriptorDacl feilet." IDS_ERR_CREATE_PIPE_OUTPUT "CreatePipe på hOutputWrite feilet." - IDS_ERR_DUP_HANDLE_ERR_WRITE "DuplicateHandle på hErrorWrite feilet." IDS_ERR_CREATE_PIPE_INPUT "CreatePipe på hInputRead feilet." IDS_ERR_DUP_HANDLE_OUT_READ "DuplicateHandle på hOutputRead feilet." IDS_ERR_DUP_HANDLE_IN_WRITE "DuplicateHandle på hInputWrite feilet." - IDS_ERR_CLOSE_HANDLE_TMP "CloseHandle på hOutputReadTmp/hInputWriteTmp feilet." IDS_ERR_CREATE_PROCESS "CreateProcess feilet, exe='%s' cmdline='%s' dir='%s'" - IDS_ERR_CLOSE_HANDLE "CloseHandle feilet." IDS_ERR_CREATE_THREAD_STATUS "CreateThread for å vise statusvindu feilet." IDS_NFO_STATE_WAIT_TERM "Status: Ventar på OpenVPN avslutning..." - IDS_ERR_OPEN_LOG_WRITE "Feil under åpning av loggfil for skrivning: %s. Du trenger sannsynligvis administrator-rettigheter for å kjøre OpenVPN." IDS_NFO_STATE_CONNECTED "Status: Tilkoblet" IDS_NFO_NOW_CONNECTED "%s er tilkoblet." IDS_NFO_ASSIGN_IP "tildelt IP: %s" @@ -215,7 +211,6 @@ BEGIN IDS_ERR_CREATE_PIPE_IN_READ "CreatePipe på hInputRead feilet." IDS_NFO_STATE_CONNECTING "Status: Kobler til" IDS_NFO_CONNECTION_XXX "OpenVPN Tilkoblet (%s)" - IDS_ERR_THREAD_READ_STDOUT "En feil oppsto under opprettelse av tråd for å lytte til OpenVPN logg." IDS_NFO_STATE_CONN_SCRIPT "Status: Kjører skript for tilkobling" IDS_NFO_STATE_DISCONN_SCRIPT "Status: Kjører skript for frakobling" IDS_ERR_RUN_CONN_SCRIPT "En feil oppsto under kjøring av skript: %s" @@ -236,10 +231,6 @@ BEGIN IDS_NFO_SERVICE_ACTIVE_EXIT "Du er tilkoblet med OpenVPN (OpenVPN tjenesten kjører). " \ "Aktive tilkoblinger vil forbli tilkoblet om du avslutter OpenVPN GUI.\n\n" \ "Vil du avslutte?" - IDS_ERR_OPTION_LOG_IN_CONFIG "Du har ""log"" eller ""log-append"" i din OpenVPN konfig fil. Du bør ikke benytte " \ - "disse innstillingene ved bruk av OpenVPN GUI, ettersom GUI'et da ikke kan ""se"" " \ - "logge meldingene fra OpenVPN. Dette er nødvendig for OpenVPN GUI's funksjon.\n\n" \ - "Vil du allikevel koble til?" /* options - Resources */ IDS_NFO_USAGE "--help\t\t\t: Vis dene meldingen.\n" \ diff --git a/openvpn-gui-res-pt.rc b/openvpn-gui-res-pt.rc index cef7e47..e42707c 100644 --- a/openvpn-gui-res-pt.rc +++ b/openvpn-gui-res-pt.rc @@ -181,16 +181,12 @@ BEGIN IDS_ERR_INIT_SEC_DESC "InitializeSecurityDescriptor falhou." IDS_ERR_SET_SEC_DESC_ACL "SetSecurityDescriptorDacl falhou." IDS_ERR_CREATE_PIPE_OUTPUT "CreatePipe em hOutputWrite falhou." - IDS_ERR_DUP_HANDLE_ERR_WRITE "DuplicateHandle em hErrorWrite falhou." IDS_ERR_CREATE_PIPE_INPUT "CreatePipe em hInputRead falhou." IDS_ERR_DUP_HANDLE_OUT_READ "DuplicateHandle em hOutputRead falhou." IDS_ERR_DUP_HANDLE_IN_WRITE "DuplicateHandle em hInputWrite falhou." - IDS_ERR_CLOSE_HANDLE_TMP "CloseHandle em hOutputReadTmp/hInputWriteTmp falhou." IDS_ERR_CREATE_PROCESS "CreateProcess falhou, exe='%s' cmdline='%s' dir='%s'" - IDS_ERR_CLOSE_HANDLE "CloseHandle falhou." IDS_ERR_CREATE_THREAD_STATUS "CreateThread falhou ao mostrar janela de status." IDS_NFO_STATE_WAIT_TERM "Estado atual: Aguardando OpenVPN terminar..." - IDS_ERR_OPEN_LOG_WRITE "Erro ao abrir arquivo de log para gravação: %s. Você provavelmente não tem permissão de administrador, que é necessária para rodar o OpenVPN." IDS_NFO_STATE_CONNECTED "Estado atual: Conectado" IDS_NFO_NOW_CONNECTED "%s está conectado." IDS_NFO_ASSIGN_IP "IP atribuído: %s" @@ -211,7 +207,6 @@ BEGIN IDS_ERR_CREATE_PIPE_IN_READ "CreatePipe em hInputRead falhou." IDS_NFO_STATE_CONNECTING "Estado atual: Conectando" IDS_NFO_CONNECTION_XXX "Conexão OpenVPN (%s)" - IDS_ERR_THREAD_READ_STDOUT "CreateThread para ler processo de saída openvpn falhou." IDS_NFO_STATE_CONN_SCRIPT "Estado atual: Rodando script de conexão" IDS_NFO_STATE_DISCONN_SCRIPT "Estado atual: Running script de desconexão" IDS_ERR_RUN_CONN_SCRIPT "Erro rodando script de conexão: %s" @@ -233,12 +228,6 @@ BEGIN IDS_NFO_SERVICE_ACTIVE_EXIT "Você está conectado atualmente (Serviço OpenVPN está rodando). " \ "Você irá ficar conectado mesmo que feche o OpenVPN GUI.\n\n" \ "Você deseja continuar e fechar o OpenVPN GUI?" - IDS_ERR_OPTION_LOG_IN_CONFIG "Você possui os parâmetros ""log"" ou ""log-append"" no seu arquivo de configuração do OpenVPN. Estas opções " \ - "não devem ser usadas com o OpenVPN GUI, sendo que elas impedem o OpenVPN de ler. " \ - "the log output of OpenVPN which is necessary for correct operation of OpenVPN " \ - "O log é sempre gravado em um arquivo de log quando o OpenVPN GUI é usado," \ - "de qualquer maneira você deve retirar esta opção.\n\nVocê deseja conectar " \ - "mesmo assim?" /* options - Resources */ IDS_NFO_USAGE "--help\t\t\t: Mostra esta mensagem.\n" \ diff --git a/openvpn-gui-res-se.rc b/openvpn-gui-res-se.rc index 5da0654..adbe0aa 100644 --- a/openvpn-gui-res-se.rc +++ b/openvpn-gui-res-se.rc @@ -186,16 +186,12 @@ BEGIN IDS_ERR_INIT_SEC_DESC "InitializeSecurityDescriptor misslyckades." IDS_ERR_SET_SEC_DESC_ACL "SetSecurityDescriptorDacl misslyckades." IDS_ERR_CREATE_PIPE_OUTPUT "CreatePipe på hOutputWrite misslyckades." - IDS_ERR_DUP_HANDLE_ERR_WRITE "DuplicateHandle på hErrorWrite misslyckades." IDS_ERR_CREATE_PIPE_INPUT "CreatePipe på hInputRead misslyckades." IDS_ERR_DUP_HANDLE_OUT_READ "DuplicateHandle på hOutputRead misslyckades." IDS_ERR_DUP_HANDLE_IN_WRITE "DuplicateHandle på hInputWrite misslyckades." - IDS_ERR_CLOSE_HANDLE_TMP "CloseHandle på hOutputReadTmp/hInputWriteTmp misslyckades." IDS_ERR_CREATE_PROCESS "CreateProcess misslyckades, exe='%s' cmdline='%s' dir='%s'" - IDS_ERR_CLOSE_HANDLE "CloseHandle misslyckades." IDS_ERR_CREATE_THREAD_STATUS "CreateThread för att visa status fönstret misslyckades." IDS_NFO_STATE_WAIT_TERM "Status: Väntar på att OpenVPN skall avslutas..." - IDS_ERR_OPEN_LOG_WRITE "Fel vid öppnande av logg fil för skrivning: %s. Du saknar förmodligen administratörs rättigheter vilket du behöver för att köra OpenVPN." IDS_NFO_STATE_CONNECTED "Status: Ansluten" IDS_NFO_NOW_CONNECTED "%s är nu ansluten." IDS_NFO_ASSIGN_IP "Tilldelad IP: %s" @@ -216,7 +212,6 @@ BEGIN IDS_ERR_CREATE_PIPE_IN_READ "CreatePipe på hInputRead misslyckades." IDS_NFO_STATE_CONNECTING "Status: Ansluter" IDS_NFO_CONNECTION_XXX "OpenVPN Anslutning (%s)" - IDS_ERR_THREAD_READ_STDOUT "Ett fel uppstod vid skapande av tråd för att lyssna på OpenVPNs logg." IDS_NFO_STATE_CONN_SCRIPT "Status: Kör anslutnings-skript" IDS_NFO_STATE_DISCONN_SCRIPT "Status: Kör frånkopplings-skript" IDS_ERR_RUN_CONN_SCRIPT "Ett fel uppstod vid körning av följande skript: %s" @@ -237,10 +232,6 @@ BEGIN IDS_NFO_SERVICE_ACTIVE_EXIT "Du är uppkopplad med OpenVPN (OpenVPN tjänsten är igång). " \ "Du kommer att förbli uppkopplad även om du avslutar OpenVPN GUI.\n\n" \ "Är du säker på att du vill avsluta OpenVPN GUI?" - IDS_ERR_OPTION_LOG_IN_CONFIG "Du har ""log"" eller ""log-append"" in din OpenVPN konfig fil. Du bör inte använda " \ - "dessa inställningar när du använder OpenVPN GUI, eftersom GUI:t då inte kan ""se"" " \ - "logg meddelandena från OpenVPN, vilka är nödvändiga för OpenVPN GUI's funktion.\n\n" \ - "Vill du fortsätta och ansluta ändå?" /* options - Resources */ IDS_NFO_USAGE "--help\t\t\t: Visa detta meddelande.\n" \ diff --git a/openvpn-gui-res.h b/openvpn-gui-res.h index 707e0c0..6901710 100644 --- a/openvpn-gui-res.h +++ b/openvpn-gui-res.h @@ -125,16 +125,12 @@ #define IDS_ERR_INIT_SEC_DESC 1209 #define IDS_ERR_SET_SEC_DESC_ACL 1210 #define IDS_ERR_CREATE_PIPE_OUTPUT 1211 -#define IDS_ERR_DUP_HANDLE_ERR_WRITE 1212 #define IDS_ERR_CREATE_PIPE_INPUT 1213 #define IDS_ERR_DUP_HANDLE_OUT_READ 1214 #define IDS_ERR_DUP_HANDLE_IN_WRITE 1215 -#define IDS_ERR_CLOSE_HANDLE_TMP 1216 #define IDS_ERR_CREATE_PROCESS 1217 -#define IDS_ERR_CLOSE_HANDLE 1218 #define IDS_ERR_CREATE_THREAD_STATUS 1219 #define IDS_NFO_STATE_WAIT_TERM 1220 -#define IDS_ERR_OPEN_LOG_WRITE 1221 #define IDS_NFO_STATE_CONNECTED 1222 #define IDS_NFO_NOW_CONNECTED 1223 #define IDS_NFO_ASSIGN_IP 1224 @@ -155,14 +151,12 @@ #define IDS_ERR_CREATE_PIPE_IN_READ 1240 #define IDS_NFO_STATE_CONNECTING 1241 #define IDS_NFO_CONNECTION_XXX 1242 -#define IDS_ERR_THREAD_READ_STDOUT 1243 #define IDS_NFO_STATE_CONN_SCRIPT 1244 #define IDS_NFO_STATE_DISCONN_SCRIPT 1245 #define IDS_ERR_RUN_CONN_SCRIPT 1246 #define IDS_ERR_GET_EXIT_CODE 1247 #define IDS_ERR_CONN_SCRIPT_FAILED 1248 #define IDS_ERR_RUN_CONN_SCRIPT_TIMEOUT 1249 -#define IDS_ERR_OPTION_LOG_IN_CONFIG 1250 #define IDS_ERR_CONFIG_EXIST 1251 /* Program Startup Related */ diff --git a/openvpn.c b/openvpn.c index 097014e..d6ddb91 100644 --- a/openvpn.c +++ b/openvpn.c @@ -18,12 +18,10 @@ * along with this program (see the file COPYING included with this * distribution); if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Parts of this sourcefile is taken from openvpnserv.c from the - * OpenVPN source, with approval from the author, James Yonan - * . */ +#define WINVER 0x0500 + #include #include #include @@ -35,7 +33,6 @@ #include "tray.h" #include "main.h" #include "openvpn.h" -#include "openvpn_monitor_process.h" #include "openvpn_config.h" #include "openvpn-gui-res.h" #include "options.h" @@ -45,105 +42,598 @@ #include "passphrase.h" #include "localization.h" +#define WM_OVPN_STOP (WM_APP + 10) +#define WM_OVPN_SUSPEND (WM_APP + 11) + extern options_t o; +static const TCHAR cfgProp[] = _T("conn"); + /* - * Creates a unique exit_event name based on the - * config file number. + * Receive banner on connection to management interface + * Format: */ -static BOOL -CreateExitEvent(int config) +void +OnReady(connection_t *c, char *msg) { - _sntprintf_0(o.conn[config].exit_event_name, _T("openvpngui_exit_event_%d"), config); - o.conn[config].exit_event = CreateEvent(NULL, TRUE, FALSE, o.conn[config].exit_event_name); - if (o.conn[config].exit_event == NULL) { - /* error creating exit event */ - ShowLocalizedMsg(IDS_ERR_CREATE_EVENT, o.conn[config].exit_event_name); - return FALSE; + ManagementCommand(c, "state on", NULL, regular); + ManagementCommand(c, "log all on", OnLogLine, combined); +} + + +/* + * Handle the request to release a hold from the OpenVPN management interface + */ +void +OnHold(connection_t *c, char *msg) +{ + ManagementCommand(c, "hold off", NULL, regular); + ManagementCommand(c, "hold release", NULL, regular); +} + +/* + * Handle a log line from the OpenVPN management interface + * Format ,, + */ +void +OnLogLine(connection_t *c, char *line) +{ + HWND logWnd = GetDlgItem(c->hwndStatus, ID_EDT_LOG); + char *flags, *message; + time_t timestamp; + TCHAR *datetime; + const SETTEXTEX ste = { + .flags = ST_SELECTION, + .codepage = CP_ACP + }; + + flags = strchr(line, ',') + 1; + if (flags - 1 == NULL) + return; + + message = strchr(flags, ',') + 1; + if (message - 1 == NULL) + return; + + /* Remove lines from log window if it is getting full */ + if (SendMessage(logWnd, EM_GETLINECOUNT, 0, 0) > MAX_LOG_LINES) + { + int pos = SendMessage(logWnd, EM_LINEINDEX, DEL_LOG_LINES, 0); + SendMessage(logWnd, EM_SETSEL, 0, pos); + SendMessage(logWnd, EM_REPLACESEL, FALSE, (LPARAM) _T("")); } - return TRUE; + + timestamp = strtol(line, NULL, 10); + datetime = _tctime(×tamp); + datetime[24] = _T(' '); + + /* Append line to log window */ + SendMessage(logWnd, EM_SETSEL, (WPARAM) -1, (LPARAM) -1); + SendMessage(logWnd, EM_REPLACESEL, FALSE, (LPARAM) datetime); + SendMessage(logWnd, EM_SETTEXTEX, (WPARAM) &ste, (LPARAM) message); + SendMessage(logWnd, EM_REPLACESEL, FALSE, (LPARAM) _T("\n")); +} + + +/* + * Handle a state change notification from the OpenVPN management interface + * Format ,,[],[][,] + */ +void +OnStateChange(connection_t *c, char *data) +{ + char *pos, *state, *message; + + pos = strchr(data, ','); + if (pos == NULL) + return; + *pos = '\0'; + + state = pos + 1; + pos = strchr(state, ','); + if (pos == NULL) + return; + *pos = '\0'; + + message = pos + 1; + pos = strchr(message, ','); + if (pos == NULL) + return; + *pos = '\0'; + + if (strcmp(state, "CONNECTED") == 0) + { + /* Run Connect Script */ + if (c->state == connecting) + RunConnectScript(c, false); + + /* Save the local IP address if available */ + char *local_ip = pos + 1; + pos = strchr(local_ip, ','); + if (pos != NULL) + *pos = '\0'; + +#ifdef _UNICODE + /* Convert the IP address to Unicode */ + MultiByteToWideChar(CP_ACP, 0, local_ip, -1, c->ip, _tsizeof(c->ip)); +#else + strncpy(c->ip, local_ip, sizeof(c->ip)); +#endif + + /* Show connection tray balloon */ + if ((c->state == connecting && o.show_balloon[0] != '0') + || (c->state == reconnecting && o.show_balloon[0] == '2')) + { + TCHAR msg[256]; + LoadLocalizedStringBuf(msg, _tsizeof(msg), IDS_NFO_NOW_CONNECTED, c->config_name); + ShowTrayBalloon(msg, (_tcslen(c->ip) ? LoadLocalizedString(IDS_NFO_ASSIGN_IP, c->ip) : _T(""))); + } + + /* Save time when we got connected. */ + c->connected_since = atoi(data); + c->failed_psw_attempts = 0; + c->state = connected; + + SetMenuStatus(c, connected); + SetTrayIcon(connected); + DeleteFile(o.proxy_authfile); + + SetDlgItemText(c->hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_CONNECTED)); + SetStatusWinIcon(c->hwndStatus, ID_ICO_CONNECTED); + + /* Hide Status Window */ + ShowWindow(c->hwndStatus, SW_HIDE); + } + else if (strcmp(state, "RECONNECTING") == 0) + { + if (strcmp(message, "auth-failure") == 0 + || strcmp(message, "private-key-password-failure") == 0) + c->failed_psw_attempts++; + + if (c->failed_psw_attempts >= o.psw_attempts - 1) + ManagementCommand(c, "auth-retry none", NULL, regular); + + CheckAndSetTrayIcon(); + + SetDlgItemText(c->hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_RECONNECTING)); + SetStatusWinIcon(c->hwndStatus, ID_ICO_CONNECTING); + } +} + + +/* + * DialogProc for OpenVPN username/password auth dialog windows + */ +static BOOL CALLBACK +UserAuthDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + connection_t *c; + TCHAR buf[50]; + char cmd[70] = "username \"Auth\" \""; + UINT username_len; + int length; + + switch (msg) + { + case WM_INITDIALOG: + /* Set connection for this dialog */ + SetProp(hwndDlg, cfgProp, (HANDLE) lParam); + SetForegroundWindow(hwndDlg); + break; + + case WM_COMMAND: + c = (connection_t *) GetProp(hwndDlg, cfgProp); + switch (LOWORD(wParam)) + { + case IDOK: + username_len = GetDlgItemText(hwndDlg, ID_EDT_AUTH_USER, buf, _tsizeof(buf)); + if (username_len == 0) + return TRUE; + length = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, buf, -1, cmd + 17, sizeof(cmd) - 17, "_", NULL); + memcpy(cmd + length + 16, "\"\0", 2); + ManagementCommand(c, cmd, NULL, regular); + + memcpy(cmd, "password", 8); + GetDlgItemText(hwndDlg, ID_EDT_AUTH_PASS, buf, _tsizeof(buf)); + length = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, buf, -1, cmd + 17, sizeof(cmd) - 17, "_", NULL); + memcpy(cmd + length + 16, "\"\0", 2); + ManagementCommand(c, cmd, NULL, regular); + + /* Clear buffers */ + memset(buf, 'x', sizeof(buf)); + buf[sizeof(buf) - 1] = _T('\0'); + SetDlgItemText(hwndDlg, ID_EDT_AUTH_USER, buf); + SetDlgItemText(hwndDlg, ID_EDT_AUTH_PASS, buf); + + EndDialog(hwndDlg, LOWORD(wParam)); + return TRUE; + + case IDCANCEL: + EndDialog(hwndDlg, LOWORD(wParam)); + StopOpenVPN(c); + return TRUE; + } + break; + + case WM_CLOSE: + EndDialog(hwndDlg, LOWORD(wParam)); + return TRUE; + + case WM_NCDESTROY: + RemoveProp(hwndDlg, cfgProp); + break; + } + + return FALSE; +} + + +/* + * DialogProc for OpenVPN private key password dialog windows + */ +static BOOL CALLBACK +PrivKeyPassDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + connection_t *c; + TCHAR buf[50]; + char cmd[80] = "password \"Private Key\" \""; + UINT length; + + switch (msg) + { + case WM_INITDIALOG: + /* Set connection for this dialog */ + SetProp(hwndDlg, cfgProp, (HANDLE) lParam); + SetForegroundWindow(hwndDlg); + + case WM_COMMAND: + c = (connection_t *) GetProp(hwndDlg, cfgProp); + switch (LOWORD(wParam)) + { + case IDOK: + GetDlgItemText(hwndDlg, ID_EDT_PASSPHRASE, buf, _tsizeof(buf)); + length = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, buf, -1, cmd + 24, sizeof(cmd) - 24, "_", NULL); + memcpy(cmd + length + 23, "\"\0", 2); + ManagementCommand(c, cmd, NULL, regular); + + /* Clear buffer */ + memset(buf, 'x', sizeof(buf)); + buf[sizeof(buf) - 1] = _T('\0'); + SetDlgItemText(hwndDlg, ID_EDT_PASSPHRASE, buf); + + EndDialog(hwndDlg, LOWORD(wParam)); + return TRUE; + + case IDCANCEL: + EndDialog(hwndDlg, LOWORD(wParam)); + return TRUE; + } + break; + + case WM_CLOSE: + EndDialog(hwndDlg, LOWORD(wParam)); + return TRUE; + + case WM_NCDESTROY: + RemoveProp(hwndDlg, cfgProp); + break; + } + return FALSE; +} + + +/* + * Handle the request to release a hold from the OpenVPN management interface + */ +void +OnPassword(connection_t *c, char *msg) +{ + if (strncmp(msg, "Verification Failed", 19) == 0) + return; + + if (strstr(msg, "'Auth'")) + { + LocalizedDialogBoxParam(ID_DLG_AUTH, UserAuthDialogFunc, (LPARAM) c); + } + else if (strstr(msg, "'Private Key'")) + { + LocalizedDialogBoxParam(ID_DLG_PASSPHRASE, PrivKeyPassDialogFunc, (LPARAM) c); + } +} + + +/* + * Handle exit of the OpenVPN process + */ +void +OnStop(connection_t *c, char *msg) +{ + UINT txt_id, msg_id; + SetMenuStatus(c, disconnected); + DeleteFile(o.proxy_authfile); + + switch (c->state) + { + case connected: + /* OpenVPN process ended unexpectedly */ + c->failed_psw_attempts = 0; + c->state = disconnected; + CheckAndSetTrayIcon(); + SetDlgItemText(c->hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_DISCONNECTED)); + SetStatusWinIcon(c->hwndStatus, ID_ICO_DISCONNECTED); + EnableWindow(GetDlgItem(c->hwndStatus, ID_DISCONNECT), FALSE); + EnableWindow(GetDlgItem(c->hwndStatus, ID_RESTART), FALSE); + SetForegroundWindow(c->hwndStatus); + ShowWindow(c->hwndStatus, SW_SHOW); + ShowLocalizedMsg(IDS_NFO_CONN_TERMINATED, c->config_name); + SendMessage(c->hwndStatus, WM_CLOSE, 0, 0); + break; + + case connecting: + case reconnecting: + /* We have failed to (re)connect */ + txt_id = c->state == connecting ? IDS_NFO_STATE_FAILED : IDS_NFO_STATE_FAILED_RECONN; + msg_id = c->state == connecting ? IDS_NFO_CONN_FAILED : IDS_NFO_RECONN_FAILED; + + c->state = disconnecting; + CheckAndSetTrayIcon(); + c->state = disconnected; + EnableWindow(GetDlgItem(c->hwndStatus, ID_DISCONNECT), FALSE); + EnableWindow(GetDlgItem(c->hwndStatus, ID_RESTART), FALSE); + SetStatusWinIcon(c->hwndStatus, ID_ICO_DISCONNECTED); + SetForegroundWindow(c->hwndStatus); + SetDlgItemText(c->hwndStatus, ID_TXT_STATUS, LoadLocalizedString(txt_id)); + ShowWindow(c->hwndStatus, SW_SHOW); + ShowLocalizedMsg(msg_id, c->config_name); + SendMessage(c->hwndStatus, WM_CLOSE, 0, 0); + break; + + case disconnecting: +// /* Check for "certificate has expired" message */ +// if ((strstr(line, "error=certificate has expired") != NULL)) +// { +// StopOpenVPN(config); +// /* Cert expired... */ +// ShowLocalizedMsg(IDS_ERR_CERT_EXPIRED); +// } +// +// /* Check for "certificate is not yet valid" message */ +// if ((strstr(line, "error=certificate is not yet valid") != NULL)) +// { +// StopOpenVPN(config); +// /* Cert not yet valid */ +// ShowLocalizedMsg(IDS_ERR_CERT_NOT_YET_VALID); +// } + /* Shutdown was initiated by us */ + c->failed_psw_attempts = 0; + c->state = disconnected; + CheckAndSetTrayIcon(); + SendMessage(c->hwndStatus, WM_CLOSE, 0, 0); + break; + + case suspending: + c->state = suspended; + CheckAndSetTrayIcon(); + SetDlgItemText(c->hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_SUSPENDED)); + break; + + default: + break; + } +} + + +/* + * DialogProc for OpenVPN status dialog windows + */ +static BOOL CALLBACK +StatusDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + connection_t *c; + + switch (msg) + { + case WM_MANAGEMENT: + /* Management interface related event */ + OnManagement(wParam, lParam); + return TRUE; + + case WM_INITDIALOG: + c = (connection_t *) lParam; + + /* Set window icon "disconnected" */ + SetStatusWinIcon(hwndDlg, ID_ICO_CONNECTING); + + /* Set connection for this dialog */ + SetProp(hwndDlg, cfgProp, (HANDLE) c); + + /* Create log window */ + HWND hLogWnd = CreateWindowEx(0, RICHEDIT_CLASS, NULL, + WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL|ES_SUNKEN|ES_LEFT| + ES_MULTILINE|ES_READONLY|ES_AUTOHSCROLL|ES_AUTOVSCROLL, + 20, 25, 350, 160, hwndDlg, (HMENU) ID_EDT_LOG, o.hInstance, NULL); + if (!hLogWnd) + { + ShowLocalizedMsg(IDS_ERR_CREATE_EDIT_LOGWINDOW); + return FALSE; + } + + /* Set font and fontsize of the log window */ + CHARFORMAT cfm = { + .cbSize = sizeof(CHARFORMAT), + .dwMask = CFM_SIZE|CFM_FACE|CFM_BOLD, + .szFaceName = _T("MS Sans Serif"), + .dwEffects = 0, + .yHeight = 100 + }; + if (SendMessage(hLogWnd, EM_SETCHARFORMAT, SCF_DEFAULT, (LPARAM) &cfm) == 0) + ShowLocalizedMsg(IDS_ERR_SET_SIZE); + + /* Set size and position of controls */ + RECT rect; + GetClientRect(hwndDlg, &rect); + MoveWindow(hLogWnd, 20, 25, rect.right - 40, rect.bottom - 70, TRUE); + MoveWindow(GetDlgItem(hwndDlg, ID_TXT_STATUS), 20, 5, rect.right - 25, 15, TRUE); + MoveWindow(GetDlgItem(hwndDlg, ID_DISCONNECT), 20, rect.bottom - 30, 90, 23, TRUE); + MoveWindow(GetDlgItem(hwndDlg, ID_RESTART), 125, rect.bottom - 30, 90, 23, TRUE); + MoveWindow(GetDlgItem(hwndDlg, ID_HIDE), rect.right - 110, rect.bottom - 30, 90, 23, TRUE); + + /* Set focus on the LogWindow so it scrolls automatically */ + SetFocus(hLogWnd); + return FALSE; + + case WM_SIZE: + MoveWindow(GetDlgItem(hwndDlg, ID_EDT_LOG), 20, 25, LOWORD(lParam) - 40, HIWORD(lParam) - 70, TRUE); + MoveWindow(GetDlgItem(hwndDlg, ID_DISCONNECT), 20, HIWORD(lParam) - 30, 90, 23, TRUE); + MoveWindow(GetDlgItem(hwndDlg, ID_RESTART), 125, HIWORD(lParam) - 30, 90, 23, TRUE); + MoveWindow(GetDlgItem(hwndDlg, ID_HIDE), LOWORD(lParam) - 110, HIWORD(lParam) - 30, 90, 23, TRUE); + MoveWindow(GetDlgItem(hwndDlg, ID_TXT_STATUS), 20, 5, LOWORD(lParam) - 25, 15, TRUE); + InvalidateRect(hwndDlg, NULL, TRUE); + return TRUE; + + case WM_COMMAND: + c = (connection_t *) GetProp(hwndDlg, cfgProp); + switch (LOWORD(wParam)) + { + case ID_DISCONNECT: + SetFocus(GetDlgItem(c->hwndStatus, ID_EDT_LOG)); + c->state = disconnecting; + StopOpenVPN(c); + return TRUE; + + case ID_HIDE: + if (c->state != disconnected) + ShowWindow(hwndDlg, SW_HIDE); + else + DestroyWindow(hwndDlg); + return TRUE; + + case ID_RESTART: + c->state = reconnecting; + SetFocus(GetDlgItem(c->hwndStatus, ID_EDT_LOG)); + ManagementCommand(c, "signal SIGHUP", NULL, regular); + return TRUE; + } + break; + + case WM_SHOWWINDOW: + if (wParam == TRUE) + { + c = (connection_t *) GetProp(hwndDlg, cfgProp); + if (c->hwndStatus) + SetFocus(GetDlgItem(c->hwndStatus, ID_EDT_LOG)); + } + return FALSE; + + case WM_CLOSE: + c = (connection_t *) GetProp(hwndDlg, cfgProp); + if (c->state != disconnected) + ShowWindow(hwndDlg, SW_HIDE); + else + DestroyWindow(hwndDlg); + return TRUE; + + case WM_NCDESTROY: + RemoveProp(hwndDlg, cfgProp); + break; + + case WM_DESTROY: + PostQuitMessage(0); + break; + } + return FALSE; +} + + +/* + * ThreadProc for OpenVPN status dialog windows + */ +static DWORD WINAPI +ThreadOpenVPNStatus(void *p) +{ + connection_t *c = p; + TCHAR conn_name[200]; + MSG msg; + + /* Cut of extention from config filename. */ + _tcsncpy(conn_name, c->config_file, _tsizeof(conn_name)); + conn_name[_tcslen(conn_name) - _tcslen(o.ext_string) - 1] = _T('\0'); + + c->state = connecting; + + /* Create and Show Status Dialog */ + c->hwndStatus = CreateLocalizedDialogParam(ID_DLG_STATUS, StatusDialogFunc, (LPARAM) c); + if (!c->hwndStatus) + return 1; + + CheckAndSetTrayIcon(); + SetMenuStatus(c, connecting); + SetDlgItemText(c->hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_CONNECTING)); + SetWindowText(c->hwndStatus, LoadLocalizedString(IDS_NFO_CONNECTION_XXX, conn_name)); + + if (!OpenManagement(c, inet_addr("127.0.0.10"), c->manage.port)) + PostMessage(c->hwndStatus, WM_CLOSE, 0, 0); + + if (o.silent_connection[0] == '0') + ShowWindow(c->hwndStatus, SW_SHOW); + + /* Run the message loop for the status window */ + while (GetMessage(&msg, NULL, 0, 0)) + { + if (msg.hwnd == NULL) + { + switch (msg.message) + { + case WM_OVPN_STOP: + c->state = disconnecting; + RunDisconnectScript(c, false); + EnableWindow(GetDlgItem(c->hwndStatus, ID_DISCONNECT), FALSE); + EnableWindow(GetDlgItem(c->hwndStatus, ID_RESTART), FALSE); + SetMenuStatus(c, disconnecting); + SetDlgItemText(c->hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_WAIT_TERM)); + SetEvent(c->exit_event); + break; + + case WM_OVPN_SUSPEND: + c->state = suspending; + EnableWindow(GetDlgItem(c->hwndStatus, ID_DISCONNECT), FALSE); + EnableWindow(GetDlgItem(c->hwndStatus, ID_RESTART), FALSE); + SetMenuStatus(&o.conn[config], disconnecting); + SetDlgItemText(c->hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_WAIT_TERM)); + SetEvent(c->exit_event); + break; + } + } + else if (IsDialogMessage(c->hwndStatus, &msg) == 0) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + return 0; } /* * Set priority based on the registry or cmd-line value */ -int SetProcessPriority(DWORD *priority) -{ - - /* set process priority */ - *priority = NORMAL_PRIORITY_CLASS; - if (!_tcscmp(o.priority_string, _T("IDLE_PRIORITY_CLASS"))) - *priority = IDLE_PRIORITY_CLASS; - else if (!_tcscmp(o.priority_string, _T("BELOW_NORMAL_PRIORITY_CLASS"))) - *priority = BELOW_NORMAL_PRIORITY_CLASS; - else if (!_tcscmp(o.priority_string, _T("NORMAL_PRIORITY_CLASS"))) - *priority = NORMAL_PRIORITY_CLASS; - else if (!_tcscmp(o.priority_string, _T("ABOVE_NORMAL_PRIORITY_CLASS"))) - *priority = ABOVE_NORMAL_PRIORITY_CLASS; - else if (!_tcscmp(o.priority_string, _T("HIGH_PRIORITY_CLASS"))) - *priority = HIGH_PRIORITY_CLASS; - else - { - /* unknown priority */ - ShowLocalizedMsg(IDS_ERR_UNKNOWN_PRIORITY, o.priority_string); - return (false); - } - - return(true); -} - - static BOOL -GetPipeHandles(PHANDLE phInputRead, PHANDLE phInputWrite, - PHANDLE phOutputRead, PHANDLE phOutputWrite) +SetProcessPriority(DWORD *priority) { - HANDLE hProc = GetCurrentProcess(); - HANDLE hOutputReadTmp, hInputWriteTmp; - SECURITY_DESCRIPTOR sd; - SECURITY_ATTRIBUTES sa; - - CLEAR(sa); - CLEAR(sd); - - /* Make security attributes for the pipes so they can be inherited */ - sa.nLength = sizeof(sa); - sa.lpSecurityDescriptor = &sd; - sa.bInheritHandle = TRUE; - if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) { - ShowLocalizedMsg(IDS_ERR_INIT_SEC_DESC); - return FALSE; - } - if (!SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE)) { - ShowLocalizedMsg(IDS_ERR_SET_SEC_DESC_ACL); - return FALSE; - } - - /* Create the stdin pipe with uninheritable write end */ - if (!CreatePipe(phInputRead, &hInputWriteTmp, &sa, 0)) { - ShowLocalizedMsg(IDS_ERR_CREATE_PIPE_IN_READ); - return FALSE; - } - if (!DuplicateHandle(hProc, hInputWriteTmp, hProc, phInputWrite, 0, FALSE, - DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { - ShowLocalizedMsg(IDS_ERR_DUP_HANDLE_IN_WRITE); - CloseHandle(*phInputRead); - return FALSE; - } - - /* Create the stdout pipe with uninheritable read end */ - if (!CreatePipe(&hOutputReadTmp, phOutputWrite, &sa, 0)) { - ShowLocalizedMsg(IDS_ERR_CREATE_PIPE_OUTPUT); - CloseHandle(*phInputRead); - CloseHandle(*phInputWrite); - return FALSE; - } - if (!DuplicateHandle(hProc, hOutputReadTmp, hProc, phOutputRead, 0, FALSE, - DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { - ShowLocalizedMsg(IDS_ERR_DUP_HANDLE_OUT_READ); - CloseHandle(*phInputRead); - CloseHandle(*phInputWrite); - CloseHandle(*phOutputWrite); + *priority = NORMAL_PRIORITY_CLASS; + if (!_tcscmp(o.priority_string, _T("IDLE_PRIORITY_CLASS"))) + *priority = IDLE_PRIORITY_CLASS; + else if (!_tcscmp(o.priority_string, _T("BELOW_NORMAL_PRIORITY_CLASS"))) + *priority = BELOW_NORMAL_PRIORITY_CLASS; + else if (!_tcscmp(o.priority_string, _T("NORMAL_PRIORITY_CLASS"))) + *priority = NORMAL_PRIORITY_CLASS; + else if (!_tcscmp(o.priority_string, _T("ABOVE_NORMAL_PRIORITY_CLASS"))) + *priority = ABOVE_NORMAL_PRIORITY_CLASS; + else if (!_tcscmp(o.priority_string, _T("HIGH_PRIORITY_CLASS"))) + *priority = HIGH_PRIORITY_CLASS; + else + { + ShowLocalizedMsg(IDS_ERR_UNKNOWN_PRIORITY, o.priority_string); return FALSE; } return TRUE; @@ -151,406 +641,217 @@ GetPipeHandles(PHANDLE phInputRead, PHANDLE phInputWrite, /* - * Launch an OpenVPN process + * Launch an OpenVPN process and the accompanying thread to monitor it */ -int StartOpenVPN(int config) +BOOL +StartOpenVPN(connection_t *c) { - HANDLE hOutputRead = NULL; - HANDLE hOutputWrite = NULL; - HANDLE hInputRead = NULL; - HANDLE hInputWrite = NULL; - HANDLE hErrorWrite = NULL; + TCHAR cmdline[1024]; + TCHAR proxy_string[100]; + TCHAR exit_event_name[17]; + HANDLE hStdInRead, hStdInWrite, hNul, hThread; + PROCESS_INFORMATION pi; + STARTUPINFO si; + DWORD priority, written; + BOOL retval = FALSE; - HANDLE hThread; - DWORD IDThread; - DWORD priority; - STARTUPINFO start_info; - PROCESS_INFORMATION proc_info; - TCHAR command_line[256]; - TCHAR proxy_string[100]; - - CLEAR (start_info); - CLEAR (proc_info); - - /* Warn if "log" or "log-append" option is found in config file */ - if ((ConfigFileOptionExist(config, "log ")) || - (ConfigFileOptionExist(config, "log-append "))) + /* Make I/O handles inheritable and accessible by all */ + SECURITY_DESCRIPTOR sd; + SECURITY_ATTRIBUTES sa = { + .nLength = sizeof(sa), + .lpSecurityDescriptor = &sd, + .bInheritHandle = TRUE + }; + if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) { - if (MessageBox(NULL, LoadLocalizedString(IDS_ERR_OPTION_LOG_IN_CONFIG), _T(PACKAGE_NAME), MB_YESNO | MB_DEFBUTTON2 | MB_ICONWARNING) != IDYES) - return(false); + ShowLocalizedMsg(IDS_ERR_INIT_SEC_DESC); + return FALSE; + } + if (!SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE)) + { + ShowLocalizedMsg(IDS_ERR_SET_SEC_DESC_ACL); + return FALSE; } - /* Clear connection unique vars */ - o.conn[config].failed_psw = 0; - CLEAR (o.conn[config].ip); - - /* Create our exit event */ - if (!CreateExitEvent(config)) - return(false); - - /* set process priority */ - if (!SetProcessPriority(&priority)) - goto failed; - - /* Check that log append flag has a valid value */ - if ((o.append_string[0] != '0') && (o.append_string[0] != '1')) + /* Check that log append flag has a valid value */ + if ((o.append_string[0] != '0') && (o.append_string[0] != '1')) { - /* append_log must be 0 or 1 */ - ShowLocalizedMsg(IDS_ERR_LOG_APPEND_BOOL, o.append_string); - goto failed; - } - - /* construct proxy string to append to command line */ - ConstructProxyCmdLine(proxy_string, _tsizeof(proxy_string)); - - /* construct command line */ - _sntprintf_0(command_line, _T("openvpn --service %s 0 --config \"%s\" %s"), - o.conn[config].exit_event_name, - o.conn[config].config_file, - proxy_string); - - if (!GetPipeHandles(&hInputRead, &hInputWrite, &hOutputRead, &hOutputWrite)) - return false; - - // Create a duplicate of the output write handle for the std error - // write handle. This is necessary in case the child application - // closes one of its std output handles. - if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite, - GetCurrentProcess(),&hErrorWrite,0, - TRUE,DUPLICATE_SAME_ACCESS)) - { - /* DuplicateHandle failed. */ - ShowLocalizedMsg(IDS_ERR_DUP_HANDLE_ERR_WRITE); - goto failed; + ShowLocalizedMsg(IDS_ERR_LOG_APPEND_BOOL, o.append_string); + return FALSE; } + /* Set process priority */ + if (!SetProcessPriority(&priority)) + return FALSE; - /* fill in STARTUPINFO struct */ - GetStartupInfo(&start_info); - start_info.cb = sizeof(start_info); - start_info.dwFlags = STARTF_USESTDHANDLES; - start_info.hStdInput = hInputRead; - start_info.hStdOutput = hOutputWrite; - start_info.hStdError = hErrorWrite; + /* Get a handle of the NUL device */ + hNul = CreateFile(_T("NUL"), GENERIC_WRITE, FILE_SHARE_WRITE, &sa, OPEN_EXISTING, 0, NULL); + if (hNul == INVALID_HANDLE_VALUE) + return FALSE; - /* Run Pre-connect script */ - RunPreconnectScript(config); - - /* create an OpenVPN process for one config file */ - if (!CreateProcess(o.exe_path, - command_line, - NULL, - NULL, - TRUE, - priority | CREATE_NO_WINDOW, - NULL, - o.conn[config].config_dir, - &start_info, - &proc_info)) + /* Create the pipe for STDIN with only the read end inheritable */ + if (!CreatePipe(&hStdInRead, &hStdInWrite, &sa, 0)) { - /* CreateProcess failed */ - ShowLocalizedMsg(IDS_ERR_CREATE_PROCESS, - o.exe_path, - command_line, - o.conn[config].config_dir); - goto failed; + ShowLocalizedMsg(IDS_ERR_CREATE_PIPE_IN_READ); + goto out_nul; + } + if (!SetHandleInformation(hStdInWrite, HANDLE_FLAG_INHERIT, 0)) + { + ShowLocalizedMsg(IDS_ERR_DUP_HANDLE_IN_WRITE); + goto out_pipe; } - - /* close unneeded handles */ - Sleep (250); /* try to prevent race if we close logfile - handle before child process DUPs it */ - - if(!CloseHandle (proc_info.hThread) || - !CloseHandle (hOutputWrite) || - !CloseHandle (hInputRead) || - !CloseHandle (hErrorWrite)) + /* Create thread to show the connection's status dialog */ + hThread = CreateThread(NULL, 0, ThreadOpenVPNStatus, c, CREATE_SUSPENDED, &c->threadId); + if (hThread == NULL) { - /* CloseHandle failed */ - ShowLocalizedMsg(IDS_ERR_CLOSE_HANDLE); - CloseHandle (o.conn[config].exit_event); - return(false); + ShowLocalizedMsg(IDS_ERR_CREATE_THREAD_STATUS); + goto out_pipe; } - hOutputWrite = NULL; - hInputRead = NULL; - hErrorWrite = NULL; - - /* Save StdIn and StdOut handles in our options struct */ - o.conn[config].hStdIn = hInputWrite; - o.conn[config].hStdOut = hOutputRead; - /* Save Process Handle */ - o.conn[config].hProcess=proc_info.hProcess; - - - /* Start Thread to show Status Dialog */ - hThread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) ThreadOpenVPNStatus, - (int *) config, // pass config nr - 0, &IDThread); - if (hThread == NULL) + /* Create an event object to signal OpenVPN to exit */ + _sntprintf_0(exit_event_name, _T("%x%08x"), GetCurrentProcessId(), c->threadId); + c->exit_event = CreateEvent(NULL, TRUE, FALSE, exit_event_name); + if (c->exit_event == NULL) { - /* CreateThread failed */ - ShowLocalizedMsg(IDS_ERR_CREATE_THREAD_STATUS); - goto failed; - } + ShowLocalizedMsg(IDS_ERR_CREATE_EVENT, exit_event_name); + goto out_thread; + } + /* Create a management interface password */ + GetRandomPassword(c->manage.password, sizeof(c->manage.password) - 1); - return(true); + /* Construct proxy string to append to command line */ + ConstructProxyCmdLine(proxy_string, _tsizeof(proxy_string)); -failed: - if (o.conn[config].exit_event) CloseHandle (o.conn[config].exit_event); - if (hOutputWrite) CloseHandle (hOutputWrite); - if (hOutputRead) CloseHandle (hOutputRead); - if (hInputWrite) CloseHandle (hInputWrite); - if (hInputRead) CloseHandle (hInputRead); - if (hErrorWrite) CloseHandle (hOutputWrite); - return(false); + /* Construct command line */ + _sntprintf_0(cmdline, _T("openvpn " + "--config \"%s\" %s --service %s 0 --log%s \"%s\" " + "--management 127.0.0.10 %hd stdin --auth-retry interact " + "--management-hold --management-query-passwords --tls-exit"), + c->config_file, proxy_string, exit_event_name, + (o.append_string[0] == '1' ? _T("-append") : _T("")), + c->log_path, c->manage.port); + CLEAR(c->ip); + RunPreconnectScript(c); + + /* Fill in STARTUPINFO struct */ + GetStartupInfo(&si); + si.cb = sizeof(si); + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdInput = hStdInRead; + si.hStdOutput = hNul; + si.hStdError = hNul; + + /* Create an OpenVPN process for the connection */ + if (!CreateProcess(o.exe_path, cmdline, NULL, NULL, TRUE, + priority | CREATE_NO_WINDOW, NULL, c->config_dir, &si, &pi)) + { + ShowLocalizedMsg(IDS_ERR_CREATE_PROCESS, o.exe_path, cmdline, c->config_dir); + CloseHandle(c->exit_event); + goto out_thread; + } + + /* Pass management password to OpenVPN process */ + c->manage.password[sizeof(c->manage.password) - 1] = '\n'; + WriteFile(hStdInWrite, c->manage.password, sizeof(c->manage.password), &written, NULL); + c->manage.password[sizeof(c->manage.password) - 1] = '\0'; + c->hProcess = pi.hProcess; + + /* Start the status dialog thread */ + ResumeThread(hThread); + + CloseHandle(pi.hThread); + retval = TRUE; + +out_thread: + CloseHandle(hThread); +out_pipe: + CloseHandle(hStdInWrite); + CloseHandle(hStdInRead); +out_nul: + CloseHandle(hNul); + return retval; } -void StopOpenVPN(int config) +void +StopOpenVPN(connection_t *c) { - o.conn[config].state = disconnecting; - - if (o.conn[config].exit_event) { - /* Run Disconnect script */ - RunDisconnectScript(config, false); - - EnableWindow(GetDlgItem(o.conn[config].hwndStatus, ID_DISCONNECT), FALSE); - EnableWindow(GetDlgItem(o.conn[config].hwndStatus, ID_RESTART), FALSE); - SetMenuStatus(config, disconnecting); - /* UserInfo: waiting for OpenVPN termination... */ - SetDlgItemText(o.conn[config].hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_WAIT_TERM)); - SetEvent(o.conn[config].exit_event); - } -} - -void SuspendOpenVPN(int config) -{ - o.conn[config].state = suspending; - o.conn[config].restart = true; - - if (o.conn[config].exit_event) { - EnableWindow(GetDlgItem(o.conn[config].hwndStatus, ID_DISCONNECT), FALSE); - EnableWindow(GetDlgItem(o.conn[config].hwndStatus, ID_RESTART), FALSE); - SetMenuStatus(config, disconnecting); - SetDlgItemText(o.conn[config].hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_WAIT_TERM)); - SetEvent(o.conn[config].exit_event); - } + PostThreadMessage(c->threadId, WM_OVPN_STOP, 0, 0); } -void StopAllOpenVPN() +void +SuspendOpenVPN(int config) { - int i; - - for(i=0; i < o.num_configs; i++) { - if(o.conn[i].state != disconnected) - StopOpenVPN(i); - } - - /* Wait for all connections to terminate (Max 5 sec) */ - for (i=0; i<20; i++, Sleep(250)) - if (CountConnState(disconnected) == o.num_configs) break; - + PostThreadMessage(o.conn[config].threadId, WM_OVPN_SUSPEND, 0, 0); } -BOOL CALLBACK StatusDialogFunc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +void +SetStatusWinIcon(HWND hwndDlg, int iconId) { - static const TCHAR cfgProp[] = _T("config"); - HWND hwndLogWindow; - RECT rect; - CHARFORMAT charformat; - UINT config; + HICON hIcon = LoadLocalizedIcon(iconId); + if (!hIcon) + return; - switch (msg) { + SendMessage(hwndDlg, WM_SETICON, (WPARAM) ICON_SMALL, (LPARAM) hIcon); + SendMessage(hwndDlg, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) hIcon); +} - case WM_INITDIALOG: - /* Set Window Icon "DisConnected" */ - SetStatusWinIcon(hwndDlg, ID_ICO_CONNECTING); - /* Set config number for this dialog */ - SetProp(hwndDlg, cfgProp, (HANDLE) lParam); +/* + * Read one line from OpenVPN's stdout. + */ +static BOOL +ReadLineFromStdOut(HANDLE hStdOut, char *line, DWORD size) +{ + DWORD len, read; - /* Create LogWindow */ - hwndLogWindow = CreateWindowEx (0, RICHEDIT_CLASS, NULL, - WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | \ - ES_SUNKEN | ES_LEFT | ES_MULTILINE | \ - ES_READONLY | ES_AUTOHSCROLL | ES_AUTOVSCROLL, - 20, 25, 350, 160, // Posision and Size - hwndDlg, // Parent window handle - (HMENU) ID_EDT_LOG, // hMenu - o.hInstance, // hInstance - NULL); // WM_CREATE lpParam - - - if (!hwndLogWindow) + while (TRUE) + { + if (!PeekNamedPipe(hStdOut, line, size, &read, NULL, NULL)) { - /* Create RichEd LogWindow Failed */ - ShowLocalizedMsg(IDS_ERR_CREATE_EDIT_LOGWINDOW); - return FALSE; + if (GetLastError() != ERROR_BROKEN_PIPE) + ShowLocalizedMsg(IDS_ERR_READ_STDOUT_PIPE); + return FALSE; } - /* Set font and fontsize of the LogWindow */ - charformat.cbSize = sizeof(CHARFORMAT); - charformat.dwMask = CFM_SIZE | CFM_FACE | CFM_BOLD | CFM_ITALIC | \ - CFM_UNDERLINE | CFM_STRIKEOUT | CFM_PROTECTED; - charformat.dwEffects = 0; - charformat.yHeight = 100; - _tcscpy(charformat.szFaceName, _T("MS Sans Serif")); - if ((SendMessage(hwndLogWindow, EM_SETCHARFORMAT, SCF_DEFAULT, (LPARAM) &charformat) && CFM_SIZE) == 0) { - /* set size failed */ - ShowLocalizedMsg(IDS_ERR_SET_SIZE); - } - - /* Set Size and Posision of controls */ - GetClientRect(hwndDlg, &rect); - MoveWindow (hwndLogWindow, 20, 25, rect.right - 40, rect.bottom - 70, TRUE); - MoveWindow (GetDlgItem(hwndDlg, ID_TXT_STATUS), 20, 5, rect.right - 25, 15, TRUE); - MoveWindow (GetDlgItem(hwndDlg, ID_DISCONNECT), 20, rect.bottom - 30, 90, 23, TRUE); - MoveWindow (GetDlgItem(hwndDlg, ID_RESTART), 125, rect.bottom - 30, 90, 23, TRUE); - MoveWindow (GetDlgItem(hwndDlg, ID_HIDE), rect.right - 110, rect.bottom - 30, 90, 23, TRUE); - - /* Set focus on the LogWindow so it scrolls automatically */ - SetFocus(hwndLogWindow); - - return FALSE; - - case WM_SIZE: - MoveWindow (GetDlgItem(hwndDlg, ID_EDT_LOG), 20, 25, LOWORD (lParam) - 40, - HIWORD (lParam) - 70, TRUE); - MoveWindow (GetDlgItem(hwndDlg, ID_DISCONNECT), 20, - HIWORD (lParam) - 30, 90, 23, TRUE); - MoveWindow (GetDlgItem(hwndDlg, ID_RESTART), 125, - HIWORD (lParam) - 30, 90, 23, TRUE); - MoveWindow (GetDlgItem(hwndDlg, ID_HIDE), LOWORD (lParam) - 110, - HIWORD (lParam) - 30, 90, 23, TRUE); - MoveWindow (GetDlgItem(hwndDlg, ID_TXT_STATUS), 20, 5, LOWORD (lParam) - 25, 15, TRUE); - InvalidateRect(hwndDlg, NULL, TRUE); - return TRUE; - - case WM_COMMAND: - config = (UINT) GetProp(hwndDlg, cfgProp); - switch (LOWORD(wParam)) { - - case ID_DISCONNECT: - SetFocus(GetDlgItem(o.conn[config].hwndStatus, ID_EDT_LOG)); - StopOpenVPN(config); - return TRUE; - - case ID_HIDE: - if (o.conn[config].state != disconnected) - { - ShowWindow(hwndDlg, SW_HIDE); - } - else - { - DestroyWindow(hwndDlg); - } - return TRUE; - - case ID_RESTART: - SetFocus(GetDlgItem(o.conn[config].hwndStatus, ID_EDT_LOG)); - o.conn[config].restart = true; - StopOpenVPN(config); - return TRUE; - } - break; - - case WM_SHOWWINDOW: - if (wParam == TRUE) + char *pos = memchr(line, '\r', read); + if (pos) { - config = (UINT) GetProp(hwndDlg, cfgProp); - if (o.conn[config].hwndStatus) - SetFocus(GetDlgItem(o.conn[config].hwndStatus, ID_EDT_LOG)); + len = pos - line + 2; + if (len > size) + return FALSE; + break; } - return FALSE; - case WM_CLOSE: - config = (UINT) GetProp(hwndDlg, cfgProp); - if (o.conn[config].state != disconnected) - { - ShowWindow(hwndDlg, SW_HIDE); - } - else - { - DestroyWindow(hwndDlg); - } - return TRUE; + /* Line doesn't fit into the buffer */ + if (read == size) + return FALSE; - case WM_NCDESTROY: - RemoveProp(hwndDlg, cfgProp); - break; - - case WM_DESTROY: - PostQuitMessage(0); - break; - } - return FALSE; -} - -void SetStatusWinIcon(HWND hwndDlg, int IconID) -{ - /* Set Window Icon */ - HICON hIcon = LoadLocalizedIcon(IconID); - if (hIcon) { - SendMessage(hwndDlg, WM_SETICON, (WPARAM) (ICON_SMALL), (LPARAM) (hIcon)); - SendMessage(hwndDlg, WM_SETICON, (WPARAM) (ICON_BIG), (LPARAM) (hIcon)); - } -} - -int AutoStartConnections() -{ - int i; - - for (i=0; i < o.num_configs; i++) - { - if (o.conn[i].auto_connect) - StartOpenVPN(i); + Sleep(100); } - return(true); -} - -int VerifyAutoConnections() -{ - int i,j; - BOOL match; - - for (i=0; (o.auto_connect[i] != 0) && (i < MAX_CONFIGS); i++) + if (!ReadFile(hStdOut, line, len, &read, NULL) || read != len) { - match = false; - for (j=0; j < MAX_CONFIGS; j++) - { - if (_tcsicmp(o.conn[j].config_file, o.auto_connect[i]) == 0) - { - match=true; - break; - } - } - if (match == false) - { - /* autostart config not found */ - ShowLocalizedMsg(IDS_ERR_AUTOSTART_CONF, o.auto_connect[i]); - return false; - } + if (GetLastError() != ERROR_BROKEN_PIPE) + ShowLocalizedMsg(IDS_ERR_READ_STDOUT_PIPE); + return FALSE; } - - return true; + + line[read - 2] = '\0'; + return TRUE; } BOOL CheckVersion() { - HANDLE hOutputRead; - HANDLE hOutputWrite; - HANDLE hInputRead; - HANDLE hInputWrite; - + HANDLE hStdOutRead; + HANDLE hStdOutWrite; BOOL retval = FALSE; STARTUPINFO si; PROCESS_INFORMATION pi; @@ -563,8 +864,35 @@ CheckVersion() CLEAR(si); CLEAR(pi); - if (!GetPipeHandles(&hInputRead, &hInputWrite, &hOutputRead, &hOutputWrite)) + /* Make handles inheritable and accessible by all */ + SECURITY_DESCRIPTOR sd; + SECURITY_ATTRIBUTES sa = { + .nLength = sizeof(sa), + .lpSecurityDescriptor = &sd, + .bInheritHandle = TRUE + }; + if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) + { + ShowLocalizedMsg(IDS_ERR_INIT_SEC_DESC); return FALSE; + } + if (!SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE)) + { + ShowLocalizedMsg(IDS_ERR_SET_SEC_DESC_ACL); + return FALSE; + } + + /* Create the pipe for STDOUT with inheritable write end */ + if (!CreatePipe(&hStdOutRead, &hStdOutWrite, &sa, 0)) + { + ShowLocalizedMsg(IDS_ERR_CREATE_PIPE_IN_READ); + return FALSE; + } + if (!SetHandleInformation(hStdOutRead, HANDLE_FLAG_INHERIT, 0)) + { + ShowLocalizedMsg(IDS_ERR_DUP_HANDLE_IN_WRITE); + goto out; + } /* Construct the process' working directory */ _tcsncpy(pwd, o.exe_path, _tsizeof(pwd)); @@ -575,16 +903,18 @@ CheckVersion() /* Fill in STARTUPINFO struct */ si.cb = sizeof(si); si.dwFlags = STARTF_USESTDHANDLES; - si.hStdInput = hInputRead; - si.hStdOutput = hOutputWrite; - si.hStdError = hOutputWrite; + si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + si.hStdOutput = hStdOutWrite; + si.hStdError = hStdOutWrite; /* Start OpenVPN to check version */ if (!CreateProcess(o.exe_path, cmdline, NULL, NULL, TRUE, - CREATE_NO_WINDOW, NULL, pwd, &si, &pi)) { + CREATE_NO_WINDOW, NULL, pwd, &si, &pi)) + { ShowLocalizedMsg(IDS_ERR_CREATE_PROCESS, o.exe_path, cmdline, pwd); } - else if (ReadLineFromStdOut(hOutputRead, 0, line)) { + else if (ReadLineFromStdOut(hStdOutRead, line, sizeof(line))) + { #ifdef DEBUG PrintDebug("VersionString: %s", line); #endif @@ -596,96 +926,9 @@ CheckVersion() retval = TRUE; } - if (!CloseHandle(hInputRead) || !CloseHandle(hInputWrite) - || !CloseHandle(hOutputRead) || !CloseHandle(hOutputWrite)) - ShowLocalizedMsg(IDS_ERR_CLOSE_HANDLE); - +out: + CloseHandle(hStdOutRead); + CloseHandle(hStdOutWrite); return retval; } - -void CheckAndSetTrayIcon() -{ - - /* Show green icon if service is running */ - if (o.service_state == service_connected) - { - SetTrayIcon(connected); - return; - } - - /* Change tray icon if no more connections is running */ - if (CountConnState(connected) != 0) - SetTrayIcon(connected); - else - { - if ((CountConnState(connecting) != 0) || - (CountConnState(reconnecting) != 0) || - (o.service_state == service_connecting)) - SetTrayIcon(connecting); - else - SetTrayIcon(disconnected); - } -} - -void ThreadOpenVPNStatus(int config) -{ - TCHAR conn_name[200]; - HANDLE hThread; - DWORD IDThread; - MSG messages; - - /* Cut of extention from config filename. */ - _tcsncpy(conn_name, o.conn[config].config_file, _tsizeof(conn_name)); - conn_name[_tcslen(conn_name) - (_tcslen(o.ext_string)+1)]=0; - - if (o.conn[config].restart) - { - /* UserInfo: Connecting */ - SetDlgItemText(o.conn[config].hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_CONNECTING)); - SetStatusWinIcon(o.conn[config].hwndStatus, ID_ICO_CONNECTING); - EnableWindow(GetDlgItem(o.conn[config].hwndStatus, ID_DISCONNECT), TRUE); - EnableWindow(GetDlgItem(o.conn[config].hwndStatus, ID_RESTART), TRUE); - SetFocus(GetDlgItem(o.conn[config].hwndStatus, ID_EDT_LOG)); - o.conn[config].restart = false; - } - else - { - /* Create and Show Status Dialog */ - o.conn[config].hwndStatus = CreateLocalizedDialogParam(ID_DLG_STATUS, StatusDialogFunc, config); - if (!o.conn[config].hwndStatus) - ExitThread(1); - /* UserInfo: Connecting */ - SetDlgItemText(o.conn[config].hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_CONNECTING)); - SetWindowText(o.conn[config].hwndStatus, LoadLocalizedString(IDS_NFO_CONNECTION_XXX, conn_name)); - - if (o.silent_connection[0]=='0') - ShowWindow(o.conn[config].hwndStatus, SW_SHOW); - } - - - /* Start Thread to monitor our OpenVPN process */ - hThread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) WatchOpenVPNProcess, - (int *) config, // pass config nr - 0, &IDThread); - if (hThread == NULL) - { - /* CreateThread failed */ - ShowLocalizedMsg(IDS_ERR_THREAD_READ_STDOUT); - ExitThread(0); - } - - /* Run the message loop. It will run until GetMessage() returns 0 */ - while (GetMessage (&messages, NULL, 0, 0)) - { - if(!IsDialogMessage(o.conn[config].hwndStatus, &messages)) - { - TranslateMessage(&messages); - DispatchMessage(&messages); - } - } - - ExitThread(0); -} - diff --git a/openvpn.h b/openvpn.h index 36a3474..fc38f1c 100644 --- a/openvpn.h +++ b/openvpn.h @@ -2,6 +2,7 @@ * OpenVPN-GUI -- A Windows GUI for OpenVPN. * * Copyright (C) 2004 Mathias Sundman + * 2010 Heiko Hund * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,20 +20,20 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -struct process_info { - HANDLE hProcess; - int config; -}; +#ifndef OEPNVPN_H +#define OPENVPN_H -int StartOpenVPN(int config); -void StopOpenVPN(int config); +BOOL StartOpenVPN(connection_t *); +void StopOpenVPN(connection_t *); void SuspendOpenVPN(int config); -void StopAllOpenVPN(); -int ReadLineFromStdOut(HANDLE hStdOut, int config, char line[1024]); -BOOL CALLBACK StatusDialogFunc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); -int AutoStartConnections(); -int VerifyAutoConnections(); BOOL CheckVersion(); -void CheckAndSetTrayIcon(); void SetStatusWinIcon(HWND hwndDlg, int IconID); -void ThreadOpenVPNStatus(int status) __attribute__ ((noreturn)); + +void OnReady(connection_t *, char *); +void OnHold(connection_t *, char *); +void OnLogLine(connection_t *, char *); +void OnStateChange(connection_t *, char *); +void OnPassword(connection_t *, char *); +void OnStop(connection_t *, char *); + +#endif diff --git a/openvpn_config.c b/openvpn_config.c index b273698..f389cf4 100644 --- a/openvpn_config.c +++ b/openvpn_config.c @@ -83,6 +83,8 @@ AddConfigFileToList(int config, TCHAR *filename, TCHAR *config_dir) _tcsncpy(conn->config_name, conn->config_file, _tsizeof(conn->config_name) - 1); conn->config_name[_tcslen(conn->config_name) - _tcslen(o.ext_string) - 1] = _T('\0'); _sntprintf_0(conn->log_path, _T("%s\\%s.log"), o.log_dir, conn->config_name); + conn->manage.sk = INVALID_SOCKET; + conn->manage.port = 25340 + config; /* Check if connection should be autostarted */ for (i = 0; i < MAX_CONFIGS && o.auto_connect[i]; ++i) diff --git a/openvpn_monitor_process.c b/openvpn_monitor_process.c deleted file mode 100644 index 7606e4f..0000000 --- a/openvpn_monitor_process.c +++ /dev/null @@ -1,659 +0,0 @@ -/* - * OpenVPN-GUI -- A Windows GUI for OpenVPN. - * - * Copyright (C) 2004 Mathias Sundman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program (see the file COPYING included with this - * distribution); if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Parts of this sourcefile is taken from openvpnserv.c from the - * OpenVPN source, with approval from the author, James Yonan - * . - */ - - -#include -#include -#include - -#include "config.h" -#include "main.h" -#include "options.h" -#include "openvpn.h" -#include "scripts.h" -#include "openvpn-gui-res.h" -#include "passphrase.h" -#include "tray.h" -#include "localization.h" - -extern options_t o; - -static const char connect_string[] = "Initialization Sequence Completed"; - -/* Wait for a complete line (CR/LF) and return it. - * Return values: - * 1 - Successful. Line is available in *line. - * 0 - Broken Pipe during ReadFile. - * -1 - Other Error during ReadFile. - * - * I'm really unhappy with this code! If anyone knows of an easier - * way to convert the streaming data from ReadFile() into lines, - * please let me know! - */ -int ReadLineFromStdOut(HANDLE hStdOut, int config, char *line) -{ - #define MAX_LINELEN 1024 - - CHAR lpBuffer[MAX_LINELEN]; - static char lastline[MAX_CONFIGS][MAX_LINELEN]; - static int charsleft[MAX_CONFIGS]; - char tmpline[MAX_LINELEN]; - DWORD nBytesRead; - char *p; - unsigned int len, i; - static int first_call = 1; - - if (first_call) - { - for (i=0; i < MAX_CONFIGS; i++) - charsleft[i]=0; - first_call = 0; - } - - while (true) - { - if (charsleft[config]) - { - /* Check for Passphrase prompt */ - CheckPrivateKeyPassphrasePrompt(lastline[config], config); - - /* Check for Username/Password Auth prompt */ - CheckAuthUsernamePrompt(lastline[config], config); - CheckAuthPasswordPrompt(lastline[config]); - - p=strchr(lastline[config], '\n'); - if (p == NULL) - { - if (!ReadFile(hStdOut,lpBuffer,sizeof(lpBuffer) - strlen(lastline[config]) - 1, - &nBytesRead,NULL) || !nBytesRead) - { - if (GetLastError() == ERROR_BROKEN_PIPE) - return(0); // pipe done - normal exit path. - else - { - /* error reading from pipe */ - ShowLocalizedMsg(IDS_ERR_READ_STDOUT_PIPE); - return(-1); - } - } - lpBuffer[nBytesRead] = '\0'; - p=strchr(lpBuffer, '\n'); - if (p == NULL) - { - strncat(lastline[config], lpBuffer, sizeof(lastline[config]) - strlen(lastline[config]) - 1); - if (strlen(lastline[config]) >= (MAX_LINELEN - 1)) - { - strncpy(line, lastline[config], MAX_LINELEN); - charsleft[config]=0; - return(1); - } - } - else - { - p[0] = '\0'; - strncpy(line, lastline[config], MAX_LINELEN - 1); - strncat(line, lpBuffer, MAX_LINELEN - strlen(line)); - if (line[strlen(line) - 1] == '\r') line[strlen(line) - 1] = '\0'; - if (nBytesRead > (strlen(lpBuffer) + 1)) - { - strncpy(lastline[config], p+1, sizeof(lastline[config]) - 1); - charsleft[config]=1; - return(1); - } - charsleft[config]=0; - return(1); - } - } - else - { - len = strlen(lastline[config]); - p[0] = '\0'; - strncpy(line, lastline[config], MAX_LINELEN - 1); - if (line[strlen(line) - 1] == '\r') line[strlen(line) - 1] = '\0'; - if (len > (strlen(line) + 2)) - { - strncpy(tmpline, p+1, sizeof(tmpline) - 1); - strncpy(lastline[config], tmpline, sizeof(lastline[config]) - 1); - charsleft[config]=1; - return(1); - } - charsleft[config]=0; - return(1); - } - } - else - { - if (!ReadFile(hStdOut,lpBuffer,sizeof(lpBuffer) - 1, - &nBytesRead,NULL) || !nBytesRead) - { - if (GetLastError() == ERROR_BROKEN_PIPE) - return(0); // pipe done - normal exit path. - else - { - /* error reading from pipe */ - ShowLocalizedMsg(IDS_ERR_READ_STDOUT_PIPE); - return(-1); - } - } - lpBuffer[nBytesRead] = '\0'; - p=strchr(lpBuffer, '\n'); - if (p == NULL) - { - if (nBytesRead >= (MAX_LINELEN - 1)) - { - strncpy(line, lpBuffer, MAX_LINELEN); - charsleft[config]=0; - return(1); - } - else - { - strncpy(lastline[config], lpBuffer, sizeof(lastline[config]) - 1); - charsleft[config]=1; - } - } - else - { - p[0] = '\0'; - strncpy(line, lpBuffer, MAX_LINELEN - 1); - if (line[strlen(line) - 1] == '\r') line[strlen(line) - 1] = '\0'; - if (nBytesRead > strlen(line)) - { - strncpy(lastline[config], p+1, sizeof(lastline[config]) - 1); - charsleft[config]=1; - return(1); - } - } - } - } -} - -/* - * Monitor the openvpn log output while CONNECTING - */ -void monitor_openvpnlog_while_connecting(int config, char *line) -{ - TCHAR msg[200]; - unsigned int i; - char *linepos; - - /* Check for Connected message */ - if (strstr(line, connect_string) != NULL) - { - /* Run Connect Script */ - RunConnectScript(config, false); - - /* Save time when we got connected. */ - o.conn[config].connected_since = time(NULL); - - o.conn[config].state = connected; - SetMenuStatus(config, connected); - SetTrayIcon(connected); - - /* Remove Proxy Auth file */ - DeleteFile(o.proxy_authfile); - - /* Zero psw attempt counter */ - o.conn[config].failed_psw_attempts = 0; - - /* UserInfo: Connected */ - SetDlgItemText(o.conn[config].hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_CONNECTED)); - SetStatusWinIcon(o.conn[config].hwndStatus, ID_ICO_CONNECTED); - - /* Show Tray Balloon msg */ - if (o.show_balloon[0] != '0') - { - LoadLocalizedStringBuf(msg, _tsizeof(msg), IDS_NFO_NOW_CONNECTED, o.conn[config].config_name); - if (_tcslen(o.conn[config].ip) > 0) - { - ShowTrayBalloon(msg, LoadLocalizedString(IDS_NFO_ASSIGN_IP, o.conn[config].ip)); - } - else - { - ShowTrayBalloon(msg, _T("")); - } - } - - /* Hide Status Window */ - ShowWindow(o.conn[config].hwndStatus, SW_HIDE); - } - - /* Check for failed passphrase log message */ - if ((strstr(line, "TLS Error: Need PEM pass phrase for private key") != NULL) || - (strstr(line, "EVP_DecryptFinal:bad decrypt") != NULL) || - (strstr(line, "PKCS12_parse:mac verify failure") != NULL) || - (strstr(line, "Received AUTH_FAILED control message") != NULL) || - (strstr(line, "Auth username is empty") != NULL)) - { - o.conn[config].failed_psw_attempts++; - o.conn[config].failed_psw=1; - o.conn[config].restart=true; - } - - /* Check for "certificate has expired" message */ - if ((strstr(line, "error=certificate has expired") != NULL)) - { - StopOpenVPN(config); - /* Cert expired... */ - ShowLocalizedMsg(IDS_ERR_CERT_EXPIRED); - } - - /* Check for "certificate is not yet valid" message */ - if ((strstr(line, "error=certificate is not yet valid") != NULL)) - { - StopOpenVPN(config); - /* Cert not yet valid */ - ShowLocalizedMsg(IDS_ERR_CERT_NOT_YET_VALID); - } - - /* Check for "Notified TAP-Win32 driver to set a DHCP IP" message */ - if (((linepos=strstr(line, "Notified TAP-Win32 driver to set a DHCP IP")) != NULL)) - { - char ip_addr[40]; - - strncpy(ip_addr, linepos+54, sizeof(ip_addr)); /* Copy IP address */ - for (i = 0; i < sizeof(ip_addr) - 1; ++i) - { - if (ip_addr[i] == '/' || ip_addr[i] == ' ') - break; - } - ip_addr[i] = '\0'; - -#ifdef _UNICODE - /* Convert the IP address to Unicode */ - o.conn[config].ip[0] = _T('\0'); - MultiByteToWideChar(CP_ACP, 0, ip_addr, -1, o.conn[config].ip, _tsizeof(o.conn[config].ip)); -#else - strncpy(o.conn[config].ip, ip_addr, sizeof(o.conn[config].ip)); -#endif - } -} - - -/* - * Monitor the openvpn log output while CONNECTED - */ -void monitor_openvpnlog_while_connected(int config, char *line) -{ - /* Check for Ping-Restart message */ - if (strstr(line, "process restarting") != NULL) - { - /* Set connect_status = ReConnecting */ - o.conn[config].state = reconnecting; - CheckAndSetTrayIcon(); - - /* Set Status Window Controls "ReConnecting" */ - SetDlgItemText(o.conn[config].hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_RECONNECTING)); - SetStatusWinIcon(o.conn[config].hwndStatus, ID_ICO_CONNECTING); - } -} - -/* - * Monitor the openvpn log output while RECONNECTING - */ -void monitor_openvpnlog_while_reconnecting(int config, char *line) -{ - TCHAR msg[200]; - char *linepos; - size_t i; - - /* Check for Connected message */ - if (strstr(line, connect_string) != NULL) - { - o.conn[config].state = connected; - SetTrayIcon(connected); - - /* Set Status Window Controls "Connected" */ - SetDlgItemText(o.conn[config].hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_CONNECTED)); - SetStatusWinIcon(o.conn[config].hwndStatus, ID_ICO_CONNECTED); - - /* Show Tray Balloon msg */ - if (o.show_balloon[0] == '2') - { - LoadLocalizedStringBuf(msg, _tsizeof(msg), IDS_NFO_NOW_CONNECTED, o.conn[config].config_name); - if (_tcslen(o.conn[config].ip) > 0) - { - ShowTrayBalloon(msg, LoadLocalizedString(IDS_NFO_ASSIGN_IP, o.conn[config].ip)); - } - else - { - ShowTrayBalloon(msg, _T("")); - } - } - } - - /* Check for failed passphrase log message */ - if ((strstr(line, "TLS Error: Need PEM pass phrase for private key") != NULL) || - (strstr(line, "EVP_DecryptFinal:bad decrypt") != NULL) || - (strstr(line, "PKCS12_parse:mac verify failure") != NULL) || - (strstr(line, "Received AUTH_FAILED control message") != NULL) || - (strstr(line, "Auth username is empty") != NULL)) - { - o.conn[config].failed_psw_attempts++; - o.conn[config].failed_psw=1; - o.conn[config].restart=true; - } - - /* Check for "certificate has expired" message */ - if ((strstr(line, "error=certificate has expired") != NULL)) - { - /* Cert expired */ - StopOpenVPN(config); - ShowLocalizedMsg(IDS_ERR_CERT_EXPIRED); - } - - /* Check for "certificate is not yet valid" message */ - if ((strstr(line, "error=certificate is not yet valid") != NULL)) - { - StopOpenVPN(config); - /* Cert not yet valid */ - ShowLocalizedMsg(IDS_ERR_CERT_NOT_YET_VALID); - } - - /* Check for "Notified TAP-Win32 driver to set a DHCP IP" message */ - if (((linepos=strstr(line, "Notified TAP-Win32 driver to set a DHCP IP")) != NULL)) - { - char ip_addr[40]; - - strncpy(ip_addr, linepos+54, sizeof(ip_addr)); /* Copy IP address */ - for (i = 0; i < sizeof(ip_addr) - 1; ++i) - { - if (ip_addr[i] == '/' || ip_addr[i] == ' ') - break; - } - ip_addr[i] = '\0'; - -#ifdef _UNICODE - /* Convert the IP address to Unicode */ - o.conn[config].ip[0] = _T('\0'); - MultiByteToWideChar(CP_ACP, 0, ip_addr, -1, o.conn[config].ip, _tsizeof(o.conn[config].ip)); -#else - strncpy(o.conn[config].ip, ip_addr, sizeof(o.conn[config].ip)); -#endif - } -} - - -/* - * Opens a log file and monitors the started OpenVPN process. - * All output from OpenVPN is written both to the logfile and - * to the status window. - * - * The output from OpenVPN is also watch for diffrent messages - * and appropriate actions are taken. - */ -void WatchOpenVPNProcess(int config) -{ - char line[1024]; - int ret; - TCHAR filemode[] = _T("w"); - FILE *fd; - int LogLines = 0; - int logpos; - HWND LogWindow; - - /* set log file append/truncate filemode */ - if (o.append_string[0] == '1') - filemode[0] = _T('a'); - - /* Set Connect_Status = "Connecting" */ - o.conn[config].state = connecting; - - /* Set Tray Icon = "Connecting" if no other connections are running */ - CheckAndSetTrayIcon(); - - /* Set MenuStatus = "Connecting" */ - SetMenuStatus(config, connecting); - - /* Clear failed_password flag */ - o.conn[config].failed_psw = 0; - - /* Open log file */ - if ((fd=_tfopen(o.conn[config].log_path, filemode)) == NULL) - ShowLocalizedMsg(IDS_ERR_OPEN_LOG_WRITE, o.conn[config].log_path); - - LogWindow = GetDlgItem(o.conn[config].hwndStatus, ID_EDT_LOG); - while(TRUE) - { - if ((ret=ReadLineFromStdOut(o.conn[config].hStdOut, config, line)) == 1) - { - - /* Do nothing if line length = 0 */ - if (strlen(line) == 0) continue; - - /* Write line to Log file */ - if (fd != NULL) - { - fputs (line, fd); - fputc ('\n', fd); - fflush (fd); - } - - /* Remove lines from LogWindow if it is getting full */ - LogLines++; - if (LogLines > MAX_LOG_LINES) - { - logpos = SendMessage(LogWindow, EM_LINEINDEX, DEL_LOG_LINES, 0); - SendMessage(LogWindow, EM_SETSEL, 0, logpos); - SendMessage(LogWindow, EM_REPLACESEL, FALSE, (LPARAM) _T("")); - LogLines -= DEL_LOG_LINES; - } - - /* Write line to LogWindow */ - strcat(line, "\r\n"); - SendMessage(LogWindow, EM_SETSEL, (WPARAM) -1, (LPARAM) -1); -#ifdef _UNICODE - TCHAR wide_line[1024]; - MultiByteToWideChar(CP_ACP, 0, line, -1, wide_line, _tsizeof(wide_line)); - SendMessage(LogWindow, EM_REPLACESEL, FALSE, (LPARAM) wide_line); -#else - SendMessage(LogWindow, EM_REPLACESEL, FALSE, (LPARAM) line); -#endif - - if (o.conn[config].state == connecting) /* Connecting state */ - monitor_openvpnlog_while_connecting(config, line); - - if (o.conn[config].state == connected) /* Connected state */ - monitor_openvpnlog_while_connected(config, line); - - if (o.conn[config].state == reconnecting) /* ReConnecting state */ - monitor_openvpnlog_while_reconnecting(config, line); - } - else break; - - } - - - /* OpenVPN has been shutdown */ - - /* Close logfile filedesc. */ - if (fd != NULL) fclose(fd); - - /* Close StdIn/StdOut handles */ - CloseHandle(o.conn[config].hStdIn); - CloseHandle(o.conn[config].hStdOut); - - /* Close exitevent handle */ - CloseHandle(o.conn[config].exit_event); - o.conn[config].exit_event = NULL; - - /* Enable/Disable menuitems for this connections */ - SetMenuStatus(config, disconnecting); - - /* Remove Proxy Auth file */ - DeleteFile(o.proxy_authfile); - - /* Process died outside our control */ - if(o.conn[config].state == connected) - { - /* Zero psw attempt counter */ - o.conn[config].failed_psw_attempts = 0; - - /* Set connect_status = "Not Connected" */ - o.conn[config].state=disconnected; - - /* Change tray icon if no more connections is running */ - CheckAndSetTrayIcon(); - - /* Show Status Window */ - SetDlgItemText(o.conn[config].hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_DISCONNECTED)); - SetStatusWinIcon(o.conn[config].hwndStatus, ID_ICO_DISCONNECTED); - EnableWindow(GetDlgItem(o.conn[config].hwndStatus, ID_DISCONNECT), FALSE); - EnableWindow(GetDlgItem(o.conn[config].hwndStatus, ID_RESTART), FALSE); - SetForegroundWindow(o.conn[config].hwndStatus); - ShowWindow(o.conn[config].hwndStatus, SW_SHOW); - ShowLocalizedMsg(IDS_NFO_CONN_TERMINATED, o.conn[config].config_name); - - /* Close Status Window */ - SendMessage(o.conn[config].hwndStatus, WM_CLOSE, 0, 0); - } - - /* We have failed to connect */ - else if(o.conn[config].state == connecting) - { - - /* Set connect_status = "DisConnecting" */ - o.conn[config].state=disconnecting; - - /* Change tray icon if no more connections is running */ - CheckAndSetTrayIcon(); - - if ((o.conn[config].failed_psw) && - (o.conn[config].failed_psw_attempts < o.psw_attempts)) - { - /* Restart OpenVPN to make another attempt to connect */ - PostMessage(o.hWnd, WM_COMMAND, (WPARAM) IDM_CONNECTMENU + config, 0); - } - else - { - /* Show Status Window */ - SetDlgItemText(o.conn[config].hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_FAILED)); - SetStatusWinIcon(o.conn[config].hwndStatus, ID_ICO_DISCONNECTED); - EnableWindow(GetDlgItem(o.conn[config].hwndStatus, ID_DISCONNECT), FALSE); - EnableWindow(GetDlgItem(o.conn[config].hwndStatus, ID_RESTART), FALSE); - SetForegroundWindow(o.conn[config].hwndStatus); - ShowWindow(o.conn[config].hwndStatus, SW_SHOW); - - /* Zero psw attempt counter */ - o.conn[config].failed_psw_attempts = 0; - - ShowLocalizedMsg(IDS_NFO_CONN_FAILED, o.conn[config].config_name); - - /* Set connect_status = "Not Connected" */ - o.conn[config].state=disconnected; - - /* Close Status Window */ - SendMessage(o.conn[config].hwndStatus, WM_CLOSE, 0, 0); - - /* Reset restart flag */ - o.conn[config].restart=false; - - } - } - - /* We have failed to reconnect */ - else if(o.conn[config].state == reconnecting) - { - - /* Set connect_status = "DisConnecting" */ - o.conn[config].state=disconnecting; - - /* Change tray icon if no more connections is running */ - CheckAndSetTrayIcon(); - - if ((o.conn[config].failed_psw) && - (o.conn[config].failed_psw_attempts < o.psw_attempts)) - { - /* Restart OpenVPN to make another attempt to connect */ - PostMessage(o.hWnd, WM_COMMAND, (WPARAM) IDM_CONNECTMENU + config, 0); - } - else - { - /* Show Status Window */ - SetDlgItemText(o.conn[config].hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_FAILED_RECONN)); - SetStatusWinIcon(o.conn[config].hwndStatus, ID_ICO_DISCONNECTED); - EnableWindow(GetDlgItem(o.conn[config].hwndStatus, ID_DISCONNECT), FALSE); - EnableWindow(GetDlgItem(o.conn[config].hwndStatus, ID_RESTART), FALSE); - SetForegroundWindow(o.conn[config].hwndStatus); - ShowWindow(o.conn[config].hwndStatus, SW_SHOW); - - /* Zero psw attempt counter */ - o.conn[config].failed_psw_attempts = 0; - - ShowLocalizedMsg(IDS_NFO_RECONN_FAILED, o.conn[config].config_name); - - /* Set connect_status = "Not Connected" */ - o.conn[config].state=disconnected; - - /* Close Status Window */ - SendMessage(o.conn[config].hwndStatus, WM_CLOSE, 0, 0); - - /* Reset restart flag */ - o.conn[config].restart=false; - } - } - - /* We have chosed to Disconnect */ - else if(o.conn[config].state == disconnecting) - { - /* Zero psw attempt counter */ - o.conn[config].failed_psw_attempts = 0; - - /* Set connect_status = "Not Connected" */ - o.conn[config].state=disconnected; - - /* Change tray icon if no more connections is running */ - CheckAndSetTrayIcon(); - - if (o.conn[config].restart) - { - /* Restart OpenVPN */ - StartOpenVPN(config); - } - else - { - /* Close Status Window */ - SendMessage(o.conn[config].hwndStatus, WM_CLOSE, 0, 0); - } - } - - /* We have chosed to Suspend */ - else if(o.conn[config].state == suspending) - { - /* Zero psw attempt counter */ - o.conn[config].failed_psw_attempts = 0; - - /* Set connect_status = "SUSPENDED" */ - o.conn[config].state=suspended; - SetDlgItemText(o.conn[config].hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_SUSPENDED)); - - /* Change tray icon if no more connections is running */ - CheckAndSetTrayIcon(); - } - - /* Enable/Disable menuitems for this connections */ - SetMenuStatus(config, disconnected); - -} - diff --git a/openvpn_monitor_process.h b/openvpn_monitor_process.h deleted file mode 100644 index d7105f3..0000000 --- a/openvpn_monitor_process.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * OpenVPN-GUI -- A Windows GUI for OpenVPN. - * - * Copyright (C) 2004 Mathias Sundman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program (see the file COPYING included with this - * distribution); if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -void WatchOpenVPNProcess(int config); diff --git a/options.c b/options.c index 1cd1d4d..1fd55ef 100644 --- a/options.c +++ b/options.c @@ -291,3 +291,14 @@ CountConnState(conn_state_t check) return count; } +connection_t* +GetConnByManagement(SOCKET sk) +{ + int i; + for (i = 0; i < o.num_configs; ++i) + { + if (o.conn[i].manage.sk == sk) + return &o.conn[i]; + } + return NULL; +} diff --git a/options.h b/options.h index b9f674c..06fc35f 100644 --- a/options.h +++ b/options.h @@ -24,9 +24,14 @@ #ifndef OPTIONS_H #define OPTIONS_H +typedef struct connection connection_t; + #include +#include #include +#include "manage.h" + /* * Maximum number of parameters associated with an option, * including the option name itself. @@ -48,26 +53,29 @@ typedef enum { } conn_state_t; /* Connections parameters */ -typedef struct { +struct connection { TCHAR config_file[MAX_PATH]; /* Name of the config file */ TCHAR config_name[MAX_PATH]; /* Name of the connection */ TCHAR config_dir[MAX_PATH]; /* Path to this configs dir */ TCHAR log_path[MAX_PATH]; /* Path to Logfile */ TCHAR ip[16]; /* Assigned IP address for this connection */ - TCHAR exit_event_name[50]; /* Exit Event name for this connection */ BOOL auto_connect; /* AutoConnect at startup id TRUE */ - BOOL restart; /* Restart connection after termination if TRUE*/ - BOOL failed_psw; /* TRUE if OpenVPN failed because of wrong psw */ conn_state_t state; /* State the connection currently is in */ - int failed_psw_attempts; /* # of failed attempts made to enter psw */ + int failed_psw_attempts; /* # of failed attempts entering password(s) */ time_t connected_since; /* Time when the connection was established */ - HANDLE exit_event; + struct { + SOCKET sk; + u_short port; + char password[16]; + mgmt_cmd_t *cmd_queue; + } manage; + HANDLE hProcess; - HANDLE hStdOut; - HANDLE hStdIn; + HANDLE exit_event; + DWORD threadId; HWND hwndStatus; -} connection_t; +}; typedef enum { @@ -147,5 +155,5 @@ typedef struct { void InitOptions(options_t *); void ProcessCommandLine(options_t *, TCHAR *); int CountConnState(conn_state_t); - +connection_t* GetConnByManagement(SOCKET); #endif diff --git a/passphrase.c b/passphrase.c index 5374b13..e938a50 100644 --- a/passphrase.c +++ b/passphrase.c @@ -2,6 +2,7 @@ * OpenVPN-GUI -- A Windows GUI for OpenVPN. * * Copyright (C) 2004 Mathias Sundman + * 2010 Heiko Hund * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,7 +20,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#ifndef DISABLE_CHANGE_PASSWORD +#include +#include +#include +#endif + #include +#include #include "config.h" #include "main.h" @@ -30,16 +38,77 @@ #include "chartable.h" #include "localization.h" -#ifndef DISABLE_CHANGE_PASSWORD -#include -#include -#include -#endif - -WCHAR passphrase[256]; extern options_t o; -int ConvertUnicode2Ascii(WCHAR str_unicode[], char str_ascii[], unsigned int str_ascii_size) +/* + * Create a random password from the printable ASCII range + */ +BOOL +GetRandomPassword(char *buf, size_t len) +{ + HCRYPTPROV cp; + BOOL retval = FALSE; + unsigned i; + + if (!CryptAcquireContext(&cp, NULL, NULL, PROV_DSS, CRYPT_VERIFYCONTEXT)) + return FALSE; + + if (!CryptGenRandom(cp, len, (PBYTE) buf)) + goto out; + + /* Make sure all values are between 0x21 '!' and 0x7e '~' */ + for (i = 0; i < len; ++i) + buf[i] = (buf[i] & 0x5d) + 0x21; + + retval = TRUE; +out: + CryptReleaseContext(cp, 0); + return retval; +} + + +#ifndef DISABLE_CHANGE_PASSWORD + +const int KEYFILE_FORMAT_PKCS12 = 1; +const int KEYFILE_FORMAT_PEM = 2; +const int MIN_PASSWORD_LEN = 8; + + +/* + * Return TRUE if new passwords match + */ +static int +ConfirmNewPassword(HWND hwndDlg) +{ + TCHAR newpsw[50]; + TCHAR newpsw2[50]; + + GetDlgItemText(hwndDlg, ID_EDT_PASS_NEW, newpsw, _tsizeof(newpsw) - 1); + GetDlgItemText(hwndDlg, ID_EDT_PASS_NEW2, newpsw2, _tsizeof(newpsw2) - 1); + + if (_tcsncmp(newpsw, newpsw2, _tsizeof(newpsw)) == 0) + return true; + else + return false; +} + + +/* + * Return lengh of the new password + */ +static int +NewPasswordLengh(HWND hwndDlg) +{ + TCHAR newpsw[50]; + + GetDlgItemText(hwndDlg, ID_EDT_PASS_NEW, newpsw, _tsizeof(newpsw) - 1); + + return (_tcslen(newpsw)); +} + + +static int +ConvertUnicode2Ascii(WCHAR str_unicode[], char str_ascii[], unsigned int str_ascii_size) { unsigned int i; unsigned int j; @@ -66,306 +135,209 @@ int ConvertUnicode2Ascii(WCHAR str_unicode[], char str_ascii[], unsigned int str return(true); } -void CheckPrivateKeyPassphrasePrompt (char *line, int config) + +/* + * ChangePasswordPEM() returns: + * -1 Wrong password + * 0 Changing password failed for unknown reason + * 1 Password changed successfully + */ +static int +ChangePasswordPEM(HWND hwndDlg) { - DWORD nCharsWritten; - char passphrase_ascii[256]; + TCHAR keyfile[MAX_PATH]; + char oldpsw[50]; + char newpsw[50]; + WCHAR oldpsw_unicode[50]; + WCHAR newpsw_unicode[50]; + FILE *fp; - /* Check for Passphrase prompt */ - if (strncmp(line, "Enter PEM pass phrase:", 22) == 0) + EVP_PKEY *privkey; + + /* Get filename, old_psw and new_psw from Dialog */ + GetDlgItemText(hwndDlg, ID_TXT_KEYFILE, keyfile, _tsizeof(keyfile) - 1); + GetDlgItemTextW(hwndDlg, ID_EDT_PASS_CUR, oldpsw_unicode, sizeof(oldpsw_unicode)/2 - 1); + GetDlgItemTextW(hwndDlg, ID_EDT_PASS_NEW, newpsw_unicode, sizeof(newpsw_unicode)/2 - 1); + + /* Convert Unicode to ASCII (CP850) */ + ConvertUnicode2Ascii(oldpsw_unicode, oldpsw, sizeof(oldpsw)); + if (!ConvertUnicode2Ascii(newpsw_unicode, newpsw, sizeof(newpsw))) { - CLEAR(passphrase); - if (LocalizedDialogBox(ID_DLG_PASSPHRASE, PassphraseDialogFunc) == IDCANCEL) - { - StopOpenVPN(config); - } - - if (wcslen(passphrase) > 0) - { - CLEAR(passphrase_ascii); - ConvertUnicode2Ascii(passphrase, passphrase_ascii, sizeof(passphrase_ascii)); - - if (!WriteFile(o.conn[config].hStdIn, passphrase_ascii, - strlen(passphrase_ascii), &nCharsWritten, NULL)) - { - /* PassPhrase -> stdin failed */ - ShowLocalizedMsg(IDS_ERR_PASSPHRASE2STDIN); - } - } - if (!WriteFile(o.conn[config].hStdIn, "\r\n", - 2, &nCharsWritten, NULL)) - { - /* CR -> stdin failed */ - ShowLocalizedMsg(IDS_ERR_CR2STDIN); - } - /* Remove Passphrase prompt from lastline buffer */ - line[0]='\0'; - - /* Clear passphrase buffer */ - CLEAR(passphrase); - CLEAR(passphrase_ascii); + ShowLocalizedMsg(IDS_ERR_INVALID_CHARS_IN_PSW); + return(-1); } - /* Check for new passphrase prompt introduced with OpenVPN 2.0-beta12. */ - if (strncmp(line, "Enter Private Key Password:", 27) == 0) + privkey = EVP_PKEY_new(); + + /* Open old keyfile for reading */ + if (! (fp = _tfopen (keyfile, _T("r")))) { - CLEAR(passphrase); - if (LocalizedDialogBox(ID_DLG_PASSPHRASE, PassphraseDialogFunc) == IDCANCEL) - { - StopOpenVPN(config); - } - - if (wcslen(passphrase) > 0) - { - CLEAR(passphrase_ascii); - ConvertUnicode2Ascii(passphrase, passphrase_ascii, sizeof(passphrase_ascii)); - - if (!WriteFile(o.conn[config].hStdIn, passphrase_ascii, - strlen(passphrase_ascii), &nCharsWritten, NULL)) - { - /* PassPhrase -> stdin failed */ - ShowLocalizedMsg(IDS_ERR_PASSPHRASE2STDIN); - } - } - else - { - if (!WriteFile(o.conn[config].hStdIn, "\n", - 1, &nCharsWritten, NULL)) - { - /* CR -> stdin failed */ - ShowLocalizedMsg(IDS_ERR_CR2STDIN); - } - } - /* Remove Passphrase prompt from lastline buffer */ - line[0]='\0'; - - /* Clear passphrase buffer */ - CLEAR(passphrase); - CLEAR(passphrase_ascii); + /* can't open key file */ + ShowLocalizedMsg(IDS_ERR_OPEN_PRIVATE_KEY_FILE, keyfile); + return(0); } -} - -void CheckAuthUsernamePrompt (char *line, int config) -{ - DWORD nCharsWritten; - struct user_auth user_auth; - - /* Check for Passphrase prompt */ - if (strncmp(line, "Enter Auth Username:", 20) == 0) + /* Import old key */ + if (! (privkey = PEM_read_PrivateKey (fp, NULL, NULL, oldpsw))) { - CLEAR(user_auth); - if (LocalizedDialogBoxParam(ID_DLG_AUTH, AuthPasswordDialogFunc, - (LPARAM)&user_auth) == IDCANCEL) - { - StopOpenVPN(config); - } - - if (strlen(user_auth.username) > 0) - { - if (!WriteFile(o.conn[config].hStdIn, user_auth.username, - strlen(user_auth.username), &nCharsWritten, NULL)) - { - ShowLocalizedMsg(IDS_ERR_AUTH_USERNAME2STDIN); - } - } - else - { - if (!WriteFile(o.conn[config].hStdIn, "\n", - 1, &nCharsWritten, NULL)) - { - ShowLocalizedMsg(IDS_ERR_CR2STDIN); - } - } - - if (strlen(user_auth.password) > 0) - { - if (!WriteFile(o.conn[config].hStdIn, user_auth.password, - strlen(user_auth.password), &nCharsWritten, NULL)) - { - ShowLocalizedMsg(IDS_ERR_AUTH_PASSWORD2STDIN); - } - } - else - { - if (!WriteFile(o.conn[config].hStdIn, "\n", - 1, &nCharsWritten, NULL)) - { - ShowLocalizedMsg(IDS_ERR_CR2STDIN); - } - } - - /* Remove Username prompt from lastline buffer */ - line[0]='\0'; - - /* Clear user_auth buffer */ - CLEAR(user_auth); + /* wrong password */ + ShowLocalizedMsg(IDS_ERR_OLD_PWD_INCORRECT); + fclose(fp); + return(-1); } -} + fclose(fp); -void CheckAuthPasswordPrompt (char *line) -{ - - /* Check for Passphrase prompt */ - if (strncmp(line, "Enter Auth Password:", 20) == 0) + /* Open keyfile for writing */ + if (! (fp = _tfopen (keyfile, _T("w")))) { - - /* Remove Passphrase prompt from lastline buffer */ - line[0]='\0'; - - } -} - -BOOL CALLBACK PassphraseDialogFunc (HWND hwndDlg, UINT msg, WPARAM wParam, UNUSED LPARAM lParam) -{ - static TCHAR empty_string[100]; - - switch (msg) { - - case WM_INITDIALOG: - SetForegroundWindow(hwndDlg); - break; - - case WM_COMMAND: - switch (LOWORD(wParam)) { - - case IDOK: // button - GetDlgItemTextW(hwndDlg, ID_EDT_PASSPHRASE, passphrase, sizeof(passphrase)/2 - 1); - - /* Clear buffer */ - SetDlgItemText(hwndDlg, ID_EDT_PASSPHRASE, empty_string); - - EndDialog(hwndDlg, LOWORD(wParam)); - return TRUE; - - case IDCANCEL: // button - EndDialog(hwndDlg, LOWORD(wParam)); - return TRUE; - } - break; - case WM_CLOSE: - EndDialog(hwndDlg, LOWORD(wParam)); - return TRUE; - - } - return FALSE; -} - -BOOL CALLBACK AuthPasswordDialogFunc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static struct user_auth *user_auth; - static TCHAR empty_string[100]; - WCHAR username_unicode[50]; - WCHAR password_unicode[50]; - - switch (msg) { - - case WM_INITDIALOG: - user_auth = (struct user_auth *) lParam; - SetForegroundWindow(hwndDlg); - break; - - case WM_COMMAND: - switch (LOWORD(wParam)) { - - case IDOK: // button - GetDlgItemTextW(hwndDlg, ID_EDT_AUTH_USER, username_unicode, sizeof(username_unicode)/2 - 1); - GetDlgItemTextW(hwndDlg, ID_EDT_AUTH_PASS, password_unicode, sizeof(password_unicode)/2 - 1); - - /* Convert username/password from Unicode to Ascii (CP850) */ - ConvertUnicode2Ascii(username_unicode, user_auth->username, sizeof(user_auth->username) - 1); - ConvertUnicode2Ascii(password_unicode, user_auth->password, sizeof(user_auth->password) - 1); - - /* Clear buffers */ - SetDlgItemText(hwndDlg, ID_EDT_AUTH_USER, empty_string); - SetDlgItemText(hwndDlg, ID_EDT_AUTH_PASS, empty_string); - - EndDialog(hwndDlg, LOWORD(wParam)); - return TRUE; - - case IDCANCEL: // button - EndDialog(hwndDlg, LOWORD(wParam)); - return TRUE; - } - break; - case WM_CLOSE: - EndDialog(hwndDlg, LOWORD(wParam)); - return TRUE; - - } - return FALSE; -} - - -#ifndef DISABLE_CHANGE_PASSWORD - -const int KEYFILE_FORMAT_PKCS12 = 1; -const int KEYFILE_FORMAT_PEM = 2; - -void ShowChangePassphraseDialog(int config) -{ - HANDLE hThread; - DWORD IDThread; - - /* Start a new thread to have our own message-loop for this dialog */ - hThread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) ChangePassphraseThread, - (int *) config, // pass config nr - 0, &IDThread); - if (hThread == NULL) - { - /* error creating thread */ - ShowLocalizedMsg(IDS_ERR_CREATE_PASS_THREAD); - return; - } - -} - -void ChangePassphraseThread(int config) -{ - HWND hwndChangePSW; - MSG messages; - TCHAR conn_name[100]; - TCHAR keyfilename[MAX_PATH]; - int keyfile_format=0; - - /* Cut of extention from config filename. */ - _tcsncpy(conn_name, o.conn[config].config_file, _tsizeof(conn_name)); - conn_name[_tcslen(conn_name) - (_tcslen(o.ext_string)+1)]=0; - - /* Get Key filename from config file */ - if (!GetKeyFilename(config, keyfilename, _tsizeof(keyfilename), &keyfile_format)) - { - ExitThread(1); + /* can't open file rw */ + ShowLocalizedMsg(IDS_ERR_OPEN_WRITE_KEY, keyfile); + EVP_PKEY_free(privkey); + return(0); } - /* Show ChangePassphrase Dialog */ - hwndChangePSW = CreateLocalizedDialog(ID_DLG_CHGPASS, ChangePassphraseDialogFunc); - if (!hwndChangePSW) - return; - SetDlgItemText(hwndChangePSW, ID_TXT_KEYFILE, keyfilename); - SetDlgItemInt(hwndChangePSW, ID_TXT_KEYFORMAT, (UINT) keyfile_format, FALSE); - - SetWindowText(hwndChangePSW, LoadLocalizedString(IDS_NFO_CHANGE_PWD, conn_name)); - - ShowWindow(hwndChangePSW, SW_SHOW); - - - /* Run the message loop. It will run until GetMessage() returns 0 */ - while (GetMessage (&messages, NULL, 0, 0)) + /* Write new key to file */ + if (strlen(newpsw) == 0) { - if(!IsDialogMessage(hwndChangePSW, &messages)) - { - TranslateMessage(&messages); - DispatchMessage(&messages); - } + /* No passphrase */ + if ( !(PEM_write_PrivateKey(fp, privkey, \ + NULL, NULL, /* Use NO encryption */ + 0, 0, NULL))) + { + /* error writing new key */ + ShowLocalizedMsg(IDS_ERR_WRITE_NEW_KEY, keyfile); + EVP_PKEY_free(privkey); + fclose(fp); + return(0); + } + } + else + { + /* Use passphrase */ + if ( !(PEM_write_PrivateKey(fp, privkey, \ + EVP_des_ede3_cbc(), /* Use 3DES encryption */ + (UCHAR*) newpsw, (int) strlen(newpsw), 0, NULL))) + { + /* can't write new key */ + ShowLocalizedMsg(IDS_ERR_WRITE_NEW_KEY, keyfile); + EVP_PKEY_free(privkey); + fclose(fp); + return(0); + } } - ExitThread(0); + EVP_PKEY_free(privkey); + fclose(fp); + + /* signal success to user */ + ShowLocalizedMsg(IDS_NFO_PWD_CHANGED); + return(1); } -BOOL CALLBACK ChangePassphraseDialogFunc (HWND hwndDlg, UINT msg, WPARAM wParam, UNUSED LPARAM lParam) + +/* + * ChangePasswordPKCS12() returns: + * -1 Wrong password + * 0 Changing password failed for unknown reason + * 1 Password changed successfully + */ +static int +ChangePasswordPKCS12(HWND hwndDlg) +{ + TCHAR keyfile[MAX_PATH]; + char oldpsw[50]; + char newpsw[50]; + WCHAR oldpsw_unicode[50]; + WCHAR newpsw_unicode[50]; + FILE *fp; + + EVP_PKEY *privkey; + X509 *cert; + STACK_OF(X509) *ca = NULL; + PKCS12 *p12; + char *alias; + + /* Get filename, old_psw and new_psw from Dialog */ + GetDlgItemText(hwndDlg, ID_TXT_KEYFILE, keyfile, _tsizeof(keyfile) - 1); + GetDlgItemTextW(hwndDlg, ID_EDT_PASS_CUR, oldpsw_unicode, sizeof(oldpsw_unicode)/2 - 1); + GetDlgItemTextW(hwndDlg, ID_EDT_PASS_NEW, newpsw_unicode, sizeof(newpsw_unicode)/2 - 1); + + /* Convert Unicode to ASCII (CP850) */ + ConvertUnicode2Ascii(oldpsw_unicode, oldpsw, sizeof(oldpsw)); + if (!ConvertUnicode2Ascii(newpsw_unicode, newpsw, sizeof(newpsw))) + { + ShowLocalizedMsg(IDS_ERR_INVALID_CHARS_IN_PSW); + return(-1); + } + + /* Load the PKCS #12 file */ + if (!(fp = _tfopen(keyfile, _T("rb")))) + { + /* error opening file */ + ShowLocalizedMsg(IDS_ERR_OPEN_PRIVATE_KEY_FILE, keyfile); + return(0); + } + p12 = d2i_PKCS12_fp(fp, NULL); + fclose (fp); + if (!p12) + { + /* error reading PKCS #12 */ + ShowLocalizedMsg(IDS_ERR_READ_PKCS12, keyfile); + return(0); + } + + /* Parse the PKCS #12 file */ + if (!PKCS12_parse(p12, oldpsw, &privkey, &cert, &ca)) + { + /* old password incorrect */ + ShowLocalizedMsg(IDS_ERR_OLD_PWD_INCORRECT); + PKCS12_free(p12); + return(-1); + } + + /* Free old PKCS12 object */ + PKCS12_free(p12); + + /* Get FriendlyName of old cert */ + alias = (char*) X509_alias_get0(cert, NULL); + + /* Create new PKCS12 object */ + p12 = PKCS12_create(newpsw, alias, privkey, cert, ca, 0,0,0,0,0); + if (!p12) + { + /* create failed */ + ShowLocalizedMsg(IDS_ERR_CREATE_PKCS12); + return(0); + } + + /* Free old key, cert and ca */ + EVP_PKEY_free(privkey); + X509_free(cert); + sk_X509_pop_free(ca, X509_free); + + /* Open keyfile for writing */ + if (!(fp = _tfopen(keyfile, _T("wb")))) + { + ShowLocalizedMsg(IDS_ERR_OPEN_WRITE_KEY, keyfile); + PKCS12_free(p12); + return(0); + } + + /* Write new key to file */ + i2d_PKCS12_fp(fp, p12); + + PKCS12_free(p12); + fclose(fp); + /* signal success to user */ + ShowLocalizedMsg(IDS_NFO_PWD_CHANGED); + + return(1); +} + + +static BOOL CALLBACK +ChangePassphraseDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, UNUSED LPARAM lParam) { HICON hIcon; TCHAR keyfile[MAX_PATH]; @@ -429,56 +401,45 @@ BOOL CALLBACK ChangePassphraseDialogFunc (HWND hwndDlg, UINT msg, WPARAM wParam, ShowLocalizedMsg(IDS_ERR_UNKNOWN_KEYFILE_FORMAT); } - DestroyWindow(hwndDlg); + DestroyWindow(hwndDlg); break; case IDCANCEL: - DestroyWindow(hwndDlg); + DestroyWindow(hwndDlg); break; } break; - case WM_DESTROY: - PostQuitMessage(0); - break; + case WM_DESTROY: + PostQuitMessage(0); + break; case WM_CLOSE: - DestroyWindow(hwndDlg); + DestroyWindow(hwndDlg); return FALSE; - + } return FALSE; } -/* Return TRUE if new passwords match */ -int ConfirmNewPassword(HWND hwndDlg) +static int +LineBeginsWith(char *line, const char *keyword, const unsigned int len) { - TCHAR newpsw[50]; - TCHAR newpsw2[50]; + if (strncmp(line, keyword, len) == 0) + { + if ((line[len] == '\t') || (line[len] == ' ')) + return true; + } - GetDlgItemText(hwndDlg, ID_EDT_PASS_NEW, newpsw, _tsizeof(newpsw) - 1); - GetDlgItemText(hwndDlg, ID_EDT_PASS_NEW2, newpsw2, _tsizeof(newpsw2) - 1); - - if (_tcsncmp(newpsw, newpsw2, _tsizeof(newpsw)) == 0) - return true; - else - return false; + return false; } -/* Return lengh of the new password */ -int NewPasswordLengh(HWND hwndDlg) -{ - TCHAR newpsw[50]; - GetDlgItemText(hwndDlg, ID_EDT_PASS_NEW, newpsw, _tsizeof(newpsw) - 1); - - return (_tcslen(newpsw)); -} - -int ParseKeyFilenameLine(int config, TCHAR *keyfilename, size_t keyfilenamesize, char *line) +static int +ParseKeyFilenameLine(int config, TCHAR *keyfilename, size_t keyfilenamesize, char *line) { const int STATE_INITIAL = 0; const int STATE_READING_QUOTED_PARM = 1; @@ -501,7 +462,7 @@ int ParseKeyFilenameLine(int config, TCHAR *keyfilename, size_t keyfilenamesize, break; else if ((line[i] == ';') || (line[i] == '#')) break; - else if ((line[i] != ' ') && (line[i] != '\t')) + else if ((line[i] != ' ') && (line[i] != '\t')) { if (line[i] == '\\') { @@ -523,7 +484,7 @@ int ParseKeyFilenameLine(int config, TCHAR *keyfilename, size_t keyfilenamesize, state=STATE_READING_UNQUOTED_PARM; } } - } + } else if (state == STATE_READING_QUOTED_PARM) { @@ -597,7 +558,7 @@ int ParseKeyFilenameLine(int config, TCHAR *keyfilename, size_t keyfilenamesize, _tcsncpy(temp_filename, o.conn[config].config_dir, _tsizeof(temp_filename)); if (temp_filename[_tcslen(temp_filename) - 1] != '\\') _tcscat(temp_filename, _T("\\")); - _tcsncat(temp_filename, keyfilename, + _tcsncat(temp_filename, keyfilename, _tsizeof(temp_filename) - _tcslen(temp_filename) - 1); _tcsncpy(keyfilename, temp_filename, keyfilenamesize - 1); } @@ -606,213 +567,8 @@ int ParseKeyFilenameLine(int config, TCHAR *keyfilename, size_t keyfilenamesize, } -/* ChangePasswordPEM() returns: - * -1 Wrong password - * 0 Changing password failed for unknown reason - * 1 Password changed successfully - */ -int ChangePasswordPEM(HWND hwndDlg) -{ - TCHAR keyfile[MAX_PATH]; - char oldpsw[50]; - char newpsw[50]; - WCHAR oldpsw_unicode[50]; - WCHAR newpsw_unicode[50]; - FILE *fp; - - EVP_PKEY *privkey; - - /* Get filename, old_psw and new_psw from Dialog */ - GetDlgItemText(hwndDlg, ID_TXT_KEYFILE, keyfile, _tsizeof(keyfile) - 1); - GetDlgItemTextW(hwndDlg, ID_EDT_PASS_CUR, oldpsw_unicode, sizeof(oldpsw_unicode)/2 - 1); - GetDlgItemTextW(hwndDlg, ID_EDT_PASS_NEW, newpsw_unicode, sizeof(newpsw_unicode)/2 - 1); - - /* Convert Unicode to ASCII (CP850) */ - ConvertUnicode2Ascii(oldpsw_unicode, oldpsw, sizeof(oldpsw)); - if (!ConvertUnicode2Ascii(newpsw_unicode, newpsw, sizeof(newpsw))) - { - ShowLocalizedMsg(IDS_ERR_INVALID_CHARS_IN_PSW); - return(-1); - } - - privkey = EVP_PKEY_new(); - - /* Open old keyfile for reading */ - if (! (fp = _tfopen (keyfile, _T("r")))) - { - /* can't open key file */ - ShowLocalizedMsg(IDS_ERR_OPEN_PRIVATE_KEY_FILE, keyfile); - return(0); - } - - /* Import old key */ - if (! (privkey = PEM_read_PrivateKey (fp, NULL, NULL, oldpsw))) - { - /* wrong password */ - ShowLocalizedMsg(IDS_ERR_OLD_PWD_INCORRECT); - fclose(fp); - return(-1); - } - - fclose(fp); - - /* Open keyfile for writing */ - if (! (fp = _tfopen (keyfile, _T("w")))) - { - /* can't open file rw */ - ShowLocalizedMsg(IDS_ERR_OPEN_WRITE_KEY, keyfile); - EVP_PKEY_free(privkey); - return(0); - } - - /* Write new key to file */ - if (strlen(newpsw) == 0) - { - /* No passphrase */ - if ( !(PEM_write_PrivateKey(fp, privkey, \ - NULL, NULL, /* Use NO encryption */ - 0, 0, NULL))) - { - /* error writing new key */ - ShowLocalizedMsg(IDS_ERR_WRITE_NEW_KEY, keyfile); - EVP_PKEY_free(privkey); - fclose(fp); - return(0); - } - } - else - { - /* Use passphrase */ - if ( !(PEM_write_PrivateKey(fp, privkey, \ - EVP_des_ede3_cbc(), /* Use 3DES encryption */ - (UCHAR*) newpsw, (int) strlen(newpsw), 0, NULL))) - { - /* can't write new key */ - ShowLocalizedMsg(IDS_ERR_WRITE_NEW_KEY, keyfile); - EVP_PKEY_free(privkey); - fclose(fp); - return(0); - } - } - - EVP_PKEY_free(privkey); - fclose(fp); - - /* signal success to user */ - ShowLocalizedMsg(IDS_NFO_PWD_CHANGED); - return(1); -} - - -/* ChangePasswordPKCS12() returns: - * -1 Wrong password - * 0 Changing password failed for unknown reason - * 1 Password changed successfully - */ -int ChangePasswordPKCS12(HWND hwndDlg) -{ - TCHAR keyfile[MAX_PATH]; - char oldpsw[50]; - char newpsw[50]; - WCHAR oldpsw_unicode[50]; - WCHAR newpsw_unicode[50]; - FILE *fp; - - EVP_PKEY *privkey; - X509 *cert; - STACK_OF(X509) *ca = NULL; - PKCS12 *p12; - char *alias; - - /* Get filename, old_psw and new_psw from Dialog */ - GetDlgItemText(hwndDlg, ID_TXT_KEYFILE, keyfile, _tsizeof(keyfile) - 1); - GetDlgItemTextW(hwndDlg, ID_EDT_PASS_CUR, oldpsw_unicode, sizeof(oldpsw_unicode)/2 - 1); - GetDlgItemTextW(hwndDlg, ID_EDT_PASS_NEW, newpsw_unicode, sizeof(newpsw_unicode)/2 - 1); - - /* Convert Unicode to ASCII (CP850) */ - ConvertUnicode2Ascii(oldpsw_unicode, oldpsw, sizeof(oldpsw)); - if (!ConvertUnicode2Ascii(newpsw_unicode, newpsw, sizeof(newpsw))) - { - ShowLocalizedMsg(IDS_ERR_INVALID_CHARS_IN_PSW); - return(-1); - } - - /* Load the PKCS #12 file */ - if (!(fp = _tfopen(keyfile, _T("rb")))) - { - /* error opening file */ - ShowLocalizedMsg(IDS_ERR_OPEN_PRIVATE_KEY_FILE, keyfile); - return(0); - } - p12 = d2i_PKCS12_fp(fp, NULL); - fclose (fp); - if (!p12) - { - /* error reading PKCS #12 */ - ShowLocalizedMsg(IDS_ERR_READ_PKCS12, keyfile); - return(0); - } - - /* Parse the PKCS #12 file */ - if (!PKCS12_parse(p12, oldpsw, &privkey, &cert, &ca)) - { - /* old password incorrect */ - ShowLocalizedMsg(IDS_ERR_OLD_PWD_INCORRECT); - PKCS12_free(p12); - return(-1); - } - - /* Free old PKCS12 object */ - PKCS12_free(p12); - - /* Get FriendlyName of old cert */ - alias = (char*) X509_alias_get0(cert, NULL); - - /* Create new PKCS12 object */ - p12 = PKCS12_create(newpsw, alias, privkey, cert, ca, 0,0,0,0,0); - if (!p12) - { - /* create failed */ - ShowLocalizedMsg(IDS_ERR_CREATE_PKCS12); - return(0); - } - - /* Free old key, cert and ca */ - EVP_PKEY_free(privkey); - X509_free(cert); - sk_X509_pop_free(ca, X509_free); - - /* Open keyfile for writing */ - if (!(fp = _tfopen(keyfile, _T("wb")))) - { - ShowLocalizedMsg(IDS_ERR_OPEN_WRITE_KEY, keyfile); - PKCS12_free(p12); - return(0); - } - - /* Write new key to file */ - i2d_PKCS12_fp(fp, p12); - - PKCS12_free(p12); - fclose(fp); - /* signal success to user */ - ShowLocalizedMsg(IDS_NFO_PWD_CHANGED); - - return(1); -} - -int LineBeginsWith(char *line, const char *keyword, const unsigned int len) -{ - if (strncmp(line, keyword, len) == 0) - { - if ((line[len] == '\t') || (line[len] == ' ')) - return true; - } - - return false; -} - -int GetKeyFilename(int config, TCHAR *keyfilename, size_t keyfilenamesize, int *keyfile_format) +static int +GetKeyFilename(int config, TCHAR *keyfilename, size_t keyfilenamesize, int *keyfile_format) { FILE *fp; char line[256]; @@ -872,7 +628,7 @@ int GetKeyFilename(int config, TCHAR *keyfilename, size_t keyfilenamesize, int * *keyfile_format = KEYFILE_FORMAT_PKCS12; if (!ParseKeyFilenameLine(config, keyfilename, keyfilenamesize, &line[7])) return(0); - } + } } if ((!found_key) && (!found_pkcs12)) @@ -886,4 +642,70 @@ int GetKeyFilename(int config, TCHAR *keyfilename, size_t keyfilenamesize, int * } +static void +ChangePassphraseThread(int config) +{ + HWND hwndChangePSW; + MSG messages; + TCHAR conn_name[100]; + TCHAR keyfilename[MAX_PATH]; + int keyfile_format=0; + + /* Cut of extention from config filename. */ + _tcsncpy(conn_name, o.conn[config].config_file, _tsizeof(conn_name)); + conn_name[_tcslen(conn_name) - (_tcslen(o.ext_string)+1)]=0; + + /* Get Key filename from config file */ + if (!GetKeyFilename(config, keyfilename, _tsizeof(keyfilename), &keyfile_format)) + { + ExitThread(1); + } + + /* Show ChangePassphrase Dialog */ + hwndChangePSW = CreateLocalizedDialog(ID_DLG_CHGPASS, ChangePassphraseDialogFunc); + if (!hwndChangePSW) + return; + SetDlgItemText(hwndChangePSW, ID_TXT_KEYFILE, keyfilename); + SetDlgItemInt(hwndChangePSW, ID_TXT_KEYFORMAT, (UINT) keyfile_format, FALSE); + + SetWindowText(hwndChangePSW, LoadLocalizedString(IDS_NFO_CHANGE_PWD, conn_name)); + + ShowWindow(hwndChangePSW, SW_SHOW); + + + /* Run the message loop. It will run until GetMessage() returns 0 */ + while (GetMessage (&messages, NULL, 0, 0)) + { + if(!IsDialogMessage(hwndChangePSW, &messages)) + { + TranslateMessage(&messages); + DispatchMessage(&messages); + } + } + + ExitThread(0); +} + + +void +ShowChangePassphraseDialog(int config) +{ + HANDLE hThread; + DWORD IDThread; + + /* Start a new thread to have our own message-loop for this dialog */ + hThread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE) ChangePassphraseThread, + (int *) config, // pass config nr + 0, &IDThread); + if (hThread == NULL) + { + /* error creating thread */ + ShowLocalizedMsg(IDS_ERR_CREATE_PASS_THREAD); + return; + } + +} + + #endif diff --git a/passphrase.h b/passphrase.h index 8470970..f67ae1d 100644 --- a/passphrase.h +++ b/passphrase.h @@ -2,6 +2,7 @@ * OpenVPN-GUI -- A Windows GUI for OpenVPN. * * Copyright (C) 2004 Mathias Sundman + * 2010 Heiko Hund * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,25 +20,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define MIN_PASSWORD_LEN 8 +#ifndef PASSPHRASE_H +#define PASSPHRASE_H -struct user_auth { - char username[50]; - char password[50]; -}; +BOOL GetRandomPassword(char *, size_t); -void CheckPrivateKeyPassphrasePrompt (char *line, int config); -void CheckAuthUsernamePrompt (char *line, int config); -void CheckAuthPasswordPrompt (char *line); -BOOL CALLBACK PassphraseDialogFunc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); -BOOL CALLBACK AuthPasswordDialogFunc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); - -void ShowChangePassphraseDialog(int config); -BOOL CALLBACK ChangePassphraseDialogFunc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); -void ChangePassphraseThread(int config); -int ConfirmNewPassword(HWND hwndDlg); -int NewPasswordLengh(HWND hwndDlg); -int ChangePasswordPEM(HWND hwndDlg); -int ChangePasswordPKCS12(HWND hwndDlg); -int GetKeyFilename(int config, TCHAR *keyfilename, size_t keyfilenamesize, int *keyfile_format); +#ifndef DISABLE_CHANGE_PASSWORD +void ShowChangePassphraseDialog(int); +#endif +#endif diff --git a/scripts.c b/scripts.c index 0c68dc4..8eab008 100644 --- a/scripts.c +++ b/scripts.c @@ -2,6 +2,7 @@ * OpenVPN-GUI -- A Windows GUI for OpenVPN. * * Copyright (C) 2004 Mathias Sundman + * 2010 Heiko Hund * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,6 +23,9 @@ #include #include #include +#include +#include +#include #include "config.h" #include "main.h" @@ -31,258 +35,174 @@ extern options_t o; -void RunConnectScript(int config, int run_as_service) + +void +RunPreconnectScript(connection_t *c) { - WIN32_FIND_DATA FindFileData; - HANDLE hFind; - STARTUPINFO start_info; - PROCESS_INFORMATION proc_info; - SECURITY_ATTRIBUTES sa; - SECURITY_DESCRIPTOR sd; - TCHAR command_line[256]; - TCHAR batch_file[100]; - DWORD ExitCode; - int i, TimeOut; + STARTUPINFO si; + PROCESS_INFORMATION pi; + TCHAR cmdline[256]; + DWORD exit_code; + struct _stat st; + int i; - /* Cut of extention from config filename and add "_up.bat". */ - _tcsncpy(batch_file, o.conn[config].config_file, _tsizeof(batch_file)); - batch_file[_tcslen(batch_file) - (_tcslen(o.ext_string)+1)]=0; - _tcsncat(batch_file, _T("_up.bat"), _tsizeof(batch_file) - _tcslen(batch_file) - 1); - _sntprintf_0(command_line, _T("%s\\%s"), o.conn[config].config_dir, batch_file); + /* Cut off extention from config filename and add "_pre.bat" */ + int len = _tcslen(c->config_file) - _tcslen(o.ext_string); + _sntprintf_0(cmdline, _T("%s\\%.*s_pre.bat"), c->config_dir, len, c->config_file); - - /* Return if no script exists */ - hFind = FindFirstFile(command_line, &FindFileData); - if (hFind == INVALID_HANDLE_VALUE) - { - return; - } + /* Return if no script exists */ + if (_tstat(cmdline, &st) == -1) + return; - FindClose(hFind); + CLEAR(si); + CLEAR(pi); - if (!run_as_service) + /* fill in STARTUPINFO struct */ + GetStartupInfo(&si); + si.cb = sizeof(si); + si.dwFlags = 0; + si.wShowWindow = SW_SHOWDEFAULT; + si.hStdInput = NULL; + si.hStdOutput = NULL; + + if (!CreateProcess(NULL, cmdline, NULL, NULL, TRUE, + (o.show_script_window[0] == '1' ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW), + NULL, c->config_dir, &si, &pi)) + return; + + for (i = 0; i <= o.preconnectscript_timeout; i++) { - /* UserInfo: Connect Script running */ - SetDlgItemText(o.conn[config].hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_CONN_SCRIPT)); + if (!GetExitCodeProcess(pi.hProcess, &exit_code)) + goto out; + + if (exit_code != STILL_ACTIVE) + goto out; + + Sleep(1000); } - - CLEAR (start_info); - CLEAR (proc_info); - CLEAR (sa); - CLEAR (sd); - - /* fill in STARTUPINFO struct */ - GetStartupInfo(&start_info); - start_info.cb = sizeof(start_info); - start_info.dwFlags = 0; - start_info.wShowWindow = SW_SHOWDEFAULT; - start_info.hStdInput = NULL; - start_info.hStdOutput = NULL; - - if (!CreateProcess(NULL, - command_line, //commandline - NULL, - NULL, - TRUE, - ((o.show_script_window[0] == '1') ? (DWORD) CREATE_NEW_CONSOLE : - (DWORD) CREATE_NO_WINDOW), - NULL, - o.conn[config].config_dir, //start-up dir - &start_info, - &proc_info)) - { - /* Running Script failed */ - ShowLocalizedMsg(IDS_ERR_RUN_CONN_SCRIPT, command_line); - return; - } - - TimeOut = o.connectscript_timeout; - - if (TimeOut == 0) - { - /* Don't check exist status, just return */ - return; - } - - for (i=0; i <= TimeOut; i++) - { - if (!GetExitCodeProcess(proc_info.hProcess, &ExitCode)) - { - /* failed to get ExitCode */ - ShowLocalizedMsg(IDS_ERR_GET_EXIT_CODE, command_line); - return; - } - - if (ExitCode != STILL_ACTIVE) - { - if (ExitCode != 0) - { - /* ConnectScript failed */ - ShowLocalizedMsg(IDS_ERR_CONN_SCRIPT_FAILED, ExitCode); - return; - } - return; - } - - Sleep(1000); - } - - /* UserInfo: Timeout */ - ShowLocalizedMsg(IDS_ERR_RUN_CONN_SCRIPT_TIMEOUT, TimeOut); - +out: + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); } -void RunDisconnectScript(int config, int run_as_service) + +void +RunConnectScript(connection_t *c, int run_as_service) { - WIN32_FIND_DATA FindFileData; - HANDLE hFind; - STARTUPINFO start_info; - PROCESS_INFORMATION proc_info; - SECURITY_ATTRIBUTES sa; - SECURITY_DESCRIPTOR sd; - TCHAR command_line[256]; - TCHAR batch_file[100]; - DWORD ExitCode; - int i, TimeOut; + STARTUPINFO si; + PROCESS_INFORMATION pi; + TCHAR cmdline[256]; + DWORD exit_code; + struct _stat st; + int i; - /* Append "_down.bat" to config name. */ - _tcsncpy(batch_file, o.conn[config].config_name, _tsizeof(batch_file)); - _tcsncat(batch_file, _T("_down.bat"), _tsizeof(batch_file) - _tcslen(batch_file) - 1); - _sntprintf_0(command_line, _T("%s\\%s"), o.conn[config].config_dir, batch_file); + /* Cut off extention from config filename and add "_up.bat" */ + int len = _tcslen(c->config_file) - _tcslen(o.ext_string); + _sntprintf_0(cmdline, _T("%s\\%.*s_up.bat"), c->config_dir, len, c->config_file); - - /* Return if no script exists */ - hFind = FindFirstFile(command_line, &FindFileData); - if (hFind == INVALID_HANDLE_VALUE) - { - return; - } + /* Return if no script exists */ + if (_tstat(cmdline, &st) == -1) + return; - FindClose(hFind); + if (!run_as_service) + SetDlgItemText(c->hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_CONN_SCRIPT)); - if (!run_as_service) + CLEAR(si); + CLEAR(pi); + + /* fill in STARTUPINFO struct */ + GetStartupInfo(&si); + si.cb = sizeof(si); + si.dwFlags = 0; + si.wShowWindow = SW_SHOWDEFAULT; + si.hStdInput = NULL; + si.hStdOutput = NULL; + + if (!CreateProcess(NULL, cmdline, NULL, NULL, TRUE, + (o.show_script_window[0] == '1' ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW), + NULL, c->config_dir, &si, &pi)) { - /* UserInfo: Disconnect Script running */ - SetDlgItemText(o.conn[config].hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_DISCONN_SCRIPT)); + ShowLocalizedMsg(IDS_ERR_RUN_CONN_SCRIPT, cmdline); + return; } - CLEAR (start_info); - CLEAR (proc_info); - CLEAR (sa); - CLEAR (sd); + if (o.connectscript_timeout == 0) + goto out; - /* fill in STARTUPINFO struct */ - GetStartupInfo(&start_info); - start_info.cb = sizeof(start_info); - start_info.dwFlags = 0; - start_info.wShowWindow = SW_SHOWDEFAULT; - start_info.hStdInput = NULL; - start_info.hStdOutput = NULL; - - if (!CreateProcess(NULL, - command_line, //commandline - NULL, - NULL, - TRUE, - ((o.show_script_window[0] == '1') ? (DWORD) CREATE_NEW_CONSOLE : - (DWORD) CREATE_NO_WINDOW), - NULL, - o.conn[config].config_dir, //start-up dir - &start_info, - &proc_info)) + for (i = 0; i <= o.connectscript_timeout; i++) { - return; + if (!GetExitCodeProcess(pi.hProcess, &exit_code)) + { + ShowLocalizedMsg(IDS_ERR_GET_EXIT_CODE, cmdline); + goto out; + } + + if (exit_code != STILL_ACTIVE) + { + if (exit_code != 0) + ShowLocalizedMsg(IDS_ERR_CONN_SCRIPT_FAILED, exit_code); + goto out; + } + + Sleep(1000); } - TimeOut = o.disconnectscript_timeout; + ShowLocalizedMsg(IDS_ERR_RUN_CONN_SCRIPT_TIMEOUT, o.connectscript_timeout); - for (i=0; i <= TimeOut; i++) - { - if (!GetExitCodeProcess(proc_info.hProcess, &ExitCode)) - { - return; - } - - if (ExitCode != STILL_ACTIVE) - { - return; - } - - Sleep(1000); - } +out: + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); } -void RunPreconnectScript(int config) + +void +RunDisconnectScript(connection_t *c, int run_as_service) { - WIN32_FIND_DATA FindFileData; - HANDLE hFind; - STARTUPINFO start_info; - PROCESS_INFORMATION proc_info; - SECURITY_ATTRIBUTES sa; - SECURITY_DESCRIPTOR sd; - TCHAR command_line[256]; - TCHAR batch_file[100]; - DWORD ExitCode; - int i, TimeOut; + STARTUPINFO si; + PROCESS_INFORMATION pi; + TCHAR cmdline[256]; + DWORD exit_code; + struct _stat st; + int i; - /* Append "_pre.bat" to config name. */ - _tcsncpy(batch_file, o.conn[config].config_name, _tsizeof(batch_file)); - _tcsncat(batch_file, _T("_pre.bat"), _tsizeof(batch_file) - _tcslen(batch_file) - 1); - _sntprintf_0(command_line, _T("%s\\%s"), o.conn[config].config_dir, batch_file); + /* Cut off extention from config filename and add "_down.bat" */ + int len = _tcslen(c->config_file) - _tcslen(o.ext_string); + _sntprintf_0(cmdline, _T("%s\\%.*s_down.bat"), c->config_dir, len, c->config_file); - - /* Return if no script exists */ - hFind = FindFirstFile(command_line, &FindFileData); - if (hFind == INVALID_HANDLE_VALUE) - { - return; - } + /* Return if no script exists */ + if (_tstat(cmdline, &st) == -1) + return; - FindClose(hFind); + if (!run_as_service) + SetDlgItemText(c->hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_DISCONN_SCRIPT)); - CLEAR (start_info); - CLEAR (proc_info); - CLEAR (sa); - CLEAR (sd); + CLEAR(si); + CLEAR(pi); - /* fill in STARTUPINFO struct */ - GetStartupInfo(&start_info); - start_info.cb = sizeof(start_info); - start_info.dwFlags = 0; - start_info.wShowWindow = SW_SHOWDEFAULT; - start_info.hStdInput = NULL; - start_info.hStdOutput = NULL; + /* fill in STARTUPINFO struct */ + GetStartupInfo(&si); + si.cb = sizeof(si); + si.dwFlags = 0; + si.wShowWindow = SW_SHOWDEFAULT; + si.hStdInput = NULL; + si.hStdOutput = NULL; - if (!CreateProcess(NULL, - command_line, //commandline - NULL, - NULL, - TRUE, - ((o.show_script_window[0] == '1') ? (DWORD) CREATE_NEW_CONSOLE : - (DWORD) CREATE_NO_WINDOW), - NULL, - o.conn[config].config_dir, //start-up dir - &start_info, - &proc_info)) + if (!CreateProcess(NULL, cmdline, NULL, NULL, TRUE, + (o.show_script_window[0] == '1' ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW), + NULL, c->config_dir, &si, &pi)) + return; + + for (i = 0; i <= o.disconnectscript_timeout; i++) { - return; + if (!GetExitCodeProcess(pi.hProcess, &exit_code)) + goto out; + + if (exit_code != STILL_ACTIVE) + goto out; + + Sleep(1000); } - - TimeOut = o.preconnectscript_timeout; - - for (i=0; i <= TimeOut; i++) - { - if (!GetExitCodeProcess(proc_info.hProcess, &ExitCode)) - { - return; - } - - if (ExitCode != STILL_ACTIVE) - { - return; - } - - Sleep(1000); - } +out: + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); } - diff --git a/scripts.h b/scripts.h index 05fc2af..b9a5a14 100644 --- a/scripts.h +++ b/scripts.h @@ -2,6 +2,7 @@ * OpenVPN-GUI -- A Windows GUI for OpenVPN. * * Copyright (C) 2004 Mathias Sundman + * 2010 Heiko Hund * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,6 +20,11 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -void RunConnectScript(int config, int run_as_service); -void RunDisconnectScript(int config, int run_as_service); -void RunPreconnectScript(int config); +#ifndef SCRIPTS_H +#define SCRIPTS_H + +void RunPreconnectScript(connection_t *); +void RunConnectScript(connection_t *, int run_as_service); +void RunDisconnectScript(connection_t *, int run_as_service); + +#endif diff --git a/service.c b/service.c index 21f14e2..2b9a62a 100644 --- a/service.c +++ b/service.c @@ -74,8 +74,8 @@ int MyStartService() } /* Run Pre-connect script */ - for (i=0; i