diff options
Diffstat (limited to 'openvpn')
-rw-r--r-- | openvpn/doc/openvpn.8 | 155 | ||||
-rw-r--r-- | openvpn/src/openvpn/manage.c | 43 | ||||
-rw-r--r-- | openvpn/src/openvpn/manage.h | 6 | ||||
-rw-r--r-- | openvpn/src/openvpn/openvpn_win32_resources.rc | 4 | ||||
-rw-r--r-- | openvpn/src/openvpn/options.c | 119 | ||||
-rw-r--r-- | openvpn/src/openvpn/socket.c | 9 | ||||
-rw-r--r-- | openvpn/src/openvpnserv/openvpnserv_resources.rc | 4 | ||||
-rw-r--r-- | openvpn/version.m4 | 2 |
8 files changed, 254 insertions, 88 deletions
diff --git a/openvpn/doc/openvpn.8 b/openvpn/doc/openvpn.8 index ee46de62..24b1a2c4 100644 --- a/openvpn/doc/openvpn.8 +++ b/openvpn/doc/openvpn.8 @@ -612,12 +612,21 @@ option. .\"********************************************************* .TP .B \-\-ipchange cmd -Execute shell command +Run command .B cmd when our remote ip-address is initially authenticated or changes. -Execute as: +.B cmd +consists of a path to script (or executable program), optionally +followed by arguments. The path and arguments may be single- or double-quoted +and/or escaped using a backslash, and should be separated by one or more spaces. + +When +.B cmd +is executed two arguments are appended after any arguments specified in +.B cmd +, as follows: .B cmd ip_address port_number @@ -632,14 +641,6 @@ script instead. See the "Environmental Variables" section below for additional parameters passed as environmental variables. -Note that -.B cmd -can be a shell command with multiple arguments, in which -case all OpenVPN-generated arguments will be appended -to -.B cmd -to build a command line which will be passed to the script. - If you are running in a dynamic IP address environment where the IP addresses of either peer could change without notice, you can use this script, for example, to edit the @@ -1047,17 +1048,32 @@ for the TAP-Win32 adapter to come up before adding routes. .\"********************************************************* .TP .B \-\-route-up cmd -Execute shell command +Run command .B cmd after routes are added, subject to .B \-\-route-delay. +.B cmd +consists of a path to script (or executable program), optionally +followed by arguments. The path and arguments may be single- or double-quoted +and/or escaped using a backslash, and should be separated by one or more spaces. + See the "Environmental Variables" section below for additional parameters passed as environmental variables. +.\"********************************************************* +.TP +.B \-\-route-pre-down cmd +Run command +.B cmd +before routes are removed upon disconnection. -Note that .B cmd -can be a shell command with multiple arguments. +consists of a path to script (or executable program), optionally +followed by arguments. The path and arguments may be single- or double-quoted +and/or escaped using a backslash, and should be separated by one or more spaces. + +See the "Environmental Variables" section below for +additional parameters passed as environmental variables. .\"********************************************************* .TP .B \-\-route-noexec @@ -1691,10 +1707,19 @@ memory available to other applications. .\"********************************************************* .TP .B \-\-up cmd -Shell command to run after successful TUN/TAP device open +Run command +.B cmd +after successful TUN/TAP device open (pre .B \-\-user -UID change). The up script is useful for specifying route +UID change). + +.B cmd +consists of a path to script (or executable program), optionally +followed by arguments. The path and arguments may be single- or double-quoted +and/or escaped using a backslash, and should be separated by one or more spaces. + +The up command is useful for specifying route commands which route IP traffic destined for private subnets which exist at the other end of the VPN connection into the tunnel. @@ -1714,13 +1739,11 @@ execute as: See the "Environmental Variables" section below for additional parameters passed as environmental variables. -Note that -.B cmd -can be a shell command with multiple arguments, in which -case all OpenVPN-generated arguments will be appended -to +Note that if .B cmd -to build a command line which will be passed to the shell. +includes arguments, all OpenVPN-generated arguments will be appended +to them to build an argument list with which the executable will be +called. Typically, .B cmd @@ -1796,12 +1819,20 @@ i.e. the receipt of the first authenticated packet from the peer. .\"********************************************************* .TP .B \-\-down cmd -Shell command to run after TUN/TAP device close +Run command +.B cmd +after TUN/TAP device close (post .B \-\-user UID change and/or .B \-\-chroot -). Called with the same parameters and environmental +). +.B cmd +consists of a path to script (or executable program), optionally +followed by arguments. The path and arguments may be single- or double-quoted +and/or escaped using a backslash, and should be separated by one or more spaces. + +Called with the same parameters and environmental variables as the .B \-\-up option above. @@ -2029,7 +2060,7 @@ options. Become a daemon after all initialization functions are completed. This option will cause all message and error output to be sent to the syslog file (such as /var/log/messages), -except for the output of shell scripts and +except for the output of scripts and ifconfig commands, which will go to /dev/null unless otherwise redirected. The syslog redirection occurs immediately at the point @@ -2949,20 +2980,29 @@ In the absence of this option, OpenVPN will disconnect a client instance upon connection of a new client having the same common name. .\"********************************************************* .TP -.B \-\-client-connect script +.B \-\-client-connect cmd Run -.B script -on client connection. The script is passed the common name +.B command cmd +on client connection. + +.B cmd +consists of a path to script (or executable program), optionally +followed by arguments. The path and arguments may be single- or double-quoted +and/or escaped using a backslash, and should be separated by one or more spaces. + +The command is passed the common name and IP address of the just-authenticated client as environmental variables (see environmental variable section -below). The script is also passed -the pathname of a freshly created temporary file as $1 -(i.e. the first command line argument), to be used by the script +below). The command is also passed +the pathname of a freshly created temporary file as the last argument +(after any arguments specified in +.B cmd +), to be used by the command to pass dynamically generated config file directives back to OpenVPN. If the script wants to generate a dynamic config file to be applied on the server when the client connects, -it should write it to the file named by $1. +it should write it to the file named by the last argument. See the .B \-\-client-config-dir @@ -2977,7 +3017,7 @@ returns a non-zero error status, it will cause the client to be disconnected. .\"********************************************************* .TP -.B \-\-client-disconnect +.B \-\-client-disconnect cmd Like .B \-\-client-connect but called on client instance shutdown. Will not be called @@ -2989,11 +3029,19 @@ successful (0) status returns. The exception to this rule is if the .B \-\-client-disconnect -script or plugins are cascaded, and at least one client-connect +command or plugins are cascaded, and at least one client-connect function succeeded, then ALL of the client-disconnect functions for scripts and plugins will be called on client instance object deletion, even in cases where some of the related client-connect functions returned an error status. + +The +.B \-\-client-disconnect +command is passed the same pathname as the corresponding +.B \-\-client-connect +command as its last argument. (after any arguments specified in +.B cmd +). .B .\"********************************************************* .TP @@ -3176,12 +3224,18 @@ and .\"********************************************************* .TP .B \-\-learn-address cmd -Run script or shell command +Run command .B cmd to validate client virtual addresses or routes. .B cmd -will be executed with 3 parameters: +consists of a path to script (or executable program), optionally +followed by arguments. The path and arguments may be single- or double-quoted +and/or escaped using a backslash, and should be separated by one or more spaces. + +Three arguments will be appended to any arguments in +.B cmd +as follows: .B [1] operation \-\- "add", "update", or "delete" based on whether or not @@ -3215,15 +3269,20 @@ policies with regard to the client's high-level common name, rather than the low level client virtual addresses. .\"********************************************************* .TP -.B \-\-auth-user-pass-verify script method +.B \-\-auth-user-pass-verify cmd method Require the client to provide a username/password (possibly in addition to a client certificate) for authentication. -OpenVPN will execute -.B script -as a shell command to validate the username/password +OpenVPN will run +.B command cmd +to validate the username/password provided by the client. +.B cmd +consists of a path to script (or executable program), optionally +followed by arguments. The path and arguments may be single- or double-quoted +and/or escaped using a backslash, and should be separated by one or more spaces. + If .B method is set to "via-env", OpenVPN will call @@ -4451,7 +4510,7 @@ username/password. It is always cached. .\"********************************************************* .TP .B \-\-tls-verify cmd -Execute shell command +Run command .B cmd to verify the X509 name of a pending TLS connection that has otherwise passed all other @@ -4464,16 +4523,16 @@ test). .B cmd should return 0 to allow the TLS handshake to proceed, or 1 to fail. -Note that .B cmd -is a command line and as such may (if enclosed in quotes) contain -whitespace separated arguments. The first word of -.B cmd -is the shell command to execute and the remaining words are its -arguments. +consists of a path to script (or executable program), optionally +followed by arguments. The path and arguments may be single- or double-quoted +and/or escaped using a backslash, and should be separated by one or more spaces. + When .B cmd -is executed two arguments are appended, as follows: +is executed two arguments are appended after any arguments specified in +.B cmd +, as follows: .B cmd certificate_depth subject @@ -6145,7 +6204,7 @@ access any machine on the 10.0.1.0/24 subnet over the secure tunnel (or vice versa). In a production environment, you could put the route command(s) -in a shell script and execute with the +in a script and execute with the .B \-\-up option. .\"********************************************************* diff --git a/openvpn/src/openvpn/manage.c b/openvpn/src/openvpn/manage.c index 1dddd41d..b9807551 100644 --- a/openvpn/src/openvpn/manage.c +++ b/openvpn/src/openvpn/manage.c @@ -66,6 +66,8 @@ struct management *management; /* GLOBAL */ /* static forward declarations */ static void man_output_standalone (struct management *man, volatile int *signal_received); static void man_reset_client_socket (struct management *man, const bool exiting); +static ssize_t write_fd (int fd, void *ptr, size_t nbytes, int flags, int sendfd); + static void man_help () @@ -1891,7 +1893,13 @@ man_write (struct management *man) if (buf && BLEN (buf)) { const int len = min_int (size_hint, BLEN (buf)); - sent = send (man->connection.sd_cli, BPTR (buf), len, MSG_NOSIGNAL); +#ifdef TARGET_ANDROID + if (man->connection.fdtosend > 0) { + sent = write_fd (man->connection.sd_cli, BPTR (buf), len, MSG_NOSIGNAL,man->connection.fdtosend); + man->connection.fdtosend = -1; + } else +#endif + sent = send (man->connection.sd_cli, BPTR (buf), len, MSG_NOSIGNAL); if (sent >= 0) { buffer_list_advance (man->connection.out, sent); @@ -3084,6 +3092,39 @@ management_query_rsa_sig (struct management *man, #endif +static ssize_t write_fd (int fd, void *ptr, size_t nbytes, int flags, int sendfd) +{ + struct msghdr msg; + struct iovec iov[1]; + + union { + struct cmsghdr cm; + char control[CMSG_SPACE(sizeof(int))]; + } control_un; + struct cmsghdr *cmptr; + + msg.msg_control = control_un.control; + msg.msg_controllen = sizeof(control_un.control); + + cmptr = CMSG_FIRSTHDR(&msg); + cmptr->cmsg_len = CMSG_LEN(sizeof(int)); + cmptr->cmsg_level = SOL_SOCKET; + cmptr->cmsg_type = SCM_RIGHTS; + *((int *) CMSG_DATA(cmptr)) = sendfd; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + + iov[0].iov_base = ptr; + iov[0].iov_len = nbytes; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + return (sendmsg(fd, &msg, flags)); +} + + + /* * Return true if management_hold() would block */ diff --git a/openvpn/src/openvpn/manage.h b/openvpn/src/openvpn/manage.h index f681f8d4..71e1a84e 100644 --- a/openvpn/src/openvpn/manage.h +++ b/openvpn/src/openvpn/manage.h @@ -208,7 +208,7 @@ struct man_persist { bool hold_release; const char *special_state_msg; - + counter_type bytes_in; counter_type bytes_out; }; @@ -303,6 +303,10 @@ struct man_connection { #ifdef MANAGMENT_EXTERNAL_KEY struct buffer_list *rsa_sig; #endif +#ifdef TARGET_ANDROID + int fdtosend; +#endif + }; struct management diff --git a/openvpn/src/openvpn/openvpn_win32_resources.rc b/openvpn/src/openvpn/openvpn_win32_resources.rc index e1cd959c..d092e21a 100644 --- a/openvpn/src/openvpn/openvpn_win32_resources.rc +++ b/openvpn/src/openvpn/openvpn_win32_resources.rc @@ -5,6 +5,8 @@ #endif #include <winresrc.h> +#pragma code_page(65001) /* UTF8 */ + LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL VS_VERSION_INFO VERSIONINFO @@ -28,7 +30,7 @@ BEGIN VALUE "FileDescription", "OpenVPN Daemon" VALUE "FileVersion", PACKAGE_VERSION ".0" VALUE "InternalName", "OpenVPN" - VALUE "LegalCopyright", "Copyright © The OpenVPN Project" + VALUE "LegalCopyright", "Copyright © The OpenVPN Project" VALUE "OriginalFilename", "openvpn.exe" VALUE "ProductName", "OpenVPN" VALUE "ProductVersion", PACKAGE_VERSION ".0" diff --git a/openvpn/src/openvpn/options.c b/openvpn/src/openvpn/options.c index 525c00cd..a2d0f6eb 100644 --- a/openvpn/src/openvpn/options.c +++ b/openvpn/src/openvpn/options.c @@ -166,7 +166,7 @@ static const char usage_message[] = " Set n=\"infinite\" to retry indefinitely.\n" "--float : Allow remote to change its IP address/port, such as through\n" " DHCP (this is the default if --remote is not used).\n" - "--ipchange cmd : Execute shell command cmd on remote ip address initial\n" + "--ipchange cmd : Run command cmd on remote ip address initial\n" " setting or change -- execute as: cmd ip-address port#\n" "--port port : TCP/UDP port # for both local and remote.\n" "--lport port : TCP/UDP port # for local (default=%d). Implies --bind.\n" @@ -223,8 +223,8 @@ static const char usage_message[] = " adding routes (may be 0). If not specified, routes will\n" " be added immediately after tun/tap open. On Windows, wait\n" " up to w seconds for TUN/TAP adapter to come up.\n" - "--route-up cmd : Execute shell cmd after routes are added.\n" - "--route-pre-down cmd : Execute shell cmd before routes are removed.\n" + "--route-up cmd : Run command cmd after routes are added.\n" + "--route-pre-down cmd : Run command cmd before routes are removed.\n" "--route-noexec : Don't add routes automatically. Instead pass routes to\n" " --route-up script using environmental variables.\n" "--route-nopull : When used with --client or --pull, accept options pushed\n" @@ -311,17 +311,17 @@ static const char usage_message[] = #endif "--mlock : Disable Paging -- ensures key material and tunnel\n" " data will never be written to disk.\n" - "--up cmd : Shell cmd to execute after successful tun device open.\n" + "--up cmd : Run command cmd after successful tun device open.\n" " Execute as: cmd tun/tap-dev tun-mtu link-mtu \\\n" " ifconfig-local-ip ifconfig-remote-ip\n" " (pre --user or --group UID/GID change)\n" "--up-delay : Delay tun/tap open and possible --up script execution\n" " until after TCP/UDP connection establishment with peer.\n" - "--down cmd : Shell cmd to run after tun device close.\n" + "--down cmd : Run command cmd after tun device close.\n" " (post --user/--group UID/GID change and/or --chroot)\n" - " (script parameters are same as --up option)\n" - "--down-pre : Call --down cmd/script before TUN/TAP close.\n" - "--up-restart : Run up/down scripts for all restarts including those\n" + " (command parameters are same as --up option)\n" + "--down-pre : Run --down command before TUN/TAP close.\n" + "--up-restart : Run up/down commands for all restarts including those\n" " caused by --ping-restart or SIGUSR1\n" "--user user : Set UID to user after initialization.\n" "--group group : Set GID to group after initialization.\n" @@ -452,7 +452,7 @@ static const char usage_message[] = " the authenticated username as the common name,\n" " rather than the common name from the client cert.\n" "--auth-user-pass-verify cmd method: Query client for username/password and\n" - " run script cmd to verify. If method='via-env', pass\n" + " run command cmd to verify. If method='via-env', pass\n" " user/pass via environment, if method='via-file', pass\n" " user/pass via temporary file.\n" "--opt-verify : Clients that connect with options that are incompatible\n" @@ -464,8 +464,8 @@ static const char usage_message[] = "--client-to-client : Internally route client-to-client traffic.\n" "--duplicate-cn : Allow multiple clients with the same common name to\n" " concurrently connect.\n" - "--client-connect cmd : Run script cmd on client connection.\n" - "--client-disconnect cmd : Run script cmd on client disconnection.\n" + "--client-connect cmd : Run command cmd on client connection.\n" + "--client-disconnect cmd : Run command cmd on client disconnection.\n" "--client-config-dir dir : Directory for custom client config files.\n" "--ccd-exclusive : Refuse connection unless custom client config is found.\n" "--tmp-dir dir : Temporary directory, used for --client-connect return file and plugin communication.\n" @@ -475,7 +475,7 @@ static const char usage_message[] = "--tcp-queue-limit n : Maximum number of queued TCP output packets.\n" "--tcp-nodelay : Macro that sets TCP_NODELAY socket flag on the server\n" " as well as pushes it to connecting clients.\n" - "--learn-address cmd : Run script cmd to validate client virtual addresses.\n" + "--learn-address cmd : Run command cmd to validate client virtual addresses.\n" "--connect-freq n s : Allow a maximum of n new connections per s seconds.\n" "--max-clients n : Allow a maximum of n simultaneously connected clients.\n" "--max-routes-per-client n : Allow a maximum of n internal routes per client.\n" @@ -609,7 +609,7 @@ static const char usage_message[] = "--askpass [file]: Get PEM password from controlling tty before we daemonize.\n" "--auth-nocache : Don't cache --askpass or --auth-user-pass passwords.\n" "--crl-verify crl ['dir']: Check peer certificate against a CRL.\n" - "--tls-verify cmd: Execute shell command cmd to verify the X509 name of a\n" + "--tls-verify cmd: Run command cmd to verify the X509 name of a\n" " pending TLS connection that has otherwise passed all other\n" " tests of certification. cmd should return 0 to allow\n" " TLS handshake to proceed, or 1 to fail. (cmd is\n" @@ -2676,6 +2676,55 @@ check_file_access(const int type, const char *file, const int mode, const char * } /* + * Verifies that the path in the "command" that comes after certain script options (e.g., --up) is a + * valid file with appropriate permissions. + * + * "command" consists of a path, optionally followed by a space, which may be + * followed by arbitrary arguments. It is NOT a full shell command line -- shell expansion is not + * performed. + * + * The path and arguments in "command" may be single- or double-quoted or escaped. + * + * The path is extracted from "command", then check_file_access() is called to check it. The + * arguments, if any, are ignored. + * + * Note that the type, mode, and opt arguments to this routine are the same as the corresponding + * check_file_access() arguments. + */ +static bool +check_cmd_access(const char *command, const char *opt) +{ + struct argv argv; + bool return_code; + + /* If no command was set, there are no errors to look for */ + if (! command) + return false; + + /* Extract executable path and arguments */ + argv = argv_new (); + argv_printf (&argv, "%sc", command); + + /* if an executable is specified then check it; otherwise, complain */ + if (argv.argv[0]) + /* Scripts requires R_OK as well, but that might fail on binaries which + * only requires X_OK to function on Unix - a scenario not unlikely to + * be seen on suid binaries. + */ + return_code = check_file_access(CHKACC_FILE, argv.argv[0], X_OK, opt); + else + { + msg (M_NOPREFIX|M_OPTERR, "%s fails with '%s': No path to executable.", + opt, command); + return_code = true; + } + + argv_reset (&argv); + + return return_code; +} + +/* * Sanity check of all file/dir options. Checks that file/dir * is accessible by OpenVPN */ @@ -2751,27 +2800,29 @@ options_postprocess_filechecks (struct options *options) #if P2MP_SERVER errs |= check_file_access (CHKACC_FILE, options->client_config_dir, R_OK|X_OK, "--client-config-dir"); - /* ** Script hooks ** */ - errs |= check_file_access (CHKACC_FILE, options->client_connect_script, - R_OK|X_OK, "--client-connect script"); - errs |= check_file_access (CHKACC_FILE, options->client_disconnect_script, - R_OK|X_OK, "--client-disconnect script"); - errs |= check_file_access (CHKACC_FILE, options->auth_user_pass_verify_script, - R_OK|X_OK, "--auth-user-pass-verify script"); - errs |= check_file_access (CHKACC_FILE, options->tls_verify, - R_OK|X_OK, "--tls-verify script"); - errs |= check_file_access (CHKACC_FILE, options->up_script, - R_OK|X_OK, "--up script"); - errs |= check_file_access (CHKACC_FILE, options->down_script, - R_OK|X_OK, "--down script"); - errs |= check_file_access (CHKACC_FILE, options->ipchange, - R_OK|X_OK, "--ipchange script"); - errs |= check_file_access (CHKACC_FILE, options->route_script, - R_OK|X_OK, "--route-up script"); - errs |= check_file_access (CHKACC_FILE, options->route_predown_script, - R_OK|X_OK, "--route-pre-down script"); - errs |= check_file_access (CHKACC_FILE, options->learn_address_script, - R_OK|X_OK, "--learn-address script"); + + /* ** Script hooks that accept an optionally quoted and/or escaped executable path, ** */ + /* ** optionally followed by arguments ** */ + errs |= check_cmd_access (options->auth_user_pass_verify_script, + "--auth-user-pass-verify script"); + errs |= check_cmd_access (options->client_connect_script, + "--client-connect script"); + errs |= check_cmd_access (options->client_disconnect_script, + "--client-disconnect script"); + errs |= check_cmd_access (options->tls_verify, + "--tls-verify script"); + errs |= check_cmd_access (options->up_script, + "--up script"); + errs |= check_cmd_access (options->down_script, + "--down script"); + errs |= check_cmd_access (options->ipchange, + "--ipchange script"); + errs |= check_cmd_access (options->route_script, + "--route-up script"); + errs |= check_cmd_access (options->route_predown_script, + "--route-pre-down script"); + errs |= check_cmd_access (options->learn_address_script, + "--learn-address script"); #endif /* P2MP_SERVER */ if (errs) diff --git a/openvpn/src/openvpn/socket.c b/openvpn/src/openvpn/socket.c index 364b97e5..e794c113 100644 --- a/openvpn/src/openvpn/socket.c +++ b/openvpn/src/openvpn/socket.c @@ -38,6 +38,8 @@ #include "ps.h" #include "manage.h" #include "misc.h" +#include "manage.h" + #include "memdbg.h" @@ -984,6 +986,11 @@ create_socket (struct link_socket *sock) { ASSERT (0); } +#ifdef TARGET_ANDROID + management->connection.fdtosend = sock->sd; + management_auth_token (management,"'PROTECT-FD'"); +#endif + } /* @@ -1341,7 +1348,7 @@ socket_connect (socket_descriptor_t *sd, } /* For stream protocols, allocate a buffer to build up packet. - Called after frame has been finalized. */ + Called after frame has been finalized. */ static void socket_frame_init (const struct frame *frame, struct link_socket *sock) diff --git a/openvpn/src/openvpnserv/openvpnserv_resources.rc b/openvpn/src/openvpnserv/openvpnserv_resources.rc index 9b79cb7c..7980193b 100644 --- a/openvpn/src/openvpnserv/openvpnserv_resources.rc +++ b/openvpn/src/openvpnserv/openvpnserv_resources.rc @@ -5,6 +5,8 @@ #endif #include <winresrc.h> +#pragma code_page(65001) /* UTF8 */ + LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL VS_VERSION_INFO VERSIONINFO @@ -28,7 +30,7 @@ BEGIN VALUE "FileDescription", "OpenVPN Service" VALUE "FileVersion", PACKAGE_VERSION ".0" VALUE "InternalName", "OpenVPN" - VALUE "LegalCopyright", "Copyright © The OpenVPN Project" + VALUE "LegalCopyright", "Copyright © The OpenVPN Project" VALUE "OriginalFilename", "openvpnserv.exe" VALUE "ProductName", "OpenVPN" VALUE "ProductVersion", PACKAGE_VERSION ".0" diff --git a/openvpn/version.m4 b/openvpn/version.m4 index 2bd1401f..1ea1c32f 100644 --- a/openvpn/version.m4 +++ b/openvpn/version.m4 @@ -1,7 +1,7 @@ dnl define the OpenVPN version define([PRODUCT_NAME], [OpenVPN]) define([PRODUCT_TARNAME], [openvpn]) -define([PRODUCT_VERSION], [2.3_alpha1]) +define([PRODUCT_VERSION], [2.3_master]) define([PRODUCT_BUGREPORT], [openvpn-users@lists.sourceforge.net]) define([PRODUCT_VERSION_RESOURCE], [2,3,0,0]) dnl define the TAP version |