Gert Doering | 27 Aug 15:00 2015
Picon

[PATCH] Replace unaligned 16bit access to TCP MSS value with bytewise access

TCP options are not always word-aligned, and accessing a 16bit value
at an odd memory address will cause a "bus error" crash on some
architectures, e.g. Linux/Sparc(64)

Trac #497

Signed-off-by: Gert Doering <gert <at> greenie.muc.de>
---
 src/openvpn/mss.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/src/openvpn/mss.c b/src/openvpn/mss.c
index 64fd722..7298c7b 100644
--- a/src/openvpn/mss.c
+++ b/src/openvpn/mss.c
 <at>  <at>  -129,7 +129,7  <at>  <at>  mss_fixup_dowork (struct buffer *buf, uint16_t maxmss)
 {
   int hlen, olen, optlen;
   uint8_t *opt;
-  uint16_t *mss;
+  uint16_t mssval;
   int accumulate;
   struct openvpn_tcphdr *tc;

 <at>  <at>  -159,14 +159,13  <at>  <at>  mss_fixup_dowork (struct buffer *buf, uint16_t maxmss)
       if (*opt == OPENVPN_TCPOPT_MAXSEG) {
         if (optlen != OPENVPN_TCPOLEN_MAXSEG)
           continue;
-        mss = (uint16_t *)(opt + 2);
-        if (ntohs (*mss) > maxmss) {
(Continue reading)

Rafael Gava | 26 Aug 03:43 2015
Picon

[PATCH] Added two features to Network Address Translator

Hi, 

this is my first submission to the list and I hope that I'm doing in the right way. :-)


Well, the features added to Network Address Translator are:

1) Allow the user to use the string "localhost" on the client-nat network configuration in a way that is not necessary to inform the IP address beforehand. Openvpn will set the dynamic received IP from DHCP. 
Example:

client-nat snat localhost 255.255.255.255 172.20.1.15 # replaces the 'localhost' string with the DHCP address received from openvpn server.

2) Allow the user to enable the FTP NAT support through the --enable-nat-ftp-support option. 
This is useful for systems that don't have conntrack-tools support, for example on Windows systems. On windows this feature is enabled by default.

enable-nat-ftp-support (yes | no)


The following patch was written based on release/2.3 branch.
--------------------------------------------------------------------------------------------------------------------------------------

From d11957a025dc6c113874e7b04ce4c8e9513c3b02 Mon Sep 17 00:00:00 2001
From: venturus <venturus <at> venturus-virtual-machine.(none)>
Date: Thu, 13 Aug 2015 08:26:36 -0300
Subject: [PATCH] Replaces the client-nat network string 'localhost' with the
 dynamic IP set to the tun/tap interface by the openvpn
 server. Example:

--client-nat snat localhost 255.255.255.255 172.20.1.15 # replaces the 'localhost' string with the DHCP address received from openvpn server.

Signed-off-by: Rafael Gava <rafael.oliveira <at> venturus.org.br>
---
 src/openvpn/clinat.c |   57 ++++++++++++++++++++++++++++++++++++++++++--------
 src/openvpn/clinat.h |    2 ++
 src/openvpn/init.c   |    4 ++++
 3 files changed, 54 insertions(+), 9 deletions(-)
 mode change 100644 => 100755 src/openvpn/clinat.c
 mode change 100644 => 100755 src/openvpn/clinat.h
 mode change 100644 => 100755 src/openvpn/init.c

diff --git a/src/openvpn/clinat.c b/src/openvpn/clinat.c
old mode 100644
new mode 100755
index af75fc9..2460185
--- a/src/openvpn/clinat.c
+++ b/src/openvpn/clinat.c
<at> <at> -107,11 +107,11 <at> <at> copy_client_nat_option_list (struct client_nat_option_list *dest,
 
 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)
+            const char *type,
+            const char *network,
+            const char *netmask,
+            const char *foreign_network,
+            int msglevel)
 {
   struct client_nat_entry e;
   bool ok;
<at> <at> -126,12 +126,19 <at> <at> add_client_nat_to_option_list (struct client_nat_option_list *dest,
       return;
     }
 
-  e.network = getaddr(0, network, 0, &ok, NULL);
-  if (!ok)
+  if (network && !strcmp(network, "localhost"))
     {
-      msg(msglevel, "client-nat: bad network: %s", network);
-      return;
+      msg (M_INFO, "*** client-nat localhost detected...");
+      e.network = 0xFFFFFFFF;
+    } else {
+      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)
     {
<at> <at> -148,6 +155,7 <at> <at> add_client_nat_to_option_list (struct client_nat_option_list *dest,
   add_entry(dest, &e);
 }
 
+
 #if 0
 static void
 print_checksum (struct openvpn_iphdr *iph, const char *prefix)
<at> <at> -266,4 +274,35 <at> <at> client_nat_transform (const struct client_nat_option_list *list,
     }
 }
 
+/*
+* Replaces the localhost token with the IP received from OpenVPN
+*/
+bool 
+update_localhost_nat(struct client_nat_option_list *dest, in_addr_t local_ip)
+{
+  int i;
+  bool ret = false;
+
+  if (!dest)
+    return ret;
+
+  for (i=0; i <= dest->n; i++) 
+    {
+      struct client_nat_entry *nat_entry = &dest->entries[i];
+      if (nat_entry && nat_entry->network == 0xFFFFFFFF) 
+        {
+          struct in_addr addr;
+          
+          nat_entry->network = ntohl(local_ip);
+          addr.s_addr = nat_entry->network;
+          char *dot_ip = inet_ntoa(addr);
+
+          msg (M_INFO, "Updating NAT table from localhost to: %s", dot_ip); 
+          ret = true;
+        }
+    }
+
+  return ret;
+}
+
 #endif
diff --git a/src/openvpn/clinat.h b/src/openvpn/clinat.h
old mode 100644
new mode 100755
index d55a727..ce995d9
--- a/src/openvpn/clinat.h
+++ b/src/openvpn/clinat.h
<at> <at> -62,4 +62,6 <at> <at> void client_nat_transform (const struct client_nat_option_list *list,
    struct buffer *ipbuf,
    const int direction);
 
+bool update_localhost_nat(struct client_nat_option_list *dest, in_addr_t local_ip);
+
 #endif
diff --git a/src/openvpn/init.c b/src/openvpn/init.c
old mode 100644
new mode 100755
index 71c91a2..4a63ee8
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
<at> <at> -1476,6 +1476,10 <at> <at> do_open_tun (struct context *c)
        c->c1.tuntap->post_open_mtu,
        SET_MTU_TUN | SET_MTU_UPPER_BOUND);
 
+#ifdef ENABLE_CLIENT_NAT
+      update_localhost_nat(c->options.client_nat, c->c1.tuntap->local);
+#endif
+
       ret = true;
       static_context = c;
     }
-- 
1.7.9.5


From 18b1411689df67feafeb15630c3519ab2cbd42d4 Mon Sep 17 00:00:00 2001
Date: Fri, 14 Aug 2015 15:27:50 -0300
Subject: [PATCH] Added FTP NAT support. This feature can be enabled via
 --enable-nat-ftp-support option.


Signed-off-by: Rafael Gava <rafael.oliveira <at> venturus.org.br>
---
 src/openvpn/clinat.c  |  773 ++++++++++++++++++++++++++++++++++++++++++++++---
 src/openvpn/clinat.h  |   15 +-
 src/openvpn/forward.c |   75 ++---
 src/openvpn/options.c |   12 +
 src/openvpn/options.h |    1 +
 5 files changed, 787 insertions(+), 89 deletions(-)
 mode change 100644 => 100755 src/openvpn/forward.c
 mode change 100644 => 100755 src/openvpn/options.c
 mode change 100644 => 100755 src/openvpn/options.h

diff --git a/src/openvpn/clinat.c b/src/openvpn/clinat.c
index 2460185..1d213f5 100755
--- a/src/openvpn/clinat.c
+++ b/src/openvpn/clinat.c
<at> <at> -36,6 +36,159 <at> <at>
 #include "proto.h"
 #include "socket.h"
 #include "memdbg.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+/* Delta Table Types */
+
+typedef struct delta_table_key {
+  uint32_t src_addr;
+  uint32_t dest_addr;
+  uint16_t src_port;
+  uint16_t dest_port;
+} delta_table_key_t;
+
+typedef struct delta_table_entry {
+  delta_table_key_t key;
+  uint16_t delta_out;
+  uint16_t delta_in;
+  uint8_t marked_to_remove;
+  uint8_t reserved[3];
+  uint32_t timestamp;
+  struct delta_table_entry *_next;
+} delta_table_entry_t;
+
+typedef struct delta_table {
+    struct delta_table_entry *head;
+} delta_table_t;
+
+
+// Global delta table
+//#define DEBUG_DELTA 1
+
+delta_table_t *table = NULL;
+
+#define TIME_TO_RESPOND 60 * 5 // 5 Minutes
+#define TIME_TO_LIVE 24 * 60 * 60
+
+/* Delta Table Functions */
+
+// In seconds, since epoch
+static uint32_t 
+get_timestamp() {
+  return (uint32_t)time(NULL);
+}
+
+static void 
+print_delta_table_entries(delta_table_t *table) {
+    delta_table_entry_t *current = table->head;
+
+  if (current == NULL) {
+    return;
+  }
+
+  while (current != NULL) {
+    printf("from %d -> to %d: removed: %s, timestamp: %d, delta_out: %d, delta_in: %d\n", 
+      current->key.src_addr, current->key.dest_addr, current->marked_to_remove ? "true" : "false", 
+      current->timestamp, current->delta_out, current->delta_in);
+    current = current->_next;
+  }
+}
+
+static struct delta_table *
+init_delta_table() {
+  delta_table_t *table = malloc(sizeof(delta_table_t));
+  table->head = NULL;
+  return table;
+}
+
+static struct delta_table_entry *
+add_delta_entry(delta_table_t *table, delta_table_entry_t *new_delta_entry) {
+  if (table->head == NULL) {
+    table->head = new_delta_entry;
+    table->head->_next = NULL;
+  } else {
+    // Add element to HEAD, for performance gain
+    new_delta_entry->_next = table->head;
+    table->head = new_delta_entry; 
+  }
+  return new_delta_entry;
+}
+
+static int 
+remove_delta_entry(delta_table_t *table, delta_table_entry_t *delta_entry) {
+  delta_table_entry_t *current = table->head;
+  delta_table_entry_t *before = NULL;
+  uint8_t found = 0;
+
+  //msg (M_INFO, "On remove_delta_entry - entry: %p", &delta_entry);
+
+  while (current != NULL) {
+    if(current == delta_entry) {
+      found = 1;
+      break;
+    }
+    before = current;
+    current = current->_next;
+  }
+
+  //Element not found
+  if (!found) {
+    return 0;
+  }
+
+  if(before==NULL){
+    table->head = table->head->_next;
+  } else {
+    before->_next = delta_entry->_next;
+  }
+
+  //msg (M_INFO, "On remove_delta_entry - entry: %p - freed", &delta_entry);
+  
+  free(delta_entry);
+  return 1;
+}
+
+static struct delta_table_entry *
+get_delta_entry(delta_table_t *table, delta_table_key_t key) {
+  delta_table_entry_t *current = table->head;
+  delta_table_entry_t *aux = NULL;
+  delta_table_entry_t *el = NULL;
+
+  while (current != NULL) {
+    // Check TTL and Timeout
+    if ((current->marked_to_remove && get_timestamp() - current->timestamp >= TIME_TO_RESPOND) /* ||  get_timestamp() - current->timestamp >= TIME_TO_LIVE */){
+      aux = current;
+      //If the CURRENT is to be removed, then dont return it
+      if (aux == el) { 
+        el = NULL;
+      }
+      current = current->_next;
+      remove_delta_entry(table, aux);
+    } else {
+      if ((
+        // Regular connection
+        (current->key.src_addr == key.src_addr &&
+         current->key.src_port == key.src_port && 
+         current->key.dest_addr == key.dest_addr && 
+         current->key.dest_port == key.dest_port) ||
+        //Check if it is a returned connection
+        (current->key.dest_addr == key.src_addr &&
+         current->key.dest_port == key.src_port && 
+         current->key.src_addr == key.dest_addr && 
+         current->key.src_port == key.dest_port))) {
+        el = current;
+      } 
+      current = current->_next;
+    }
+  }
+
+  return el;
+}
+
+/* Delta Table Functions End */
+
 
 static bool
 add_entry(struct client_nat_option_list *dest,
<at> <at> -192,19 +345,533 <at> <at> print_pkt (struct openvpn_iphdr *iph, const char *prefix, const int direction, c
   gc_free (&gc);
 }
 
+#if DEBUG_DELTA
+
+#ifndef HEXDUMP_COLS
+#define HEXDUMP_COLS 8
+#endif
+
+static void hexdump(void *mem, unsigned int len)
+{
+  unsigned int i, j;
+        
+  for(i = 0; i < len + ((len % HEXDUMP_COLS) ? (HEXDUMP_COLS - len % HEXDUMP_COLS) : 0); i++)
+  {
+    /* print offset */
+    if(i % HEXDUMP_COLS == 0)
+    {
+      printf("0x%06x: ", i);
+    }
+    /* print hex data */
+    if(i < len)
+    {
+      printf("%02x ", 0xFF & ((char*)mem)[i]);
+    }
+    else /* end of block, just aligning for ASCII dump */
+    {
+      printf("   ");
+    }
+                
+    /* print ASCII dump */
+    if(i % HEXDUMP_COLS == (HEXDUMP_COLS - 1))
+    {
+      for(j = i - (HEXDUMP_COLS - 1); j <= i; j++)
+      {
+        unsigned char ch = 0xFF & ((char*)mem)[j];
+
+        if(j >= len) /* end of block, not really printing */
+        {
+          putchar(' ');
+        } 
+        else if (ch >= 0x80) 
+        {
+          putchar('.');
+        }
+        else if(isprint(((char*)mem)[j])) /* printable char */
+        {
+          putchar(0xFF & ((char*)mem)[j]);        
+        }
+        else /* other char */
+        {
+          putchar('.');
+        }
+      }
+      putchar('\n');
+    }
+  }
+}
+#endif
+
+static int try_number(const char *data, size_t dlen, uint32_t array[],
+          int array_size, char sep, char term)
+{
+  uint32_t i, len;
+
+  memset(array, 0, sizeof(array[0])*array_size);
+
+  /* Keep data pointing at next char. */
+  for (i = 0, len = 0; len < dlen && i < array_size; len++, data++) {
+    if (*data >= '0' && *data <= '9') {
+      array[i] = array[i]*10 + *data - '0';
+    }
+    else if (*data == sep)
+      i++;
+    else {
+      /* Unexpected character; true if it's the
+         terminator and we're finished. */
+      if (*data == term && i == array_size - 1)
+        return len;
+
+      msg (M_ERRNO, "CNAT - try_number - Char %u (got %u nums) `%u' unexpected\n", len, i, *data);
+      return 0;
+    }
+  }
+
+  msg (M_ERRNO, "CNAT - ERROR: Failed to fill %u numbers separated by %c\n", array_size, sep);
+
+  return 0;
+}
+
+static int try_rfc959(const char *, size_t, u_int32_t [], char);
+
+static struct ftp_search {
+  int direction;
+  const char *pattern;
+  size_t plen;
+  char skip;
+  char term;
+  int (*getnum)(const char *, size_t, u_int32_t[], char);
+} search[] = {
+  {
+    CN_OUTGOING,
+    "PORT",  sizeof("PORT") - 1, ' ', '\r',
+    try_rfc959,
+  },
+  {
+    CN_INCOMING,
+    "227 ",  sizeof("227 ") - 1, '(', ')',
+    try_rfc959,
+  },
+};
+
+
+/* Returns 0, or length of numbers: 192,168,1,1,5,6 */
+static int 
+try_rfc959(const char *data, size_t dlen, u_int32_t array[6],
+           char term)
+{
+  return try_number(data, dlen, array, 6, ',', term);
+}
+
+/* Grab port: number up to delimiter */
+static int 
+get_port(const char *data, int start, size_t dlen, char delim,
+        u_int32_t array[2])
+{
+  u_int16_t port = 0;
+  int i;
+
+  for (i = start; i < dlen; i++) {
+    /* Finished? */
+    if (data[i] == delim) {
+      if (port == 0)
+        break;
+      array[0] = port >> 8;
+      array[1] = port;
+      return i + 1;
+    }
+    else if (data[i] >= '0' && data[i] <= '9')
+      port = port*10 + data[i] - '0';
+    else /* Some other crap */
+      break;
+  }
+  return 0;
+}
+
+/* Return 1 for match, 0 for accept, -1 for partial. */
+static int 
+find_pattern(const char *data, size_t dlen,
+      const char *pattern, size_t plen,
+      char skip, char term,
+      unsigned int *numoff,
+      unsigned int *numlen,
+      u_int32_t array[6],
+      int (*getnum)(const char *, size_t, u_int32_t[], char))
+{
+  size_t i;
+
+  if (check_debug_level (D_CLIENT_NAT))
+    msg (M_INFO, "CNAT - find_pattern %s: dlen = %u\n", pattern, dlen);
+
+  if (dlen == 0)
+    return 0;
+
+  if (dlen <= plen) {
+    /* Short packet: try for partial? */
+    if (strncasecmp(data, pattern, dlen) == 0)
+      return -1;
+    else return 0;
+  }
+
+  if (strncasecmp(data, pattern, plen) != 0) {
+    return 0;
+  }
+
+  if (check_debug_level (D_CLIENT_NAT))
+    msg (M_INFO, "CNAT - Pattern matches!\n");
+
+  /* Now we've found the constant string, try to skip
+     to the 'skip' character */
+  for (i = plen; data[i] != skip; i++)
+    if (i == dlen - 1) return -1;
+
+  /* Skip over the last character */
+  i++;
+
+  if (check_debug_level (D_CLIENT_NAT))
+    msg (M_INFO, "CNAT - Skipped up to `%c'!\n", skip);
+
+  *numoff = i;
+  *numlen = getnum(data + i, dlen - i, array, term);
+  if (!*numlen)
+    return -1;
+
+  if (check_debug_level (D_CLIENT_NAT))
+    msg (M_INFO, "CNAT - Match succeeded!\n");
+  
+  return 1;
+}
+
+static uint16_t
+tcp_checksum (const uint8_t *buf,
+        const int len_tcp,
+        const uint32_t src_addr,
+        const uint32_t dest_addr)
+{
+  uint16_t word16;
+  uint32_t sum = 0;
+  int i;
+  uint8_t * psrc_addr = (uint8_t *) &src_addr;
+  uint8_t * pdest_addr = (uint8_t *) &dest_addr;
+  
+  /* make 16 bit words out of every two adjacent 8 bit words and  */
+  /* calculate the sum of all 16 bit words */
+  for (i = 0; i < len_tcp; i += 2){
+    word16 = ((buf[i] << 8) & 0xFF00) + ((i + 1 < len_tcp) ? (buf[i+1] & 0xFF) : 0);
+    sum += word16;
+  }
+
+  /* add the TCP pseudo header which contains the IP source and destination addresses */
+  for (i = 0; i < 4; i += 2){
+    word16 =((psrc_addr[i] << 8) & 0xFF00) + (psrc_addr[i+1] & 0xFF);
+    sum += word16;
+  }
+  for (i = 0; i < 4; i += 2){
+    word16 =((pdest_addr[i] << 8) & 0xFF00) + (pdest_addr[i+1] & 0xFF);
+    sum += word16;   
+  }
+
+  /* the protocol number and the length of the TCP packet */
+  sum += (uint16_t) OPENVPN_IPPROTO_TCP + (uint16_t) len_tcp;
+
+  /* keep only the last 16 bits of the 32 bit calculated sum and add the carries */
+  while (sum >> 16)
+    sum = (sum & 0xFFFF) + (sum >> 16);
+    
+  /* Take the one's complement of sum */
+  return ((uint16_t) ~sum);
+}
+
+static uint16_t 
+ip_checksum(const void *buf, uint16_t hdr_len) {
+  unsigned long sum = 0;
+  const uint16_t *ip1;
+
+  ip1 = buf;
+  while (hdr_len > 1) {
+    sum += *ip1++;
+    if (sum & 0x80000000)
+      sum = (sum & 0xFFFF) + (sum >> 16);
+    hdr_len -= 2;
+  }
+
+  while (sum >> 16)
+    sum = (sum & 0xFFFF) + (sum >> 16);
+
+  return(~sum);
+}
+
+static int 
+client_nat_ftp_transform(struct buffer *ipbuf,
+          const int direction, const uint32_t from_address, uint32_t replace_address) {
+
+  uint32_t array[6] = {0};
+  int ret = 0;
+  int data_len = 0;
+
+  struct ip_tcp_udp_hdr *hdr = (struct ip_tcp_udp_hdr *) BPTR (ipbuf);
+
+  if (hdr->ip.protocol != OPENVPN_IPPROTO_TCP)
+    return ret;
+
+  if (table == NULL) 
+      table = init_delta_table();
+  
+  delta_table_entry_t *entry = NULL;
+  delta_table_key_t delta_key;
+
+  // Because the address already was NATed, probably on OpenVPN Server
+  if (direction == CN_OUTGOING)
+    delta_key.src_addr = from_address;
+  else if (direction == CN_INCOMING)
+    delta_key.src_addr = hdr->ip.saddr;
+
+  delta_key.src_port = hdr->u.tcp.source;
+  delta_key.dest_addr = hdr->ip.daddr;
+  delta_key.dest_port = hdr->u.tcp.dest;
+
+#if DEBUG_DELTA
+  msg (M_INFO, "delta_key - saddr: %d, sport: %d, daddr: %d, dport: %d", 
+  delta_key.src_addr, delta_key.src_port, delta_key.dest_addr, delta_key.dest_port);
+
+  msg (M_INFO, "seq: %x, ack: %x", 
+  hdr->u.tcp.seq, hdr->u.tcp.ack_seq);
+#endif
+
+  int tcp_data_offset = OPENVPN_TCPH_GET_DOFF (hdr->u.tcp.doff_res);
+
+  struct buffer tcpbuf = *ipbuf;
+  if (!buf_advance (&tcpbuf, sizeof(struct openvpn_iphdr) + tcp_data_offset))
+    return ret;
+
+  uint8_t * tcp_data = (uint8_t *) BPTR (&tcpbuf);
+
+#if DEBUG_DELTA
+  msg (M_INFO, "TCP DATA BEFORE NAT:");
+  hexdump(tcp_data, BLEN(&tcpbuf));    
+#endif
+
+  u_int32_t matchlen, matchoff;
+  int found_pattern = -1;
+  int i = 0;
+
+  for (i = 0; i < sizeof(search) / sizeof(search[0]); i++) {
+    if (search[i].direction != direction) continue;
+
+    found_pattern = find_pattern(tcp_data, BLEN(&tcpbuf),
+             search[i].pattern,
+             search[i].plen,
+             search[i].skip,
+             search[i].term,
+             &matchoff, &matchlen,
+             array,
+             search[i].getnum);
+    if (found_pattern) break;
+  }
+
+  if (found_pattern > 0) 
+    {
+
+      if (check_debug_level (D_CLIENT_NAT)) 
+        {
+          msg (M_INFO, "client-nat FTP match: %.*s - data: %.*s\n",
+            matchoff, tcp_data, matchlen, &tcp_data[matchoff]);
+        }
+
+      data_len = BLEN(&tcpbuf) - matchoff;
+
+      uint32_t ip = htonl((array[0] << 24) | (array[1] << 16)
+        | (array[2] << 8) | array[3]);
+      uint16_t port = htons(array[4] << 8 | array[5]);
+      uint8_t * addr_tmp = (uint8_t *) &replace_address;
+
+      uint8_t new_tcp_data[32];
+      memset(&new_tcp_data[0], 0, sizeof(new_tcp_data));
+
+      int new_len = sprintf((char *) &new_tcp_data[0], "%d,%d,%d,%d,%d,%d%.*s",
+        addr_tmp[0], addr_tmp[1], addr_tmp[2], addr_tmp[3], array[4], array[5], 
+        data_len - matchlen, (char *)&tcp_data[matchoff + matchlen]);
+
+      if (check_debug_level (D_CLIENT_NAT)) 
+        {
+          msg (M_INFO, "client-nat replaced address from: %.*s to: %.*s\n",
+            data_len, &tcp_data[matchoff], new_len, &new_tcp_data[0]);
+        }
+
+      //If the new len is greater than the old, there will be there an adjustment
+      if (new_len > data_len) 
+        {
+          //If the entry already exists
+          if (entry = get_delta_entry(table, delta_key)) 
+            {
+              if (direction == CN_OUTGOING) 
+                {
+                  hdr->u.tcp.seq = htonl(ntohl(hdr->u.tcp.seq) + (entry->delta_out));       // Need to update seq and ack
+                  hdr->u.tcp.ack_seq = htonl(ntohl(hdr->u.tcp.ack_seq) - entry->delta_in);
+                  entry->delta_out += new_len - data_len;
+                }
+              else
+                {
+                  hdr->u.tcp.seq = htonl(ntohl(hdr->u.tcp.seq) + (entry->delta_in));        // Need to update seq and ack
+                  hdr->u.tcp.ack_seq = htonl(ntohl(hdr->u.tcp.ack_seq) - entry->delta_out);
+                  entry->delta_in += new_len - data_len;
+                }
+              //Update timestamp entry on delta entry, to keep this delta alive
+              entry->timestamp = get_timestamp();
+            }
+          else 
+            {
+              // No entry found. Add a new one.
+              entry = malloc(sizeof(delta_table_entry_t));
+              entry->key = delta_key;
+
+              if (direction == CN_OUTGOING) 
+                {
+                  entry->delta_out = new_len - data_len;
+                  entry->delta_in = 0;
+                }
+              else
+                {
+                  entry->delta_in = new_len - data_len;
+                  entry->delta_out = 0;
+                }
+              entry->marked_to_remove = 0;
+              entry->timestamp = get_timestamp();
+        
+              //Add it to delta table
+              add_delta_entry(table, entry);
+            }
+
+#if DEBUG_DELTA
+          print_delta_table_entries(table);
+#endif
+
+          //Increase the tcpbuf and ipbuf reflecting the delta chars added to the segment.
+          ASSERT(buf_inc_len(&tcpbuf, new_len - data_len));
+          ASSERT(buf_inc_len(ipbuf, new_len - data_len));
+
+          //Update tot_len
+          hdr->ip.tot_len = htons(ntohs(hdr->ip.tot_len) + (new_len - data_len));
+
+          // Readjust IP Checksum
+          uint16_t head_len = OPENVPN_IPH_GET_LEN(hdr->ip.version_len);
+          hdr->ip.check = 0;
+          uint16_t check = ip_checksum( BPTR (ipbuf), head_len);
+          hdr->ip.check = check;
+
+          //Use new_len here!
+          memcpy(&tcp_data[matchoff], new_tcp_data, new_len); 
+        }
+      else
+        {
+          // The replace size is the lesser or iqual the original? Pad with 0 if necessary.
+          memcpy(&tcp_data[matchoff], new_tcp_data, data_len); 
+
+          //If the entry already exists
+          if (entry = get_delta_entry(table, delta_key)) 
+            {
+              if (direction == CN_OUTGOING) 
+                {
+                  hdr->u.tcp.seq = htonl(ntohl(hdr->u.tcp.seq) + (entry->delta_out));       // Need to update seq and ack
+                  hdr->u.tcp.ack_seq = htonl(ntohl(hdr->u.tcp.ack_seq) - entry->delta_in);
+                }
+              else
+                {
+                  hdr->u.tcp.seq = htonl(ntohl(hdr->u.tcp.seq) + (entry->delta_in));        // Need to update seq and ack
+                  hdr->u.tcp.ack_seq = htonl(ntohl(hdr->u.tcp.ack_seq) - entry->delta_out);
+                }
+              //Update timestamp entry on delta entry, to keep this delta alive
+              entry->timestamp = get_timestamp();
+            }
+
+        }
+
+      //Update TCP checksum
+      hdr->u.tcp.check = 0;
+
+      uint16_t tot_len = ntohs(hdr->ip.tot_len);
+      uint16_t head_len = OPENVPN_IPH_GET_LEN(hdr->ip.version_len);
+
+      uint16_t check = tcp_checksum(BPTR (ipbuf) + head_len, 
+      tot_len - head_len, hdr->ip.saddr, hdr->ip.daddr); 
+
+      hdr->u.tcp.check = htons(check);
+      ret = 1;
+    }
+  else 
+    {
+      //No pattern found. Check if there is a delta entry for this connection
+      if(entry = get_delta_entry(table, delta_key)) 
+        {
+          if (direction == CN_OUTGOING) 
+            {
+              hdr->u.tcp.seq = htonl(ntohl(hdr->u.tcp.seq) + entry->delta_out);
+              hdr->u.tcp.ack_seq = htonl(ntohl(hdr->u.tcp.ack_seq) - entry->delta_in);
+            } 
+          else 
+            {
+              hdr->u.tcp.seq = htonl(ntohl(hdr->u.tcp.seq) + entry->delta_in);
+              hdr->u.tcp.ack_seq = htonl(ntohl(hdr->u.tcp.ack_seq) - entry->delta_out);
+            }
+
+          //Update TCP checksum
+          hdr->u.tcp.check = 0;
+
+          uint16_t tot_len = ntohs(hdr->ip.tot_len);
+          uint16_t head_len = OPENVPN_IPH_GET_LEN(hdr->ip.version_len);
+
+          uint16_t check = tcp_checksum(BPTR (ipbuf) + head_len, 
+          tot_len - head_len, hdr->ip.saddr, hdr->ip.daddr); 
+
+          hdr->u.tcp.check = htons(check);
+
+          //Update timestamp entry on delta entry
+          entry->timestamp = get_timestamp();
+
+          // If it is a FIN package, then remove entry from delta table
+          if (OPENVPN_TCPH_FIN_MASK & hdr->u.tcp.flags) 
+            {
+              entry->marked_to_remove = 1;
+              msg (M_INFO, "Delta marked to be removed!");
+            }
+  
+          ret = 1; 
+        }
+      else 
+        {
+#if DEBUG_DELTA
+          // Regular package!
+          msg (M_INFO, "Regular package!: tot_len %d, seq %x, ack %x\n", ntohs(hdr->ip.tot_len), ntohl(hdr->u.tcp.seq), ntohl(hdr->u.tcp.ack_seq));
+#endif
+        }
+    }
+
+#if DEBUG_DELTA
+  msg (M_INFO, "TCP DATA AFTER NAT:");
+  hexdump(tcp_data, BLEN(&tcpbuf));
+#endif
+
+  return ret;
+}
+
 void
 client_nat_transform (const struct client_nat_option_list *list,
-      struct buffer *ipbuf,
-      const int direction)
+          struct buffer *ipbuf,
+          const int direction, 
+          const bool enable_nat_ftp_support)
 {
   struct ip_tcp_udp_hdr *h = (struct ip_tcp_udp_hdr *) BPTR (ipbuf);
   int i;
-  uint32_t addr, *addr_ptr;
+  uint32_t addr, *addr_ptr, from_addr;
   const uint32_t *from, *to;
   int accumulate = 0;
   unsigned int amask;
   unsigned int alog = 0;
 
+  uint32_t orig_saddr = h->ip.saddr;
+  uint32_t orig_daddr = h->ip.daddr;
+
   if (check_debug_level (D_CLIENT_NAT))
     print_pkt (&h->ip, "BEFORE", direction, D_CLIENT_NAT);
 
<at> <at> -212,65 +879,81 <at> <at> client_nat_transform (const struct client_nat_option_list *list,
     {
       const struct client_nat_entry *e = &list->entries[i]; /* current NAT rule */
       if (e->type ^ direction)
- {
-  addr = *(addr_ptr = &h->ip.daddr);
-  amask = 2;
- }
+        {
+          addr = *(addr_ptr = &h->ip.daddr);
+          amask = 2;
+        }
       else
- {
-  addr = *(addr_ptr = &h->ip.saddr);
-  amask = 1;
- }
+        {
+          addr = *(addr_ptr = &h->ip.saddr);
+          amask = 1;
+        }
       if (direction)
- {
-  from = &e->foreign_network;
-  to = &e->network;
- }
+        {
+          from = &e->foreign_network;
+          to = &e->network;
+        }
       else
- {
-  from = &e->network;
-  to = &e->foreign_network;
- }
+        {
+          from = &e->network;
+          to = &e->foreign_network;
+        }
 
       if (((addr & e->netmask) == *from) && !(amask & alog))
- {
-  /* pre-adjust IP checksum */
-  ADD_CHECKSUM_32(accumulate, addr);
+        {
+          from_addr = *from;
+    
+          /* pre-adjust IP checksum */
+          ADD_CHECKSUM_32(accumulate, addr);
 
-  /* do NAT transform */
-  addr = (addr & ~e->netmask) | *to;
+          /* do NAT transform */
+          addr = (addr & ~e->netmask) | *to;
 
-  /* post-adjust IP checksum */
-  SUB_CHECKSUM_32(accumulate, addr);
+          /* post-adjust IP checksum */
+          SUB_CHECKSUM_32(accumulate, addr);
 
-  /* write the modified address to packet */
-  *addr_ptr = addr;
+          /* write the modified address to packet */
+          *addr_ptr = addr;
 
-  /* mark as modified */
-  alog |= amask;
- }
+          /* mark as modified */
+          alog |= amask;
+        }
     }
   if (alog)
     {
       if (check_debug_level (D_CLIENT_NAT))
- print_pkt (&h->ip, "AFTER", direction, 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);
-    }
- }
+        {
+          if (BLEN(ipbuf) >= sizeof(struct openvpn_iphdr) + sizeof(struct openvpn_tcphdr))
+            {
+              ADJUST_CHECKSUM(accumulate, h->u.tcp.check);
+            }
+
+          uint32_t repl_addr = addr;
+      
+          if (amask == 2) 
+            {
+              if (direction)
+                repl_addr = orig_saddr;
+              else
+                repl_addr = orig_daddr;
+            }
+      
+          if (enable_nat_ftp_support)
+            client_nat_ftp_transform(ipbuf, direction, from_addr, repl_addr);
+    
+        }
       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);
-    }
- }
+        {
+          if (BLEN(ipbuf) >= sizeof(struct openvpn_iphdr) + sizeof(struct openvpn_udphdr))
+           {
+              ADJUST_CHECKSUM(accumulate, h->u.udp.check);
+            }
+        }
     }
 }
 
<at> <at> -297,7 +980,7 <at> <at> update_localhost_nat(struct client_nat_option_list *dest, in_addr_t local_ip)
           addr.s_addr = nat_entry->network;
           char *dot_ip = inet_ntoa(addr);
 
-          msg (M_INFO, "Updating NAT table from localhost to: %s", dot_ip); 
+          msg (M_INFO, "CNAT - Updating NAT table from localhost to: %s", dot_ip); 
           ret = true;
         }
     }
diff --git a/src/openvpn/clinat.h b/src/openvpn/clinat.h
index ce995d9..a58da5d 100755
--- a/src/openvpn/clinat.h
+++ b/src/openvpn/clinat.h
<at> <at> -52,15 +52,16 <at> <at> void copy_client_nat_option_list (struct client_nat_option_list *dest, const str
 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);
+            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);
+            struct buffer *ipbuf,
+            const int direction,
+            const bool enable_nat_ftp_support);
 
 bool update_localhost_nat(struct client_nat_option_list *dest, in_addr_t local_ip);
 
diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c
old mode 100644
new mode 100755
index 217fbb3..615db7a
--- a/src/openvpn/forward.c
+++ b/src/openvpn/forward.c
<at> <at> -980,9 +980,6 <at> <at> process_incoming_tun (struct context *c)
 
   perf_push (PERF_PROC_IN_TUN);
 
-  if (c->c2.buf.len > 0)
-    c->c2.tun_read_bytes += c->c2.buf.len;
-
 #ifdef LOG_RW
   if (c->c2.log_rw && c->c2.buf.len > 0)
     fprintf (stderr, "r");
<at> <at> -999,6 +996,9 <at> <at> process_incoming_tun (struct context *c)
        */
       process_ip_header (c, PIPV4_PASSTOS|PIP_MSSFIX|PIPV4_CLIENT_NAT, &c->c2.buf);
 
+      if (c->c2.buf.len > 0)
+        c->c2.tun_read_bytes += c->c2.buf.len;
+
 #ifdef PACKET_TRUNCATION_CHECK
       /* if (c->c2.buf.len > 1) --c->c2.buf.len; */
       ipv4_packet_size_verify (BPTR (&c->c2.buf),
<at> <at> -1041,43 +1041,44 <at> <at> process_ip_header (struct context *c, unsigned int flags, struct buffer *buf)
 #else
       if (flags & PIP_MSSFIX)
 #endif
- {
-  struct buffer ipbuf = *buf;
-  if (is_ipv4 (TUNNEL_TYPE (c->c1.tuntap), &ipbuf))
-    {
-#if PASSTOS_CAPABILITY
-      /* extract TOS from IP header */
-      if (flags & PIPV4_PASSTOS)
- link_socket_extract_tos (c->c2.link_socket, &ipbuf);
-#endif
-  
-      /* possibly alter the TCP MSS */
-      if (flags & PIP_MSSFIX)
- mss_fixup_ipv4 (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame)));
+        {
+          if (is_ipv4 (TUNNEL_TYPE (c->c1.tuntap), buf))
+            {
 
 #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);
- }
+              /* 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, buf, direction, c->options.enable_nat_ftp_support);
+                }
 #endif
-      /* possibly extract a DHCP router message */
-      if (flags & PIPV4_EXTRACT_DHCP_ROUTER)
- {
-  const in_addr_t dhcp_router = dhcp_extract_router_msg (&ipbuf);
-  if (dhcp_router)
-    route_list_add_vpn_gateway (c->c1.route_list, c->c2.es, dhcp_router);
- }
-    }
-  else if (is_ipv6 (TUNNEL_TYPE (c->c1.tuntap), &ipbuf))
-    {
-      /* possibly alter the TCP MSS */
-      if (flags & PIP_MSSFIX)
- mss_fixup_ipv6 (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame)));
-    }
- }
+
+#if PASSTOS_CAPABILITY
+              /* extract TOS from IP header */
+              if (flags & PIPV4_PASSTOS)
+                link_socket_extract_tos (c->c2.link_socket, buf);
+#endif
+
+              /* possibly alter the TCP MSS */
+              if (flags & PIP_MSSFIX)
+                mss_fixup_ipv4 (buf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame)));
+
+              /* possibly extract a DHCP router message */
+              if (flags & PIPV4_EXTRACT_DHCP_ROUTER)
+                {
+                  const in_addr_t dhcp_router = dhcp_extract_router_msg (buf);
+                  if (dhcp_router)
+                    route_list_add_vpn_gateway (c->c1.route_list, c->c2.es, dhcp_router);
+                }
+            }
+          else if (is_ipv6 (TUNNEL_TYPE (c->c1.tuntap), buf))
+            {
+              /* possibly alter the TCP MSS */
+              if (flags & PIP_MSSFIX)
+                mss_fixup_ipv6 (buf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame)));
+            }
+        }
     }
 }
 
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
old mode 100644
new mode 100755
index 007bd8c..73b615a
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
<at> <at> -236,6 +236,7 <at> <at> static const char usage_message[] =
   "                  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"
+  "--enable-nat-ftp-support : Enable NAT FTP Support, updating the IP address on FTP PORT commands or PASV responses\n"  
 #endif
 #ifdef ENABLE_PUSH_PEER_INFO
   "--push-peer-info : (client only) push client info to server.\n"
<at> <at> -789,6 +790,11 <at> <at> init_options (struct options *o, const bool init_gc)
   o->max_routes = MAX_ROUTES_DEFAULT;
   o->resolve_retry_seconds = RESOLV_RETRY_INFINITE;
   o->proto_force = -1;
+
+#ifdef ENABLE_CLIENT_NAT
+  o->enable_nat_ftp_support = false;
+#endif
+  
 #ifdef ENABLE_OCC
   o->occ = true;
 #endif
<at> <at> -1535,6 +1541,8 <at> <at> show_settings (const struct options *o)
 #ifdef ENABLE_CLIENT_NAT
   if (o->client_nat)
     print_client_nat_list(o->client_nat, D_SHOW_PARMS);
+
+  SHOW_BOOL(enable_nat_ftp_support);
 #endif
 
 #ifdef ENABLE_MANAGEMENT
<at> <at> -5287,6 +5295,10 <at> <at> add_option (struct options *options,
       cnol_check_alloc (options);
       add_client_nat_to_option_list(options->client_nat, p[1], p[2], p[3], p[4], msglevel);
     }
+  else if (streq (p[0], "enable_nat_ftp_support"))
+    {
+      options->enable_nat_ftp_support = true;
+    }
 #endif
   else if (streq (p[0], "route") && p[1])
     {
diff --git a/src/openvpn/options.h b/src/openvpn/options.h
old mode 100644
new mode 100755
index af9a47f..2b27368
--- a/src/openvpn/options.h
+++ b/src/openvpn/options.h
<at> <at> -347,6 +347,7 <at> <at> struct options
   bool allow_pull_fqdn; /* as a client, allow server to push a FQDN for certain parameters */
 
 #ifdef ENABLE_CLIENT_NAT
+  bool enable_nat_ftp_support;
   struct client_nat_option_list *client_nat;
 #endif
 
-- 
1.7.9.5


From 0aa64f57ecf653cd067dbef2b2378bdfc4f9a754 Mon Sep 17 00:00:00 2001
Date: Fri, 14 Aug 2015 16:46:13 -0300
Subject: [PATCH] Removed debug messages.


Signed-off-by: Rafael Gava <rafael.oliveira <at> venturus.org.br>
---
 src/openvpn/clinat.c |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/openvpn/clinat.c b/src/openvpn/clinat.c
index 1d213f5..991ea75 100755
--- a/src/openvpn/clinat.c
+++ b/src/openvpn/clinat.c
<at> <at> -833,7 +833,9 <at> <at> client_nat_ftp_transform(struct buffer *ipbuf,
           if (OPENVPN_TCPH_FIN_MASK & hdr->u.tcp.flags) 
             {
               entry->marked_to_remove = 1;
+#if DEBUG_DELTA              
               msg (M_INFO, "Delta marked to be removed!");
+#endif
             }
   
           ret = 1; 
-- 
1.7.9.5


From cf7af4e4784c83a64b8c1e12601d33bdc5b14d59 Mon Sep 17 00:00:00 2001
Date: Thu, 20 Aug 2015 08:47:08 -0300
Subject: [PATCH] Fixed FTP NAT IP address.


Signed-off-by: Rafael Gava <rafael.oliveira <at> venturus.org.br>
---
 src/openvpn/clinat.c |   30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/src/openvpn/clinat.c b/src/openvpn/clinat.c
index 991ea75..ef400de 100755
--- a/src/openvpn/clinat.c
+++ b/src/openvpn/clinat.c
<at> <at> -423,7 +423,7 <at> <at> static int try_number(const char *data, size_t dlen, uint32_t array[],
       if (*data == term && i == array_size - 1)
         return len;
 
-      msg (M_ERRNO, "CNAT - try_number - Char %u (got %u nums) `%u' unexpected\n", len, i, *data);
+      msg (M_ERRNO, "CNAT - try_number - Char %u (got %u nums) '%u' unexpected\n", len, i, *data);
       return 0;
     }
   }
<at> <at> -433,7 +433,7 <at> <at> static int try_number(const char *data, size_t dlen, uint32_t array[],
   return 0;
 }
 
-static int try_rfc959(const char *, size_t, u_int32_t [], char);
+static int try_rfc959(const char *, size_t, uint32_t [], char);
 
 static struct ftp_search {
   int direction;
<at> <at> -441,7 +441,7 <at> <at> static struct ftp_search {
   size_t plen;
   char skip;
   char term;
-  int (*getnum)(const char *, size_t, u_int32_t[], char);
+  int (*getnum)(const char *, size_t, uint32_t[], char);
 } search[] = {
   {
     CN_OUTGOING,
<at> <at> -458,7 +458,7 <at> <at> static struct ftp_search {
 
 /* Returns 0, or length of numbers: 192,168,1,1,5,6 */
 static int 
-try_rfc959(const char *data, size_t dlen, u_int32_t array[6],
+try_rfc959(const char *data, size_t dlen, uint32_t array[6],
            char term)
 {
   return try_number(data, dlen, array, 6, ',', term);
<at> <at> -467,9 +467,9 <at> <at> try_rfc959(const char *data, size_t dlen, u_int32_t array[6],
 /* Grab port: number up to delimiter */
 static int 
 get_port(const char *data, int start, size_t dlen, char delim,
-        u_int32_t array[2])
+        uint32_t array[2])
 {
-  u_int16_t port = 0;
+  uint16_t port = 0;
   int i;
 
   for (i = start; i < dlen; i++) {
<at> <at> -496,13 +496,13 <at> <at> find_pattern(const char *data, size_t dlen,
       char skip, char term,
       unsigned int *numoff,
       unsigned int *numlen,
-      u_int32_t array[6],
-      int (*getnum)(const char *, size_t, u_int32_t[], char))
+      uint32_t array[6],
+      int (*getnum)(const char *, size_t, uint32_t[], char))
 {
   size_t i;
 
   if (check_debug_level (D_CLIENT_NAT))
-    msg (M_INFO, "CNAT - find_pattern %s: dlen = %u\n", pattern, dlen);
+    msg (M_INFO, "CNAT - find_pattern %s: dlen = %u\n", pattern, (uint32_t) dlen);
 
   if (dlen == 0)
     return 0;
<at> <at> -530,7 +530,7 <at> <at> find_pattern(const char *data, size_t dlen,
   i++;
 
   if (check_debug_level (D_CLIENT_NAT))
-    msg (M_INFO, "CNAT - Skipped up to `%c'!\n", skip);
+    msg (M_INFO, "CNAT - Skipped up to '%c' (%d)!\n", skip, skip);
 
   *numoff = i;
   *numlen = getnum(data + i, dlen - i, array, term);
<at> <at> -652,7 +652,7 <at> <at> client_nat_ftp_transform(struct buffer *ipbuf,
   hexdump(tcp_data, BLEN(&tcpbuf));    
 #endif
 
-  u_int32_t matchlen, matchoff;
+  uint32_t matchlen, matchoff;
   int found_pattern = -1;
   int i = 0;
 
<at> <at> -689,7 +689,7 <at> <at> client_nat_ftp_transform(struct buffer *ipbuf,
       uint8_t new_tcp_data[32];
       memset(&new_tcp_data[0], 0, sizeof(new_tcp_data));
 
-      int new_len = sprintf((char *) &new_tcp_data[0], "%d,%d,%d,%d,%d,%d%.*s",
+      int new_len = sprintf((char *) &new_tcp_data[0], "%03d,%03d,%03d,%03d,%03d,%03d%.*s",
         addr_tmp[0], addr_tmp[1], addr_tmp[2], addr_tmp[3], array[4], array[5], 
         data_len - matchlen, (char *)&tcp_data[matchoff + matchlen]);
 
<at> <at> -700,7 +700,7 <at> <at> client_nat_ftp_transform(struct buffer *ipbuf,
         }
 
       //If the new len is greater than the old, there will be there an adjustment
-      if (new_len > data_len) 
+      if (replace_address != ip && new_len > data_len) 
         {
           //If the entry already exists
           if (entry = get_delta_entry(table, delta_key)) 
<at> <at> -765,8 +765,8 <at> <at> client_nat_ftp_transform(struct buffer *ipbuf,
         }
       else
         {
-          // The replace size is the lesser or iqual the original? Pad with 0 if necessary.
-          memcpy(&tcp_data[matchoff], new_tcp_data, data_len); 
+          if (replace_address != ip)
+            memcpy(&tcp_data[matchoff], new_tcp_data, data_len); 
 
           //If the entry already exists
           if (entry = get_delta_entry(table, delta_key)) 
-- 
1.7.9.5


From 63b1ddad1628eb1a179c2bf5010b781284d2bc4f Mon Sep 17 00:00:00 2001
Date: Sat, 15 Aug 2015 16:58:45 -0300
Subject: [PATCH] Fixed options parameter name enable-nat-ftp-support.


Signed-off-by: Rafael Gava <rafael.oliveira <at> venturus.org.br>
---
 src/openvpn/options.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index 73b615a..1a012e4 100755
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
<at> <at> -5295,7 +5295,7 <at> <at> add_option (struct options *options,
       cnol_check_alloc (options);
       add_client_nat_to_option_list(options->client_nat, p[1], p[2], p[3], p[4], msglevel);
     }
-  else if (streq (p[0], "enable_nat_ftp_support"))
+  else if (streq (p[0], "enable-nat-ftp-support"))
     {
       options->enable_nat_ftp_support = true;
     }
-- 
1.7.9.5


From 2f5ac96c0c2c5d9d06a11e0b08ae958e09c2e9b5 Mon Sep 17 00:00:00 2001
Date: Mon, 24 Aug 2015 09:15:34 -0300
Subject: [PATCH] Allows set yes/no option to enable-nat-ftp-support feature.


Signed-off-by: Rafael Gava <rafael.oliveira <at> venturus.org.br>
---
 src/openvpn/options.c |   21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index 1a012e4..4d73d87 100755
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
<at> <at> -236,7 +236,9 <at> <at> static const char usage_message[] =
   "                  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"
-  "--enable-nat-ftp-support : Enable NAT FTP Support, updating the IP address on FTP PORT commands or PASV responses\n"  
+  "--enable-nat-ftp-support : Enable NAT FTP Support, replacing the IP address on FTP PORT commands or PASV responses?\n"  
+  "                  'no'    -- No, disable this feature.\n"
+  "                  'yes'   -- Yes, enable this feature (Enabled by default on Windows).\n"
 #endif
 #ifdef ENABLE_PUSH_PEER_INFO
   "--push-peer-info : (client only) push client info to server.\n"
<at> <at> -792,8 +794,12 <at> <at> init_options (struct options *o, const bool init_gc)
   o->proto_force = -1;
 
 #ifdef ENABLE_CLIENT_NAT
+#ifdef WIN32
+  o->enable_nat_ftp_support = true;
+#else
   o->enable_nat_ftp_support = false;
 #endif
+#endif
   
 #ifdef ENABLE_OCC
   o->occ = true;
<at> <at> -5297,7 +5303,18 <at> <at> add_option (struct options *options,
     }
   else if (streq (p[0], "enable-nat-ftp-support"))
     {
-      options->enable_nat_ftp_support = true;
+      if (p[1])
+        {
+          if (streq (p[1], "yes"))
+            options->enable_nat_ftp_support = true;
+          else if (streq (p[1], "no"))
+            options->enable_nat_ftp_support = false;
+          else
+            {
+              msg (msglevel, "bad enable-nat-ftp-support option: %s -- must be 'yes' or 'no'", p[1]);
+              goto err;
+            }
+        }
     }
 #endif
   else if (streq (p[0], "route") && p[1])
-- 
1.7.9.5


------------------------------------------------------------------------------
_______________________________________________
Openvpn-devel mailing list
Openvpn-devel <at> lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel
Steffan Karger | 26 Aug 00:29 2015

[PATCH] Add missing strdup() return value checks

As reported by Bill Parker in trac #600, strdup() return values are not
always correctly checked for failed allocations.  This patch adds missing
checks.

Note that in misc.c and options.c, the check is after the dirname() or
basename() call, because these can deal with NULL params and we need to
keep MSVC happy with its ancient no-declaration-after-statement policy.

Signed-off-by: Steffan Karger <steffan <at> karger.me>
---
 src/openvpn/cryptoapi.c    | 1 +
 src/openvpn/init.c         | 1 +
 src/openvpn/misc.c         | 1 +
 src/openvpn/options.c      | 1 +
 src/openvpn/ssl_polarssl.c | 1 +
 5 files changed, 5 insertions(+)

diff --git a/src/openvpn/cryptoapi.c b/src/openvpn/cryptoapi.c
index b7fc11e..62f30be 100644
--- a/src/openvpn/cryptoapi.c
+++ b/src/openvpn/cryptoapi.c
 <at>  <at>  -127,6 +127,7  <at>  <at>  static char *ms_error_text(DWORD ms_err)
 		    break;
 	    }
     }
+    check_malloc_return(rv);
     return rv;
 }

diff --git a/src/openvpn/init.c b/src/openvpn/init.c
index b7c153b..0809cc7 100644
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
 <at>  <at>  -817,6 +817,7  <at>  <at>  init_options_dev (struct options *options)
 {
   if (!options->dev && options->dev_node) {
     char *dev_node = strdup(options->dev_node); /* POSIX basename() implementaions may modify its
arguments */
+    check_malloc_return(dev_node);
     options->dev = basename (dev_node);
   }
 }
diff --git a/src/openvpn/misc.c b/src/openvpn/misc.c
index a5bad0d..b543b65 100644
--- a/src/openvpn/misc.c
+++ b/src/openvpn/misc.c
 <at>  <at>  -1608,6 +1608,7  <at>  <at>  argv_extract_cmd_name (const char *path)
     {
       char *path_cp = strdup(path); /* POSIX basename() implementaions may modify its arguments */
       const char *bn = basename (path_cp);
+      check_malloc_return(path_cp);
       if (bn)
 	{
 	  char *ret = string_alloc (bn, NULL);
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index 2784580..dba7c9d 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
 <at>  <at>  -2588,6 +2588,7  <at>  <at>  check_file_access(const int type, const char *file, const int mode, const char *
     {
       char *fullpath = strdup(file);  /* POSIX dirname() implementaion may modify its arguments */
       char *dirpath = dirname(fullpath);
+      check_malloc_return(fullpath);

       if (platform_access (dirpath, mode|X_OK) != 0)
           errcode = errno;
diff --git a/src/openvpn/ssl_polarssl.c b/src/openvpn/ssl_polarssl.c
index 3fc811e..673dbbe 100644
--- a/src/openvpn/ssl_polarssl.c
+++ b/src/openvpn/ssl_polarssl.c
 <at>  <at>  -198,6 +198,7  <at>  <at>  tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers)
   /* Parse allowed ciphers, getting IDs */
   i = 0;
   tmp_ciphers_orig = tmp_ciphers = strdup(ciphers);
+  check_malloc_return(tmp_ciphers);

   token = strtok (tmp_ciphers, ":");
   while(token)
--

-- 
2.1.4

------------------------------------------------------------------------------
Boris Lytochkin | 24 Aug 18:54 2015
Picon

Log cert serial no if it is revoked

Hi.

Author: Boris Lytochkin <lytboris <at> yandex-team.ru>
Sponsored-by: Yandex LLC

Log serial number of revoked certificate

In most of situations admin of OpenVPN server needs to know which particular certificate is used by client.
In the case when certificate is OK, environment variable can be used for that but once it is revoked no user
scripts are invoked so there is no way to get serial number: only subject is printed in 
logs. Patch attached addresses this issue logging certificate directly on the line with certificate subject.

Tested with OpenSSL but PolarSSL should be good too.

Signed-off-by Boris Lytochkin <lytboris <at> yandex-team.ru>

-- 
Boris Lytochkin
Yandex NOC
+7 (495) 739 70 00 ext. 7671

diff --git a/src/openvpn/ssl_verify_openssl.c b/src/openvpn/ssl_verify_openssl.c
index 81b2e38..0a3cbe6 100644
--- a/src/openvpn/ssl_verify_openssl.c
+++ b/src/openvpn/ssl_verify_openssl.c
 <at>  <at>  -585,6 +585,7  <at>  <at>  x509_verify_crl(const char *crl_file, X509 *peer_cert, const char *subject)
   BIO *in=NULL;
   int n,i;
   result_t retval = FAILURE;
+  struct gc_arena gc = gc_new();

   in = BIO_new_file (crl_file, "r");

 <at>  <at>  -609,7 +610,7  <at>  <at>  x509_verify_crl(const char *crl_file, X509 *peer_cert, const char *subject)
   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(peer_cert)) == 0) {
-      msg (D_HANDSHAKE, "CRL CHECK FAILED: %s is REVOKED",subject);
+      msg (D_HANDSHAKE, "CRL CHECK FAILED: %s (serial %s) is REVOKED", subject,
backend_x509_get_serial_hex(peer_cert, &gc));
       goto end;
     }
   }
 <at>  <at>  -618,6 +619,7  <at>  <at>  x509_verify_crl(const char *crl_file, X509 *peer_cert, const char *subject)
   msg (D_HANDSHAKE, "CRL CHECK OK: %s",subject);

 end:
+  gc_free(&gc);
   BIO_free(in);
   if (crl)
     X509_CRL_free (crl);
diff --git a/src/openvpn/ssl_verify_polarssl.c b/src/openvpn/ssl_verify_polarssl.c
index 2edf21d..14730f2 100644
--- a/src/openvpn/ssl_verify_polarssl.c
+++ b/src/openvpn/ssl_verify_polarssl.c
 <at>  <at>  -373,6 +373,7  <at>  <at>  x509_verify_crl(const char *crl_file, x509_crt *cert, const char *subject)
 {
   result_t retval = FAILURE;
   x509_crl crl = {0};
+  struct gc_arena gc = gc_new();

   int polar_retval = x509_crl_parse_file(&crl, crl_file);
   if (polar_retval != 0)
 <at>  <at>  -394,7 +395,7  <at>  <at>  x509_verify_crl(const char *crl_file, x509_crt *cert, const char *subject)

   if (0 != x509_crt_revoked(cert, &crl))
     {
-      msg (D_HANDSHAKE, "CRL CHECK FAILED: %s is REVOKED", subject);
+      msg (D_HANDSHAKE, "CRL CHECK FAILED: %s (serial %s) is REVOKED", subject,
backend_x509_get_serial_hex(cert, &gc));
       goto end;
     }

 <at>  <at>  -402,6 +403,7  <at>  <at>  x509_verify_crl(const char *crl_file, x509_crt *cert, const char *subject)
   msg (D_HANDSHAKE, "CRL CHECK OK: %s",subject);

 end:
+  gc_free(&gc);
   x509_crl_free(&crl);
   return retval;
 }
------------------------------------------------------------------------------
_______________________________________________
Openvpn-devel mailing list
Openvpn-devel <at> lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel
Samuli Seppänen | 24 Aug 14:15 2015
Picon

Topics for today's (24th Aug 2015) community meeting

Hi,

We're going to have an IRC meeting today, 24th August, starting at
20:00 CEST (18:00 UTC) on #openvpn-devel <at> irc.freenode.net.
Current topic list along with basic information is here:

<https://community.openvpn.net/openvpn/wiki/Topics-2015-08-24>

If you have any other things you'd like to bring up, respond to this
mail, send me mail privately or add them to the list yourself.

In case you can't attend the meeting, please feel free to make comments
on the topics by responding to this email or to the summary email sent
after the meeting. Whenever possible, we'll also respond to existing,
related email threads.

NOTE: It's required to use a registered Freenode IRC nickname to join
#openvpn-devel - look here for details:

<https://community.openvpn.net/openvpn/wiki/GettingHelp#DeveloperIRCchannel>

--

-- 
Samuli Seppänen
Community Manager
OpenVPN Technologies, Inc

irc freenode net: mattock

------------------------------------------------------------------------------
naf.nafise2 | 15 Aug 14:22 2015
Picon

Could you help me


Sent from my iPad

------------------------------------------------------------------------------
Saeid Tasharoei | 12 Aug 02:32 2015
Picon

(no subject)

------------------------------------------------------------------------------
_______________________________________________
Openvpn-devel mailing list
Openvpn-devel <at> lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel
David Sommerseth | 11 Aug 18:41 2015
Picon

[PATCH v3 0/4] Reworking the interface for querying users

From: David Sommerseth <davids <at> redhat.com>

This is the third round of improving the API for querying users for information,
after it was discussed in the developer meeting August 10 2015.

The previous patch set can be found here:
 <http://thread.gmane.org/gmane.network.openvpn.devel/9657>

Most of the changes was in patch 1/4, where the most important changes are
replacing QUERY_USER_FOREACH macro with a for() loop and the query_user_init() 
function was changed to a void function which will do msg(M_FATAL,...) on
malloc() failures directly.  The QUERY_USER_FOREACH change also required a
minor adoptation in patch 2/4 too.

It was also reported build issues [1] if both systemd.pc and libsystemd.pc files
were installed.  This has also been fixed in patch 4/4.  The issue was that
the previous PKG_CHECK_MODULES() check would do call 
'pkg-config --modversion systemd libsystemd' which would return the mod-version
twice, separated by a newline.  The check for systemd, libsystemd and
libsystemd-daemon have now been split into separate checks.

[1] <http://thread.gmane.org/gmane.network.openvpn.devel/9657/focus=9661>

During the review it was also discovered that the announced --icon argument
was not present in patch 4/4.  This had just slipped in the patches sent to
the mailing list.

David Sommerseth (4):
  Rework the user input interface to make it more modular
  Re-implement the systemd support using the new query user API
  autotools: Add support for extracting version information from
    pkg-config modules
  systemd: Do not mask usernames when querying for it via
    systemd-ask-password

 configure.ac                  |  13 ++-
 m4/pkg.m4                     |   7 +-
 src/openvpn/Makefile.am       |  15 ++-
 src/openvpn/console.c         | 224 ++++++--------------------------------
 src/openvpn/console.h         |  83 +++++++++++++-
 src/openvpn/console_builtin.c | 246 ++++++++++++++++++++++++++++++++++++++++++
 src/openvpn/console_systemd.c | 119 ++++++++++++++++++++
 src/openvpn/misc.c            |  64 ++++++++---
 src/openvpn/pkcs11.c          |  12 ++-
 9 files changed, 562 insertions(+), 221 deletions(-)
 create mode 100644 src/openvpn/console_builtin.c
 create mode 100644 src/openvpn/console_systemd.c

--

-- 
1.8.3.1

------------------------------------------------------------------------------
Gergely Czuczy | 11 Aug 16:42 2015
Picon

SRV record support

Hello,

I would like to ask some help, I'm looking at the OpenVPN source tree
from GitHub as I would like to see how much effort would it be me to add
SRV record support, as it has increasing demand these days (and really
makes sense, especially for enterprises).

So, the question is, what would be the best place to hook up the support
for SRV records?
SRV record mechanism/requirements are the following:
  - It's protocol-specific, so at lookup time it has to be known whether
it's for UDP or TCP
  - The SRV records supply the service port, so in this case it's not
taken from the configuration file.
  - Basically for a service it's one or more DNS records in the
following format:
   _service._proto.name. TTL class SRV priority weight port target.
   I guess _service should be _openvpn, _proto is either _tcp or _udp.
port is obvious, and target is the target host to connect to using the
previously specified port.
   If there are multiple records, then priority makes sense, first the
hosts with the lowest values have to be tried, then rest increasingly
   If there are multiple hosts with the same priority then weight kicks
in, a host to be chosen is determined by the weight factors. Attempts to
a different priority can be made after all hosts from this priority are
exhausted.

So, basically first there has to be a lookup against the server's SRV
record, once that lookup returned results, and the priority/weight
algorithm returns the first candidate, the existing connection mechanism
can be used to check it. If it succeeds, life goes on as it is
currently, if it fails, then the prio/weight algorithm's next target has
to be tried.

So, where should I be looking at the source that would probably be a
good place to hook this up?

Thanks in advance,
Gergely

PS: Please see the wikipedia article on SRV records:
https://en.wikipedia.org/wiki/SRV_record

------------------------------------------------------------------------------
Samuli Seppänen | 10 Aug 15:24 2015
Picon

Topics for today's (Monday, 10th Aug 2015) community meeting

Hi,

We're going to have an IRC meeting today, 10th August, starting at 20:00 
CEST (18:00 UTC) on #openvpn-devel <at> irc.freenode.net. Current topic 
list along with basic information is here:

<https://community.openvpn.net/openvpn/wiki/Topics-2015-08-10>

If you have any other things you'd like to bring up, respond to this 
mail, send me mail privately or add them to the list yourself.

In case you can't attend the meeting, please feel free to make comments 
on the topics by responding to this email or to the summary email sent 
after the meeting. Whenever possible, we'll also respond to existing, 
related email threads.

NOTE: It's required to use a registered Freenode IRC nickname to join 
#openvpn-devel - look here for details:

<https://community.openvpn.net/openvpn/wiki/GettingHelp#DeveloperIRCchannel>

--

-- 
Samuli Seppänen
Community Manager
OpenVPN Technologies, Inc

irc freenode net: mattock

------------------------------------------------------------------------------
Bill Parker | 8 Aug 22:14 2015
Picon

Bug Tracker 590 Post Request

As requested, I'm sending these patch files to the mailing list for review...

INSTALL.patch adds some additional information to the current INSTALL file for OpenVPN-2.3.x

INSTALL-nonstandard.txt shows how to integrate OpenSSL/LZO unpacked from tarballs and built, with a successful build with OpenVPN-2.3.x

Bill Parker (wp02855 at gmail dot com)
Installing OpenVPN-2.3.8 with non-standard library/header file locations:

Occasionally, a user or developer may want to build OpenVPN using
source tarballs like LZO (real-time compression library), OpenSSL
(needed for encryption) (0.9.8 or higher, 1.0.2d is the latest
version as of this writing), PolarSSL (alternative encryption
library, version 1.1 or higher), LibPAM, or PKCS, etc.

The source code for LZO real-time compression library can be found at:

http://www.oberhumer.com/opensource/lzo/


The source code for the OpenSSL encryption library can be found at:

http://www.openssl.org


The source code for the PolarSSL encryption library can be found at:

https://polarssl.org/


Below are some variables which can be added to the './configure' line
to let GCC know where to find various header files and/or library files.

Variables with _CFLAGS typically take the following form:

nnn_CFLAGS="-I<path to include files>"

Note the '-I' before the <path to include files>

Variables with _LIBS typically take the following form:

nnn_LIBS="-L<path to library (static or shared) files>

Note the '-L' before the <path to library (static or shared) files>

also make sure to tell OpenVPN where to 'look' for the libraries
with -lssl and -lcrypto flags on your _LIBS options.

As an example, here is what the options would look for using OpenSSL
built from source tarball (which installs in /usr/local/ssl) and using
LZO built from source tarball:

./configure LZO_CFLAGS="-I/usr/local/include/lzo" \
		    LZO_LIS="--L/usr/local/lib" \
			OPENSSL_SSL_CFLAGS="-I/usr/local/ssl/include/openssl" \
			OPENSSL_SSL_LIBS="-L/usr/local/ssl/lib -lssl" \
			OPENSSL_CRYPTO_LIBS="-L/usr/local/ssl/lib -lcrypto" \
			OPENSSL_CRYPTO_CFLAGS="-I/usr/local/ssl/include/openssl"

Note: the above could also be entered on a single line with a space
between each option.

The CFLAGS option 'LZO_CFLAGS' specifies where the LZO header/include
files can be found by GCC, and the LIBS option 'LZO_LIBS' specifies
where the LZO library files can be found by GCC.

The above example is from a default install of LZO-2.0.9 using the
following build for LZO:

./configure; make; make check; make test; make install

As you can see, the CFLAGS option 'OPENSSL_SSL_CFLAGS/OPENSSL_CRYPTO_CFLAGS'
gives the full path where GCC can find the source header/include files for
OpenSSL and the LIBS option 'OPENSSL_SSL_LIBS/OPENSSL_CRYPTO_LIBS' gives
the full path where GCC can find the library files for OpenSSL.

The above example is from a default install of OpenSSL-1.0.2d using the
following build for OpenSSL:

./config; make; make test; make install

This also assumes you unpacked the source tarball(s) in
/usr/local/src, and you have the following layout below
(your operating system may have a different layout):

drwxr-xr-x.  2 root root 4096 Aug  3 19:57 bin
drwxr-xr-x.  2 root root 4096 Aug 16  2014 etc
drwxr-xr-x.  2 root root 4096 Aug 16  2014 games
drwxr-xr-x.  5 root root 4096 Aug  4 15:01 include
drwxr-xr-x.  7 root root 4096 Aug  4 15:01 lib
drwxr-xr-x.  4 root root 4096 Aug  3 19:57 lib64
drwxr-xr-x.  2 root root 4096 Aug 16  2014 libexec
drwxr-xr-x.  6 root root 4096 Aug  3 19:57 openssl
drwxr-xr-x.  2 root root 4096 Aug 16  2014 sbin
drwxr-xr-x.  6 root root 4096 Jul 31 19:25 share
drwxr-xr-x. 42 root root 4096 Aug  4 14:56 src
drwxr-xr-x.  9 root root 4096 Aug  4 14:03 ssl

Here is a sample of various flags below can be added
to the ./configure line as additional options:

LZO_LIBS				<full path to LZO static/shared library files>
LZO_CFLAGS				<full path to LZO include/header files>
POLARSSL_LIBS			<full path to PolarSSL static/shared library files>
POLARSSL_CFLAGS			<full path to PolarSSL include/header files>
OPENSSL_SSL_LIBS		<full path to OpenSSL SSL static/shared library files>
OPENSSL_SSL_CFLAGS		<full path to OpenSSL SSL include/header files>
OPENSSL_CRYPTO_LIBS		<full path to OpenSSL Crypto static/shared library files>
OPENSSL_CRYPTO_CFLAGS	<full path to OpenSSL Crypto include/header files>
PKCS11_HELPER_LIBS		<full path to PKCS11 Helper static/shared library files>
PKCS11_HELPER_CFLAGS	<full path to PKCS11 Helper include/header files>
LIBPAM_LIBS				<full path to PAM static/shared library files>
LIBPAM_CFLAGS			<full path to PAM library include/header files>

Here is an example if PAM/LibPam is build from source and the header files
are installed in /usr/local/pam/include and the library files are installed
in /usr/local/pam/lib:

./configure LIBPAM_CFLAGS="-I/usr/local/pam/include" LIBPAM_LIBS="-L/usr/local/pam/lib"

If the PAM library files were stored in '/usr/local/lib', and the header files were
stored in '/usr/local/include', the 'configure' line would look like this:

./configure LIBPAM_CFLAGS="-I/usr/local/include" LIBPAM_LIBS="-L/usr/local/lib"

Attachment (INSTALL.patch): application/octet-stream, 2370 bytes
------------------------------------------------------------------------------
_______________________________________________
Openvpn-devel mailing list
Openvpn-devel <at> lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Gmane