mirror of
https://github.com/OpenVPN/openvpn.git
synced 2026-06-11 09:50:26 -04:00
Merge branch 'svn-branch-2.1' into merge
Pulling in changes from James' 2.1/openvpn branch in SVN. Conflicts: buffer.c init.c manage.h multi.c openvpn.8 options.c ssl.c version.m4 win/sign.py Signed-off-by: David Sommerseth <dazo@users.sourceforge.net>
This commit is contained in:
commit
20b18fd799
39 changed files with 1707 additions and 338 deletions
|
|
@ -82,7 +82,9 @@ openvpn_SOURCES = \
|
|||
basic.h \
|
||||
buffer.c buffer.h \
|
||||
circ_list.h \
|
||||
clinat.c clinat.h \
|
||||
common.h \
|
||||
config-win32.h \
|
||||
crypto.c crypto.h \
|
||||
dhcp.c dhcp.h \
|
||||
errlevel.h \
|
||||
|
|
|
|||
10
buffer.c
10
buffer.c
|
|
@ -235,22 +235,24 @@ buf_puts(struct buffer *buf, const char *str)
|
|||
* This is necessary due to certain buggy implementations of snprintf,
|
||||
* that don't guarantee null termination for size > 0.
|
||||
*
|
||||
* Return false on overflow.
|
||||
*
|
||||
* This function is duplicated into service-win32/openvpnserv.c
|
||||
* Any modifications here should be done to the other place as well.
|
||||
*/
|
||||
|
||||
int openvpn_snprintf(char *str, size_t size, const char *format, ...)
|
||||
bool openvpn_snprintf(char *str, size_t size, const char *format, ...)
|
||||
{
|
||||
va_list arglist;
|
||||
int ret = 0;
|
||||
int len = -1;
|
||||
if (size > 0)
|
||||
{
|
||||
va_start (arglist, format);
|
||||
ret = vsnprintf (str, size, format, arglist);
|
||||
len = vsnprintf (str, size, format, arglist);
|
||||
va_end (arglist);
|
||||
str[size - 1] = 0;
|
||||
}
|
||||
return ret;
|
||||
return (len >= 0 && len < size);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
2
buffer.h
2
buffer.h
|
|
@ -284,7 +284,7 @@ bool buf_puts (struct buffer *buf, const char *str);
|
|||
/*
|
||||
* Like snprintf but guarantees null termination for size > 0
|
||||
*/
|
||||
int openvpn_snprintf(char *str, size_t size, const char *format, ...)
|
||||
bool openvpn_snprintf(char *str, size_t size, const char *format, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__ ((format (printf, 3, 4)))
|
||||
#endif
|
||||
|
|
|
|||
263
clinat.c
Normal file
263
clinat.c
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
/*
|
||||
* OpenVPN -- An application to securely tunnel IP networks
|
||||
* over a single TCP/UDP port, with support for SSL/TLS-based
|
||||
* session authentication and key exchange,
|
||||
* packet encryption, packet authentication, and
|
||||
* packet compression.
|
||||
*
|
||||
* Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* 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 "syshead.h"
|
||||
|
||||
#if defined(ENABLE_CLIENT_NAT)
|
||||
|
||||
#include "clinat.h"
|
||||
#include "proto.h"
|
||||
#include "socket.h"
|
||||
#include "memdbg.h"
|
||||
|
||||
static bool
|
||||
add_entry(struct client_nat_option_list *dest,
|
||||
const struct client_nat_entry *e)
|
||||
{
|
||||
if (dest->n >= MAX_CLIENT_NAT)
|
||||
{
|
||||
msg (M_WARN, "WARNING: client-nat table overflow (max %d entries)", MAX_CLIENT_NAT);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
dest->entries[dest->n++] = *e;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
print_client_nat_list(const struct client_nat_option_list *list, int msglevel)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
int i;
|
||||
|
||||
msg (msglevel, "*** CNAT list");
|
||||
if (list)
|
||||
{
|
||||
for (i = 0; i < list->n; ++i)
|
||||
{
|
||||
const struct client_nat_entry *e = &list->entries[i];
|
||||
msg (msglevel, " CNAT[%d] t=%d %s/%s/%s",
|
||||
i,
|
||||
e->type,
|
||||
print_in_addr_t (e->network, IA_NET_ORDER, &gc),
|
||||
print_in_addr_t (e->netmask, IA_NET_ORDER, &gc),
|
||||
print_in_addr_t (e->foreign_network, IA_NET_ORDER, &gc));
|
||||
}
|
||||
}
|
||||
gc_free (&gc);
|
||||
}
|
||||
|
||||
struct client_nat_option_list *
|
||||
new_client_nat_list (struct gc_arena *gc)
|
||||
{
|
||||
struct client_nat_option_list *ret;
|
||||
ALLOC_OBJ_CLEAR_GC (ret, struct client_nat_option_list, gc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct client_nat_option_list *
|
||||
clone_client_nat_option_list (const struct client_nat_option_list *src, struct gc_arena *gc)
|
||||
{
|
||||
struct client_nat_option_list *ret;
|
||||
ALLOC_OBJ_GC (ret, struct client_nat_option_list, gc);
|
||||
*ret = *src;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
copy_client_nat_option_list (struct client_nat_option_list *dest,
|
||||
const struct client_nat_option_list *src)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < src->n; ++i)
|
||||
{
|
||||
if (!add_entry(dest, &src->entries[i]))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
add_client_nat_to_option_list (struct client_nat_option_list *dest,
|
||||
const char *type,
|
||||
const char *network,
|
||||
const char *netmask,
|
||||
const char *foreign_network,
|
||||
int msglevel)
|
||||
{
|
||||
struct client_nat_entry e;
|
||||
bool ok;
|
||||
|
||||
if (!strcmp(type, "snat"))
|
||||
e.type = CN_SNAT;
|
||||
else if (!strcmp(type, "dnat"))
|
||||
e.type = CN_DNAT;
|
||||
else
|
||||
{
|
||||
msg(msglevel, "client-nat: type must be 'snat' or 'dnat'");
|
||||
return;
|
||||
}
|
||||
|
||||
e.network = getaddr(0, network, 0, &ok, NULL);
|
||||
if (!ok)
|
||||
{
|
||||
msg(msglevel, "client-nat: bad network: %s", network);
|
||||
return;
|
||||
}
|
||||
e.netmask = getaddr(0, netmask, 0, &ok, NULL);
|
||||
if (!ok)
|
||||
{
|
||||
msg(msglevel, "client-nat: bad netmask: %s", netmask);
|
||||
return;
|
||||
}
|
||||
e.foreign_network = getaddr(0, foreign_network, 0, &ok, NULL);
|
||||
if (!ok)
|
||||
{
|
||||
msg(msglevel, "client-nat: bad foreign network: %s", foreign_network);
|
||||
return;
|
||||
}
|
||||
|
||||
add_entry(dest, &e);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
print_checksum (struct openvpn_iphdr *iph, const char *prefix)
|
||||
{
|
||||
uint16_t *sptr;
|
||||
unsigned int sum = 0;
|
||||
int i = 0;
|
||||
for (sptr = (uint16_t *)iph; (uint8_t *)sptr < (uint8_t *)iph + sizeof(struct openvpn_iphdr); sptr++)
|
||||
{
|
||||
i += 1;
|
||||
sum += *sptr;
|
||||
}
|
||||
msg (M_INFO, "** CKSUM[%d] %s %08x", i, prefix, sum);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
print_pkt (struct openvpn_iphdr *iph, const char *prefix, const int direction, const int msglevel)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
|
||||
char *dirstr = "???";
|
||||
if (direction == CN_OUTGOING)
|
||||
dirstr = "OUT";
|
||||
else if (direction == CN_INCOMING)
|
||||
dirstr = "IN";
|
||||
|
||||
msg(msglevel, "** CNAT %s %s %s -> %s",
|
||||
dirstr,
|
||||
prefix,
|
||||
print_in_addr_t (iph->saddr, IA_NET_ORDER, &gc),
|
||||
print_in_addr_t (iph->daddr, IA_NET_ORDER, &gc));
|
||||
|
||||
gc_free (&gc);
|
||||
}
|
||||
|
||||
void
|
||||
client_nat_transform (const struct client_nat_option_list *list,
|
||||
struct buffer *ipbuf,
|
||||
const int direction)
|
||||
{
|
||||
struct ip_tcp_udp_hdr *h = (struct ip_tcp_udp_hdr *) BPTR (ipbuf);
|
||||
int i;
|
||||
uint32_t addr, *addr_ptr;
|
||||
const uint32_t *from, *to;
|
||||
int accumulate = 0;
|
||||
unsigned int amask;
|
||||
unsigned int alog = 0;
|
||||
|
||||
if (check_debug_level (D_CLIENT_NAT))
|
||||
print_pkt (&h->ip, "BEFORE", direction, D_CLIENT_NAT);
|
||||
|
||||
for (i = 0; i < list->n; ++i)
|
||||
{
|
||||
const struct client_nat_entry *e = &list->entries[i]; /* current NAT rule */
|
||||
if (e->type ^ direction)
|
||||
{
|
||||
addr = *(addr_ptr = &h->ip.daddr);
|
||||
amask = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = *(addr_ptr = &h->ip.saddr);
|
||||
amask = 1;
|
||||
}
|
||||
if (direction)
|
||||
{
|
||||
from = &e->foreign_network;
|
||||
to = &e->network;
|
||||
}
|
||||
else
|
||||
{
|
||||
from = &e->network;
|
||||
to = &e->foreign_network;
|
||||
}
|
||||
|
||||
if (((addr & e->netmask) == *from) && !(amask & alog))
|
||||
{
|
||||
/* pre-adjust IP checksum */
|
||||
ADD_CHECKSUM_32(accumulate, addr);
|
||||
|
||||
/* do NAT transform */
|
||||
addr = (addr & ~e->netmask) | *to;
|
||||
|
||||
/* post-adjust IP checksum */
|
||||
SUB_CHECKSUM_32(accumulate, addr);
|
||||
|
||||
/* write the modified address to packet */
|
||||
*addr_ptr = addr;
|
||||
|
||||
/* mark as modified */
|
||||
alog |= amask;
|
||||
}
|
||||
}
|
||||
if (alog)
|
||||
{
|
||||
if (check_debug_level (D_CLIENT_NAT))
|
||||
print_pkt (&h->ip, "AFTER", direction, D_CLIENT_NAT);
|
||||
|
||||
ADJUST_CHECKSUM(accumulate, h->ip.check);
|
||||
|
||||
if (h->ip.protocol == OPENVPN_IPPROTO_TCP)
|
||||
{
|
||||
if (BLEN(ipbuf) >= sizeof(struct openvpn_iphdr) + sizeof(struct openvpn_tcphdr))
|
||||
{
|
||||
ADJUST_CHECKSUM(accumulate, h->u.tcp.check);
|
||||
}
|
||||
}
|
||||
else if (h->ip.protocol == OPENVPN_IPPROTO_UDP)
|
||||
{
|
||||
if (BLEN(ipbuf) >= sizeof(struct openvpn_iphdr) + sizeof(struct openvpn_udphdr))
|
||||
{
|
||||
ADJUST_CHECKSUM(accumulate, h->u.udp.check);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
65
clinat.h
Normal file
65
clinat.h
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* OpenVPN -- An application to securely tunnel IP networks
|
||||
* over a single TCP/UDP port, with support for SSL/TLS-based
|
||||
* session authentication and key exchange,
|
||||
* packet encryption, packet authentication, and
|
||||
* packet compression.
|
||||
*
|
||||
* Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#if !defined(CLINAT_H) && defined(ENABLE_CLIENT_NAT)
|
||||
#define CLINAT_H
|
||||
|
||||
#include "buffer.h"
|
||||
|
||||
#define MAX_CLIENT_NAT 64
|
||||
|
||||
#define CN_OUTGOING 0
|
||||
#define CN_INCOMING 1
|
||||
|
||||
struct client_nat_entry {
|
||||
# define CN_SNAT 0
|
||||
# define CN_DNAT 1
|
||||
int type;
|
||||
in_addr_t network;
|
||||
in_addr_t netmask;
|
||||
in_addr_t foreign_network;
|
||||
};
|
||||
|
||||
struct client_nat_option_list {
|
||||
int n;
|
||||
struct client_nat_entry entries[MAX_CLIENT_NAT];
|
||||
};
|
||||
|
||||
struct client_nat_option_list *new_client_nat_list (struct gc_arena *gc);
|
||||
struct client_nat_option_list *clone_client_nat_option_list (const struct client_nat_option_list *src, struct gc_arena *gc);
|
||||
void copy_client_nat_option_list (struct client_nat_option_list *dest, const struct client_nat_option_list *src);
|
||||
void print_client_nat_list(const struct client_nat_option_list *list, int msglevel);
|
||||
|
||||
void add_client_nat_to_option_list (struct client_nat_option_list *dest,
|
||||
const char *type,
|
||||
const char *network,
|
||||
const char *netmask,
|
||||
const char *foreign_network,
|
||||
int msglevel);
|
||||
|
||||
void client_nat_transform (const struct client_nat_option_list *list,
|
||||
struct buffer *ipbuf,
|
||||
const int direction);
|
||||
|
||||
#endif
|
||||
5
common.h
5
common.h
|
|
@ -86,6 +86,11 @@ typedef unsigned long ptr_type;
|
|||
*/
|
||||
#define PUSH_BUNDLE_SIZE 1024
|
||||
|
||||
/*
|
||||
* In how many seconds does client re-send PUSH_REQUEST if we haven't yet received a reply
|
||||
*/
|
||||
#define PUSH_REQUEST_INTERVAL 5
|
||||
|
||||
/*
|
||||
* A sort of pseudo-filename for data provided inline within
|
||||
* the configuration file.
|
||||
|
|
|
|||
15
configure.ac
15
configure.ac
|
|
@ -68,6 +68,12 @@ AC_ARG_ENABLE(lzo,
|
|||
[LZO="yes"]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE(lzo-stub,
|
||||
[ --enable-lzo-stub Don't compile LZO compression support but still allow limited interoperability with LZO-enabled peers],
|
||||
[LZO_STUB="$enableval"],
|
||||
[LZO_STUB="no"]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE(crypto,
|
||||
[ --disable-crypto Disable OpenSSL crypto support],
|
||||
[CRYPTO="$enableval"],
|
||||
|
|
@ -662,7 +668,7 @@ dnl
|
|||
dnl check for LZO library
|
||||
dnl
|
||||
|
||||
if test "$LZO" = "yes"; then
|
||||
if test "$LZO" = "yes" && test "$LZO_STUB" = "no"; then
|
||||
LZO_H=""
|
||||
AC_CHECKING([for LZO Library and Header files])
|
||||
AC_CHECK_HEADER(lzo/lzo1x.h,
|
||||
|
|
@ -692,10 +698,15 @@ if test "$LZO" = "yes"; then
|
|||
else
|
||||
AC_MSG_RESULT([LZO headers were not found])
|
||||
AC_MSG_RESULT([LZO library available from http://www.oberhumer.com/opensource/lzo/])
|
||||
AC_MSG_ERROR([Or try ./configure --disable-lzo])
|
||||
AC_MSG_ERROR([Or try ./configure --disable-lzo OR ./configure --enable-lzo-stub])
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl enable multi-client mode
|
||||
if test "$LZO_STUB" = "yes"; then
|
||||
AC_DEFINE(LZO_STUB, 1, [Enable LZO stub capability])
|
||||
fi
|
||||
|
||||
dnl
|
||||
dnl check for OpenSSL-crypto library
|
||||
dnl
|
||||
|
|
|
|||
20
errlevel.h
20
errlevel.h
|
|
@ -71,9 +71,7 @@
|
|||
#define D_ALIGN_ERRORS LOGLEV(1, 14, M_NONFATAL) /* show bad struct alignments */
|
||||
|
||||
#define D_HANDSHAKE LOGLEV(2, 20, 0) /* show data & control channel handshakes */
|
||||
#define D_MTU_INFO LOGLEV(2, 21, 0) /* show terse MTU info */
|
||||
#define D_CLOSE LOGLEV(2, 22, 0) /* show socket and TUN/TAP close */
|
||||
#define D_SHOW_OCC_HASH LOGLEV(2, 23, 0) /* show MD5 hash of option compatibility string */
|
||||
#define D_PROXY LOGLEV(2, 24, 0) /* show http proxy control packets */
|
||||
#define D_ARGV LOGLEV(2, 25, 0) /* show struct argv errors */
|
||||
|
||||
|
|
@ -85,7 +83,7 @@
|
|||
#define D_RESTART LOGLEV(3, 33, 0) /* show certain restart messages */
|
||||
#define D_PUSH LOGLEV(3, 34, 0) /* show push/pull info */
|
||||
#define D_IFCONFIG_POOL LOGLEV(3, 35, 0) /* show ifconfig pool info */
|
||||
#define D_BACKTRACK LOGLEV(3, 36, 0) /* show replay backtracks */
|
||||
#define D_PID_DEBUG_LOW LOGLEV(3, 36, 0) /* show low-freq packet-id debugging info */
|
||||
#define D_AUTH LOGLEV(3, 37, 0) /* show user/pass auth info */
|
||||
#define D_MULTI_LOW LOGLEV(3, 38, 0) /* show point-to-multipoint low-freq debug info */
|
||||
#define D_PLUGIN LOGLEV(3, 39, 0) /* show plugin calls */
|
||||
|
|
@ -104,12 +102,19 @@
|
|||
#define D_PACKET_TRUNC_ERR LOGLEV(4, 55, 0) /* PACKET_TRUNCATION_CHECK */
|
||||
#define D_PF_DROPPED LOGLEV(4, 56, 0) /* packet filter dropped a packet */
|
||||
#define D_MULTI_DROPPED LOGLEV(4, 57, 0) /* show point-to-multipoint packet drops */
|
||||
#define D_MULTI_MEDIUM LOGLEV(4, 58, 0) /* show medium frequency multi messages */
|
||||
#define D_X509_ATTR LOGLEV(4, 59, 0) /* show x509-track attributes on connection */
|
||||
#define D_INIT_MEDIUM LOGLEV(4, 60, 0) /* show medium frequency init messages */
|
||||
#define D_MTU_INFO LOGLEV(4, 61, 0) /* show terse MTU info */
|
||||
#define D_SHOW_OCC_HASH LOGLEV(4, 62, 0) /* show MD5 hash of option compatibility string */
|
||||
#define D_PID_DEBUG_MEDIUM LOGLEV(4, 63, 0) /* show medium-freq packet-id debugging info */
|
||||
|
||||
#define D_LOG_RW LOGLEV(5, 0, 0) /* Print 'R' or 'W' to stdout for read/write */
|
||||
|
||||
#define D_LINK_RW LOGLEV(6, 60, M_DEBUG) /* show TCP/UDP reads/writes (terse) */
|
||||
#define D_TUN_RW LOGLEV(6, 60, M_DEBUG) /* show TUN/TAP reads/writes */
|
||||
#define D_TAP_WIN32_DEBUG LOGLEV(6, 60, M_DEBUG) /* show TAP-Win32 driver debug info */
|
||||
#define D_LINK_RW LOGLEV(6, 69, M_DEBUG) /* show TCP/UDP reads/writes (terse) */
|
||||
#define D_TUN_RW LOGLEV(6, 69, M_DEBUG) /* show TUN/TAP reads/writes */
|
||||
#define D_TAP_WIN32_DEBUG LOGLEV(6, 69, M_DEBUG) /* show TAP-Win32 driver debug info */
|
||||
#define D_CLIENT_NAT LOGLEV(6, 69, M_DEBUG) /* show client NAT debug info */
|
||||
|
||||
#define D_SHOW_KEYS LOGLEV(7, 70, M_DEBUG) /* show data channel encryption keys */
|
||||
#define D_SHOW_KEY_SOURCE LOGLEV(7, 70, M_DEBUG) /* show data channel key source entropy */
|
||||
|
|
@ -117,7 +122,6 @@
|
|||
#define D_FRAG_DEBUG LOGLEV(7, 70, M_DEBUG) /* show fragment debugging info */
|
||||
#define D_WIN32_IO_LOW LOGLEV(7, 70, M_DEBUG) /* low freq win32 I/O debugging info */
|
||||
#define D_MTU_DEBUG LOGLEV(7, 70, M_DEBUG) /* show MTU debugging info */
|
||||
#define D_PID_DEBUG_LOW LOGLEV(7, 70, M_DEBUG) /* show low-freq packet-id debugging info */
|
||||
#define D_MULTI_DEBUG LOGLEV(7, 70, M_DEBUG) /* show medium-freq multi debugging info */
|
||||
#define D_MSS LOGLEV(7, 70, M_DEBUG) /* show MSS adjustments */
|
||||
#define D_COMP_LOW LOGLEV(7, 70, M_DEBUG) /* show adaptive compression state changes */
|
||||
|
|
@ -141,6 +145,7 @@
|
|||
#define D_TLS_KEYSELECT LOGLEV(7, 70, M_DEBUG) /* show information on key selection for data channel */
|
||||
#define D_ARGV_PARSE_CMD LOGLEV(7, 70, M_DEBUG) /* show parse_line() errors in argv_printf %sc */
|
||||
#define D_CRYPTO_DEBUG LOGLEV(7, 70, M_DEBUG) /* show detailed info from crypto.c routines */
|
||||
#define D_PID_DEBUG LOGLEV(7, 70, M_DEBUG) /* show packet-id debugging info */
|
||||
#define D_PF_DROPPED_BCAST LOGLEV(7, 71, M_DEBUG) /* packet filter dropped a broadcast packet */
|
||||
#define D_PF_DEBUG LOGLEV(7, 72, M_DEBUG) /* packet filter debugging, must also define PF_DEBUG in pf.h */
|
||||
|
||||
|
|
@ -158,7 +163,6 @@
|
|||
#define D_READ_WRITE LOGLEV(9, 70, M_DEBUG) /* show all tun/tcp/udp reads/writes/opens */
|
||||
#define D_PACKET_CONTENT LOGLEV(9, 70, M_DEBUG) /* show before/after encryption packet content */
|
||||
#define D_TLS_NO_SEND_KEY LOGLEV(9, 70, M_DEBUG) /* show when no data channel send-key exists */
|
||||
#define D_PID_DEBUG LOGLEV(9, 70, M_DEBUG) /* show packet-id debugging info */
|
||||
#define D_PID_PERSIST_DEBUG LOGLEV(9, 70, M_DEBUG) /* show packet-id persist debugging info */
|
||||
#define D_LINK_RW_VERBOSE LOGLEV(9, 70, M_DEBUG) /* show link reads/writes with greater verbosity */
|
||||
#define D_STREAM_DEBUG LOGLEV(9, 70, M_DEBUG) /* show TCP stream debug info */
|
||||
|
|
|
|||
29
error.c
29
error.c
|
|
@ -340,7 +340,7 @@ void x_msg (const unsigned int flags, const char *format, ...)
|
|||
}
|
||||
|
||||
if (flags & M_FATAL)
|
||||
msg (M_INFO, "Exiting");
|
||||
msg (M_INFO, "Exiting due to fatal error");
|
||||
|
||||
if (flags & M_FATAL)
|
||||
openvpn_exit (OPENVPN_EXIT_STATUS_ERROR); /* exit point */
|
||||
|
|
@ -651,35 +651,38 @@ const struct virtual_output *x_msg_virtual_output; /* GLOBAL */
|
|||
void
|
||||
openvpn_exit (const int status)
|
||||
{
|
||||
void tun_abort();
|
||||
if (!forked)
|
||||
{
|
||||
void tun_abort();
|
||||
#ifdef ENABLE_PLUGIN
|
||||
void plugin_abort (void);
|
||||
void plugin_abort (void);
|
||||
#endif
|
||||
|
||||
tun_abort();
|
||||
tun_abort();
|
||||
|
||||
#ifdef WIN32
|
||||
uninit_win32 ();
|
||||
uninit_win32 ();
|
||||
#endif
|
||||
|
||||
close_syslog ();
|
||||
close_syslog ();
|
||||
|
||||
#ifdef ENABLE_PLUGIN
|
||||
plugin_abort ();
|
||||
plugin_abort ();
|
||||
#endif
|
||||
|
||||
#if PORT_SHARE
|
||||
if (port_share)
|
||||
port_share_abort (port_share);
|
||||
if (port_share)
|
||||
port_share_abort (port_share);
|
||||
#endif
|
||||
|
||||
#ifdef ABORT_ON_ERROR
|
||||
if (status == OPENVPN_EXIT_STATUS_ERROR)
|
||||
abort ();
|
||||
if (status == OPENVPN_EXIT_STATUS_ERROR)
|
||||
abort ();
|
||||
#endif
|
||||
|
||||
if (status == OPENVPN_EXIT_STATUS_GOOD)
|
||||
perf_output_results ();
|
||||
if (status == OPENVPN_EXIT_STATUS_GOOD)
|
||||
perf_output_results ();
|
||||
}
|
||||
|
||||
exit (status);
|
||||
}
|
||||
|
|
|
|||
4
event.c
4
event.c
|
|
@ -522,10 +522,10 @@ ep_ctl (struct event_set *es, event_t event, unsigned int rwflags, void *arg)
|
|||
if (errno == ENOENT)
|
||||
{
|
||||
if (epoll_ctl (eps->epfd, EPOLL_CTL_ADD, event, &ev) < 0)
|
||||
msg (M_ERR, "EVENT: epoll_ctl EPOLL_CTL_ADD failed");
|
||||
msg (M_ERR, "EVENT: epoll_ctl EPOLL_CTL_ADD failed, sd=%d", (int)event);
|
||||
}
|
||||
else
|
||||
msg (M_ERR, "EVENT: epoll_ctl EPOLL_CTL_MOD failed");
|
||||
msg (M_ERR, "EVENT: epoll_ctl EPOLL_CTL_MOD failed, sd=%d", (int)event);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
32
forward.c
32
forward.c
|
|
@ -155,7 +155,9 @@ check_incoming_control_channel_dowork (struct context *c)
|
|||
else if (buf_string_match_head_str (&buf, "PUSH_"))
|
||||
incoming_push_message (c, &buf);
|
||||
else if (buf_string_match_head_str (&buf, "RESTART"))
|
||||
server_pushed_restart (c, &buf);
|
||||
server_pushed_signal (c, &buf, true, 7);
|
||||
else if (buf_string_match_head_str (&buf, "HALT"))
|
||||
server_pushed_signal (c, &buf, false, 4);
|
||||
else
|
||||
msg (D_PUSH_ERRORS, "WARNING: Received unknown control message: %s", BSTR (&buf));
|
||||
}
|
||||
|
|
@ -176,8 +178,8 @@ check_push_request_dowork (struct context *c)
|
|||
{
|
||||
send_push_request (c);
|
||||
|
||||
/* if no response to first push_request, retry at 5 second intervals */
|
||||
event_timeout_modify_wakeup (&c->c2.push_request_interval, 5);
|
||||
/* if no response to first push_request, retry at PUSH_REQUEST_INTERVAL second intervals */
|
||||
event_timeout_modify_wakeup (&c->c2.push_request_interval, PUSH_REQUEST_INTERVAL);
|
||||
}
|
||||
|
||||
#endif /* P2MP */
|
||||
|
|
@ -230,22 +232,28 @@ bool
|
|||
send_control_channel_string (struct context *c, const char *str, int msglevel)
|
||||
{
|
||||
#if defined(USE_CRYPTO) && defined(USE_SSL)
|
||||
|
||||
if (c->c2.tls_multi) {
|
||||
struct gc_arena gc = gc_new ();
|
||||
bool stat;
|
||||
|
||||
/* buffered cleartext write onto TLS control channel */
|
||||
stat = tls_send_payload (c->c2.tls_multi, (uint8_t*) str, strlen (str) + 1);
|
||||
|
||||
/* reschedule tls_multi_process */
|
||||
/*
|
||||
* Reschedule tls_multi_process.
|
||||
* NOTE: in multi-client mode, usually the below two statements are
|
||||
* insufficient to reschedule the client instance object unless
|
||||
* multi_schedule_context_wakeup(m, mi) is also called.
|
||||
*/
|
||||
interval_action (&c->c2.tmp_int);
|
||||
context_immediate_reschedule (c); /* ZERO-TIMEOUT */
|
||||
|
||||
msg (msglevel, "SENT CONTROL [%s]: '%s' (status=%d)",
|
||||
tls_common_name (c->c2.tls_multi, false),
|
||||
str,
|
||||
sanitize_control_message (str, &gc),
|
||||
(int) stat);
|
||||
|
||||
gc_free (&gc);
|
||||
return stat;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -968,7 +976,7 @@ process_incoming_tun (struct context *c)
|
|||
* The --passtos and --mssfix options require
|
||||
* us to examine the IPv4 header.
|
||||
*/
|
||||
process_ipv4_header (c, PIPV4_PASSTOS|PIPV4_MSSFIX, &c->c2.buf);
|
||||
process_ipv4_header (c, PIPV4_PASSTOS|PIPV4_MSSFIX|PIPV4_CLIENT_NAT, &c->c2.buf);
|
||||
|
||||
#ifdef PACKET_TRUNCATION_CHECK
|
||||
/* if (c->c2.buf.len > 1) --c->c2.buf.len; */
|
||||
|
|
@ -1026,6 +1034,14 @@ process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf)
|
|||
if (flags & PIPV4_MSSFIX)
|
||||
mss_fixup (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame)));
|
||||
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
/* possibly do NAT on packet */
|
||||
if ((flags & PIPV4_CLIENT_NAT) && c->options.client_nat)
|
||||
{
|
||||
const int direction = (flags & PIPV4_OUTGOING) ? CN_INCOMING : CN_OUTGOING;
|
||||
client_nat_transform (c->options.client_nat, &ipbuf, direction);
|
||||
}
|
||||
#endif
|
||||
/* possibly extract a DHCP router message */
|
||||
if (flags & PIPV4_EXTRACT_DHCP_ROUTER)
|
||||
{
|
||||
|
|
@ -1188,7 +1204,7 @@ process_outgoing_tun (struct context *c)
|
|||
* The --mssfix option requires
|
||||
* us to examine the IPv4 header.
|
||||
*/
|
||||
process_ipv4_header (c, PIPV4_MSSFIX|PIPV4_EXTRACT_DHCP_ROUTER|PIPV4_OUTGOING, &c->c2.to_tun);
|
||||
process_ipv4_header (c, PIPV4_MSSFIX|PIPV4_EXTRACT_DHCP_ROUTER|PIPV4_CLIENT_NAT|PIPV4_OUTGOING, &c->c2.to_tun);
|
||||
|
||||
if (c->c2.to_tun.len <= MAX_RW_SIZE_TUN (&c->c2.frame))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ bool send_control_channel_string (struct context *c, const char *str, int msglev
|
|||
#define PIPV4_MSSFIX (1<<1)
|
||||
#define PIPV4_OUTGOING (1<<2)
|
||||
#define PIPV4_EXTRACT_DHCP_ROUTER (1<<3)
|
||||
#define PIPV4_CLIENT_NAT (1<<4)
|
||||
|
||||
void process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf);
|
||||
|
||||
|
|
|
|||
70
init.c
70
init.c
|
|
@ -102,13 +102,6 @@ update_options_ce_post (struct options *options)
|
|||
options->ping_rec_timeout_action = PING_RESTART;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_CRYPTO
|
||||
/*
|
||||
* Don't use replay window for TCP mode (i.e. require that packets be strictly in sequence).
|
||||
*/
|
||||
if (link_socket_proto_connection_oriented (options->ce.proto))
|
||||
options->replay_window = options->replay_time = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HTTP_PROXY_FALLBACK
|
||||
|
|
@ -521,7 +514,9 @@ init_port_share (struct context *c)
|
|||
if (!port_share && (c->options.port_share_host && c->options.port_share_port))
|
||||
{
|
||||
port_share = port_share_open (c->options.port_share_host,
|
||||
c->options.port_share_port);
|
||||
c->options.port_share_port,
|
||||
MAX_RW_SIZE_LINK (&c->c2.frame),
|
||||
c->options.port_share_journal_dir);
|
||||
if (port_share == NULL)
|
||||
msg (M_FATAL, "Fatal error: Port sharing failed");
|
||||
}
|
||||
|
|
@ -601,6 +596,27 @@ init_static (void)
|
|||
return false;
|
||||
#endif
|
||||
|
||||
#ifdef TEST_GET_DEFAULT_GATEWAY
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
in_addr_t addr;
|
||||
char macaddr[6];
|
||||
|
||||
if (get_default_gateway(&addr, NULL))
|
||||
msg (M_INFO, "GW %s", print_in_addr_t(addr, 0, &gc));
|
||||
else
|
||||
msg (M_INFO, "GDG ERROR");
|
||||
|
||||
if (get_default_gateway_mac_addr(macaddr))
|
||||
msg (M_INFO, "MAC %s", format_hex_ex (macaddr, 6, 0, 1, ":", &gc));
|
||||
else
|
||||
msg (M_INFO, "GDGMA ERROR");
|
||||
|
||||
gc_free (&gc);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GEN_PATH_TEST
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
|
|
@ -1223,7 +1239,14 @@ do_route (const struct options *options,
|
|||
struct env_set *es)
|
||||
{
|
||||
if (!options->route_noexec && ( route_list || route_ipv6_list ) )
|
||||
add_routes (route_list, route_ipv6_list, tt, ROUTE_OPTION_FLAGS (options), es);
|
||||
{
|
||||
add_routes (route_list, route_ipv6_list, tt, ROUTE_OPTION_FLAGS (options), es);
|
||||
setenv_int (es, "redirect_gateway", route_list->did_redirect_default_gateway);
|
||||
}
|
||||
#ifdef ENABLE_MANAGEMENT
|
||||
if (management)
|
||||
management_up_down (management, "UP", es);
|
||||
#endif
|
||||
|
||||
if (plugin_defined (plugins, OPENVPN_PLUGIN_ROUTE_UP))
|
||||
{
|
||||
|
|
@ -1441,7 +1464,10 @@ do_close_tun (struct context *c, bool force)
|
|||
#ifdef ENABLE_MANAGEMENT
|
||||
/* tell management layer we are about to close the TUN/TAP device */
|
||||
if (management)
|
||||
management_pre_tunnel_close (management);
|
||||
{
|
||||
management_pre_tunnel_close (management);
|
||||
management_up_down (management, "DOWN", c->c2.es);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* delete any routes we added */
|
||||
|
|
@ -1586,7 +1612,6 @@ pull_permission_mask (const struct context *c)
|
|||
unsigned int flags =
|
||||
OPT_P_UP
|
||||
| OPT_P_ROUTE_EXTRAS
|
||||
| OPT_P_IPWIN32
|
||||
| OPT_P_SOCKBUF
|
||||
| OPT_P_SOCKFLAGS
|
||||
| OPT_P_SETENV
|
||||
|
|
@ -1600,7 +1625,7 @@ pull_permission_mask (const struct context *c)
|
|||
| OPT_P_PULL_MODE;
|
||||
|
||||
if (!c->options.route_nopull)
|
||||
flags |= OPT_P_ROUTE;
|
||||
flags |= (OPT_P_ROUTE | OPT_P_IPWIN32);
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
|
@ -1749,8 +1774,10 @@ socket_restart_pause (struct context *c)
|
|||
if (auth_retry_get () == AR_NOINTERACT)
|
||||
sec = 10;
|
||||
|
||||
#if 0 /* not really needed because of c->persist.restart_sleep_seconds */
|
||||
if (c->options.server_poll_timeout && sec > 1)
|
||||
sec = 1;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (c->persist.restart_sleep_seconds > 0 && c->persist.restart_sleep_seconds > sec)
|
||||
|
|
@ -1868,8 +1895,11 @@ do_init_crypto_static (struct context *c, const unsigned int flags)
|
|||
/* Initialize packet ID tracking */
|
||||
if (options->replay)
|
||||
{
|
||||
packet_id_init (&c->c2.packet_id, options->replay_window,
|
||||
options->replay_time);
|
||||
packet_id_init (&c->c2.packet_id,
|
||||
link_socket_proto_connection_oriented (options->ce.proto),
|
||||
options->replay_window,
|
||||
options->replay_time,
|
||||
"STATIC", 0);
|
||||
c->c2.crypto_options.packet_id = &c->c2.packet_id;
|
||||
c->c2.crypto_options.pid_persist = &c->c1.pid_persist;
|
||||
c->c2.crypto_options.flags |= CO_PACKET_ID_LONG_FORM;
|
||||
|
|
@ -1965,7 +1995,7 @@ do_init_crypto_tls_c1 (struct context *c)
|
|||
msg (M_FATAL, "Error: private key password verification failed");
|
||||
break;
|
||||
case AR_INTERACT:
|
||||
ssl_purge_auth ();
|
||||
ssl_purge_auth (false);
|
||||
case AR_NOINTERACT:
|
||||
c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- Password failure error */
|
||||
break;
|
||||
|
|
@ -2017,7 +2047,7 @@ do_init_crypto_tls_c1 (struct context *c)
|
|||
}
|
||||
else
|
||||
{
|
||||
msg (M_INFO, "Re-using SSL/TLS context");
|
||||
msg (D_INIT_MEDIUM, "Re-using SSL/TLS context");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2070,6 +2100,7 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
|
|||
to.replay = options->replay;
|
||||
to.replay_window = options->replay_window;
|
||||
to.replay_time = options->replay_time;
|
||||
to.tcp_mode = link_socket_proto_connection_oriented (options->ce.proto);
|
||||
to.transition_window = options->transition_window;
|
||||
to.handshake_window = options->handshake_window;
|
||||
to.packet_timeout = options->tls_timeout;
|
||||
|
|
@ -2094,9 +2125,11 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
|
|||
to.verify_export_cert = options->tls_export_cert;
|
||||
to.verify_x509name = options->tls_remote;
|
||||
to.crl_file = options->crl_file;
|
||||
to.ssl_flags = options->ssl_flags;
|
||||
to.ns_cert_type = options->ns_cert_type;
|
||||
memmove (to.remote_cert_ku, options->remote_cert_ku, sizeof (to.remote_cert_ku));
|
||||
to.remote_cert_eku = options->remote_cert_eku;
|
||||
to.verify_hash = options->verify_hash;
|
||||
to.es = c->c2.es;
|
||||
|
||||
#ifdef ENABLE_DEBUG
|
||||
|
|
@ -2113,11 +2146,14 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
|
|||
to.auth_user_pass_verify_script = options->auth_user_pass_verify_script;
|
||||
to.auth_user_pass_verify_script_via_file = options->auth_user_pass_verify_script_via_file;
|
||||
to.tmp_dir = options->tmp_dir;
|
||||
to.ssl_flags = options->ssl_flags;
|
||||
if (options->ccd_exclusive)
|
||||
to.client_config_dir_exclusive = options->client_config_dir;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_X509_TRACK
|
||||
to.x509_track = options->x509_track;
|
||||
#endif
|
||||
|
||||
/* TLS handshake authentication (--tls-auth) */
|
||||
if (options->tls_auth_file)
|
||||
{
|
||||
|
|
|
|||
32
lzo.c
32
lzo.c
|
|
@ -32,6 +32,8 @@
|
|||
|
||||
#include "memdbg.h"
|
||||
|
||||
#ifndef LZO_STUB
|
||||
|
||||
static bool
|
||||
lzo_adaptive_compress_test (struct lzo_adaptive_compress *ac)
|
||||
{
|
||||
|
|
@ -79,6 +81,8 @@ lzo_adaptive_compress_data (struct lzo_adaptive_compress *ac, int n_total, int n
|
|||
ac->n_comp += n_comp;
|
||||
}
|
||||
|
||||
#endif /* LZO_STUB */
|
||||
|
||||
void lzo_adjust_frame_parameters (struct frame *frame)
|
||||
{
|
||||
/* Leave room for our one-byte compressed/didn't-compress prefix byte. */
|
||||
|
|
@ -94,14 +98,18 @@ lzo_compress_init (struct lzo_compress_workspace *lzowork, unsigned int flags)
|
|||
{
|
||||
CLEAR (*lzowork);
|
||||
|
||||
lzowork->wmem_size = LZO_WORKSPACE;
|
||||
lzowork->flags = flags;
|
||||
#ifndef LZO_STUB
|
||||
lzowork->wmem_size = LZO_WORKSPACE;
|
||||
|
||||
if (lzo_init () != LZO_E_OK)
|
||||
msg (M_FATAL, "Cannot initialize LZO compression library");
|
||||
lzowork->wmem = (lzo_voidp) lzo_malloc (lzowork->wmem_size);
|
||||
check_malloc_return (lzowork->wmem);
|
||||
msg (M_INFO, "LZO compression initialized");
|
||||
msg (D_INIT_MEDIUM, "LZO compression initialized");
|
||||
#else
|
||||
msg (D_INIT_MEDIUM, "LZO stub compression initialized");
|
||||
#endif
|
||||
lzowork->defined = true;
|
||||
}
|
||||
|
||||
|
|
@ -111,8 +119,10 @@ lzo_compress_uninit (struct lzo_compress_workspace *lzowork)
|
|||
if (lzowork)
|
||||
{
|
||||
ASSERT (lzowork->defined);
|
||||
#ifndef LZO_STUB
|
||||
lzo_free (lzowork->wmem);
|
||||
lzowork->wmem = NULL;
|
||||
#endif
|
||||
lzowork->defined = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -120,6 +130,7 @@ lzo_compress_uninit (struct lzo_compress_workspace *lzowork)
|
|||
static inline bool
|
||||
lzo_compression_enabled (struct lzo_compress_workspace *lzowork)
|
||||
{
|
||||
#ifndef LZO_STUB
|
||||
if ((lzowork->flags & (LZO_SELECTED|LZO_ON)) == (LZO_SELECTED|LZO_ON))
|
||||
{
|
||||
if (lzowork->flags & LZO_ADAPTIVE)
|
||||
|
|
@ -127,6 +138,7 @@ lzo_compression_enabled (struct lzo_compress_workspace *lzowork)
|
|||
else
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -139,15 +151,18 @@ lzo_compress (struct buffer *buf, struct buffer work,
|
|||
struct lzo_compress_workspace *lzowork,
|
||||
const struct frame* frame)
|
||||
{
|
||||
#ifndef LZO_STUB
|
||||
lzo_uint zlen = 0;
|
||||
int err;
|
||||
bool compressed = false;
|
||||
#endif
|
||||
|
||||
ASSERT (lzowork->defined);
|
||||
|
||||
if (buf->len <= 0)
|
||||
return;
|
||||
|
||||
#ifndef LZO_STUB
|
||||
/*
|
||||
* In order to attempt compression, length must be at least COMPRESS_THRESHOLD,
|
||||
* and our adaptive level must give the OK.
|
||||
|
|
@ -193,6 +208,7 @@ lzo_compress (struct buffer *buf, struct buffer work,
|
|||
*buf = work;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
uint8_t *header = buf_prepend (buf, 1);
|
||||
*header = NO_COMPRESS;
|
||||
|
|
@ -204,9 +220,11 @@ lzo_decompress (struct buffer *buf, struct buffer work,
|
|||
struct lzo_compress_workspace *lzowork,
|
||||
const struct frame* frame)
|
||||
{
|
||||
#ifndef LZO_STUB
|
||||
lzo_uint zlen = EXPANDED_SIZE (frame);
|
||||
uint8_t c; /* flag indicating whether or not our peer compressed */
|
||||
int err;
|
||||
#endif
|
||||
uint8_t c; /* flag indicating whether or not our peer compressed */
|
||||
|
||||
ASSERT (lzowork->defined);
|
||||
|
||||
|
|
@ -220,6 +238,7 @@ lzo_decompress (struct buffer *buf, struct buffer work,
|
|||
|
||||
if (c == YES_COMPRESS) /* packet was compressed */
|
||||
{
|
||||
#ifndef LZO_STUB
|
||||
ASSERT (buf_safe (&work, zlen));
|
||||
err = LZO_DECOMPRESS (BPTR (buf), BLEN (buf), BPTR (&work), &zlen,
|
||||
lzowork->wmem);
|
||||
|
|
@ -238,6 +257,11 @@ lzo_decompress (struct buffer *buf, struct buffer work,
|
|||
lzowork->post_decompress += work.len;
|
||||
|
||||
*buf = work;
|
||||
#else
|
||||
dmsg (D_COMP_ERRORS, "LZO decompression error: LZO capability not compiled");
|
||||
buf->len = 0;
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
else if (c == NO_COMPRESS) /* packet was not compressed */
|
||||
{
|
||||
|
|
@ -264,10 +288,12 @@ void lzo_print_stats (const struct lzo_compress_workspace *lzo_compwork, struct
|
|||
{
|
||||
ASSERT (lzo_compwork->defined);
|
||||
|
||||
#ifndef LZO_STUB
|
||||
status_printf (so, "pre-compress bytes," counter_format, lzo_compwork->pre_compress);
|
||||
status_printf (so, "post-compress bytes," counter_format, lzo_compwork->post_compress);
|
||||
status_printf (so, "pre-decompress bytes," counter_format, lzo_compwork->pre_decompress);
|
||||
status_printf (so, "post-decompress bytes," counter_format, lzo_compwork->post_decompress);
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
|
|||
29
lzo.h
29
lzo.h
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#ifdef USE_LZO
|
||||
|
||||
#ifndef LZO_STUB
|
||||
#ifdef LZO_HEADER_DIR
|
||||
#include "lzo/lzoutil.h"
|
||||
#include "lzo/lzo1x.h"
|
||||
|
|
@ -34,6 +35,7 @@
|
|||
#include "lzoutil.h"
|
||||
#include "lzo1x.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "buffer.h"
|
||||
#include "mtu.h"
|
||||
|
|
@ -45,6 +47,18 @@
|
|||
#define LZO_ON (1<<1)
|
||||
#define LZO_ADAPTIVE (1<<2)
|
||||
|
||||
/*
|
||||
* Length of prepended prefix on LZO packets
|
||||
*/
|
||||
#define LZO_PREFIX_LEN 1
|
||||
|
||||
/*
|
||||
* LZO 2.0 worst case size expansion
|
||||
*/
|
||||
#define LZO_EXTRA_BUFFER(len) ((len)/8 + 128 + 3)
|
||||
|
||||
#ifndef LZO_STUB
|
||||
|
||||
/*
|
||||
* Use LZO compress routine lzo1x_1_15_compress which is described
|
||||
* as faster but needs a bit more memory than the standard routine.
|
||||
|
|
@ -58,18 +72,11 @@
|
|||
#define LZO_WORKSPACE LZO1X_1_15_MEM_COMPRESS
|
||||
#define LZO_DECOMPRESS lzo1x_decompress_safe
|
||||
|
||||
#define LZO_EXTRA_BUFFER(len) ((len)/8 + 128 + 3) /* LZO 2.0 worst case size expansion. */
|
||||
|
||||
/*
|
||||
* Don't try to compress any packet smaller than this.
|
||||
*/
|
||||
#define COMPRESS_THRESHOLD 100
|
||||
|
||||
/*
|
||||
* Length of prepended prefix on LZO packets
|
||||
*/
|
||||
#define LZO_PREFIX_LEN 1
|
||||
|
||||
/*
|
||||
* Adaptive compress parameters
|
||||
*/
|
||||
|
|
@ -88,23 +95,27 @@ struct lzo_adaptive_compress {
|
|||
int n_comp;
|
||||
};
|
||||
|
||||
#endif /* LZO_STUB */
|
||||
|
||||
/*
|
||||
* Compress and Uncompress routines.
|
||||
*/
|
||||
|
||||
struct lzo_compress_workspace
|
||||
{
|
||||
bool defined;
|
||||
unsigned int flags;
|
||||
#ifndef LZO_STUB
|
||||
lzo_voidp wmem;
|
||||
int wmem_size;
|
||||
struct lzo_adaptive_compress ac;
|
||||
unsigned int flags;
|
||||
bool defined;
|
||||
|
||||
/* statistics */
|
||||
counter_type pre_decompress;
|
||||
counter_type post_decompress;
|
||||
counter_type pre_compress;
|
||||
counter_type post_compress;
|
||||
#endif
|
||||
};
|
||||
|
||||
void lzo_adjust_frame_parameters(struct frame *frame);
|
||||
|
|
|
|||
75
manage.c
75
manage.c
|
|
@ -96,7 +96,7 @@ man_help ()
|
|||
msg (M_CLIENT, "client-auth-nt CID KID : Authenticate client-id/key-id CID/KID");
|
||||
msg (M_CLIENT, "client-deny CID KID R [CR] : Deny auth client-id/key-id CID/KID with log reason");
|
||||
msg (M_CLIENT, " text R and optional client reason text CR");
|
||||
msg (M_CLIENT, "client-kill CID : Kill client instance CID");
|
||||
msg (M_CLIENT, "client-kill CID [M] : Kill client instance CID with message M (def=RESTART)");
|
||||
msg (M_CLIENT, "env-filter [level] : Set env-var filter level");
|
||||
#ifdef MANAGEMENT_PF
|
||||
msg (M_CLIENT, "client-pf CID : Define packet filter for client CID (MULTILINE)");
|
||||
|
|
@ -698,7 +698,7 @@ static void
|
|||
man_forget_passwords (struct management *man)
|
||||
{
|
||||
#if defined(USE_CRYPTO) && defined(USE_SSL)
|
||||
ssl_purge_auth ();
|
||||
ssl_purge_auth (false);
|
||||
msg (M_CLIENT, "SUCCESS: Passwords were forgotten");
|
||||
#endif
|
||||
}
|
||||
|
|
@ -947,14 +947,14 @@ man_client_deny (struct management *man, const char *cid_str, const char *kid_st
|
|||
}
|
||||
|
||||
static void
|
||||
man_client_kill (struct management *man, const char *cid_str)
|
||||
man_client_kill (struct management *man, const char *cid_str, const char *kill_msg)
|
||||
{
|
||||
unsigned long cid = 0;
|
||||
if (parse_cid (cid_str, &cid))
|
||||
{
|
||||
if (man->persist.callback.kill_by_cid)
|
||||
{
|
||||
const bool status = (*man->persist.callback.kill_by_cid) (man->persist.callback.arg, cid);
|
||||
const bool status = (*man->persist.callback.kill_by_cid) (man->persist.callback.arg, cid, kill_msg);
|
||||
if (status)
|
||||
{
|
||||
msg (M_CLIENT, "SUCCESS: client-kill command succeeded");
|
||||
|
|
@ -1265,8 +1265,8 @@ man_dispatch_command (struct management *man, struct status_output *so, const ch
|
|||
#ifdef MANAGEMENT_DEF_AUTH
|
||||
else if (streq (p[0], "client-kill"))
|
||||
{
|
||||
if (man_need (man, p, 1, 0))
|
||||
man_client_kill (man, p[1]);
|
||||
if (man_need (man, p, 1, MN_AT_LEAST))
|
||||
man_client_kill (man, p[1], p[2]);
|
||||
}
|
||||
else if (streq (p[0], "client-deny"))
|
||||
{
|
||||
|
|
@ -1682,7 +1682,7 @@ man_reset_client_socket (struct management *man, const bool exiting)
|
|||
{
|
||||
#if defined(USE_CRYPTO) && defined(USE_SSL)
|
||||
if (man->settings.flags & MF_FORGET_DISCONNECT)
|
||||
ssl_purge_auth ();
|
||||
ssl_purge_auth (false);
|
||||
#endif
|
||||
if (man->settings.flags & MF_SIGNAL) {
|
||||
int mysig = man_mod_signal (man, SIGUSR1);
|
||||
|
|
@ -2190,6 +2190,7 @@ management_open (struct management *man,
|
|||
void
|
||||
management_close (struct management *man)
|
||||
{
|
||||
man_output_list_push_finalize (man); /* flush output queue */
|
||||
man_connection_close (man);
|
||||
man_settings_close (&man->settings);
|
||||
man_persist_close (&man->persist);
|
||||
|
|
@ -2252,8 +2253,6 @@ management_set_state (struct management *man,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef MANAGEMENT_DEF_AUTH
|
||||
|
||||
static bool
|
||||
env_filter_match (const char *env_str, const int env_filter_level)
|
||||
{
|
||||
|
|
@ -2261,7 +2260,7 @@ env_filter_match (const char *env_str, const int env_filter_level)
|
|||
"username=",
|
||||
"password=",
|
||||
"X509_0_CN=",
|
||||
"tls_serial_0=",
|
||||
"tls_serial_",
|
||||
"untrusted_ip=",
|
||||
"ifconfig_local=",
|
||||
"ifconfig_netmask=",
|
||||
|
|
@ -2274,24 +2273,28 @@ env_filter_match (const char *env_str, const int env_filter_level)
|
|||
"bytes_sent=",
|
||||
"bytes_received="
|
||||
};
|
||||
if (env_filter_level >= 1)
|
||||
|
||||
if (env_filter_level == 0)
|
||||
return true;
|
||||
else if (env_filter_level <= 1 && !strncmp(env_str, "X509_", 5))
|
||||
return true;
|
||||
else if (env_filter_level <= 2)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < SIZE(env_names); ++i)
|
||||
{
|
||||
const char *en = env_names[i];
|
||||
const size_t len = strlen(en);
|
||||
if (strncmp(env_str, en, len) == 0)
|
||||
if (!strncmp(env_str, en, len))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
man_output_env (const struct env_set *es, const bool tail, const int env_filter_level)
|
||||
man_output_env (const struct env_set *es, const bool tail, const int env_filter_level, const char *prefix)
|
||||
{
|
||||
if (es)
|
||||
{
|
||||
|
|
@ -2299,15 +2302,15 @@ man_output_env (const struct env_set *es, const bool tail, const int env_filter_
|
|||
for (e = es->list; e != NULL; e = e->next)
|
||||
{
|
||||
if (e->string && (!env_filter_level || env_filter_match(e->string, env_filter_level)))
|
||||
msg (M_CLIENT, ">CLIENT:ENV,%s", e->string);
|
||||
msg (M_CLIENT, ">%s:ENV,%s", prefix, e->string);
|
||||
}
|
||||
}
|
||||
if (tail)
|
||||
msg (M_CLIENT, ">CLIENT:ENV,END");
|
||||
msg (M_CLIENT, ">%s:ENV,END", prefix);
|
||||
}
|
||||
|
||||
static void
|
||||
man_output_extra_env (struct management *man)
|
||||
man_output_extra_env (struct management *man, const char *prefix)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
struct env_set *es = env_set_create (&gc);
|
||||
|
|
@ -2316,10 +2319,28 @@ man_output_extra_env (struct management *man)
|
|||
const int nclients = (*man->persist.callback.n_clients) (man->persist.callback.arg);
|
||||
setenv_int (es, "n_clients", nclients);
|
||||
}
|
||||
man_output_env (es, false, man->connection.env_filter_level);
|
||||
man_output_env (es, false, man->connection.env_filter_level, prefix);
|
||||
gc_free (&gc);
|
||||
}
|
||||
|
||||
void
|
||||
management_up_down(struct management *man, const char *updown, const struct env_set *es)
|
||||
{
|
||||
if (man->settings.flags & MF_UP_DOWN)
|
||||
{
|
||||
msg (M_CLIENT, ">UPDOWN:%s", updown);
|
||||
man_output_env (es, true, 0, "UPDOWN");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
management_notify(struct management *man, const char *severity, const char *type, const char *text)
|
||||
{
|
||||
msg (M_CLIENT, ">NOTIFY:%s,%s,%s", severity, type, text);
|
||||
}
|
||||
|
||||
#ifdef MANAGEMENT_DEF_AUTH
|
||||
|
||||
static bool
|
||||
validate_peer_info_line(const char *line)
|
||||
{
|
||||
|
|
@ -2384,9 +2405,9 @@ management_notify_client_needing_auth (struct management *management,
|
|||
if (mdac->flags & DAF_CONNECTION_ESTABLISHED)
|
||||
mode = "REAUTH";
|
||||
msg (M_CLIENT, ">CLIENT:%s,%lu,%u", mode, mdac->cid, mda_key_id);
|
||||
man_output_extra_env (management);
|
||||
man_output_extra_env (management, "CLIENT");
|
||||
man_output_peer_info_env(management, mdac);
|
||||
man_output_env (es, true, management->connection.env_filter_level);
|
||||
man_output_env (es, true, management->connection.env_filter_level, "CLIENT");
|
||||
mdac->flags |= DAF_INITIAL_AUTH;
|
||||
}
|
||||
}
|
||||
|
|
@ -2398,8 +2419,8 @@ management_connection_established (struct management *management,
|
|||
{
|
||||
mdac->flags |= DAF_CONNECTION_ESTABLISHED;
|
||||
msg (M_CLIENT, ">CLIENT:ESTABLISHED,%lu", mdac->cid);
|
||||
man_output_extra_env (management);
|
||||
man_output_env (es, true, management->connection.env_filter_level);
|
||||
man_output_extra_env (management, "CLIENT");
|
||||
man_output_env (es, true, management->connection.env_filter_level, "CLIENT");
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -2410,7 +2431,7 @@ management_notify_client_close (struct management *management,
|
|||
if ((mdac->flags & DAF_INITIAL_AUTH) && !(mdac->flags & DAF_CONNECTION_CLOSED))
|
||||
{
|
||||
msg (M_CLIENT, ">CLIENT:DISCONNECT,%lu", mdac->cid);
|
||||
man_output_env (es, true, management->connection.env_filter_level);
|
||||
man_output_env (es, true, management->connection.env_filter_level, "CLIENT");
|
||||
mdac->flags |= DAF_CONNECTION_CLOSED;
|
||||
}
|
||||
}
|
||||
|
|
@ -2494,6 +2515,12 @@ management_auth_failure (struct management *man, const char *type, const char *r
|
|||
msg (M_CLIENT, ">PASSWORD:Verification Failed: '%s'", type);
|
||||
}
|
||||
|
||||
void
|
||||
management_auth_token (struct management *man, const char *token)
|
||||
{
|
||||
msg (M_CLIENT, ">PASSWORD:Auth-Token:%s", token);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
man_persist_state (unsigned int *persistent, const int n)
|
||||
{
|
||||
|
|
|
|||
14
manage.h
14
manage.h
|
|
@ -156,7 +156,7 @@ struct management_callback
|
|||
void (*delete_event) (void *arg, event_t event);
|
||||
int (*n_clients) (void *arg);
|
||||
#ifdef MANAGEMENT_DEF_AUTH
|
||||
bool (*kill_by_cid) (void *arg, const unsigned long cid);
|
||||
bool (*kill_by_cid) (void *arg, const unsigned long cid, const char *kill_msg);
|
||||
bool (*client_auth) (void *arg,
|
||||
const unsigned long cid,
|
||||
const unsigned int mda_key_id,
|
||||
|
|
@ -274,7 +274,6 @@ struct man_connection {
|
|||
#ifdef MANAGEMENT_DEF_AUTH
|
||||
unsigned long in_extra_cid;
|
||||
unsigned int in_extra_kid;
|
||||
int env_filter_level;
|
||||
#endif
|
||||
#ifdef MANAGMENT_EXTERNAL_KEY
|
||||
# define EKS_UNDEF 0
|
||||
|
|
@ -286,6 +285,7 @@ struct man_connection {
|
|||
#endif
|
||||
#endif
|
||||
struct event_set *es;
|
||||
int env_filter_level;
|
||||
|
||||
bool state_realtime;
|
||||
bool log_realtime;
|
||||
|
|
@ -332,6 +332,7 @@ struct management *management_init (void);
|
|||
#ifdef MANAGMENT_EXTERNAL_KEY
|
||||
# define MF_EXTERNAL_KEY (1<<9)
|
||||
#endif
|
||||
#define MF_UP_DOWN (1<<10)
|
||||
|
||||
bool management_open (struct management *man,
|
||||
const char *addr,
|
||||
|
|
@ -372,6 +373,10 @@ bool management_hold (struct management *man);
|
|||
|
||||
void management_event_loop_n_seconds (struct management *man, int sec);
|
||||
|
||||
void management_up_down(struct management *man, const char *updown, const struct env_set *es);
|
||||
|
||||
void management_notify(struct management *man, const char *severity, const char *type, const char *text);
|
||||
|
||||
#ifdef MANAGEMENT_DEF_AUTH
|
||||
void management_notify_client_needing_auth (struct management *management,
|
||||
const unsigned int auth_id,
|
||||
|
|
@ -466,6 +471,11 @@ void management_echo (struct management *man, const char *string, const bool pul
|
|||
|
||||
void management_auth_failure (struct management *man, const char *type, const char *reason);
|
||||
|
||||
/*
|
||||
* Echo an authentication token to management interface
|
||||
*/
|
||||
void management_auth_token (struct management *man, const char *token);
|
||||
|
||||
/*
|
||||
* These functions drive the bytecount in/out counters.
|
||||
*/
|
||||
|
|
|
|||
44
misc.c
44
misc.c
|
|
@ -1713,6 +1713,16 @@ purge_user_pass (struct user_pass *up, const bool force)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
set_auth_token (struct user_pass *up, const char *token)
|
||||
{
|
||||
if (token && strlen(token) && up && up->defined && !up->nocache)
|
||||
{
|
||||
CLEAR (up->password);
|
||||
strncpynt (up->password, token, USER_PASS_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Process string received by untrusted peer before
|
||||
* printing to console or log file.
|
||||
|
|
@ -2381,3 +2391,37 @@ openvpn_basename (const char *path)
|
|||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove SESS_ID_x strings (i.e. auth tokens) from control message
|
||||
* strings so that they will not be output to log file.
|
||||
*/
|
||||
const char *
|
||||
sanitize_control_message(const char *str, struct gc_arena *gc)
|
||||
{
|
||||
char *ret = gc_malloc (strlen(str)+1, false, gc);
|
||||
char *cp = ret;
|
||||
bool redact = false;
|
||||
|
||||
strcpy(ret, str);
|
||||
for (;;)
|
||||
{
|
||||
const char c = *cp;
|
||||
if (c == '\0')
|
||||
break;
|
||||
if (c == 'S' && !strncmp(cp, "SESS_ID_", 8))
|
||||
{
|
||||
cp += 7;
|
||||
redact = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c == ',') /* end of session id? */
|
||||
redact = false;
|
||||
if (redact)
|
||||
*cp = '_';
|
||||
}
|
||||
++cp;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
4
misc.h
4
misc.h
|
|
@ -316,6 +316,8 @@ void fail_user_pass (const char *prefix,
|
|||
|
||||
void purge_user_pass (struct user_pass *up, const bool force);
|
||||
|
||||
void set_auth_token (struct user_pass *up, const char *token);
|
||||
|
||||
/*
|
||||
* Process string received by untrusted peer before
|
||||
* printing to console or log file.
|
||||
|
|
@ -337,6 +339,8 @@ void openvpn_sleep (const int n);
|
|||
|
||||
void configure_path (void);
|
||||
|
||||
const char *sanitize_control_message(const char *str, struct gc_arena *gc);
|
||||
|
||||
#if AUTO_USERID
|
||||
void get_user_pass_auto_userid (struct user_pass *up, const char *tag);
|
||||
#endif
|
||||
|
|
|
|||
10
multi.c
10
multi.c
|
|
@ -626,7 +626,7 @@ multi_create_instance (struct multi_context *m, const struct mroute_addr *real)
|
|||
|
||||
perf_push (PERF_MULTI_CREATE_INSTANCE);
|
||||
|
||||
msg (D_MULTI_LOW, "MULTI: multi_create_instance called");
|
||||
msg (D_MULTI_MEDIUM, "MULTI: multi_create_instance called");
|
||||
|
||||
ALLOC_OBJ_CLEAR (mi, struct multi_instance);
|
||||
|
||||
|
|
@ -1237,6 +1237,9 @@ multi_select_virtual_addr (struct multi_context *m, struct multi_instance *mi)
|
|||
mi->context.c2.push_ifconfig_defined = true;
|
||||
mi->context.c2.push_ifconfig_local = mi->context.options.push_ifconfig_local;
|
||||
mi->context.c2.push_ifconfig_remote_netmask = mi->context.options.push_ifconfig_remote_netmask;
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
mi->context.c2.push_ifconfig_local_alias = mi->context.options.push_ifconfig_local_alias;
|
||||
#endif
|
||||
|
||||
/* the current implementation does not allow "static IPv4, pool IPv6",
|
||||
* (see below) so issue a warning if that happens - don't break the
|
||||
|
|
@ -2650,13 +2653,14 @@ lookup_by_cid (struct multi_context *m, const unsigned long cid)
|
|||
}
|
||||
|
||||
static bool
|
||||
management_kill_by_cid (void *arg, const unsigned long cid)
|
||||
management_kill_by_cid (void *arg, const unsigned long cid, const char *kill_msg)
|
||||
{
|
||||
struct multi_context *m = (struct multi_context *) arg;
|
||||
struct multi_instance *mi = lookup_by_cid (m, cid);
|
||||
if (mi)
|
||||
{
|
||||
send_restart (&mi->context); /* was: multi_signal_instance (m, mi, SIGTERM); */
|
||||
send_restart (&mi->context, kill_msg); /* was: multi_signal_instance (m, mi, SIGTERM); */
|
||||
multi_schedule_context_wakeup(m, mi);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
|
|
|||
106
openvpn.8
106
openvpn.8
|
|
@ -1083,6 +1083,31 @@ and
|
|||
.B \-\-route-gateway.
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B \-\-client-nat snat|dnat network netmask alias
|
||||
This pushable client option sets up a stateless one-to-one NAT
|
||||
rule on packet addresses (not ports), and is useful in cases
|
||||
where routes or ifconfig settings pushed to the client would
|
||||
create an IP numbering conflict.
|
||||
|
||||
.B network/netmask
|
||||
(for example 192.168.0.0/255.255.0.0)
|
||||
defines the local view of a resource from the client perspective, while
|
||||
.B alias/netmask
|
||||
(for example 10.64.0.0/255.255.0.0)
|
||||
defines the remote view from the server perspective.
|
||||
|
||||
Use
|
||||
.B snat
|
||||
(source NAT) for resources owned by the client and
|
||||
.B dnat
|
||||
(destination NAT) for remote resources.
|
||||
|
||||
Set
|
||||
.B \-\-verb 6
|
||||
for debugging info showing the transformation of src/dest
|
||||
addresses in packets.
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B \-\-redirect-gateway flags...
|
||||
(Experimental) Automatically execute routing commands to cause all outgoing IP traffic
|
||||
to be redirected over the VPN.
|
||||
|
|
@ -2406,6 +2431,11 @@ lines of log file history for usage
|
|||
by the management channel.
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B \-\-management-up-down
|
||||
Report tunnel up/down events to management interface.
|
||||
.B
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B \-\-management-client-auth
|
||||
Gives management interface client the responsibility
|
||||
to authenticate clients after their client certificate
|
||||
|
|
@ -2740,7 +2770,7 @@ This option is deprecated, and should be replaced with
|
|||
which is functionally equivalent.
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B \-\-ifconfig-push local remote-netmask
|
||||
.B \-\-ifconfig-push local remote-netmask [alias]
|
||||
Push virtual IP endpoints for client tunnel,
|
||||
overriding the \-\-ifconfig-pool dynamic allocation.
|
||||
|
||||
|
|
@ -2759,6 +2789,15 @@ are from the perspective of the client, not the server. They may be
|
|||
DNS names rather than IP addresses, in which case they will be resolved
|
||||
on the server at the time of client connection.
|
||||
|
||||
The optional
|
||||
.B alias
|
||||
parameter may be used in cases where NAT causes the client view
|
||||
of its local endpoint to differ from the server view. In this case
|
||||
.B local/remote-netmask
|
||||
will refer to the server view while
|
||||
.B alias/remote-netmask
|
||||
will refer to the client view.
|
||||
|
||||
This option must be associated with a specific client instance,
|
||||
which means that it must be specified either in a client
|
||||
instance config file using
|
||||
|
|
@ -3259,7 +3298,7 @@ disable the remapping feature. Don't use this option unless you
|
|||
know what you are doing!
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B \-\-port-share host port
|
||||
.B \-\-port-share host port [dir]
|
||||
When run in TCP server mode, share the OpenVPN port with
|
||||
another application, such as an HTTPS server. If OpenVPN
|
||||
senses a connection to its port which is using a non-OpenVPN
|
||||
|
|
@ -3269,6 +3308,16 @@ Currently only designed to work with HTTP/HTTPS,
|
|||
though it would be theoretically possible to extend to
|
||||
other protocols such as ssh.
|
||||
|
||||
.B dir
|
||||
specifies an optional directory where a temporary file with name N
|
||||
containing content C will be dynamically generated for each proxy
|
||||
connection, where N is the source IP:port of the client connection
|
||||
and C is the source IP:port of the connection to the proxy
|
||||
receiver. This directory can be used as a dictionary by
|
||||
the proxy receiver to determine the origin of the connection.
|
||||
Each generated file will be automatically deleted when the proxied
|
||||
connection is torn down.
|
||||
|
||||
Not implemented on Windows.
|
||||
.\"*********************************************************
|
||||
.SS Client Mode
|
||||
|
|
@ -3902,6 +3951,22 @@ that for certificate authority functions, you must set up the files
|
|||
).
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B \-\-extra-certs file
|
||||
Specify a
|
||||
.B file
|
||||
containing one or more PEM certs (concatenated together)
|
||||
that complete the
|
||||
local certificate chain.
|
||||
|
||||
This option is useful for "split" CAs, where the CA for server
|
||||
certs is different than the CA for client certs. Putting certs
|
||||
in this file allows them to be used to complete the local
|
||||
certificate chain without trusting them to verify the peer-submitted
|
||||
certificate, as would be the case if the certs were placed in the
|
||||
.B ca
|
||||
file.
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B \-\-key file
|
||||
Local peer's private key in .pem format. Use the private key which was generated
|
||||
when you built your peer's certificate (see
|
||||
|
|
@ -3918,6 +3983,17 @@ and
|
|||
.B \-\-key.
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B \-\-verify-hash hash
|
||||
Specify SHA1 fingerprint for level-1 cert. The level-1 cert is the
|
||||
CA (or intermediate cert) that signs the leaf certificate, and is
|
||||
one removed from the leaf certificate in the direction of the root.
|
||||
When accepting a connection from a peer, the level-1 cert
|
||||
fingerprint must match
|
||||
.B hash
|
||||
or certificate verification will fail. Hash is specified
|
||||
as XX:XX:... For example: AD:B0:95:D8:09:C8:36:45:12:A9:89:C8:90:09:CB:13:72:A6:AD:16
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B \-\-pkcs11-cert-private [0|1]...
|
||||
Set if access to certificate object should be performed after login.
|
||||
Every provider has its own setting.
|
||||
|
|
@ -4347,7 +4423,7 @@ additional parameters passed as environmental variables.
|
|||
.TP
|
||||
.B \-\-tls-export-cert directory
|
||||
Store the certificates the clients uses upon connection to this
|
||||
directory. This will be done before --tls-verify is called. The
|
||||
directory. This will be done before \-\-tls-verify is called. The
|
||||
certificates will use a temporary name and will be deleted when
|
||||
the tls-verify script returns. The file name used for the certificate
|
||||
is available via the peer_cert environment variable.
|
||||
|
|
@ -4387,6 +4463,18 @@ works in a
|
|||
environment too.
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B \-\-x509-track attribute
|
||||
Save peer X509
|
||||
.B attribute
|
||||
value in environment for use by plugins and management interface.
|
||||
Prepend a '+' to
|
||||
.B attribute
|
||||
to save values from full cert chain. Values will be encoded
|
||||
as X509_<depth>_<attribute>=<value>. Multiple
|
||||
.B \-\-x509-track
|
||||
options can be defined to track multiple attributes.
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B \-\-ns-cert-type client|server
|
||||
Require that peer certificate was signed with an explicit
|
||||
.B nsCertType
|
||||
|
|
@ -4472,7 +4560,7 @@ or
|
|||
.B \-\-tls-verify.
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B \-\-crl-verify crl
|
||||
.B \-\-crl-verify crl ['dir']
|
||||
Check peer certificate against the file
|
||||
.B crl
|
||||
in PEM format.
|
||||
|
|
@ -4488,6 +4576,16 @@ overall integrity of the PKI.
|
|||
|
||||
The only time when it would be necessary to rebuild the entire PKI from scratch would be
|
||||
if the root certificate key itself was compromised.
|
||||
|
||||
If the optional
|
||||
.B dir
|
||||
flag is specified, enable a different mode where
|
||||
.B crl
|
||||
is a directory containing files named as revoked serial numbers
|
||||
(the files may be empty, the contents are never read). If a client
|
||||
requests a connection, where the client certificate serial number
|
||||
(decimal string) is the name of a file present in the directory,
|
||||
it will be rejected.
|
||||
.\"*********************************************************
|
||||
.SS SSL Library information:
|
||||
.\"*********************************************************
|
||||
|
|
|
|||
|
|
@ -417,8 +417,12 @@ struct context_2
|
|||
/* --ifconfig endpoints to be pushed to client */
|
||||
bool push_reply_deferred;
|
||||
bool push_ifconfig_defined;
|
||||
bool sent_push_reply;
|
||||
in_addr_t push_ifconfig_local;
|
||||
in_addr_t push_ifconfig_remote_netmask;
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
in_addr_t push_ifconfig_local_alias;
|
||||
#endif
|
||||
|
||||
bool push_ifconfig_ipv6_defined;
|
||||
struct in6_addr push_ifconfig_ipv6_local;
|
||||
|
|
@ -435,6 +439,7 @@ struct context_2
|
|||
#endif
|
||||
|
||||
struct event_timeout push_request_interval;
|
||||
int n_sent_push_requests;
|
||||
bool did_pre_pull_restore;
|
||||
|
||||
/* hash of pulled options, so we can compare when options change */
|
||||
|
|
|
|||
143
options.c
143
options.c
|
|
@ -223,6 +223,9 @@ static const char usage_message[] =
|
|||
" Add 'bypass-dns' flag to similarly bypass tunnel for DNS.\n"
|
||||
"--redirect-private [flags]: Like --redirect-gateway, but omit actually changing\n"
|
||||
" the default gateway. Useful when pushing private subnets.\n"
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
"--client-nat snat|dnat network netmask alias : on client add 1-to-1 NAT rule.\n"
|
||||
#endif
|
||||
#ifdef ENABLE_PUSH_PEER_INFO
|
||||
"--push-peer-info : (client only) push client info to server.\n"
|
||||
#endif
|
||||
|
|
@ -359,6 +362,7 @@ static const char usage_message[] =
|
|||
"--management-signal : Issue SIGUSR1 when management disconnect event occurs.\n"
|
||||
"--management-forget-disconnect : Forget passwords when management disconnect\n"
|
||||
" event occurs.\n"
|
||||
"--management-up-down : Report tunnel up/down events to management interface.\n"
|
||||
"--management-log-cache n : Cache n lines of log file history for usage\n"
|
||||
" by the management channel.\n"
|
||||
#if UNIX_SOCK_SUPPORT
|
||||
|
|
@ -448,8 +452,9 @@ static const char usage_message[] =
|
|||
"--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"
|
||||
#if PORT_SHARE
|
||||
"--port-share host port : When run in TCP mode, proxy incoming HTTPS sessions\n"
|
||||
" to a web server at host:port.\n"
|
||||
"--port-share host port [dir] : When run in TCP mode, proxy incoming HTTPS\n"
|
||||
" sessions to a web server at host:port. dir specifies an\n"
|
||||
" optional directory to write origin IP:port data.\n"
|
||||
#endif
|
||||
#endif
|
||||
"\n"
|
||||
|
|
@ -527,6 +532,7 @@ static const char usage_message[] =
|
|||
" Use \"openssl dhparam -out dh1024.pem 1024\" to generate.\n"
|
||||
"--cert file : Local certificate in .pem format -- must be signed\n"
|
||||
" by a Certificate Authority in --ca file.\n"
|
||||
"--extra-certs file : one or more PEM certs that complete the cert chain.\n"
|
||||
"--key file : Local private key in .pem format.\n"
|
||||
"--pkcs12 file : PKCS#12 file containing local private key, local certificate\n"
|
||||
" and optionally the root CA certificate.\n"
|
||||
|
|
@ -534,6 +540,7 @@ static const char usage_message[] =
|
|||
"--x509-username-field : Field used in x509 certificat to be username.\n"
|
||||
" Default is CN.\n"
|
||||
#endif
|
||||
"--verify-hash : Specify SHA1 fingerprint for level-1 cert.\n"
|
||||
#ifdef WIN32
|
||||
"--cryptoapicert select-string : Load the certificate and private key from the\n"
|
||||
" Windows Certificate System Store.\n"
|
||||
|
|
@ -558,7 +565,7 @@ static const char usage_message[] =
|
|||
" see --secret option for more info.\n"
|
||||
"--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: Check peer certificate against a CRL.\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"
|
||||
" pending TLS connection that has otherwise passed all other\n"
|
||||
" tests of certification. cmd should return 0 to allow\n"
|
||||
|
|
@ -572,6 +579,8 @@ static const char usage_message[] =
|
|||
" of verification.\n"
|
||||
"--ns-cert-type t: Require that peer certificate was signed with an explicit\n"
|
||||
" nsCertType designation t = 'client' | 'server'.\n"
|
||||
"--x509-track x : Save peer X509 attribute x in environment for use by\n"
|
||||
" plugins and management interface.\n"
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
|
||||
"--remote-cert-ku v ... : Require that the peer certificate was signed with\n"
|
||||
" explicit key usage, you can specify more than one value.\n"
|
||||
|
|
@ -1000,6 +1009,40 @@ is_stateful_restart (const struct options *o)
|
|||
return is_persist_option (o) || connection_list_defined (o);
|
||||
}
|
||||
|
||||
#ifdef USE_SSL
|
||||
static uint8_t *
|
||||
parse_hash_fingerprint(const char *str, int nbytes, int msglevel, struct gc_arena *gc)
|
||||
{
|
||||
int i;
|
||||
const char *cp = str;
|
||||
uint8_t *ret = (uint8_t *) gc_malloc (nbytes, true, gc);
|
||||
char term = 1;
|
||||
int byte;
|
||||
char bs[3];
|
||||
|
||||
for (i = 0; i < nbytes; ++i)
|
||||
{
|
||||
if (strlen(cp) < 2)
|
||||
msg (msglevel, "format error in hash fingerprint: %s", str);
|
||||
bs[0] = *cp++;
|
||||
bs[1] = *cp++;
|
||||
bs[2] = 0;
|
||||
byte = 0;
|
||||
if (sscanf(bs, "%x", &byte) != 1)
|
||||
msg (msglevel, "format error in hash fingerprint hex byte: %s", str);
|
||||
ret[i] = (uint8_t)byte;
|
||||
term = *cp++;
|
||||
if (term != ':' && term != 0)
|
||||
msg (msglevel, "format error in hash fingerprint delimiter: %s", str);
|
||||
if (term == 0)
|
||||
break;
|
||||
}
|
||||
if (term != 0 || i != nbytes-1)
|
||||
msg (msglevel, "hash fingerprint is different length than expected (%d bytes): %s", nbytes, str);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#ifdef ENABLE_DEBUG
|
||||
|
|
@ -1133,7 +1176,6 @@ show_p2mp_parms (const struct options *o)
|
|||
SHOW_INT (max_routes_per_client);
|
||||
SHOW_STR (auth_user_pass_verify_script);
|
||||
SHOW_BOOL (auth_user_pass_verify_script_via_file);
|
||||
SHOW_INT (ssl_flags);
|
||||
#if PORT_SHARE
|
||||
SHOW_STR (port_share_host);
|
||||
SHOW_INT (port_share_port);
|
||||
|
|
@ -1223,6 +1265,9 @@ options_detach (struct options *o)
|
|||
{
|
||||
gc_detach (&o->gc);
|
||||
o->routes = NULL;
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
o->client_nat = NULL;
|
||||
#endif
|
||||
#if P2MP_SERVER
|
||||
clone_push_list(o);
|
||||
#endif
|
||||
|
|
@ -1242,6 +1287,15 @@ rol6_check_alloc (struct options *options)
|
|||
options->routes_ipv6 = new_route_ipv6_option_list (options->max_routes, &options->gc);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
static void
|
||||
cnol_check_alloc (struct options *options)
|
||||
{
|
||||
if (!options->client_nat)
|
||||
options->client_nat = new_client_nat_list (&options->gc);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_DEBUG
|
||||
static void
|
||||
show_connection_entry (const struct connection_entry *o)
|
||||
|
|
@ -1435,6 +1489,11 @@ show_settings (const struct options *o)
|
|||
SHOW_BOOL (allow_pull_fqdn);
|
||||
if (o->routes)
|
||||
print_route_options (o->routes, D_SHOW_PARMS);
|
||||
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
if (o->client_nat)
|
||||
print_client_nat_list(o->client_nat, D_SHOW_PARMS);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_MANAGEMENT
|
||||
SHOW_STR (management_addr);
|
||||
|
|
@ -1496,6 +1555,7 @@ show_settings (const struct options *o)
|
|||
SHOW_INT (remote_cert_ku[i]);
|
||||
}
|
||||
SHOW_STR (remote_cert_eku);
|
||||
SHOW_INT (ssl_flags);
|
||||
|
||||
SHOW_INT (tls_timeout);
|
||||
|
||||
|
|
@ -2548,6 +2608,13 @@ pre_pull_save (struct options *o)
|
|||
o->pre_pull->routes = clone_route_option_list(o->routes, &o->gc);
|
||||
o->pre_pull->routes_defined = true;
|
||||
}
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
if (o->client_nat)
|
||||
{
|
||||
o->pre_pull->client_nat = clone_client_nat_option_list(o->client_nat, &o->gc);
|
||||
o->pre_pull->client_nat_defined = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2569,6 +2636,16 @@ pre_pull_restore (struct options *o)
|
|||
else
|
||||
o->routes = NULL;
|
||||
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
if (pp->client_nat_defined)
|
||||
{
|
||||
cnol_check_alloc (o);
|
||||
copy_client_nat_option_list (o->client_nat, pp->client_nat);
|
||||
}
|
||||
else
|
||||
o->client_nat = NULL;
|
||||
#endif
|
||||
|
||||
o->foreign_option_index = pp->foreign_option_index;
|
||||
}
|
||||
|
||||
|
|
@ -3865,6 +3942,11 @@ add_option (struct options *options,
|
|||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
options->management_flags |= MF_FORGET_DISCONNECT;
|
||||
}
|
||||
else if (streq (p[0], "management-up-down"))
|
||||
{
|
||||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
options->management_flags |= MF_UP_DOWN;
|
||||
}
|
||||
else if (streq (p[0], "management-client"))
|
||||
{
|
||||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
|
|
@ -3886,6 +3968,13 @@ add_option (struct options *options,
|
|||
options->management_flags |= MF_CLIENT_AUTH;
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_X509_TRACK
|
||||
else if (streq (p[0], "x509-track") && p[1])
|
||||
{
|
||||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
x509_track_add (&options->x509_track, p[1], msglevel, &options->gc);
|
||||
}
|
||||
#endif
|
||||
#ifdef MANAGEMENT_PF
|
||||
else if (streq (p[0], "management-client-pf"))
|
||||
{
|
||||
|
|
@ -4792,6 +4881,14 @@ add_option (struct options *options,
|
|||
VERIFY_PERMISSION (OPT_P_PERSIST_IP);
|
||||
options->persist_remote_ip = true;
|
||||
}
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
else if (streq (p[0], "client-nat") && p[1] && p[2] && p[3] && p[4])
|
||||
{
|
||||
VERIFY_PERMISSION (OPT_P_ROUTE);
|
||||
cnol_check_alloc (options);
|
||||
add_client_nat_to_option_list(options->client_nat, p[1], p[2], p[3], p[4], msglevel);
|
||||
}
|
||||
#endif
|
||||
else if (streq (p[0], "route") && p[1])
|
||||
{
|
||||
VERIFY_PERMISSION (OPT_P_ROUTE);
|
||||
|
|
@ -4958,6 +5055,12 @@ add_option (struct options *options,
|
|||
msg (msglevel, "this is a generic configuration and cannot directly be used");
|
||||
goto err;
|
||||
}
|
||||
#ifdef ENABLE_PUSH_PEER_INFO
|
||||
else if (streq (p[1], "PUSH_PEER_INFO"))
|
||||
{
|
||||
options->push_peer_info = true;
|
||||
}
|
||||
#endif
|
||||
#if P2MP
|
||||
else if (streq (p[1], "SERVER_POLL_TIMEOUT") && p[2])
|
||||
{
|
||||
|
|
@ -5352,6 +5455,7 @@ add_option (struct options *options,
|
|||
|
||||
options->port_share_host = p[1];
|
||||
options->port_share_port = port;
|
||||
options->port_share_journal_dir = p[3];
|
||||
}
|
||||
#endif
|
||||
else if (streq (p[0], "client-to-client"))
|
||||
|
|
@ -5392,6 +5496,10 @@ add_option (struct options *options,
|
|||
options->push_ifconfig_defined = true;
|
||||
options->push_ifconfig_local = local;
|
||||
options->push_ifconfig_remote_netmask = remote_netmask;
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
if (p[3])
|
||||
options->push_ifconfig_local_alias = getaddr (GETADDR_HOST_ORDER|GETADDR_RESOLVE, p[3], 0, NULL, NULL);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -6051,6 +6159,22 @@ add_option (struct options *options,
|
|||
}
|
||||
#endif
|
||||
}
|
||||
else if (streq (p[0], "extra-certs") && p[1])
|
||||
{
|
||||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
options->extra_certs_file = p[1];
|
||||
#if ENABLE_INLINE_FILES
|
||||
if (streq (p[1], INLINE_FILE_TAG) && p[2])
|
||||
{
|
||||
options->extra_certs_file_inline = p[2];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (streq (p[0], "verify-hash") && p[1])
|
||||
{
|
||||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
options->verify_hash = parse_hash_fingerprint(p[1], SHA_DIGEST_LENGTH, msglevel, &options->gc);
|
||||
}
|
||||
#ifdef WIN32
|
||||
else if (streq (p[0], "cryptoapicert") && p[1])
|
||||
{
|
||||
|
|
@ -6095,6 +6219,15 @@ add_option (struct options *options,
|
|||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
ssl_set_auth_nocache ();
|
||||
}
|
||||
else if (streq (p[0], "auth-token") && p[1])
|
||||
{
|
||||
VERIFY_PERMISSION (OPT_P_ECHO);
|
||||
ssl_set_auth_token(p[1]);
|
||||
#ifdef ENABLE_MANAGEMENT
|
||||
if (management)
|
||||
management_auth_token (management, p[1]);
|
||||
#endif
|
||||
}
|
||||
else if (streq (p[0], "single-session"))
|
||||
{
|
||||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
|
|
@ -6120,6 +6253,8 @@ add_option (struct options *options,
|
|||
else if (streq (p[0], "crl-verify") && p[1])
|
||||
{
|
||||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
if (p[2] && streq(p[2], "dir"))
|
||||
options->ssl_flags |= SSLF_CRL_VERIFY_DIR;
|
||||
options->crl_file = p[1];
|
||||
}
|
||||
else if (streq (p[0], "tls-verify") && p[1])
|
||||
|
|
|
|||
23
options.h
23
options.h
|
|
@ -41,6 +41,7 @@
|
|||
#include "proxy.h"
|
||||
#include "lzo.h"
|
||||
#include "pushlist.h"
|
||||
#include "clinat.h"
|
||||
|
||||
/*
|
||||
* Maximum number of parameters associated with an option,
|
||||
|
|
@ -67,6 +68,11 @@ struct options_pre_pull
|
|||
bool routes_defined;
|
||||
struct route_option_list *routes;
|
||||
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
bool client_nat_defined;
|
||||
struct client_nat_option_list *client_nat;
|
||||
#endif
|
||||
|
||||
int foreign_option_index;
|
||||
};
|
||||
|
||||
|
|
@ -334,6 +340,10 @@ struct options
|
|||
bool route_gateway_via_dhcp;
|
||||
bool allow_pull_fqdn; /* as a client, allow server to push a FQDN for certain parameters */
|
||||
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
struct client_nat_option_list *client_nat;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_OCC
|
||||
/* Enable options consistency check between peers */
|
||||
bool occ;
|
||||
|
|
@ -410,6 +420,9 @@ struct options
|
|||
bool push_ifconfig_defined;
|
||||
in_addr_t push_ifconfig_local;
|
||||
in_addr_t push_ifconfig_remote_netmask;
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
in_addr_t push_ifconfig_local_alias;
|
||||
#endif
|
||||
bool push_ifconfig_constraint_defined;
|
||||
in_addr_t push_ifconfig_constraint_network;
|
||||
in_addr_t push_ifconfig_constraint_netmask;
|
||||
|
|
@ -426,10 +439,10 @@ struct options
|
|||
|
||||
const char *auth_user_pass_verify_script;
|
||||
bool auth_user_pass_verify_script_via_file;
|
||||
unsigned int ssl_flags; /* set to SSLF_x flags from ssl.h */
|
||||
#if PORT_SHARE
|
||||
char *port_share_host;
|
||||
int port_share_port;
|
||||
const char *port_share_journal_dir;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
@ -476,6 +489,7 @@ struct options
|
|||
const char *ca_path;
|
||||
const char *dh_file;
|
||||
const char *cert_file;
|
||||
const char *extra_certs_file;
|
||||
const char *priv_key_file;
|
||||
const char *pkcs12_file;
|
||||
const char *cipher_list;
|
||||
|
|
@ -487,6 +501,7 @@ struct options
|
|||
#if ENABLE_INLINE_FILES
|
||||
const char *ca_file_inline;
|
||||
const char *cert_file_inline;
|
||||
const char *extra_certs_file_inline;
|
||||
char *priv_key_file_inline;
|
||||
const char *dh_file_inline;
|
||||
const char *pkcs12_file_inline; /* contains the base64 encoding of pkcs12 file */
|
||||
|
|
@ -495,6 +510,8 @@ struct options
|
|||
int ns_cert_type; /* set to 0, NS_SSL_SERVER, or NS_SSL_CLIENT */
|
||||
unsigned remote_cert_ku[MAX_PARMS];
|
||||
const char *remote_cert_eku;
|
||||
uint8_t *verify_hash;
|
||||
unsigned int ssl_flags; /* set to SSLF_x flags from ssl.h */
|
||||
|
||||
#ifdef ENABLE_PKCS11
|
||||
const char *pkcs11_providers[MAX_PARMS];
|
||||
|
|
@ -551,6 +568,10 @@ struct options
|
|||
#endif /* USE_SSL */
|
||||
#endif /* USE_CRYPTO */
|
||||
|
||||
#ifdef ENABLE_X509_TRACK
|
||||
const struct x509_track *x509_track;
|
||||
#endif
|
||||
|
||||
/* special state parms */
|
||||
int foreign_option_index;
|
||||
|
||||
|
|
|
|||
152
packet_id.c
152
packet_id.c
|
|
@ -41,6 +41,8 @@
|
|||
|
||||
#include "memdbg.h"
|
||||
|
||||
/* #define PID_SIMULATE_BACKTRACK */
|
||||
|
||||
/*
|
||||
* Special time_t value that indicates that
|
||||
* sequence number has expired.
|
||||
|
|
@ -48,17 +50,39 @@
|
|||
#define SEQ_UNSEEN ((time_t)0)
|
||||
#define SEQ_EXPIRED ((time_t)1)
|
||||
|
||||
void
|
||||
packet_id_init (struct packet_id *p, int seq_backtrack, int time_backtrack)
|
||||
static void packet_id_debug_print (int msglevel,
|
||||
const struct packet_id_rec *p,
|
||||
const struct packet_id_net *pin,
|
||||
const char *message,
|
||||
int value);
|
||||
|
||||
static inline void
|
||||
packet_id_debug (int msglevel,
|
||||
const struct packet_id_rec *p,
|
||||
const struct packet_id_net *pin,
|
||||
const char *message,
|
||||
int value)
|
||||
{
|
||||
dmsg (D_PID_DEBUG_LOW, "PID packet_id_init seq_backtrack=%d time_backtrack=%d",
|
||||
seq_backtrack,
|
||||
time_backtrack);
|
||||
#ifdef ENABLE_DEBUG
|
||||
if (unlikely(check_debug_level(msglevel)))
|
||||
packet_id_debug_print (msglevel, p, pin, message, value);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
packet_id_init (struct packet_id *p, bool tcp_mode, int seq_backtrack, int time_backtrack, const char *name, int unit)
|
||||
{
|
||||
dmsg (D_PID_DEBUG, "PID packet_id_init tcp_mode=%d seq_backtrack=%d time_backtrack=%d",
|
||||
tcp_mode,
|
||||
seq_backtrack,
|
||||
time_backtrack);
|
||||
|
||||
ASSERT (p);
|
||||
CLEAR (*p);
|
||||
|
||||
if (seq_backtrack)
|
||||
p->rec.name = name;
|
||||
p->rec.unit = unit;
|
||||
if (seq_backtrack && !tcp_mode)
|
||||
{
|
||||
ASSERT (MIN_SEQ_BACKTRACK <= seq_backtrack && seq_backtrack <= MAX_SEQ_BACKTRACK);
|
||||
ASSERT (MIN_TIME_BACKTRACK <= time_backtrack && time_backtrack <= MAX_TIME_BACKTRACK);
|
||||
|
|
@ -74,7 +98,7 @@ packet_id_free (struct packet_id *p)
|
|||
{
|
||||
if (p)
|
||||
{
|
||||
dmsg (D_PID_DEBUG_LOW, "PID packet_id_free");
|
||||
dmsg (D_PID_DEBUG, "PID packet_id_free");
|
||||
if (p->rec.seq_list)
|
||||
free (p->rec.seq_list);
|
||||
CLEAR (*p);
|
||||
|
|
@ -105,7 +129,11 @@ packet_id_add (struct packet_id_rec *p, const struct packet_id_net *pin)
|
|||
CIRC_LIST_RESET (p->seq_list);
|
||||
}
|
||||
|
||||
while (p->id < pin->id)
|
||||
while (p->id < pin->id
|
||||
#ifdef PID_SIMULATE_BACKTRACK
|
||||
|| (get_random() % 64) < 31
|
||||
#endif
|
||||
)
|
||||
{
|
||||
CIRC_LIST_PUSH (p->seq_list, SEQ_UNSEEN);
|
||||
++p->id;
|
||||
|
|
@ -155,17 +183,13 @@ packet_id_reap (struct packet_id_rec *p)
|
|||
* it is a replay.
|
||||
*/
|
||||
bool
|
||||
packet_id_test (const struct packet_id_rec *p,
|
||||
packet_id_test (struct packet_id_rec *p,
|
||||
const struct packet_id_net *pin)
|
||||
{
|
||||
static int max_backtrack_stat;
|
||||
packet_id_type diff;
|
||||
|
||||
dmsg (D_PID_DEBUG,
|
||||
"PID TEST " time_format ":" packet_id_format " " time_format ":" packet_id_format "",
|
||||
(time_type)p->time, (packet_id_print_type)p->id, (time_type)pin->time,
|
||||
(packet_id_print_type)pin->id);
|
||||
|
||||
packet_id_debug (D_PID_DEBUG, p, pin, "PID_TEST", 0);
|
||||
|
||||
ASSERT (p->initialized);
|
||||
|
||||
if (!pin->id)
|
||||
|
|
@ -189,19 +213,35 @@ packet_id_test (const struct packet_id_rec *p,
|
|||
diff = p->id - pin->id;
|
||||
|
||||
/* keep track of maximum backtrack seen for debugging purposes */
|
||||
if ((int)diff > max_backtrack_stat)
|
||||
if ((int)diff > p->max_backtrack_stat)
|
||||
{
|
||||
max_backtrack_stat = (int)diff;
|
||||
msg (D_BACKTRACK, "Replay-window backtrack occurred [%d]", max_backtrack_stat);
|
||||
p->max_backtrack_stat = (int)diff;
|
||||
packet_id_debug (D_PID_DEBUG_LOW, p, pin, "PID_ERR replay-window backtrack occurred", p->max_backtrack_stat);
|
||||
}
|
||||
|
||||
if (diff >= (packet_id_type) CIRC_LIST_SIZE (p->seq_list))
|
||||
return false;
|
||||
{
|
||||
packet_id_debug (D_PID_DEBUG_LOW, p, pin, "PID_ERR large diff", diff);
|
||||
return false;
|
||||
}
|
||||
|
||||
return CIRC_LIST_ITEM (p->seq_list, diff) == 0;
|
||||
{
|
||||
const time_t v = CIRC_LIST_ITEM (p->seq_list, diff);
|
||||
if (v == 0)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
/* might want to increase this to D_PID_DEBUG_MEDIUM (or even D_PID_DEBUG) in the future */
|
||||
packet_id_debug (D_PID_DEBUG_LOW, p, pin, "PID_ERR replay", diff);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pin->time < p->time) /* if time goes back, reject */
|
||||
return false;
|
||||
{
|
||||
packet_id_debug (D_PID_DEBUG_LOW, p, pin, "PID_ERR time backtrack", 0);
|
||||
return false;
|
||||
}
|
||||
else /* time moved forward */
|
||||
return true;
|
||||
}
|
||||
|
|
@ -434,6 +474,76 @@ packet_id_persist_print (const struct packet_id_persist *p, struct gc_arena *gc)
|
|||
return (char *)out.data;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_DEBUG
|
||||
|
||||
static void
|
||||
packet_id_debug_print (int msglevel,
|
||||
const struct packet_id_rec *p,
|
||||
const struct packet_id_net *pin,
|
||||
const char *message,
|
||||
int value)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
struct buffer out = alloc_buf_gc (256, &gc);
|
||||
struct timeval tv;
|
||||
const time_t prev_now = now;
|
||||
const struct seq_list *sl = p->seq_list;
|
||||
int i;
|
||||
|
||||
CLEAR (tv);
|
||||
gettimeofday (&tv, NULL);
|
||||
|
||||
buf_printf (&out, "%s [%d]", message, value);
|
||||
buf_printf (&out, " [%s-%d] [", p->name, p->unit);
|
||||
for (i = 0; i < sl->x_size; ++i)
|
||||
{
|
||||
char c;
|
||||
time_t v;
|
||||
int diff;
|
||||
|
||||
v = CIRC_LIST_ITEM(sl, i);
|
||||
if (v == SEQ_UNSEEN)
|
||||
c = '_';
|
||||
else if (v == SEQ_EXPIRED)
|
||||
c = 'E';
|
||||
else
|
||||
{
|
||||
diff = (int) prev_now - v;
|
||||
if (diff < 0)
|
||||
c = 'N';
|
||||
else if (diff < 10)
|
||||
c = '0' + diff;
|
||||
else
|
||||
c = '>';
|
||||
}
|
||||
buf_printf(&out, "%c", c);
|
||||
}
|
||||
buf_printf (&out, "] " time_format ":" packet_id_format, (time_type)p->time, (packet_id_print_type)p->id);
|
||||
if (pin)
|
||||
buf_printf (&out, " " time_format ":" packet_id_format, (time_type)pin->time, (packet_id_print_type)pin->id);
|
||||
|
||||
buf_printf (&out, " t=" time_format "[%d]",
|
||||
(time_type)prev_now,
|
||||
(int)(prev_now - tv.tv_sec));
|
||||
|
||||
buf_printf (&out, " r=[%d,%d,%d,%d,%d]",
|
||||
(int)(p->last_reap - tv.tv_sec),
|
||||
p->seq_backtrack,
|
||||
p->time_backtrack,
|
||||
p->max_backtrack_stat,
|
||||
(int)p->initialized);
|
||||
buf_printf (&out, " sl=[%d,%d,%d,%d]",
|
||||
sl->x_head,
|
||||
sl->x_size,
|
||||
sl->x_cap,
|
||||
sl->x_sizeof);
|
||||
|
||||
msg (msglevel, "%s", BSTR(&out));
|
||||
gc_free (&gc);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef PID_TEST
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -138,8 +138,11 @@ struct packet_id_rec
|
|||
packet_id_type id; /* highest sequence number received */
|
||||
int seq_backtrack; /* set from --replay-window */
|
||||
int time_backtrack; /* set from --replay-window */
|
||||
int max_backtrack_stat; /* maximum backtrack seen so far */
|
||||
bool initialized; /* true if packet_id_init was called */
|
||||
struct seq_list *seq_list; /* packet-id "memory" */
|
||||
const char *name;
|
||||
int unit;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -207,11 +210,11 @@ struct packet_id
|
|||
struct packet_id_rec rec;
|
||||
};
|
||||
|
||||
void packet_id_init (struct packet_id *p, int seq_backtrack, int time_backtrack);
|
||||
void packet_id_init (struct packet_id *p, bool tcp_mode, int seq_backtrack, int time_backtrack, const char *name, int unit);
|
||||
void packet_id_free (struct packet_id *p);
|
||||
|
||||
/* should we accept an incoming packet id ? */
|
||||
bool packet_id_test (const struct packet_id_rec *p,
|
||||
bool packet_id_test (struct packet_id_rec *p,
|
||||
const struct packet_id_net *pin);
|
||||
|
||||
/* change our current state to reflect an accepted packet id */
|
||||
|
|
|
|||
37
proto.h
37
proto.h
|
|
@ -164,6 +164,14 @@ struct openvpn_tcphdr {
|
|||
#define OPENVPN_TCPOPT_MAXSEG 2
|
||||
#define OPENVPN_TCPOLEN_MAXSEG 4
|
||||
|
||||
struct ip_tcp_udp_hdr {
|
||||
struct openvpn_iphdr ip;
|
||||
union {
|
||||
struct openvpn_tcphdr tcp;
|
||||
struct openvpn_udphdr udp;
|
||||
} u;
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
/*
|
||||
|
|
@ -175,19 +183,30 @@ struct openvpn_tcphdr {
|
|||
* is the checksum value to be updated.
|
||||
*/
|
||||
#define ADJUST_CHECKSUM(acc, cksum) { \
|
||||
(acc) += (cksum); \
|
||||
if ((acc) < 0) { \
|
||||
(acc) = -(acc); \
|
||||
(acc) = ((acc) >> 16) + ((acc) & 0xffff); \
|
||||
(acc) += (acc) >> 16; \
|
||||
(cksum) = (uint16_t) ~(acc); \
|
||||
int _acc = acc; \
|
||||
_acc += (cksum); \
|
||||
if (_acc < 0) { \
|
||||
_acc = -_acc; \
|
||||
_acc = (_acc >> 16) + (_acc & 0xffff); \
|
||||
_acc += _acc >> 16; \
|
||||
(cksum) = (uint16_t) ~_acc; \
|
||||
} else { \
|
||||
(acc) = ((acc) >> 16) + ((acc) & 0xffff); \
|
||||
(acc) += (acc) >> 16; \
|
||||
(cksum) = (uint16_t) (acc); \
|
||||
_acc = (_acc >> 16) + (_acc & 0xffff); \
|
||||
_acc += _acc >> 16; \
|
||||
(cksum) = (uint16_t) _acc; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ADD_CHECKSUM_32(acc, u32) { \
|
||||
acc += (u32) & 0xffff; \
|
||||
acc += (u32) >> 16; \
|
||||
}
|
||||
|
||||
#define SUB_CHECKSUM_32(acc, u32) { \
|
||||
acc -= (u32) & 0xffff; \
|
||||
acc -= (u32) >> 16; \
|
||||
}
|
||||
|
||||
/*
|
||||
* We are in a "liberal" position with respect to MSS,
|
||||
* i.e. we assume that MSS can be calculated from MTU
|
||||
|
|
|
|||
116
ps.c
116
ps.c
|
|
@ -69,6 +69,7 @@ struct proxy_connection {
|
|||
bool buffer_initial;
|
||||
int rwflags;
|
||||
int sd;
|
||||
char *jfn;
|
||||
};
|
||||
|
||||
#if 0
|
||||
|
|
@ -226,7 +227,9 @@ port_share_sendmsg (const socket_descriptor_t sd,
|
|||
|
||||
status = sendmsg (sd, &mesg, MSG_NOSIGNAL);
|
||||
if (status == -1)
|
||||
msg (M_WARN, "PORT SHARE: sendmsg failed (unable to communicate with background process)");
|
||||
msg (M_WARN|M_ERRNO_SOCK, "PORT SHARE: sendmsg failed -- unable to communicate with background process (%d,%d,%d,%d)",
|
||||
sd, sd_send, sd_null[0], sd_null[1]
|
||||
);
|
||||
|
||||
close_socket_if_defined (sd_null[0]);
|
||||
close_socket_if_defined (sd_null[1]);
|
||||
|
|
@ -261,6 +264,12 @@ proxy_entry_mark_for_close (struct proxy_connection *pc, struct event_set *es)
|
|||
pc->buffer_initial = false;
|
||||
pc->rwflags = 0;
|
||||
pc->defined = false;
|
||||
if (pc->jfn)
|
||||
{
|
||||
unlink (pc->jfn);
|
||||
free (pc->jfn);
|
||||
pc->jfn = NULL;
|
||||
}
|
||||
if (cp && cp->defined && cp->counterpart == pc)
|
||||
proxy_entry_mark_for_close (cp, es);
|
||||
}
|
||||
|
|
@ -296,6 +305,48 @@ proxy_list_housekeeping (struct proxy_connection **list)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Record IP/port of client in filesystem, so that server receiving
|
||||
* the proxy can determine true client origin.
|
||||
*/
|
||||
static void
|
||||
journal_add (const char *journal_dir, struct proxy_connection *pc, struct proxy_connection *cp)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
struct openvpn_sockaddr from, to;
|
||||
socklen_t slen, dlen;
|
||||
int fnlen;
|
||||
char *jfn;
|
||||
int fd;
|
||||
|
||||
slen = sizeof(from.sa);
|
||||
dlen = sizeof(to.sa);
|
||||
if (!getpeername (pc->sd, (struct sockaddr *) &from.sa, &slen)
|
||||
&& !getsockname (cp->sd, (struct sockaddr *) &to.sa, &dlen))
|
||||
{
|
||||
const char *f = print_sockaddr_ex (&from, ":", PS_SHOW_PORT, &gc);
|
||||
const char *t = print_sockaddr_ex (&to, ":", PS_SHOW_PORT, &gc);
|
||||
fnlen = strlen(journal_dir) + strlen(t) + 2;
|
||||
jfn = (char *) malloc(fnlen);
|
||||
check_malloc_return (jfn);
|
||||
openvpn_snprintf (jfn, fnlen, "%s/%s", journal_dir, t);
|
||||
dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: client origin %s -> %s", jfn, f);
|
||||
fd = open (jfn, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (fd != -1)
|
||||
{
|
||||
write(fd, f, strlen(f));
|
||||
close (fd);
|
||||
cp->jfn = jfn;
|
||||
}
|
||||
else
|
||||
{
|
||||
msg (M_WARN|M_ERRNO, "PORT SHARE: unable to write journal file in %s", jfn);
|
||||
free (jfn);
|
||||
}
|
||||
}
|
||||
gc_free (&gc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cleanup function, on proxy process exit.
|
||||
*/
|
||||
|
|
@ -349,7 +400,8 @@ proxy_entry_new (struct proxy_connection **list,
|
|||
const in_addr_t server_addr,
|
||||
const int server_port,
|
||||
const socket_descriptor_t sd_client,
|
||||
struct buffer *initial_data)
|
||||
struct buffer *initial_data,
|
||||
const char *journal_dir)
|
||||
{
|
||||
struct openvpn_sockaddr osaddr;
|
||||
socket_descriptor_t sd_server;
|
||||
|
|
@ -359,7 +411,11 @@ proxy_entry_new (struct proxy_connection **list,
|
|||
|
||||
/* connect to port share server */
|
||||
sock_addr_set (&osaddr, server_addr, server_port);
|
||||
sd_server = create_socket_tcp ();
|
||||
if ((sd_server = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
|
||||
{
|
||||
msg (M_WARN|M_ERRNO_SOCK, "PORT SHARE PROXY: cannot create socket");
|
||||
return false;
|
||||
}
|
||||
status = openvpn_connect (sd_server, &osaddr, 5, NULL);
|
||||
if (status)
|
||||
{
|
||||
|
|
@ -396,6 +452,10 @@ proxy_entry_new (struct proxy_connection **list,
|
|||
|
||||
/* add to list */
|
||||
*list = pc;
|
||||
|
||||
/* add journal entry */
|
||||
if (journal_dir)
|
||||
journal_add (journal_dir, pc, cp);
|
||||
|
||||
dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: NEW CONNECTION [c=%d s=%d]", (int)sd_client, (int)sd_server);
|
||||
|
||||
|
|
@ -417,9 +477,14 @@ control_message_from_parent (const socket_descriptor_t sd_control,
|
|||
struct proxy_connection **list,
|
||||
struct event_set *es,
|
||||
const in_addr_t server_addr,
|
||||
const int server_port)
|
||||
const int server_port,
|
||||
const int max_initial_buf,
|
||||
const char *journal_dir)
|
||||
{
|
||||
struct buffer buf = alloc_buf (PROXY_CONNECTION_BUFFER_SIZE);
|
||||
/* this buffer needs to be large enough to handle the largest buffer
|
||||
that might be returned by the link_socket_read call in read_incoming_link. */
|
||||
struct buffer buf = alloc_buf (max_initial_buf);
|
||||
|
||||
struct msghdr mesg;
|
||||
struct cmsghdr* h;
|
||||
struct iovec iov[2];
|
||||
|
|
@ -455,7 +520,7 @@ control_message_from_parent (const socket_descriptor_t sd_control,
|
|||
|| h->cmsg_level != SOL_SOCKET
|
||||
|| h->cmsg_type != SCM_RIGHTS )
|
||||
{
|
||||
ret = false;
|
||||
msg (M_WARN, "PORT SHARE PROXY: received unknown message");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -470,7 +535,8 @@ control_message_from_parent (const socket_descriptor_t sd_control,
|
|||
server_addr,
|
||||
server_port,
|
||||
received_fd,
|
||||
&buf))
|
||||
&buf,
|
||||
journal_dir))
|
||||
{
|
||||
CLEAR (buf); /* we gave the buffer to proxy_entry_new */
|
||||
}
|
||||
|
|
@ -505,6 +571,7 @@ proxy_connection_io_recv (struct proxy_connection *pc)
|
|||
{
|
||||
if (!status)
|
||||
return IOSTAT_READ_ERROR;
|
||||
dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: read[%d] %d", (int)pc->sd, status);
|
||||
pc->buf.len = status;
|
||||
}
|
||||
return IOSTAT_GOOD;
|
||||
|
|
@ -532,7 +599,7 @@ proxy_connection_io_send (struct proxy_connection *pc, int *bytes_sent)
|
|||
}
|
||||
else
|
||||
{
|
||||
/*dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: wrote[%d] %d", (int)sd, status);*/
|
||||
dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: wrote[%d] %d", (int)sd, status);
|
||||
pc->buf.len = 0;
|
||||
pc->buf.offset = 0;
|
||||
}
|
||||
|
|
@ -615,6 +682,8 @@ proxy_connection_io_dispatch (struct proxy_connection *pc,
|
|||
int rwflags_pc = pc->rwflags;
|
||||
int rwflags_cp = cp->rwflags;
|
||||
|
||||
ASSERT(pc->defined && cp->defined && cp->counterpart == pc);
|
||||
|
||||
if (rwflags & EVENT_READ)
|
||||
{
|
||||
const int status = proxy_connection_io_xfer (pc, max_transfer_per_iteration);
|
||||
|
|
@ -641,7 +710,11 @@ proxy_connection_io_dispatch (struct proxy_connection *pc,
|
|||
* This is the main function for the port share proxy background process.
|
||||
*/
|
||||
static void
|
||||
port_share_proxy (const in_addr_t hostaddr, const int port, const socket_descriptor_t sd_control)
|
||||
port_share_proxy (const in_addr_t hostaddr,
|
||||
const int port,
|
||||
const socket_descriptor_t sd_control,
|
||||
const int max_initial_buf,
|
||||
const char *journal_dir)
|
||||
{
|
||||
if (send_control (sd_control, RESPONSE_INIT_SUCCEEDED) >= 0)
|
||||
{
|
||||
|
|
@ -675,7 +748,7 @@ port_share_proxy (const in_addr_t hostaddr, const int port, const socket_descrip
|
|||
const struct event_set_return *e = &esr[i];
|
||||
if (e->arg == sd_control_marker)
|
||||
{
|
||||
if (!control_message_from_parent (sd_control, &list, es, hostaddr, port))
|
||||
if (!control_message_from_parent (sd_control, &list, es, hostaddr, port, max_initial_buf, journal_dir))
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
|
|
@ -701,7 +774,7 @@ port_share_proxy (const in_addr_t hostaddr, const int port, const socket_descrip
|
|||
proxy_list_close (&list);
|
||||
event_free (es);
|
||||
}
|
||||
msg (D_PS_PROXY, "PORT SHARE PROXY: proxy exiting");
|
||||
msg (M_INFO, "PORT SHARE PROXY: proxy exiting");
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -709,7 +782,10 @@ port_share_proxy (const in_addr_t hostaddr, const int port, const socket_descrip
|
|||
* share proxy.
|
||||
*/
|
||||
struct port_share *
|
||||
port_share_open (const char *host, const int port)
|
||||
port_share_open (const char *host,
|
||||
const int port,
|
||||
const int max_initial_buf,
|
||||
const char *journal_dir)
|
||||
{
|
||||
pid_t pid;
|
||||
socket_descriptor_t fd[2];
|
||||
|
|
@ -717,6 +793,8 @@ port_share_open (const char *host, const int port)
|
|||
struct port_share *ps;
|
||||
|
||||
ALLOC_OBJ_CLEAR (ps, struct port_share);
|
||||
ps->foreground_fd = -1;
|
||||
ps->background_pid = -1;
|
||||
|
||||
/*
|
||||
* Get host's IP address
|
||||
|
|
@ -758,9 +836,17 @@ port_share_open (const char *host, const int port)
|
|||
status = recv_control (fd[0]);
|
||||
if (status == RESPONSE_INIT_SUCCEEDED)
|
||||
{
|
||||
/* note that this will cause possible EAGAIN when writing to
|
||||
control socket if proxy process is backlogged */
|
||||
set_nonblock (fd[0]);
|
||||
|
||||
ps->foreground_fd = fd[0];
|
||||
return ps;
|
||||
}
|
||||
else
|
||||
{
|
||||
msg (M_SOCKERR, "PORT SHARE: unexpected init recv_control status=%d", status);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -787,7 +873,7 @@ port_share_open (const char *host, const int port)
|
|||
prng_init (NULL, 0);
|
||||
|
||||
/* execute the event loop */
|
||||
port_share_proxy (hostaddr, port, fd[1]);
|
||||
port_share_proxy (hostaddr, port, fd[1], max_initial_buf, journal_dir);
|
||||
|
||||
openvpn_close_socket (fd[1]);
|
||||
|
||||
|
|
@ -872,7 +958,9 @@ void
|
|||
port_share_redirect (struct port_share *ps, const struct buffer *head, socket_descriptor_t sd)
|
||||
{
|
||||
if (ps)
|
||||
port_share_sendmsg (ps->foreground_fd, COMMAND_REDIRECT, head, sd);
|
||||
{
|
||||
port_share_sendmsg (ps->foreground_fd, COMMAND_REDIRECT, head, sd);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
4
ps.h
4
ps.h
|
|
@ -44,7 +44,9 @@ struct port_share {
|
|||
extern struct port_share *port_share;
|
||||
|
||||
struct port_share *port_share_open (const char *host,
|
||||
const int port);
|
||||
const int port,
|
||||
const int max_initial_buf,
|
||||
const char *journal_dir);
|
||||
|
||||
void port_share_close (struct port_share *ps);
|
||||
void port_share_abort (struct port_share *ps);
|
||||
|
|
|
|||
97
push.c
97
push.c
|
|
@ -42,7 +42,7 @@
|
|||
void
|
||||
receive_auth_failed (struct context *c, const struct buffer *buffer)
|
||||
{
|
||||
msg (M_VERB0, "AUTH: Received AUTH_FAILED control message");
|
||||
msg (M_VERB0, "AUTH: Received control message: %s", BSTR(buffer));
|
||||
connection_list_set_no_advance(&c->options);
|
||||
if (c->options.pull)
|
||||
{
|
||||
|
|
@ -52,7 +52,7 @@ receive_auth_failed (struct context *c, const struct buffer *buffer)
|
|||
c->sig->signal_received = SIGTERM; /* SOFT-SIGTERM -- Auth failure error */
|
||||
break;
|
||||
case AR_INTERACT:
|
||||
ssl_purge_auth ();
|
||||
ssl_purge_auth (false);
|
||||
case AR_NOINTERACT:
|
||||
c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- Auth failure error */
|
||||
break;
|
||||
|
|
@ -87,13 +87,48 @@ receive_auth_failed (struct context *c, const struct buffer *buffer)
|
|||
* Act on received restart message from server
|
||||
*/
|
||||
void
|
||||
server_pushed_restart (struct context *c, const struct buffer *buffer)
|
||||
server_pushed_signal (struct context *c, const struct buffer *buffer, const bool restart, const int adv)
|
||||
{
|
||||
if (c->options.pull)
|
||||
{
|
||||
msg (D_STREAM_ERRORS, "Connection reset command was pushed by server");
|
||||
c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- server-pushed connection reset */
|
||||
c->sig->signal_text = "server-pushed-connection-reset";
|
||||
struct buffer buf = *buffer;
|
||||
const char *m = "";
|
||||
if (buf_advance (&buf, adv) && buf_read_u8 (&buf) == ',' && BLEN (&buf))
|
||||
m = BSTR (&buf);
|
||||
|
||||
/* preserve cached passwords? */
|
||||
{
|
||||
bool purge = true;
|
||||
|
||||
if (m[0] == '[')
|
||||
{
|
||||
int i;
|
||||
for (i = 1; m[i] != '\0' && m[i] != ']'; ++i)
|
||||
{
|
||||
if (m[i] == 'P')
|
||||
purge = false;
|
||||
}
|
||||
}
|
||||
if (purge)
|
||||
ssl_purge_auth (true);
|
||||
}
|
||||
|
||||
if (restart)
|
||||
{
|
||||
msg (D_STREAM_ERRORS, "Connection reset command was pushed by server ('%s')", m);
|
||||
c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- server-pushed connection reset */
|
||||
c->sig->signal_text = "server-pushed-connection-reset";
|
||||
}
|
||||
else
|
||||
{
|
||||
msg (D_STREAM_ERRORS, "Halt command was pushed by server ('%s')", m);
|
||||
c->sig->signal_received = SIGTERM; /* SOFT-SIGTERM -- server-pushed halt */
|
||||
c->sig->signal_text = "server-pushed-halt";
|
||||
}
|
||||
#ifdef ENABLE_MANAGEMENT
|
||||
if (management)
|
||||
management_notify (management, "info", c->sig->signal_text, m);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -130,10 +165,10 @@ send_auth_failed (struct context *c, const char *client_reason)
|
|||
* Send restart message from server to client.
|
||||
*/
|
||||
void
|
||||
send_restart (struct context *c)
|
||||
send_restart (struct context *c, const char *kill_msg)
|
||||
{
|
||||
schedule_exit (c, c->options.scheduled_exit_interval, SIGTERM);
|
||||
send_control_channel_string (c, "RESTART", D_PUSH);
|
||||
send_control_channel_string (c, kill_msg ? kill_msg : "RESTART", D_PUSH);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -149,7 +184,7 @@ incoming_push_message (struct context *c, const struct buffer *buffer)
|
|||
unsigned int option_types_found = 0;
|
||||
int status;
|
||||
|
||||
msg (D_PUSH, "PUSH: Received control message: '%s'", BSTR (buffer));
|
||||
msg (D_PUSH, "PUSH: Received control message: '%s'", sanitize_control_message(BSTR(buffer), &gc));
|
||||
|
||||
status = process_incoming_push_msg (c,
|
||||
buffer,
|
||||
|
|
@ -158,7 +193,7 @@ incoming_push_message (struct context *c, const struct buffer *buffer)
|
|||
&option_types_found);
|
||||
|
||||
if (status == PUSH_MSG_ERROR)
|
||||
msg (D_PUSH_ERRORS, "WARNING: Received bad push/pull message: %s", BSTR (buffer));
|
||||
msg (D_PUSH_ERRORS, "WARNING: Received bad push/pull message: %s", sanitize_control_message(BSTR(buffer), &gc));
|
||||
else if (status == PUSH_MSG_REPLY || status == PUSH_MSG_CONTINUATION)
|
||||
{
|
||||
if (status == PUSH_MSG_REPLY)
|
||||
|
|
@ -172,7 +207,18 @@ incoming_push_message (struct context *c, const struct buffer *buffer)
|
|||
bool
|
||||
send_push_request (struct context *c)
|
||||
{
|
||||
return send_control_channel_string (c, "PUSH_REQUEST", D_PUSH);
|
||||
const int max_push_requests = c->options.handshake_window / PUSH_REQUEST_INTERVAL;
|
||||
if (++c->c2.n_sent_push_requests <= max_push_requests)
|
||||
{
|
||||
return send_control_channel_string (c, "PUSH_REQUEST", D_PUSH);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg (D_STREAM_ERRORS, "No reply from server after sending %d push requests", max_push_requests);
|
||||
c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- server-pushed connection reset */
|
||||
c->sig->signal_text = "no-push-reply";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#if P2MP_SERVER
|
||||
|
|
@ -185,7 +231,7 @@ send_push_reply (struct context *c)
|
|||
struct push_entry *e = c->options.push_list.head;
|
||||
bool multi_push = false;
|
||||
static char cmd[] = "PUSH_REPLY";
|
||||
const int extra = 64; /* extra space for possible trailing ifconfig and push-continuation */
|
||||
const int extra = 84; /* extra space for possible trailing ifconfig and push-continuation */
|
||||
const int safe_cap = BCAP (&buf) - extra;
|
||||
bool push_sent = false;
|
||||
|
||||
|
|
@ -238,9 +284,16 @@ send_push_reply (struct context *c)
|
|||
}
|
||||
|
||||
if (c->c2.push_ifconfig_defined && c->c2.push_ifconfig_local && c->c2.push_ifconfig_remote_netmask)
|
||||
buf_printf (&buf, ",ifconfig %s %s",
|
||||
print_in_addr_t (c->c2.push_ifconfig_local, 0, &gc),
|
||||
print_in_addr_t (c->c2.push_ifconfig_remote_netmask, 0, &gc));
|
||||
{
|
||||
in_addr_t ifconfig_local = c->c2.push_ifconfig_local;
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
if (c->c2.push_ifconfig_local_alias)
|
||||
ifconfig_local = c->c2.push_ifconfig_local_alias;
|
||||
#endif
|
||||
buf_printf (&buf, ",ifconfig %s %s",
|
||||
print_in_addr_t (ifconfig_local, 0, &gc),
|
||||
print_in_addr_t (c->c2.push_ifconfig_remote_netmask, 0, &gc));
|
||||
}
|
||||
if (multi_push)
|
||||
buf_printf (&buf, ",push-continuation 1");
|
||||
|
||||
|
|
@ -359,8 +412,18 @@ process_incoming_push_msg (struct context *c,
|
|||
}
|
||||
else if (!c->c2.push_reply_deferred && c->c2.context_auth == CAS_SUCCEEDED)
|
||||
{
|
||||
if (send_push_reply (c))
|
||||
ret = PUSH_MSG_REQUEST;
|
||||
if (c->c2.sent_push_reply)
|
||||
{
|
||||
ret = PUSH_MSG_ALREADY_REPLIED;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (send_push_reply (c))
|
||||
{
|
||||
ret = PUSH_MSG_REQUEST;
|
||||
c->c2.sent_push_reply = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
5
push.h
5
push.h
|
|
@ -35,6 +35,7 @@
|
|||
#define PUSH_MSG_REQUEST_DEFERRED 3
|
||||
#define PUSH_MSG_AUTH_FAILURE 4
|
||||
#define PUSH_MSG_CONTINUATION 5
|
||||
#define PUSH_MSG_ALREADY_REPLIED 6
|
||||
|
||||
void incoming_push_message (struct context *c,
|
||||
const struct buffer *buffer);
|
||||
|
|
@ -49,7 +50,7 @@ bool send_push_request (struct context *c);
|
|||
|
||||
void receive_auth_failed (struct context *c, const struct buffer *buffer);
|
||||
|
||||
void server_pushed_restart (struct context *c, const struct buffer *buffer);
|
||||
void server_pushed_signal (struct context *c, const struct buffer *buffer, const bool restart, const int adv);
|
||||
|
||||
#if P2MP_SERVER
|
||||
|
||||
|
|
@ -66,7 +67,7 @@ void remove_iroutes_from_push_route_list (struct options *o);
|
|||
|
||||
void send_auth_failed (struct context *c, const char *client_reason);
|
||||
|
||||
void send_restart (struct context *c);
|
||||
void send_restart (struct context *c, const char *kill_msg);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
163
route.c
163
route.c
|
|
@ -2324,70 +2324,26 @@ get_default_gateway (in_addr_t *ret, in_addr_t *netmask)
|
|||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/route.h>
|
||||
#include <net/if_dl.h>
|
||||
|
||||
/* all of this is taken from <net/route.h> in Darwin */
|
||||
#define RTA_DST 0x1
|
||||
#define RTA_GATEWAY 0x2
|
||||
#define RTA_NETMASK 0x4
|
||||
|
||||
#define RTM_GET 0x4
|
||||
#define RTM_VERSION 5
|
||||
|
||||
#define RTF_UP 0x1
|
||||
#define RTF_GATEWAY 0x2
|
||||
|
||||
/*
|
||||
* These numbers are used by reliable protocols for determining
|
||||
* retransmission behavior and are included in the routing structure.
|
||||
*/
|
||||
struct rt_metrics {
|
||||
u_long rmx_locks; /* Kernel must leave these values alone */
|
||||
u_long rmx_mtu; /* MTU for this path */
|
||||
u_long rmx_hopcount; /* max hops expected */
|
||||
u_long rmx_expire; /* lifetime for route, e.g. redirect */
|
||||
u_long rmx_recvpipe; /* inbound delay-bandwidth product */
|
||||
u_long rmx_sendpipe; /* outbound delay-bandwidth product */
|
||||
u_long rmx_ssthresh; /* outbound gateway buffer limit */
|
||||
u_long rmx_rtt; /* estimated round trip time */
|
||||
u_long rmx_rttvar; /* estimated rtt variance */
|
||||
u_long rmx_pksent; /* packets sent using this route */
|
||||
u_long rmx_filler[4]; /* will be used for T/TCP later */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structures for routing messages.
|
||||
*/
|
||||
struct rt_msghdr {
|
||||
u_short rtm_msglen; /* to skip over non-understood messages */
|
||||
u_char rtm_version; /* future binary compatibility */
|
||||
u_char rtm_type; /* message type */
|
||||
u_short rtm_index; /* index for associated ifp */
|
||||
int rtm_flags; /* flags, incl. kern & message, e.g. DONE */
|
||||
int rtm_addrs; /* bitmask identifying sockaddrs in msg */
|
||||
pid_t rtm_pid; /* identify sender */
|
||||
int rtm_seq; /* for sender to identify action */
|
||||
int rtm_errno; /* why failed */
|
||||
int rtm_use; /* from rtentry */
|
||||
u_long rtm_inits; /* which metrics we are initializing */
|
||||
struct rt_metrics rtm_rmx; /* metrics themselves */
|
||||
};
|
||||
|
||||
struct {
|
||||
struct rtmsg {
|
||||
struct rt_msghdr m_rtm;
|
||||
char m_space[512];
|
||||
} m_rtmsg;
|
||||
};
|
||||
|
||||
#define ROUNDUP(a) \
|
||||
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
|
||||
((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
|
||||
|
||||
bool
|
||||
get_default_gateway (in_addr_t *ret, in_addr_t *netmask)
|
||||
static bool
|
||||
get_default_gateway_ex (in_addr_t *ret, in_addr_t *netmask, char **ifname)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
struct rtmsg m_rtmsg;
|
||||
int s, seq, l, pid, rtm_addrs, i;
|
||||
struct sockaddr so_dst, so_mask;
|
||||
char *cp = m_rtmsg.m_space;
|
||||
struct sockaddr *gate = NULL, *sa;
|
||||
struct sockaddr *gate = NULL, *ifp = NULL, *sa;
|
||||
struct rt_msghdr *rtm_aux;
|
||||
|
||||
#define NEXTADDR(w, u) \
|
||||
|
|
@ -2401,8 +2357,9 @@ get_default_gateway (in_addr_t *ret, in_addr_t *netmask)
|
|||
|
||||
pid = getpid();
|
||||
seq = 0;
|
||||
rtm_addrs = RTA_DST | RTA_NETMASK;
|
||||
rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP;
|
||||
|
||||
bzero(&m_rtmsg, sizeof(m_rtmsg));
|
||||
bzero(&so_dst, sizeof(so_dst));
|
||||
bzero(&so_mask, sizeof(so_mask));
|
||||
bzero(&rtm, sizeof(struct rt_msghdr));
|
||||
|
|
@ -2444,11 +2401,16 @@ get_default_gateway (in_addr_t *ret, in_addr_t *netmask)
|
|||
cp = ((char *)(rtm_aux + 1));
|
||||
if (rtm_aux->rtm_addrs) {
|
||||
for (i = 1; i; i <<= 1)
|
||||
if (i & rtm_aux->rtm_addrs) {
|
||||
sa = (struct sockaddr *)cp;
|
||||
if (i == RTA_GATEWAY )
|
||||
gate = sa;
|
||||
ADVANCE(cp, sa);
|
||||
{
|
||||
if (i & rtm_aux->rtm_addrs)
|
||||
{
|
||||
sa = (struct sockaddr *)cp;
|
||||
if (i == RTA_GATEWAY )
|
||||
gate = sa;
|
||||
else if (i == RTA_IFP)
|
||||
ifp = sa;
|
||||
ADVANCE(cp, sa);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -2471,6 +2433,16 @@ get_default_gateway (in_addr_t *ret, in_addr_t *netmask)
|
|||
*netmask = 0xFFFFFF00; // FIXME -- get the real netmask of the adapter containing the default gateway
|
||||
}
|
||||
|
||||
if (ifp && ifname)
|
||||
{
|
||||
struct sockaddr_dl *adl = (struct sockaddr_dl *) ifp;
|
||||
char *name = malloc(adl->sdl_nlen+1);
|
||||
check_malloc_return(name);
|
||||
memcpy(name, adl->sdl_data, adl->sdl_nlen);
|
||||
name[adl->sdl_nlen] = '\0';
|
||||
*ifname = name;
|
||||
}
|
||||
|
||||
gc_free (&gc);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2481,6 +2453,12 @@ get_default_gateway (in_addr_t *ret, in_addr_t *netmask)
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
get_default_gateway (in_addr_t *ret, in_addr_t *netmask)
|
||||
{
|
||||
return get_default_gateway_ex(ret, netmask, NULL);
|
||||
}
|
||||
|
||||
#elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
|
||||
|
||||
#include <sys/types.h>
|
||||
|
|
@ -2896,6 +2874,73 @@ get_default_gateway_mac_addr (unsigned char *macaddr)
|
|||
return false;
|
||||
}
|
||||
|
||||
#elif defined(TARGET_DARWIN)
|
||||
|
||||
bool
|
||||
get_default_gateway_mac_addr (unsigned char *macaddr)
|
||||
{
|
||||
# define max(a,b) ((a) > (b) ? (a) : (b))
|
||||
struct gc_arena gc = gc_new ();
|
||||
struct ifconf ifc;
|
||||
struct ifreq *ifr;
|
||||
char *buffer, *cp;
|
||||
bool status = false;
|
||||
in_addr_t gw = 0;
|
||||
char *ifname = NULL;
|
||||
int sockfd = -1;
|
||||
const int bufsize = 4096;
|
||||
|
||||
if (!get_default_gateway_ex (&gw, NULL, &ifname)) /* get interface name of default gateway */
|
||||
{
|
||||
msg (M_WARN, "GDGMA: get_default_gateway_ex failed");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!ifname)
|
||||
{
|
||||
msg (M_WARN, "GDGMA: cannot get default gateway ifname");
|
||||
goto done;
|
||||
}
|
||||
|
||||
buffer = (char *) gc_malloc (bufsize, true, &gc);
|
||||
|
||||
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sockfd < 0)
|
||||
{
|
||||
msg (M_WARN, "GDGMA: socket failed");
|
||||
goto done;
|
||||
}
|
||||
|
||||
ifc.ifc_len = bufsize;
|
||||
ifc.ifc_buf = buffer;
|
||||
|
||||
if (ioctl(sockfd, SIOCGIFCONF, (char *)&ifc) < 0)
|
||||
{
|
||||
msg (M_WARN, "GDGMA: ioctl failed");
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (cp = buffer; cp <= buffer + bufsize - sizeof(struct ifreq); )
|
||||
{
|
||||
ifr = (struct ifreq *)cp;
|
||||
if (ifr->ifr_addr.sa_family == AF_LINK && !strncmp(ifr->ifr_name, ifname, IFNAMSIZ))
|
||||
{
|
||||
struct sockaddr_dl *sdl = (struct sockaddr_dl *)&ifr->ifr_addr;
|
||||
memcpy(macaddr, LLADDR(sdl), 6);
|
||||
status = true;
|
||||
}
|
||||
cp += sizeof(ifr->ifr_name) + max(sizeof(ifr->ifr_addr), ifr->ifr_addr.sa_len);
|
||||
}
|
||||
|
||||
done:
|
||||
if (sockfd >= 0)
|
||||
close (sockfd);
|
||||
free (ifname);
|
||||
gc_free (&gc);
|
||||
return status;
|
||||
# undef max
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -133,15 +133,15 @@ static HANDLE exit_event = NULL;
|
|||
int openvpn_snprintf(char *str, size_t size, const char *format, ...)
|
||||
{
|
||||
va_list arglist;
|
||||
int ret = 0;
|
||||
int len = -1;
|
||||
if (size > 0)
|
||||
{
|
||||
va_start (arglist, format);
|
||||
ret = vsnprintf (str, size, format, arglist);
|
||||
len = vsnprintf (str, size, format, arglist);
|
||||
va_end (arglist);
|
||||
str[size - 1] = 0;
|
||||
}
|
||||
return ret;
|
||||
return (len >= 0 && len < size);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
34
socket.c
34
socket.c
|
|
@ -2014,21 +2014,25 @@ link_socket_init_phase2 (struct link_socket *sock,
|
|||
#endif
|
||||
|
||||
/* print local address */
|
||||
if (sock->inetd)
|
||||
msg (M_INFO, "%s link local: [inetd]", proto2ascii (sock->info.proto, true));
|
||||
else
|
||||
msg (M_INFO, "%s link local%s: %s",
|
||||
proto2ascii (sock->info.proto, true),
|
||||
(sock->bind_local ? " (bound)" : ""),
|
||||
print_sockaddr_ex (&sock->info.lsa->local, ":", sock->bind_local ? PS_SHOW_PORT : 0, &gc));
|
||||
{
|
||||
const int msglevel = (sock->mode == LS_MODE_TCP_ACCEPT_FROM) ? D_INIT_MEDIUM : M_INFO;
|
||||
|
||||
/* print active remote address */
|
||||
msg (M_INFO, "%s link remote: %s",
|
||||
proto2ascii (sock->info.proto, true),
|
||||
print_link_socket_actual_ex (&sock->info.lsa->actual,
|
||||
":",
|
||||
PS_SHOW_PORT_IF_DEFINED,
|
||||
&gc));
|
||||
if (sock->inetd)
|
||||
msg (msglevel, "%s link local: [inetd]", proto2ascii (sock->info.proto, true));
|
||||
else
|
||||
msg (msglevel, "%s link local%s: %s",
|
||||
proto2ascii (sock->info.proto, true),
|
||||
(sock->bind_local ? " (bound)" : ""),
|
||||
print_sockaddr_ex (&sock->info.lsa->local, ":", sock->bind_local ? PS_SHOW_PORT : 0, &gc));
|
||||
|
||||
/* print active remote address */
|
||||
msg (msglevel, "%s link remote: %s",
|
||||
proto2ascii (sock->info.proto, true),
|
||||
print_link_socket_actual_ex (&sock->info.lsa->actual,
|
||||
":",
|
||||
PS_SHOW_PORT_IF_DEFINED,
|
||||
&gc));
|
||||
}
|
||||
|
||||
done:
|
||||
if (sig_save && signal_received)
|
||||
|
|
@ -2057,7 +2061,7 @@ link_socket_close (struct link_socket *sock)
|
|||
#endif
|
||||
if (!gremlin)
|
||||
{
|
||||
msg (D_CLOSE, "TCP/UDP: Closing socket");
|
||||
msg (D_LOW, "TCP/UDP: Closing socket");
|
||||
if (openvpn_close_socket (sock->sd))
|
||||
msg (M_WARN | M_ERRNO_SOCK, "TCP/UDP: Close Socket failed");
|
||||
}
|
||||
|
|
|
|||
358
ssl.c
358
ssl.c
|
|
@ -320,16 +320,28 @@ ssl_set_auth_nocache (void)
|
|||
auth_user_pass.nocache = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set an authentication token
|
||||
*/
|
||||
void
|
||||
ssl_set_auth_token (const char *token)
|
||||
{
|
||||
set_auth_token (&auth_user_pass, token);
|
||||
}
|
||||
|
||||
/*
|
||||
* Forget private key password AND auth-user-pass username/password.
|
||||
*/
|
||||
void
|
||||
ssl_purge_auth (void)
|
||||
ssl_purge_auth (const bool auth_user_pass_only)
|
||||
{
|
||||
if (!auth_user_pass_only)
|
||||
{
|
||||
#ifdef USE_PKCS11
|
||||
pkcs11_logout ();
|
||||
pkcs11_logout ();
|
||||
#endif
|
||||
purge_user_pass (&passbuf, true);
|
||||
purge_user_pass (&passbuf, true);
|
||||
}
|
||||
purge_user_pass (&auth_user_pass, true);
|
||||
#ifdef ENABLE_CLIENT_CR
|
||||
ssl_purge_auth_challenge();
|
||||
|
|
@ -573,6 +585,96 @@ bool extract_x509_extension(X509 *cert, char *fieldname, char *out, int size)
|
|||
sk_GENERAL_NAME_free (extensions);
|
||||
}
|
||||
return retval;
|
||||
#ifdef ENABLE_X509_TRACK
|
||||
/*
|
||||
* setenv_x509_track function -- save X509 fields to environment,
|
||||
* using the naming convention:
|
||||
*
|
||||
* X509_{cert_depth}_{name}={value}
|
||||
*
|
||||
* This function differs from setenv_x509 below in the following ways:
|
||||
*
|
||||
* (1) Only explicitly named attributes in xt are saved, per usage
|
||||
* of --x509-track program options.
|
||||
* (2) Only the level 0 cert info is saved unless the XT_FULL_CHAIN
|
||||
* flag is set in xt->flags (corresponds with prepending a '+'
|
||||
* to the name when specified by --x509-track program option).
|
||||
* (3) This function supports both X509 subject name fields as
|
||||
* well as X509 V3 extensions.
|
||||
*/
|
||||
|
||||
/* worker method for setenv_x509_track */
|
||||
static void
|
||||
do_setenv_x509 (struct env_set *es, const char *name, char *value, int depth)
|
||||
{
|
||||
char *name_expand;
|
||||
size_t name_expand_size;
|
||||
|
||||
string_mod (value, CC_ANY, CC_CRLF, '?');
|
||||
msg (D_X509_ATTR, "X509 ATTRIBUTE name='%s' value='%s' depth=%d", name, value, depth);
|
||||
name_expand_size = 64 + strlen (name);
|
||||
name_expand = (char *) malloc (name_expand_size);
|
||||
check_malloc_return (name_expand);
|
||||
openvpn_snprintf (name_expand, name_expand_size, "X509_%d_%s", depth, name);
|
||||
setenv_str (es, name_expand, value);
|
||||
free (name_expand);
|
||||
}
|
||||
|
||||
static void
|
||||
setenv_x509_track (const struct x509_track *xt, struct env_set *es, const int depth, X509 *x509)
|
||||
{
|
||||
X509_NAME *x509_name = X509_get_subject_name (x509);
|
||||
const char nullc = '\0';
|
||||
int i;
|
||||
|
||||
while (xt)
|
||||
{
|
||||
if (depth == 0 || (xt->flags & XT_FULL_CHAIN))
|
||||
{
|
||||
i = X509_NAME_get_index_by_NID(x509_name, xt->nid, -1);
|
||||
if (i >= 0)
|
||||
{
|
||||
X509_NAME_ENTRY *ent = X509_NAME_get_entry(x509_name, i);
|
||||
if (ent)
|
||||
{
|
||||
ASN1_STRING *val = X509_NAME_ENTRY_get_data (ent);
|
||||
unsigned char *buf;
|
||||
buf = (unsigned char *)1; /* bug in OpenSSL 0.9.6b ASN1_STRING_to_UTF8 requires this workaround */
|
||||
if (ASN1_STRING_to_UTF8 (&buf, val) > 0)
|
||||
{
|
||||
do_setenv_x509(es, xt->name, (char *)buf, depth);
|
||||
OPENSSL_free (buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
i = X509_get_ext_by_NID(x509, xt->nid, -1);
|
||||
if (i >= 0)
|
||||
{
|
||||
X509_EXTENSION *ext = X509_get_ext(x509, i);
|
||||
if (ext)
|
||||
{
|
||||
BIO *bio = BIO_new(BIO_s_mem());
|
||||
if (bio)
|
||||
{
|
||||
if (X509V3_EXT_print(bio, ext, 0, 0))
|
||||
{
|
||||
if (BIO_write(bio, &nullc, 1) == 1)
|
||||
{
|
||||
char *str;
|
||||
BIO_get_mem_data(bio, &str);
|
||||
do_setenv_x509(es, xt->name, str, depth);
|
||||
}
|
||||
}
|
||||
BIO_free(bio);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
xt = xt->next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -834,6 +936,7 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
|
|||
const struct tls_options *opt;
|
||||
const int max_depth = MAX_CERT_DEPTH;
|
||||
struct argv argv = argv_new ();
|
||||
char *serial = NULL;
|
||||
|
||||
/* get the tls_session pointer */
|
||||
ssl = X509_STORE_CTX_get_ex_data (ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
|
||||
|
|
@ -854,7 +957,12 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
|
|||
}
|
||||
|
||||
/* Save X509 fields in environment */
|
||||
setenv_x509 (opt->es, ctx->error_depth, X509_get_subject_name (ctx->current_cert));
|
||||
#ifdef ENABLE_X509_TRACK
|
||||
if (opt->x509_track)
|
||||
setenv_x509_track (opt->x509_track, opt->es, ctx->error_depth, ctx->current_cert);
|
||||
else
|
||||
#endif
|
||||
setenv_x509 (opt->es, ctx->error_depth, X509_get_subject_name (ctx->current_cert));
|
||||
|
||||
/* enforce character class restrictions in X509 name */
|
||||
string_mod_sslname (subject, X509_NAME_CHAR_CLASS, opt->ssl_flags);
|
||||
|
|
@ -918,6 +1026,16 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
|
|||
goto err; /* Reject connection */
|
||||
}
|
||||
|
||||
/* verify level 1 cert, i.e. the CA that signed our leaf cert */
|
||||
if (ctx->error_depth == 1 && opt->verify_hash)
|
||||
{
|
||||
if (memcmp (ctx->current_cert->sha1_hash, opt->verify_hash, SHA_DIGEST_LENGTH))
|
||||
{
|
||||
msg (D_TLS_ERRORS, "TLS Error: level-1 certificate hash verification failed");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* save common name in session object */
|
||||
if (ctx->error_depth == 0)
|
||||
set_common_name (session, common_name);
|
||||
|
|
@ -943,32 +1061,17 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
|
|||
setenv_str (opt->es, envname, common_name);
|
||||
#endif
|
||||
|
||||
/* export serial number as environmental variable */
|
||||
/* export serial number as environmental variable,
|
||||
use bignum in case serial number is large */
|
||||
{
|
||||
BIO *bio = NULL;
|
||||
char serial[100];
|
||||
int n1, n2;
|
||||
|
||||
CLEAR (serial);
|
||||
if ((bio = BIO_new (BIO_s_mem ())) == NULL)
|
||||
{
|
||||
msg (M_WARN, "CALLBACK: Cannot create BIO (for tls_serial_%d)", ctx->error_depth);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* "prints" the serial number onto the BIO and read it back */
|
||||
if ( ! ( ( (n1 = i2a_ASN1_INTEGER(bio, X509_get_serialNumber (ctx->current_cert))) >= 0 ) &&
|
||||
( (n2 = BIO_read (bio, serial, sizeof (serial)-1)) >= 0 ) &&
|
||||
( n1 == n2 ) ) )
|
||||
{
|
||||
msg (M_WARN, "CALLBACK: Error reading/writing BIO (for tls_serial_%d)", ctx->error_depth);
|
||||
CLEAR (serial); /* empty string */
|
||||
}
|
||||
|
||||
openvpn_snprintf (envname, sizeof(envname), "tls_serial_%d", ctx->error_depth);
|
||||
setenv_str (opt->es, envname, serial);
|
||||
BIO_free(bio);
|
||||
}
|
||||
ASN1_INTEGER *asn1_i;
|
||||
BIGNUM *bignum;
|
||||
asn1_i = X509_get_serialNumber(ctx->current_cert);
|
||||
bignum = ASN1_INTEGER_to_BN(asn1_i, NULL);
|
||||
serial = BN_bn2dec(bignum);
|
||||
openvpn_snprintf (envname, sizeof(envname), "tls_serial_%d", ctx->error_depth);
|
||||
setenv_str (opt->es, envname, serial);
|
||||
BN_free(bignum);
|
||||
}
|
||||
|
||||
/* export current untrusted IP */
|
||||
|
|
@ -1108,67 +1211,89 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
|
|||
/* check peer cert against CRL */
|
||||
if (opt->crl_file)
|
||||
{
|
||||
X509_CRL *crl=NULL;
|
||||
X509_REVOKED *revoked;
|
||||
BIO *in=NULL;
|
||||
int n,i,retval = 0;
|
||||
|
||||
in=BIO_new(BIO_s_file());
|
||||
|
||||
if (in == NULL) {
|
||||
msg (M_ERR, "CRL: BIO err");
|
||||
goto end;
|
||||
}
|
||||
if (BIO_read_filename(in, opt->crl_file) <= 0) {
|
||||
msg (M_ERR, "CRL: cannot read: %s", opt->crl_file);
|
||||
goto end;
|
||||
}
|
||||
crl=PEM_read_bio_X509_CRL(in,NULL,NULL,NULL);
|
||||
if (crl == NULL) {
|
||||
msg (M_ERR, "CRL: cannot read CRL from file %s", opt->crl_file);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (X509_NAME_cmp(X509_CRL_get_issuer(crl), X509_get_issuer_name(ctx->current_cert)) != 0) {
|
||||
msg (M_WARN, "CRL: CRL %s is from a different issuer than the issuer of certificate %s", opt->crl_file, subject);
|
||||
retval = 1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
n = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl));
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
revoked = (X509_REVOKED *)sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i);
|
||||
if (ASN1_INTEGER_cmp(revoked->serialNumber, X509_get_serialNumber(ctx->current_cert)) == 0) {
|
||||
msg (D_HANDSHAKE, "CRL CHECK FAILED: %s is REVOKED",subject);
|
||||
goto end;
|
||||
if (opt->ssl_flags & SSLF_CRL_VERIFY_DIR)
|
||||
{
|
||||
char fn[256];
|
||||
int fd;
|
||||
if (!openvpn_snprintf(fn, sizeof(fn), "%s%c%s", opt->crl_file, OS_SPECIFIC_DIRSEP, serial))
|
||||
{
|
||||
msg (D_HANDSHAKE, "VERIFY CRL: filename overflow");
|
||||
goto err;
|
||||
}
|
||||
fd = open (fn, O_RDONLY);
|
||||
if (fd >= 0)
|
||||
{
|
||||
msg (D_HANDSHAKE, "VERIFY CRL: certificate serial number %s is revoked", serial);
|
||||
close(fd);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
X509_CRL *crl=NULL;
|
||||
X509_REVOKED *revoked;
|
||||
BIO *in=NULL;
|
||||
int n,i,retval = 0;
|
||||
|
||||
retval = 1;
|
||||
msg (D_HANDSHAKE, "CRL CHECK OK: %s",subject);
|
||||
in=BIO_new(BIO_s_file());
|
||||
|
||||
end:
|
||||
if (in == NULL) {
|
||||
msg (M_ERR, "CRL: BIO err");
|
||||
goto end;
|
||||
}
|
||||
if (BIO_read_filename(in, opt->crl_file) <= 0) {
|
||||
msg (M_ERR, "CRL: cannot read: %s", opt->crl_file);
|
||||
goto end;
|
||||
}
|
||||
crl=PEM_read_bio_X509_CRL(in,NULL,NULL,NULL);
|
||||
if (crl == NULL) {
|
||||
msg (M_ERR, "CRL: cannot read CRL from file %s", opt->crl_file);
|
||||
goto end;
|
||||
}
|
||||
|
||||
BIO_free(in);
|
||||
if (crl)
|
||||
X509_CRL_free (crl);
|
||||
if (!retval)
|
||||
goto err;
|
||||
if (X509_NAME_cmp(X509_CRL_get_issuer(crl), X509_get_issuer_name(ctx->current_cert)) != 0) {
|
||||
msg (M_WARN, "CRL: CRL %s is from a different issuer than the issuer of certificate %s", opt->crl_file, subject);
|
||||
retval = 1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
n = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl));
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
revoked = (X509_REVOKED *)sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i);
|
||||
if (ASN1_INTEGER_cmp(revoked->serialNumber, X509_get_serialNumber(ctx->current_cert)) == 0) {
|
||||
msg (D_HANDSHAKE, "CRL CHECK FAILED: %s is REVOKED",subject);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
retval = 1;
|
||||
msg (D_HANDSHAKE, "CRL CHECK OK: %s",subject);
|
||||
|
||||
end:
|
||||
|
||||
BIO_free(in);
|
||||
if (crl)
|
||||
X509_CRL_free (crl);
|
||||
if (!retval)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
msg (D_HANDSHAKE, "VERIFY OK: depth=%d, %s", ctx->error_depth, subject);
|
||||
|
||||
session->verified = true;
|
||||
|
||||
done:
|
||||
OPENSSL_free (subject);
|
||||
if (serial)
|
||||
OPENSSL_free(serial);
|
||||
argv_reset (&argv);
|
||||
return 1; /* Accept connection */
|
||||
return (session->verified == true) ? 1 : 0;
|
||||
|
||||
err:
|
||||
ERR_clear_error ();
|
||||
OPENSSL_free (subject);
|
||||
argv_reset (&argv);
|
||||
return 0; /* Reject connection */
|
||||
session->verified = false;
|
||||
goto done;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1232,6 +1357,31 @@ tls_lock_username (struct tls_multi *multi, const char *username)
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_X509_TRACK
|
||||
|
||||
void
|
||||
x509_track_add (const struct x509_track **ll_head, const char *name, int msglevel, struct gc_arena *gc)
|
||||
{
|
||||
struct x509_track *xt;
|
||||
ALLOC_OBJ_CLEAR_GC (xt, struct x509_track, gc);
|
||||
if (*name == '+')
|
||||
{
|
||||
xt->flags |= XT_FULL_CHAIN;
|
||||
++name;
|
||||
}
|
||||
xt->name = name;
|
||||
xt->nid = OBJ_txt2nid(name);
|
||||
if (xt->nid != NID_undef)
|
||||
{
|
||||
xt->next = *ll_head;
|
||||
*ll_head = xt;
|
||||
}
|
||||
else
|
||||
msg(msglevel, "x509_track: no such attribute '%s'", name);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_DEF_AUTH
|
||||
/* key_state_test_auth_control_file return values,
|
||||
NOTE: acf_merge indexing depends on these values */
|
||||
|
|
@ -1978,7 +2128,7 @@ init_ssl (const struct options *options)
|
|||
{
|
||||
if (!X509_STORE_add_cert(ctx->cert_store,sk_X509_value(ca, i)))
|
||||
msg (M_SSLERR, "Cannot add certificate to certificate chain (X509_STORE_add_cert)");
|
||||
if (!SSL_CTX_add_client_CA(ctx, sk_X509_value(ca, i)))
|
||||
if (options->tls_server && !SSL_CTX_add_client_CA(ctx, sk_X509_value(ca, i)))
|
||||
msg (M_SSLERR, "Cannot add certificate to client CA list (SSL_CTX_add_client_CA)");
|
||||
}
|
||||
}
|
||||
|
|
@ -2090,11 +2240,11 @@ init_ssl (const struct options *options)
|
|||
#endif
|
||||
{
|
||||
/* Load CA file for verifying peer supplied certificate */
|
||||
status = SSL_CTX_load_verify_locations (ctx, options->ca_file, options->ca_path);
|
||||
status = SSL_CTX_load_verify_locations (ctx, options->ca_file, NULL);
|
||||
}
|
||||
|
||||
if (!status)
|
||||
msg (M_SSLERR, "Cannot load CA certificate file %s path %s (SSL_CTX_load_verify_locations)", options->ca_file, options->ca_path);
|
||||
msg (M_SSLERR, "Cannot load CA certificate file %s path %s (SSL_CTX_load_verify_locations)", np(options->ca_file), np(options->ca_path));
|
||||
|
||||
/* Set a store for certs (CA & CRL) with a lookup on the "capath" hash directory */
|
||||
if (options->ca_path) {
|
||||
|
|
@ -2118,7 +2268,7 @@ init_ssl (const struct options *options)
|
|||
}
|
||||
|
||||
/* Load names of CAs from file and use it as a client CA list */
|
||||
if (options->ca_file) {
|
||||
if (options->ca_file && options->tls_server) {
|
||||
STACK_OF(X509_NAME) *cert_names = NULL;
|
||||
#if ENABLE_INLINE_FILES
|
||||
if (!strcmp (options->ca_file, INLINE_FILE_TAG) && options->ca_file_inline)
|
||||
|
|
@ -2132,7 +2282,7 @@ init_ssl (const struct options *options)
|
|||
}
|
||||
if (!cert_names)
|
||||
msg (M_SSLERR, "Cannot load CA certificate file %s (SSL_load_client_CA_file)", options->ca_file);
|
||||
SSL_CTX_set_client_CA_list (ctx, cert_names);
|
||||
SSL_CTX_set_client_CA_list (ctx, cert_names);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2143,6 +2293,37 @@ init_ssl (const struct options *options)
|
|||
msg (M_SSLERR, "Cannot load certificate chain file %s (SSL_use_certificate_chain_file)", options->cert_file);
|
||||
}
|
||||
|
||||
/* Load extra certificates that are part of our own certificate
|
||||
chain but shouldn't be included in the verify chain */
|
||||
if (options->extra_certs_file || options->extra_certs_file_inline)
|
||||
{
|
||||
BIO *bio;
|
||||
X509 *cert;
|
||||
#if ENABLE_INLINE_FILES
|
||||
if (!strcmp (options->extra_certs_file, INLINE_FILE_TAG) && options->extra_certs_file_inline)
|
||||
{
|
||||
bio = BIO_new_mem_buf ((char *)options->extra_certs_file_inline, -1);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
bio = BIO_new(BIO_s_file());
|
||||
if (BIO_read_filename(bio, options->extra_certs_file) <= 0)
|
||||
msg (M_SSLERR, "Cannot load extra-certs file: %s", options->extra_certs_file);
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
cert = NULL;
|
||||
if (!PEM_read_bio_X509 (bio, &cert, 0, NULL)) /* takes ownership of cert */
|
||||
break;
|
||||
if (!cert)
|
||||
msg (M_SSLERR, "Error reading extra-certs certificate");
|
||||
if (SSL_CTX_add_extra_chain_cert(ctx, cert) != 1)
|
||||
msg (M_SSLERR, "Error adding extra-certs certificate");
|
||||
}
|
||||
BIO_free (bio);
|
||||
}
|
||||
|
||||
/* Require peer certificate verification */
|
||||
#if P2MP_SERVER
|
||||
if (options->ssl_flags & SSLF_CLIENT_CERT_NOT_REQUIRED)
|
||||
|
|
@ -2674,8 +2855,10 @@ key_state_init (struct tls_session *session, struct key_state *ks)
|
|||
|
||||
/* init packet ID tracker */
|
||||
packet_id_init (&ks->packet_id,
|
||||
session->opt->tcp_mode,
|
||||
session->opt->replay_window,
|
||||
session->opt->replay_time);
|
||||
session->opt->replay_time,
|
||||
"SSL", ks->key_id);
|
||||
|
||||
#ifdef MANAGEMENT_DEF_AUTH
|
||||
ks->mda_key_id = session->opt->mda_context->mda_key_id_counter++;
|
||||
|
|
@ -2779,8 +2962,10 @@ tls_session_init (struct tls_multi *multi, struct tls_session *session)
|
|||
|
||||
/* initialize packet ID replay window for --tls-auth */
|
||||
packet_id_init (session->tls_auth.packet_id,
|
||||
session->opt->tcp_mode,
|
||||
session->opt->replay_window,
|
||||
session->opt->replay_time);
|
||||
session->opt->replay_time,
|
||||
"TLS_AUTH", session->key_id);
|
||||
|
||||
/* load most recent packet-id to replay protect on --tls-auth */
|
||||
packet_id_persist_load_obj (session->tls_auth.pid_persist, session->tls_auth.packet_id);
|
||||
|
|
@ -3851,6 +4036,11 @@ push_peer_info(struct buffer *buf, struct tls_session *session)
|
|||
buf_printf (&out, "IV_HWADDR=%s\n", format_hex_ex (macaddr, 6, 0, 1, ":", &gc));
|
||||
}
|
||||
|
||||
/* push LZO status */
|
||||
#ifdef LZO_STUB
|
||||
buf_printf (&out, "IV_LZO_STUB=1\n");
|
||||
#endif
|
||||
|
||||
/* push env vars that begin with UV_ */
|
||||
for (e=es->list; e != NULL; e=e->next)
|
||||
{
|
||||
|
|
|
|||
25
ssl.h
25
ssl.h
|
|
@ -404,6 +404,21 @@ struct key_state
|
|||
#endif
|
||||
};
|
||||
|
||||
#ifdef ENABLE_X509_TRACK
|
||||
|
||||
struct x509_track
|
||||
{
|
||||
const struct x509_track *next;
|
||||
const char *name;
|
||||
# define XT_FULL_CHAIN (1<<0)
|
||||
unsigned int flags;
|
||||
int nid;
|
||||
};
|
||||
|
||||
void x509_track_add (const struct x509_track **ll_head, const char *name, int msglevel, struct gc_arena *gc);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Our const options, obtained directly or derived from
|
||||
* command line options.
|
||||
|
|
@ -454,6 +469,7 @@ struct tls_options
|
|||
int ns_cert_type;
|
||||
unsigned remote_cert_ku[MAX_PARMS];
|
||||
const char *remote_cert_eku;
|
||||
uint8_t *verify_hash;
|
||||
|
||||
/* allow openvpn config info to be
|
||||
passed over control channel */
|
||||
|
|
@ -465,6 +481,7 @@ struct tls_options
|
|||
|
||||
int replay_window; /* --replay-window parm */
|
||||
int replay_time; /* --replay-window parm */
|
||||
bool tcp_mode;
|
||||
|
||||
/* packet authentication for TLS handshake */
|
||||
struct crypto_options tls_auth;
|
||||
|
|
@ -491,12 +508,17 @@ struct tls_options
|
|||
# define SSLF_AUTH_USER_PASS_OPTIONAL (1<<2)
|
||||
# define SSLF_NO_NAME_REMAPPING (1<<3)
|
||||
# define SSLF_OPT_VERIFY (1<<4)
|
||||
# define SSLF_CRL_VERIFY_DIR (1<<5)
|
||||
unsigned int ssl_flags;
|
||||
|
||||
#ifdef MANAGEMENT_DEF_AUTH
|
||||
struct man_def_auth_context *mda_context;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_X509_TRACK
|
||||
const struct x509_track *x509_track;
|
||||
#endif
|
||||
|
||||
/* --gremlin bits */
|
||||
int gremlin;
|
||||
};
|
||||
|
|
@ -703,7 +725,8 @@ void pem_password_setup (const char *auth_file);
|
|||
int pem_password_callback (char *buf, int size, int rwflag, void *u);
|
||||
void auth_user_pass_setup (const char *auth_file);
|
||||
void ssl_set_auth_nocache (void);
|
||||
void ssl_purge_auth (void);
|
||||
void ssl_set_auth_token (const char *token);
|
||||
void ssl_purge_auth (const bool auth_user_pass_only);
|
||||
|
||||
|
||||
#ifdef ENABLE_CLIENT_CR
|
||||
|
|
|
|||
24
syshead.h
24
syshead.h
|
|
@ -598,6 +598,13 @@ socket_defined (const socket_descriptor_t sd)
|
|||
#define ENABLE_PKCS11
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Enable x509-track feature?
|
||||
*/
|
||||
#if defined(USE_CRYPTO) && defined(USE_SSL)
|
||||
#define ENABLE_X509_TRACK
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Is poll available on this platform?
|
||||
*/
|
||||
|
|
@ -676,4 +683,21 @@ socket_defined (const socket_descriptor_t sd)
|
|||
*/
|
||||
#define ENABLE_PUSH_PEER_INFO
|
||||
|
||||
/*
|
||||
* Do we support internal client-side NAT?
|
||||
*/
|
||||
#define ENABLE_CLIENT_NAT
|
||||
|
||||
/*
|
||||
* Support LZO as a stub in client? (LZO lib not included, but we
|
||||
* we still support LZO protocol changes that allow us to
|
||||
* communicate with an LZO-enabled server)
|
||||
*/
|
||||
#ifdef LZO_STUB
|
||||
#undef USE_LZO
|
||||
#undef LZO_VERSION_NUM
|
||||
#define USE_LZO 1
|
||||
#define LZO_VERSION_NUM "STUB"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
2
tun.c
2
tun.c
|
|
@ -991,7 +991,6 @@ do_ifconfig (struct tuntap *tt,
|
|||
tt->did_ifconfig = true;
|
||||
|
||||
#elif defined(TARGET_DARWIN)
|
||||
|
||||
/*
|
||||
* Darwin (i.e. Mac OS X) seems to exhibit similar behaviour to OpenBSD...
|
||||
*/
|
||||
|
|
@ -1037,6 +1036,7 @@ do_ifconfig (struct tuntap *tt,
|
|||
tun_mtu
|
||||
);
|
||||
}
|
||||
|
||||
argv_msg (M_INFO, &argv);
|
||||
openvpn_execve_check (&argv, es, S_FATAL, "Mac OS X ifconfig failed");
|
||||
tt->did_ifconfig = true;
|
||||
|
|
|
|||
12
win/sign.py
12
win/sign.py
|
|
@ -4,16 +4,20 @@ from wb import config, choose_arch, home_fn
|
|||
if 'SIGNTOOL' in config:
|
||||
sys.path.append(home_fn(config['SIGNTOOL']))
|
||||
|
||||
def main(conf, arch):
|
||||
def main(conf, arch, tap_dir):
|
||||
from signtool import SignTool
|
||||
st = SignTool(conf)
|
||||
st = SignTool(conf, tap_dir)
|
||||
for x64 in choose_arch(arch):
|
||||
st.sign_verify(x64=x64)
|
||||
|
||||
# if we are run directly, and not loaded as a module
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) >= 2:
|
||||
main(config, sys.argv[1])
|
||||
if len(sys.argv) >= 3:
|
||||
tap_dir = home_fn(sys.argv[2])
|
||||
else:
|
||||
tap_dir = None
|
||||
main(config, sys.argv[1], tap_dir)
|
||||
else:
|
||||
print "usage: sign <x64|x86|all>"
|
||||
print "usage: sign <x64|x86|all> [tap-dir]"
|
||||
sys.exit(2)
|
||||
|
|
|
|||
Loading…
Reference in a new issue