Bye bye Pluto!

Charon will take over IKEv1 duties from here.  This also removes
libfreeswan and whack.
This commit is contained in:
Tobias Brunner 2012-05-15 16:59:00 +02:00
parent 4a54860986
commit fff4b74db2
180 changed files with 41 additions and 69881 deletions

View File

@ -6,12 +6,10 @@ include $(CLEAR_VARS)
# build/target/product/core.mk
# possible executables are
# starter - allows to control and configure the daemons from the command line
# charon - the IKEv2 daemon
# pluto - the IKEv1 daemon
# charon - the IKE daemon
# if you enable starter and/or pluto (see above) uncomment the proper lines here
# if you enable starter (see above) uncomment this line too
# strongswan_BUILD_STARTER := true
# strongswan_BUILD_PLUTO := true
# this is the list of plugins that are built into libstrongswan and charon
# also these plugins are loaded by default (if not changed in strongswan.conf)
@ -19,20 +17,10 @@ strongswan_CHARON_PLUGINS := openssl fips-prf random pubkey pkcs1 \
pem xcbc hmac kernel-netlink socket-default android \
stroke eap-identity eap-mschapv2 eap-md5
ifneq ($(strongswan_BUILD_PLUTO),)
# if both daemons are enabled we use raw sockets in charon
strongswan_CHARON_PLUGINS := $(subst socket-default,socket-raw, \
$(strongswan_CHARON_PLUGINS))
# plugins loaded by pluto
strongswan_PLUTO_PLUGINS := openssl fips-prf random pubkey pkcs1 \
pem xcbc hmac kernel-netlink xauth
endif
strongswan_STARTER_PLUGINS := kernel-netlink
# list of all plugins - used to enable them with the function below
strongswan_PLUGINS := $(sort $(strongswan_CHARON_PLUGINS) \
$(strongswan_PLUTO_PLUGINS) \
$(strongswan_STARTER_PLUGINS))
# helper macros to only add source files for plugins included in the list above
@ -115,18 +103,10 @@ strongswan_BUILD := \
ifneq ($(strongswan_BUILD_STARTER),)
strongswan_BUILD += \
libfreeswan \
starter \
stroke \
ipsec
endif
ifneq ($(strongswan_BUILD_PLUTO),)
strongswan_BUILD += \
libfreeswan \
pluto \
whack
endif
include $(addprefix $(LOCAL_PATH)/src/,$(addsuffix /Android.mk, \
$(sort $(strongswan_BUILD))))

View File

@ -164,12 +164,9 @@ ARG_ENABL_SET([manager], [enable web management console (proof of concept
ARG_ENABL_SET([mediation], [enable IKEv2 Mediation Extension.])
ARG_ENABL_SET([integrity-test], [enable integrity testing of libstrongswan and plugins.])
ARG_DISBL_SET([load-warning], [disable the charon/pluto plugin load option warning in starter.])
ARG_ENABL_SET([pluto], [enable the IKEv1 keying daemon pluto.])
ARG_DISBL_SET([ikev1], [disable IKEv1 protocol support in charon.])
ARG_DISBL_SET([ikev2], [disable IKEv2 protocol support in charon.])
ARG_DISBL_SET([xauth], [disable xauth plugin.])
ARG_DISBL_SET([threads], [disable the use of threads in pluto. Charon always uses threads.])
ARG_DISBL_SET([adns], [disable the use of adns in pluto (disables opportunistic encryption).])
ARG_DISBL_SET([charon], [disable the IKEv1/IKEv2 keying daemon charon.])
ARG_DISBL_SET([tools], [disable additional utilities (openac, scepclient and pki).])
ARG_DISBL_SET([scripts], [disable additional utilities (found in directory scripts).])
@ -303,16 +300,6 @@ if test x$medcli = xtrue; then
mediation=true
fi
if test x$pluto = xtrue; then
if test x$socket_raw = xfalse; then
AC_MSG_NOTICE([Enforcing --enable-socket-raw, as pluto is enabled])
socket_raw=true
if test x$socket_default_given = xfalse; then
socket_default=false
fi
fi
fi
dnl ===========================================
dnl check required libraries and header files
dnl ===========================================
@ -789,7 +776,6 @@ m4_include(m4/macros/add-plugin.m4)
# plugin lists for all components
charon_plugins=
pluto_plugins=
starter_plugins=
pool_plugins=
attest_plugins=
@ -802,59 +788,57 @@ medsrv_plugins=
nm_plugins=
# location specific lists for checksumming,
# for src/libcharon, src/pluto, src/libhydra and src/libstrongswan
# for src/libcharon, src/libhydra and src/libstrongswan
c_plugins=
p_plugins=
h_plugins=
s_plugins=
ADD_PLUGIN([test-vectors], [s charon pluto openac scepclient pki])
ADD_PLUGIN([curl], [s charon pluto scepclient scripts nm])
ADD_PLUGIN([soup], [s charon pluto scripts nm])
ADD_PLUGIN([ldap], [s charon pluto scepclient scripts nm])
ADD_PLUGIN([mysql], [s charon pluto pool manager medsrv attest])
ADD_PLUGIN([sqlite], [s charon pluto pool manager medsrv attest])
ADD_PLUGIN([test-vectors], [s charon openac scepclient pki])
ADD_PLUGIN([curl], [s charon scepclient scripts nm])
ADD_PLUGIN([soup], [s charon scripts nm])
ADD_PLUGIN([ldap], [s charon scepclient scripts nm])
ADD_PLUGIN([mysql], [s charon pool manager medsrv attest])
ADD_PLUGIN([sqlite], [s charon pool manager medsrv attest])
ADD_PLUGIN([pkcs11], [s charon pki nm])
ADD_PLUGIN([aes], [s charon pluto openac scepclient pki scripts nm])
ADD_PLUGIN([des], [s charon pluto openac scepclient pki scripts nm])
ADD_PLUGIN([blowfish], [s charon pluto openac scepclient pki scripts nm])
ADD_PLUGIN([sha1], [s charon pluto openac scepclient pki scripts medsrv attest nm])
ADD_PLUGIN([sha2], [s charon pluto openac scepclient pki scripts medsrv attest nm])
ADD_PLUGIN([aes], [s charon openac scepclient pki scripts nm])
ADD_PLUGIN([des], [s charon openac scepclient pki scripts nm])
ADD_PLUGIN([blowfish], [s charon openac scepclient pki scripts nm])
ADD_PLUGIN([sha1], [s charon openac scepclient pki scripts medsrv attest nm])
ADD_PLUGIN([sha2], [s charon openac scepclient pki scripts medsrv attest nm])
ADD_PLUGIN([md4], [s charon openac manager scepclient pki nm])
ADD_PLUGIN([md5], [s charon pluto openac scepclient pki scripts attest nm])
ADD_PLUGIN([random], [s charon pluto openac scepclient pki scripts medsrv attest nm])
ADD_PLUGIN([md5], [s charon openac scepclient pki scripts attest nm])
ADD_PLUGIN([random], [s charon openac scepclient pki scripts medsrv attest nm])
ADD_PLUGIN([nonce], [s charon nm])
ADD_PLUGIN([x509], [s charon pluto openac scepclient pki scripts attest nm])
ADD_PLUGIN([x509], [s charon openac scepclient pki scripts attest nm])
ADD_PLUGIN([revocation], [s charon nm])
ADD_PLUGIN([constraints], [s charon nm])
ADD_PLUGIN([pubkey], [s charon])
ADD_PLUGIN([pkcs1], [s charon pluto openac scepclient pki scripts manager medsrv attest nm])
ADD_PLUGIN([pkcs8], [s charon pluto openac scepclient pki scripts manager medsrv attest nm])
ADD_PLUGIN([pgp], [s charon pluto])
ADD_PLUGIN([dnskey], [s pluto])
ADD_PLUGIN([pem], [s charon pluto openac scepclient pki scripts manager medsrv attest nm])
ADD_PLUGIN([pkcs1], [s charon openac scepclient pki scripts manager medsrv attest nm])
ADD_PLUGIN([pkcs8], [s charon openac scepclient pki scripts manager medsrv attest nm])
ADD_PLUGIN([pgp], [s charon])
ADD_PLUGIN([dnskey], [s charon])
ADD_PLUGIN([pem], [s charon openac scepclient pki scripts manager medsrv attest nm])
ADD_PLUGIN([padlock], [s charon])
ADD_PLUGIN([openssl], [s charon pluto openac scepclient pki scripts manager medsrv attest nm])
ADD_PLUGIN([gcrypt], [s charon pluto openac scepclient pki scripts manager medsrv attest nm])
ADD_PLUGIN([af-alg], [s charon pluto openac scepclient pki scripts medsrv attest nm])
ADD_PLUGIN([openssl], [s charon openac scepclient pki scripts manager medsrv attest nm])
ADD_PLUGIN([gcrypt], [s charon openac scepclient pki scripts manager medsrv attest nm])
ADD_PLUGIN([af-alg], [s charon openac scepclient pki scripts medsrv attest nm])
ADD_PLUGIN([fips-prf], [s charon nm])
ADD_PLUGIN([gmp], [s charon pluto openac scepclient pki scripts manager medsrv attest nm])
ADD_PLUGIN([gmp], [s charon openac scepclient pki scripts manager medsrv attest nm])
ADD_PLUGIN([agent], [s charon nm])
ADD_PLUGIN([xcbc], [s charon nm])
ADD_PLUGIN([cmac], [s charon nm])
ADD_PLUGIN([hmac], [s charon pluto scripts nm])
ADD_PLUGIN([hmac], [s charon scripts nm])
ADD_PLUGIN([ctr], [s charon scripts nm])
ADD_PLUGIN([ccm], [s charon scripts nm])
ADD_PLUGIN([gcm], [s charon scripts nm])
ADD_PLUGIN([xauth], [p pluto])
ADD_PLUGIN([attr], [h charon pluto])
ADD_PLUGIN([attr-sql], [h charon pluto])
ADD_PLUGIN([attr], [h charon])
ADD_PLUGIN([attr-sql], [h charon])
ADD_PLUGIN([load-tester], [c charon])
ADD_PLUGIN([kernel-pfkey], [h charon pluto starter nm])
ADD_PLUGIN([kernel-pfroute], [h charon pluto starter nm])
ADD_PLUGIN([kernel-klips], [h charon pluto starter])
ADD_PLUGIN([kernel-netlink], [h charon pluto starter nm])
ADD_PLUGIN([resolve], [h charon pluto])
ADD_PLUGIN([kernel-pfkey], [h charon starter nm])
ADD_PLUGIN([kernel-pfroute], [h charon starter nm])
ADD_PLUGIN([kernel-klips], [h charon starter])
ADD_PLUGIN([kernel-netlink], [h charon starter nm])
ADD_PLUGIN([resolve], [h charon])
ADD_PLUGIN([socket-default], [c charon nm])
ADD_PLUGIN([socket-raw], [c charon nm])
ADD_PLUGIN([socket-dynamic], [c charon])
@ -907,7 +891,6 @@ ADD_PLUGIN([addrblock], [c charon])
ADD_PLUGIN([unit-tester], [c charon])
AC_SUBST(charon_plugins)
AC_SUBST(pluto_plugins)
AC_SUBST(starter_plugins)
AC_SUBST(pool_plugins)
AC_SUBST(attest_plugins)
@ -1039,10 +1022,6 @@ AM_CONDITIONAL(USE_KERNEL_PFKEY, test x$kernel_pfkey = xtrue)
AM_CONDITIONAL(USE_KERNEL_PFROUTE, test x$kernel_pfroute = xtrue)
AM_CONDITIONAL(USE_RESOLVE, test x$resolve = xtrue)
dnl pluto plugins
dnl =============
AM_CONDITIONAL(USE_XAUTH, test x$xauth = xtrue)
dnl other options
dnl =============
AM_CONDITIONAL(USE_SMARTCARD, test x$smartcard = xtrue)
@ -1058,7 +1037,6 @@ AM_CONDITIONAL(USE_MANAGER, test x$manager = xtrue)
AM_CONDITIONAL(USE_ME, test x$mediation = xtrue)
AM_CONDITIONAL(USE_INTEGRITY_TEST, test x$integrity_test = xtrue)
AM_CONDITIONAL(USE_LOAD_WARNING, test x$load_warning = xtrue)
AM_CONDITIONAL(USE_PLUTO, test x$pluto = xtrue)
AM_CONDITIONAL(USE_IKEV1, test x$ikev1 = xtrue)
AM_CONDITIONAL(USE_IKEV2, test x$ikev2 = xtrue)
AM_CONDITIONAL(USE_THREADS, test x$threads = xtrue)
@ -1068,13 +1046,13 @@ AM_CONDITIONAL(USE_NM, test x$nm = xtrue)
AM_CONDITIONAL(USE_TOOLS, test x$tools = xtrue)
AM_CONDITIONAL(USE_SCRIPTS, test x$scripts = xtrue)
AM_CONDITIONAL(USE_CONFTEST, test x$conftest = xtrue)
AM_CONDITIONAL(USE_LIBSTRONGSWAN, test x$charon = xtrue -o x$pluto = xtrue -o x$tools = xtrue -o x$conftest = xtrue -o x$fast = xtrue -o x$imcv = xtrue -o x$nm = xtrue)
AM_CONDITIONAL(USE_LIBHYDRA, test x$charon = xtrue -o x$pluto = xtrue -o x$nm = xtrue)
AM_CONDITIONAL(USE_LIBSTRONGSWAN, test x$charon = xtrue -o x$tools = xtrue -o x$conftest = xtrue -o x$fast = xtrue -o x$imcv = xtrue -o x$nm = xtrue)
AM_CONDITIONAL(USE_LIBHYDRA, test x$charon = xtrue -o x$nm = xtrue)
AM_CONDITIONAL(USE_LIBCHARON, test x$charon = xtrue -o x$conftest = xtrue -o x$nm = xtrue)
AM_CONDITIONAL(USE_LIBTNCIF, test x$tnc_tnccs = xtrue -o x$imcv = xtrue)
AM_CONDITIONAL(USE_LIBTNCCS, test x$tnc_tnccs = xtrue)
AM_CONDITIONAL(USE_FILE_CONFIG, test x$pluto = xtrue -o x$stroke = xtrue)
AM_CONDITIONAL(USE_IPSEC_SCRIPT, test x$pluto = xtrue -o x$stroke = xtrue -o x$tools = xtrue -o x$conftest = xtrue)
AM_CONDITIONAL(USE_FILE_CONFIG, test x$stroke = xtrue)
AM_CONDITIONAL(USE_IPSEC_SCRIPT, test x$stroke = xtrue -o x$tools = xtrue -o x$conftest = xtrue)
AM_CONDITIONAL(USE_LIBCAP, test x$capabilities = xlibcap)
AM_CONDITIONAL(USE_VSTR, test x$vstr = xtrue)
AM_CONDITIONAL(USE_SIMAKA, test x$simaka = xtrue)
@ -1162,7 +1140,6 @@ AC_OUTPUT(
src/libhydra/plugins/kernel_pfkey/Makefile
src/libhydra/plugins/kernel_pfroute/Makefile
src/libhydra/plugins/resolve/Makefile
src/libfreeswan/Makefile
src/libsimaka/Makefile
src/libtls/Makefile
src/libradius/Makefile
@ -1176,9 +1153,6 @@ AC_OUTPUT(
src/libimcv/plugins/imv_test/Makefile
src/libimcv/plugins/imc_scanner/Makefile
src/libimcv/plugins/imv_scanner/Makefile
src/pluto/Makefile
src/pluto/plugins/xauth/Makefile
src/whack/Makefile
src/charon/Makefile
src/charon-nm/Makefile
src/libcharon/Makefile

View File

@ -41,17 +41,13 @@ if USE_LIBCHARON
endif
if USE_FILE_CONFIG
SUBDIRS += libfreeswan starter
SUBDIRS += starter
endif
if USE_IPSEC_SCRIPT
SUBDIRS += ipsec _copyright
endif
if USE_PLUTO
SUBDIRS += pluto whack
endif
if USE_CHARON
SUBDIRS += charon
endif
@ -69,7 +65,7 @@ if USE_UPDOWN
endif
if USE_TOOLS
SUBDIRS += libfreeswan openac scepclient pki
SUBDIRS += openac scepclient pki
endif
if USE_CONFTEST

View File

@ -79,11 +79,6 @@ if !MONOLITHIC
endif
endif
if USE_PLUTO
exes += $(top_builddir)/src/pluto/.libs/pluto
AM_CFLAGS += -DP_PLUGINS=\""${p_plugins}\""
endif
if USE_TOOLS
exes += $(top_builddir)/src/openac/.libs/openac
exes += $(top_builddir)/src/pki/.libs/pki

View File

@ -1,38 +0,0 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# copy-n-paste from Makefile.am
LOCAL_SRC_FILES := \
addrtoa.c addrtot.c addrtypeof.c anyaddr.c atoaddr.c atoasr.c \
atosubnet.c atoul.c copyright.c datatot.c freeswan.h \
goodmask.c initaddr.c initsaid.c initsubnet.c internal.h ipsec_param.h \
pfkey_v2_build.c pfkey_v2_debug.c \
pfkey_v2_ext_bits.c pfkey_v2_parse.c portof.c rangetoa.c \
pfkey.h pfkeyv2.h rangetosubnet.c sameaddr.c \
satot.c subnetof.c subnettoa.c subnettot.c \
subnettypeof.c ttoaddr.c ttodata.c ttoprotoport.c ttosa.c ttosubnet.c ttoul.c \
ultoa.c ultot.c
# build libfreeswan ------------------------------------------------------------
LOCAL_C_INCLUDES += \
$(libvstr_PATH) \
$(strongswan_PATH)/src/include \
$(strongswan_PATH)/src/libstrongswan \
$(strongswan_PATH)/src/libhydra \
$(strongswan_PATH)/src/pluto
LOCAL_CFLAGS := $(strongswan_CFLAGS)
LOCAL_MODULE := libfreeswan
LOCAL_MODULE_TAGS := optional
LOCAL_ARM_MODE := arm
LOCAL_PRELINK_MODULE := false
LOCAL_SHARED_LIBRARIES += libstrongswan
include $(BUILD_SHARED_LIBRARY)

View File

@ -1,22 +0,0 @@
noinst_LIBRARIES = libfreeswan.a
libfreeswan_a_SOURCES = \
addrtoa.c addrtot.c addrtypeof.c anyaddr.c atoaddr.c atoasr.c \
atosubnet.c atoul.c copyright.c datatot.c freeswan.h \
goodmask.c initaddr.c initsaid.c initsubnet.c internal.h ipsec_param.h \
pfkey_v2_build.c pfkey_v2_debug.c \
pfkey_v2_ext_bits.c pfkey_v2_parse.c portof.c rangetoa.c \
pfkey.h pfkeyv2.h rangetosubnet.c sameaddr.c \
satot.c subnetof.c subnettoa.c subnettot.c \
subnettypeof.c ttoaddr.c ttodata.c ttoprotoport.c ttosa.c ttosubnet.c ttoul.c \
ultoa.c ultot.c
INCLUDES = \
-I$(top_srcdir)/src/libstrongswan \
-I$(top_srcdir)/src/libhydra \
-I$(top_srcdir)/src/pluto
dist_man3_MANS = anyaddr.3 atoaddr.3 atoasr.3 atoul.3 goodmask.3 initaddr.3 initsubnet.3 \
portof.3 rangetosubnet.3 sameaddr.3 subnetof.3 \
ttoaddr.3 ttodata.3 ttosa.3 ttoul.3
EXTRA_DIST = Android.mk

View File

@ -1,66 +0,0 @@
/*
* addresses to ASCII
* Copyright (C) 1998, 1999 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include "internal.h"
#include "freeswan.h"
#define NBYTES 4 /* bytes in an address */
#define PERBYTE 4 /* three digits plus a dot or NUL */
#define BUFLEN (NBYTES*PERBYTE)
#if BUFLEN != ADDRTOA_BUF
#error "ADDRTOA_BUF in freeswan.h inconsistent with addrtoa() code"
#endif
/*
- addrtoa - convert binary address to ASCII dotted decimal
*/
size_t /* space needed for full conversion */
addrtoa(addr, format, dst, dstlen)
struct in_addr addr;
int format; /* character */
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
unsigned long a = ntohl(addr.s_addr);
int i;
size_t n;
unsigned long byte;
char buf[BUFLEN];
char *p;
switch (format) {
case 0:
break;
default:
return 0;
break;
}
p = buf;
for (i = NBYTES-1; i >= 0; i--) {
byte = (a >> (i*8)) & 0xff;
p += ultoa(byte, 10, p, PERBYTE);
if (i != 0)
*(p-1) = '.';
}
n = p - buf;
if (dstlen > 0) {
if (n > dstlen)
buf[dstlen - 1] = '\0';
strcpy(dst, buf);
}
return n;
}

View File

@ -1,302 +0,0 @@
/*
* addresses to text
* Copyright (C) 2000 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include <sys/socket.h>
#include "internal.h"
#include "freeswan.h"
#define IP4BYTES 4 /* bytes in an IPv4 address */
#define PERBYTE 4 /* three digits plus a dot or NUL */
#define IP6BYTES 16 /* bytes in an IPv6 address */
/* forwards */
static size_t normal4(const unsigned char *s, size_t len, char *b, char **dp);
static size_t normal6(const unsigned char *s, size_t len, char *b, char **dp, int squish);
static size_t reverse4(const unsigned char *s, size_t len, char *b, char **dp);
static size_t reverse6(const unsigned char *s, size_t len, char *b, char **dp);
/*
- addrtot - convert binary address to text (dotted decimal or IPv6 string)
*/
size_t /* space needed for full conversion */
addrtot(src, format, dst, dstlen)
const ip_address *src;
int format; /* character */
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
const unsigned char *b;
size_t n;
char buf[1+ADDRTOT_BUF+1]; /* :address: */
char *p;
int t = addrtypeof(src);
# define TF(t, f) (((t)<<8) | (f))
n = addrbytesptr(src, &b);
if (n == 0)
return 0;
switch (TF(t, format)) {
case TF(AF_INET, 0):
n = normal4(b, n, buf, &p);
break;
case TF(AF_INET6, 0):
n = normal6(b, n, buf, &p, 1);
break;
case TF(AF_INET, 'Q'):
n = normal4(b, n, buf, &p);
break;
case TF(AF_INET6, 'Q'):
n = normal6(b, n, buf, &p, 0);
break;
case TF(AF_INET, 'r'):
n = reverse4(b, n, buf, &p);
break;
case TF(AF_INET6, 'r'):
n = reverse6(b, n, buf, &p);
break;
default: /* including (AF_INET, 'R') */
return 0;
break;
}
if (dstlen > 0) {
if (dstlen < n)
p[dstlen - 1] = '\0';
strcpy(dst, p);
}
return n;
}
/*
- normal4 - normal IPv4 address-text conversion
*/
static size_t /* size of text, including NUL */
normal4(srcp, srclen, buf, dstp)
const unsigned char *srcp;
size_t srclen;
char *buf; /* guaranteed large enough */
char **dstp; /* where to put result pointer */
{
int i;
char *p;
if (srclen != IP4BYTES) /* "can't happen" */
return 0;
p = buf;
for (i = 0; i < IP4BYTES; i++) {
p += ultot(srcp[i], 10, p, PERBYTE);
if (i != IP4BYTES - 1)
*(p-1) = '.'; /* overwrites the NUL */
}
*dstp = buf;
return p - buf;
}
/*
- normal6 - normal IPv6 address-text conversion
*/
static size_t /* size of text, including NUL */
normal6(srcp, srclen, buf, dstp, squish)
const unsigned char *srcp;
size_t srclen;
char *buf; /* guaranteed large enough, plus 2 */
char **dstp; /* where to put result pointer */
int squish; /* whether to squish out 0:0 */
{
int i;
unsigned long piece;
char *p;
char *q;
if (srclen != IP6BYTES) /* "can't happen" */
return 0;
p = buf;
*p++ = ':';
for (i = 0; i < IP6BYTES/2; i++) {
piece = (srcp[2*i] << 8) + srcp[2*i + 1];
p += ultot(piece, 16, p, 5); /* 5 = abcd + NUL */
*(p-1) = ':'; /* overwrites the NUL */
}
*p = '\0';
q = strstr(buf, ":0:0:");
if (squish && q != NULL) { /* zero squishing is possible */
p = q + 1;
while (*p == '0' && *(p+1) == ':')
p += 2;
q++;
*q++ = ':'; /* overwrite first 0 */
while (*p != '\0')
*q++ = *p++;
*q = '\0';
if (!(*(q-1) == ':' && *(q-2) == ':'))
*--q = '\0'; /* strip final : unless :: */
p = buf;
if (!(*p == ':' && *(p+1) == ':'))
p++; /* skip initial : unless :: */
} else {
q = p;
*--q = '\0'; /* strip final : */
p = buf + 1; /* skip initial : */
}
*dstp = p;
return q - p + 1;
}
/*
- reverse4 - IPv4 reverse-lookup conversion
*/
static size_t /* size of text, including NUL */
reverse4(srcp, srclen, buf, dstp)
const unsigned char *srcp;
size_t srclen;
char *buf; /* guaranteed large enough */
char **dstp; /* where to put result pointer */
{
int i;
char *p;
if (srclen != IP4BYTES) /* "can't happen" */
return 0;
p = buf;
for (i = IP4BYTES-1; i >= 0; i--) {
p += ultot(srcp[i], 10, p, PERBYTE);
*(p-1) = '.'; /* overwrites the NUL */
}
strcpy(p, "IN-ADDR.ARPA.");
*dstp = buf;
return strlen(buf) + 1;
}
/*
- reverse6 - IPv6 reverse-lookup conversion (RFC 1886)
* A trifle inefficient, really shouldn't use ultot...
*/
static size_t /* size of text, including NUL */
reverse6(srcp, srclen, buf, dstp)
const unsigned char *srcp;
size_t srclen;
char *buf; /* guaranteed large enough */
char **dstp; /* where to put result pointer */
{
int i;
unsigned long piece;
char *p;
if (srclen != IP6BYTES) /* "can't happen" */
return 0;
p = buf;
for (i = IP6BYTES-1; i >= 0; i--) {
piece = srcp[i];
p += ultot(piece&0xf, 16, p, 2);
*(p-1) = '.';
p += ultot(piece>>4, 16, p, 2);
*(p-1) = '.';
}
strcpy(p, "IP6.ARPA.");
*dstp = buf;
return strlen(buf) + 1;
}
/*
- reverse6 - modern IPv6 reverse-lookup conversion (RFC 2874)
* this version removed as it was obsoleted in the end.
*/
#ifdef ADDRTOT_MAIN
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void regress(void);
int
main(int argc, char *argv[])
{
if (argc < 2) {
fprintf(stderr, "Usage: %s {addr|net/mask|begin...end|-r}\n",
argv[0]);
exit(2);
}
if (strcmp(argv[1], "-r") == 0) {
regress();
fprintf(stderr, "regress() returned?!?\n");
exit(1);
}
exit(0);
}
struct rtab {
char *input;
char format;
char *output; /* NULL means error expected */
} rtab[] = {
{"1.2.3.0", 0, "1.2.3.0"},
{"1:2::3:4", 0, "1:2::3:4"},
{"1:2::3:4", 'Q', "1:2:0:0:0:0:3:4"},
{"1:2:0:0:3:4:0:0", 0, "1:2::3:4:0:0"},
{"1.2.3.4", 'r' , "4.3.2.1.IN-ADDR.ARPA."},
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f */
{"1:2::3:4", 'r', "4.0.0.0.3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.1.0.0.0.IP6.ARPA."},
{NULL, 0, NULL}
};
void
regress()
{
struct rtab *r;
int status = 0;
ip_address a;
char in[100];
char buf[100];
const char *oops;
size_t n;
for (r = rtab; r->input != NULL; r++) {
strcpy(in, r->input);
/* convert it *to* internal format */
oops = ttoaddr(in, strlen(in), 0, &a);
/* now convert it back */
n = addrtot(&a, r->format, buf, sizeof(buf));
if (n == 0 && r->output == NULL)
{} /* okay, error expected */
else if (n == 0) {
printf("`%s' atoasr failed\n", r->input);
status = 1;
} else if (r->output == NULL) {
printf("`%s' atoasr succeeded unexpectedly '%c'\n",
r->input, r->format);
status = 1;
} else {
if (strcasecmp(r->output, buf) != 0) {
printf("`%s' '%c' gave `%s', expected `%s'\n",
r->input, r->format, buf, r->output);
status = 1;
}
}
}
exit(status);
}
#endif /* ADDRTOT_MAIN */

View File

@ -1,94 +0,0 @@
/*
* extract parts of an ip_address
* Copyright (C) 2000 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include <sys/socket.h>
#include "internal.h"
#include "freeswan.h"
/*
- addrtypeof - get the type of an ip_address
*/
int
addrtypeof(src)
const ip_address *src;
{
return src->u.v4.sin_family;
}
/*
- addrbytesptr - get pointer to the address bytes of an ip_address
*/
size_t /* 0 for error */
addrbytesptr(src, dstp)
const ip_address *src;
const unsigned char **dstp; /* NULL means just a size query */
{
const unsigned char *p;
size_t n;
switch (src->u.v4.sin_family) {
case AF_INET:
p = (const unsigned char *)&src->u.v4.sin_addr.s_addr;
n = 4;
break;
case AF_INET6:
p = (const unsigned char *)&src->u.v6.sin6_addr;
n = 16;
break;
default:
return 0;
break;
}
if (dstp != NULL)
*dstp = p;
return n;
}
/*
- addrlenof - get length of the address bytes of an ip_address
*/
size_t /* 0 for error */
addrlenof(src)
const ip_address *src;
{
return addrbytesptr(src, NULL);
}
/*
- addrbytesof - get the address bytes of an ip_address
*/
size_t /* 0 for error */
addrbytesof(src, dst, dstlen)
const ip_address *src;
unsigned char *dst;
size_t dstlen;
{
const unsigned char *p;
size_t n;
size_t ncopy;
n = addrbytesptr(src, &p);
if (n == 0)
return 0;
if (dstlen > 0) {
ncopy = n;
if (ncopy > dstlen)
ncopy = dstlen;
memcpy(dst, p, ncopy);
}
return n;
}

View File

@ -1,86 +0,0 @@
.TH IPSEC_ANYADDR 3 "8 Sept 2000"
.SH NAME
ipsec anyaddr \- get "any" address
.br
ipsec isanyaddr \- test address for equality to "any" address
.br
ipsec unspecaddr \- get "unspecified" address
.br
ipsec isunspecaddr \- test address for equality to "unspecified" address
.br
ipsec loopbackaddr \- get loopback address
.br
ipsec isloopbackaddr \- test address for equality to loopback address
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "const char *anyaddr(int af, ip_address *dst);"
.br
.B "int isanyaddr(const ip_address *src);"
.br
.B "const char *unspecaddr(int af, ip_address *dst);"
.br
.B "int isunspecaddr(const ip_address *src);"
.br
.B "const char *loopbackaddr(int af, ip_address *dst);"
.br
.B "int isloopbackaddr(const ip_address *src);"
.SH DESCRIPTION
These functions fill in, and test for, special values of the
.I ip_address
type.
.PP
.I Anyaddr
fills in the destination
.I *dst
with the ``any'' address of address family
.IR af
(normally
.B AF_INET
or
.BR AF_INET6 ).
The IPv4 ``any'' address is the one embodied in the old
.B INADDR_ANY
macro.
.PP
.I Isanyaddr
returns
.B 1
if the
.I src
address equals the ``any'' address,
and
.B 0
otherwise.
.PP
Similarly,
.I unspecaddr
supplies, and
.I isunspecaddr
tests for,
the ``unspecified'' address,
which may be the same as the ``any'' address.
.PP
Similarly,
.I loopbackaddr
supplies, and
.I islookbackaddr
tests for,
the loopback address.
.PP
.IR Anyaddr ,
.IR unspecaddr ,
and
.I loopbackaddr
return
.B NULL
for success and
a pointer to a string-literal error message for failure;
see DIAGNOSTICS.
.SH SEE ALSO
inet(3), ipsec_addrtot(3), ipsec_sameaddr(3)
.SH DIAGNOSTICS
Fatal errors in the address-supplying functions are:
unknown address family.
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.

View File

@ -1,147 +0,0 @@
/*
* special addresses
* Copyright (C) 2000 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include <sys/socket.h>
#include "internal.h"
#include "freeswan.h"
/* OpenSolaris defines strange versions of these macros */
#ifdef __sun
#undef IN6ADDR_ANY_INIT
#define IN6ADDR_ANY_INIT {{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }}}
#undef IN6ADDR_LOOPBACK_INIT
#define IN6ADDR_LOOPBACK_INIT {{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }}}
#endif
static struct in6_addr v6any = IN6ADDR_ANY_INIT;
static struct in6_addr v6loop = IN6ADDR_LOOPBACK_INIT;
/*
- anyaddr - initialize to the any-address value
*/
err_t /* NULL for success, else string literal */
anyaddr(af, dst)
int af; /* address family */
ip_address *dst;
{
uint32_t v4any = htonl(INADDR_ANY);
switch (af) {
case AF_INET:
return initaddr((unsigned char *)&v4any, sizeof(v4any), af, dst);
break;
case AF_INET6:
return initaddr((unsigned char *)&v6any, sizeof(v6any), af, dst);
break;
default:
return "unknown address family in anyaddr/unspecaddr";
break;
}
}
/*
- unspecaddr - initialize to the unspecified-address value
*/
err_t /* NULL for success, else string literal */
unspecaddr(af, dst)
int af; /* address family */
ip_address *dst;
{
return anyaddr(af, dst);
}
/*
- loopbackaddr - initialize to the loopback-address value
*/
err_t /* NULL for success, else string literal */
loopbackaddr(af, dst)
int af; /* address family */
ip_address *dst;
{
uint32_t v4loop = htonl(INADDR_LOOPBACK);
switch (af) {
case AF_INET:
return initaddr((unsigned char *)&v4loop, sizeof(v4loop), af, dst);
break;
case AF_INET6:
return initaddr((unsigned char *)&v6loop, sizeof(v6loop), af, dst);
break;
default:
return "unknown address family in loopbackaddr";
break;
}
}
/*
- isanyaddr - test for the any-address value
*/
int
isanyaddr(src)
const ip_address *src;
{
uint32_t v4any = htonl(INADDR_ANY);
int cmp;
switch (src->u.v4.sin_family) {
case AF_INET:
cmp = memcmp(&src->u.v4.sin_addr.s_addr, &v4any, sizeof(v4any));
break;
case AF_INET6:
cmp = memcmp(&src->u.v6.sin6_addr, &v6any, sizeof(v6any));
break;
default:
return 0;
break;
}
return (cmp == 0) ? 1 : 0;
}
/*
- isunspecaddr - test for the unspecified-address value
*/
int
isunspecaddr(src)
const ip_address *src;
{
return isanyaddr(src);
}
/*
- isloopbackaddr - test for the loopback-address value
*/
int
isloopbackaddr(src)
const ip_address *src;
{
uint32_t v4loop = htonl(INADDR_LOOPBACK);
int cmp;
switch (src->u.v4.sin_family) {
case AF_INET:
cmp = memcmp(&src->u.v4.sin_addr.s_addr, &v4loop, sizeof(v4loop));
break;
case AF_INET6:
cmp = memcmp(&src->u.v6.sin6_addr, &v6loop, sizeof(v6loop));
break;
default:
return 0;
break;
}
return (cmp == 0) ? 1 : 0;
}

View File

@ -1,291 +0,0 @@
.TH IPSEC_ATOADDR 3 "11 June 2001"
.SH NAME
ipsec atoaddr, addrtoa \- convert Internet addresses to and from ASCII
.br
ipsec atosubnet, subnettoa \- convert subnet/mask ASCII form to and from addresses
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "const char *atoaddr(const char *src, size_t srclen,"
.ti +1c
.B "struct in_addr *addr);"
.br
.B "size_t addrtoa(struct in_addr addr, int format,"
.ti +1c
.B "char *dst, size_t dstlen);"
.sp
.B "const char *atosubnet(const char *src, size_t srclen,"
.ti +1c
.B "struct in_addr *addr, struct in_addr *mask);"
.br
.B "size_t subnettoa(struct in_addr addr, struct in_addr mask,"
.ti +1c
.B "int format, char *dst, size_t dstlen);"
.SH DESCRIPTION
These functions are obsolete; see
.IR ipsec_ttoaddr (3)
for their replacements.
.PP
.I Atoaddr
converts an ASCII name or dotted-decimal address into a binary address
(in network byte order).
.I Addrtoa
does the reverse conversion, back to an ASCII dotted-decimal address.
.I Atosubnet
and
.I subnettoa
do likewise for the ``address/mask'' ASCII form used to write a
specification of a subnet.
.PP
An address is specified in ASCII as a
dotted-decimal address (e.g.
.BR 1.2.3.4 ),
an eight-digit network-order hexadecimal number with the usual C prefix (e.g.
.BR 0x01020304 ,
which is synonymous with
.BR 1.2.3.4 ),
an eight-digit host-order hexadecimal number with a
.B 0h
prefix (e.g.
.BR 0h01020304 ,
which is synonymous with
.B 1.2.3.4
on a big-endian host and
.B 4.3.2.1
on a little-endian host),
a DNS name to be looked up via
.IR getaddrinfo (3),
or an old-style network name to be looked up via
.IR getnetbyname (3).
.PP
A dotted-decimal address may be incomplete, in which case
ASCII-to-binary conversion implicitly appends
as many instances of
.B .0
as necessary to bring it up to four components.
The components of a dotted-decimal address are always taken as
decimal, and leading zeros are ignored.
For example,
.B 10
is synonymous with
.BR 10.0.0.0 ,
and
.B 128.009.000.032
is synonymous with
.BR 128.9.0.32
(the latter example is verbatim from RFC 1166).
The result of
.I addrtoa
is always complete and does not contain leading zeros.
.PP
The letters in
a hexadecimal address may be uppercase or lowercase or any mixture thereof.
Use of hexadecimal addresses is
.B strongly
.BR discouraged ;
they are included only to save hassles when dealing with
the handful of perverted programs which already print
network addresses in hexadecimal.
.PP
DNS names may be complete (optionally terminated with a ``.'')
or incomplete, and are looked up as specified by local system configuration
(see
.IR resolver (5)).
The first value returned by
.IR getaddrinfo (3)
is used,
so with current DNS implementations,
the result when the name corresponds to more than one address is
difficult to predict.
Name lookup resorts to
.IR getnetbyname (3)
only if
.IR getaddrinfo (3)
fails.
.PP
A subnet specification is of the form \fInetwork\fB/\fImask\fR.
The
.I network
and
.I mask
can be any form acceptable to
.IR atoaddr .
In addition, the
.I mask
can be a decimal integer (leading zeros ignored) giving a bit count,
in which case
it stands for a mask with that number of high bits on and all others off
(e.g.,
.B 24
means
.BR 255.255.255.0 ).
In any case, the mask must be contiguous
(a sequence of high bits on and all remaining low bits off).
As a special case, the subnet specification
.B %default
is a synonym for
.BR 0.0.0.0/0 .
.PP
.I Atosubnet
ANDs the mask with the address before returning,
so that any non-network bits in the address are turned off
(e.g.,
.B 10.1.2.3/24
is synonymous with
.BR 10.1.2.0/24 ).
.I Subnettoa
generates the decimal-integer-bit-count
form of the mask,
with no leading zeros,
unless the mask is non-contiguous.
.PP
The
.I srclen
parameter of
.I atoaddr
and
.I atosubnet
specifies the length of the ASCII string pointed to by
.IR src ;
it is an error for there to be anything else
(e.g., a terminating NUL) within that length.
As a convenience for cases where an entire NUL-terminated string is
to be converted,
a
.I srclen
value of
.B 0
is taken to mean
.BR strlen(src) .
.PP
The
.I dstlen
parameter of
.I addrtoa
and
.I subnettoa
specifies the size of the
.I dst
parameter;
under no circumstances are more than
.I dstlen
bytes written to
.IR dst .
A result which will not fit is truncated.
.I Dstlen
can be zero, in which case
.I dst
need not be valid and no result is written,
but the return value is unaffected;
in all other cases, the (possibly truncated) result is NUL-terminated.
The
.I freeswan.h
header file defines constants,
.B ADDRTOA_BUF
and
.BR SUBNETTOA_BUF ,
which are the sizes of buffers just large enough for worst-case results.
.PP
The
.I format
parameter of
.I addrtoa
and
.I subnettoa
specifies what format is to be used for the conversion.
The value
.B 0
(not the ASCII character
.BR '0' ,
but a zero value)
specifies a reasonable default,
and is in fact the only format currently available.
This parameter is a hedge against future needs.
.PP
The ASCII-to-binary functions return NULL for success and
a pointer to a string-literal error message for failure;
see DIAGNOSTICS.
The binary-to-ASCII functions return
.B 0
for a failure, and otherwise
always return the size of buffer which would
be needed to
accommodate the full conversion result, including terminating NUL;
it is the caller's responsibility to check this against the size of
the provided buffer to determine whether truncation has occurred.
.SH SEE ALSO
inet(3)
.SH DIAGNOSTICS
Fatal errors in
.I atoaddr
are:
empty input;
attempt to allocate temporary storage for a very long name failed;
name lookup failed;
syntax error in dotted-decimal form;
dotted-decimal component too large to fit in 8 bits.
.PP
Fatal errors in
.I atosubnet
are:
no
.B /
in
.IR src ;
.I atoaddr
error in conversion of
.I network
or
.IR mask ;
bit-count mask too big;
mask non-contiguous.
.PP
Fatal errors in
.I addrtoa
and
.I subnettoa
are:
unknown format.
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
The interpretation of incomplete dotted-decimal addresses
(e.g.
.B 10/24
means
.BR 10.0.0.0/24 )
differs from that of some older conversion
functions, e.g. those of
.IR inet (3).
The behavior of the older functions has never been
particularly consistent or particularly useful.
.PP
Ignoring leading zeros in dotted-decimal components and bit counts
is arguably the most useful behavior in this application,
but it might occasionally cause confusion with the historical use of leading
zeros to denote octal numbers.
.PP
It is barely possible that somebody, somewhere,
might have a legitimate use for non-contiguous subnet masks.
.PP
.IR Getnetbyname (3)
is a historical dreg.
.PP
The restriction of ASCII-to-binary error reports to literal strings
(so that callers don't need to worry about freeing them or copying them)
does limit the precision of error reporting.
.PP
The ASCII-to-binary error-reporting convention lends itself
to slightly obscure code,
because many readers will not think of NULL as signifying success.
A good way to make it clearer is to write something like:
.PP
.RS
.nf
.B "const char *error;"
.sp
.B "error = atoaddr( /* ... */ );"
.B "if (error != NULL) {"
.B " /* something went wrong */"
.fi
.RE

View File

@ -1,261 +0,0 @@
/*
* conversion from ASCII forms of addresses to internal ones
* Copyright (C) 1998, 1999 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include <sys/socket.h>
#include "internal.h"
#include "freeswan.h"
/*
* Define NOLEADINGZEROS to interpret 032 as an error, not as 32. There
* is deliberately no way to interpret it as 26 (i.e., as octal).
*/
/*
* Legal characters in a domain name. Underscore technically is not,
* but is a common misunderstanding.
*/
static const char namechars[] = "abcdefghijklmnopqrstuvwxyz0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ-_.";
static const char *try8hex(const char *, size_t, struct in_addr *);
static const char *try8hosthex(const char *, size_t, struct in_addr *);
static const char *trydotted(const char *, size_t, struct in_addr *);
static const char *getbyte(const char **, const char *, int *);
/*
- atoaddr - convert ASCII name or dotted-decimal address to binary address
*/
const char * /* NULL for success, else string literal */
atoaddr(src, srclen, addrp)
const char *src;
size_t srclen; /* 0 means "apply strlen" */
struct in_addr *addrp;
{
struct addrinfo hints, *res;
struct netent *ne = NULL;
const char *oops, *msg = NULL;
# define HEXLEN 10 /* strlen("0x11223344") */
# ifndef ATOADDRBUF
# define ATOADDRBUF 100
# endif
char namebuf[ATOADDRBUF];
char *p = namebuf;
char *q;
int error;
if (srclen == 0)
srclen = strlen(src);
if (srclen == 0)
return "empty string";
/* might it be hex? */
if (srclen == HEXLEN && *src == '0' && CIEQ(*(src+1), 'x'))
return try8hex(src+2, srclen-2, addrp);
if (srclen == HEXLEN && *src == '0' && CIEQ(*(src+1), 'h'))
return try8hosthex(src+2, srclen-2, addrp);
/* try it as dotted decimal */
oops = trydotted(src, srclen, addrp);
if (oops == NULL)
return NULL; /* it worked */
if (*oops != '?')
return oops; /* it *was* probably meant as a d.q. */
/* try it as a name -- first, NUL-terminate it */
if (srclen > sizeof(namebuf)-1) {
p = (char *) MALLOC(srclen+1);
if (p == NULL)
return "unable to allocate temporary space for name";
}
p[0] = '\0';
strncat(p, src, srclen);
/* next, check that it's a vaguely legal name */
for (q = p; *q != '\0'; q++)
{
if (!isprint(*q))
{
msg = "unprintable character in name";
goto error;
}
}
if (strspn(p, namechars) != srclen)
{
msg = "illegal (non-DNS-name) character in name";
goto error;
}
/* try as host name, failing that as /etc/networks network name */
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
error = getaddrinfo(p, NULL, &hints, &res);
if (error != 0)
{
ne = getnetbyname(p);
if (ne == NULL)
{
msg = "name lookup failed";
goto error;
}
addrp->s_addr = htonl(ne->n_net);
}
else
{
struct sockaddr_in *in = (struct sockaddr_in*)res->ai_addr;
memcpy(&addrp->s_addr, &in->sin_addr.s_addr, sizeof(addrp->s_addr));
freeaddrinfo(res);
}
error:
if (p != namebuf)
{
FREE(p);
}
return msg;
}
/*
- try8hosthex - try conversion as an eight-digit host-order hex number
*/
const char * /* NULL for success, else string literal */
try8hosthex(src, srclen, addrp)
const char *src;
size_t srclen; /* should be 8 */
struct in_addr *addrp;
{
const char *oops;
unsigned long addr;
if (srclen != 8)
return "internal error, try8hex called with bad length";
oops = atoul(src, srclen, 16, &addr);
if (oops != NULL)
return oops;
addrp->s_addr = addr;
return NULL;
}
/*
- try8hex - try conversion as an eight-digit network-order hex number
*/
const char * /* NULL for success, else string literal */
try8hex(src, srclen, addrp)
const char *src;
size_t srclen; /* should be 8 */
struct in_addr *addrp;
{
const char *oops;
oops = try8hosthex(src, srclen, addrp);
if (oops != NULL)
return oops;
addrp->s_addr = htonl(addrp->s_addr);
return NULL;
}
/*
- trydotted - try conversion as dotted decimal
*
* If the first char of a complaint is '?', that means "didn't look like
* dotted decimal at all".
*/
const char * /* NULL for success, else string literal */
trydotted(src, srclen, addrp)
const char *src;
size_t srclen;
struct in_addr *addrp;
{
const char *stop = src + srclen; /* just past end */
int byte;
const char *oops;
unsigned long addr;
int i;
# define NBYTES 4
# define BYTE 8
addr = 0;
for (i = 0; i < NBYTES && src < stop; i++) {
oops = getbyte(&src, stop, &byte);
if (oops != NULL) {
if (*oops != '?')
return oops; /* bad number */
if (i > 1)
return oops+1; /* failed number */
return oops; /* with leading '?' */
}
addr = (addr << BYTE) | byte;
if (i < 3 && src < stop && *src++ != '.') {
if (i == 0)
return "?syntax error in dotted-decimal address";
else
return "syntax error in dotted-decimal address";
}
}
addr <<= (NBYTES - i) * BYTE;
if (src != stop)
return "extra garbage on end of dotted-decimal address";
addrp->s_addr = htonl(addr);
return NULL;
}
/*
- getbyte - try to scan a byte in dotted decimal
* A subtlety here is that all this arithmetic on ASCII digits really is
* highly portable -- ANSI C guarantees that digits 0-9 are contiguous.
* It's easier to just do it ourselves than set up for a call to atoul().
*
* If the first char of a complaint is '?', that means "didn't look like a
* number at all".
*/
const char * /* NULL for success, else string literal */
getbyte(srcp, stop, retp)
const char **srcp; /* *srcp is updated */
const char *stop; /* first untouchable char */
int *retp; /* return-value pointer */
{
char c;
const char *p;
int no;
if (*srcp >= stop)
return "?empty number in dotted-decimal address";
if (stop - *srcp >= 3 && **srcp == '0' && CIEQ(*(*srcp+1), 'x'))
return "hex numbers not supported in dotted-decimal addresses";
#ifdef NOLEADINGZEROS
if (stop - *srcp >= 2 && **srcp == '0' && isdigit(*(*srcp+1)))
return "octal numbers not supported in dotted-decimal addresses";
#endif /* NOLEADINGZEROS */
/* must be decimal, if it's numeric at all */
no = 0;
p = *srcp;
while (p < stop && no <= 255 && (c = *p) >= '0' && c <= '9') {
no = no*10 + (c - '0');
p++;
}
if (p == *srcp)
return "?non-numeric component in dotted-decimal address";
*srcp = p;
if (no > 255)
return "byte overflow in dotted-decimal address";
*retp = no;
return NULL;
}

View File

@ -1,185 +0,0 @@
.TH IPSEC_ATOASR 3 "11 June 2001"
.SH NAME
ipsec atoasr \- convert ASCII to Internet address, subnet, or range
.br
ipsec rangetoa \- convert Internet address range to ASCII
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "const char *atoasr(const char *src, size_t srclen,"
.ti +1c
.B "char *type, struct in_addr *addrs);"
.br
.B "size_t rangetoa(struct in_addr *addrs, int format,
.ti +1c
.B "char *dst, size_t dstlen);"
.SH DESCRIPTION
These functions are obsolete;
there is no current equivalent,
because so far they have not proved useful.
.PP
.I Atoasr
converts an ASCII address, subnet, or address range
into a suitable combination of binary addresses
(in network byte order).
.I Rangetoa
converts an address range back into ASCII,
using dotted-decimal form for the addresses
(the other reverse conversions are handled by
.IR ipsec_addrtoa (3)
and
.IR ipsec_subnettoa (3)).
.PP
A single address can be any form acceptable to
.IR ipsec_atoaddr (3):
dotted decimal, DNS name, or hexadecimal number.
A subnet
specification uses the form \fInetwork\fB/\fImask\fR
interpreted by
.IR ipsec_atosubnet (3).
.PP
An address range is two
.IR ipsec_atoaddr (3)
addresses separated by a
.B ...
delimiter.
If there are four dots rather than three, the first is taken as
part of the begin address,
e.g. for a complete DNS name which ends with
.B .
to suppress completion attempts.
The begin address of a range must be
less than or equal to the end address.
.PP
The
.I srclen
parameter of
.I atoasr
specifies the length of the ASCII string pointed to by
.IR src ;
it is an error for there to be anything else
(e.g., a terminating NUL) within that length.
As a convenience for cases where an entire NUL-terminated string is
to be converted,
a
.I srclen
value of
.B 0
is taken to mean
.BR strlen(src) .
.PP
The
.I type
parameter of
.I atoasr
must point to a
.B char
variable used to record which form was found.
The
.I addrs
parameter must point to a two-element array of
.B "struct in_addr"
which receives the results.
The values stored into
.BR *type ,
and the corresponding values in the array, are:
.PP
.ta 3c +2c +3c
*type addrs[0] addrs[1]
.sp 0.8
address \&\fB'a'\fR address -
.br
subnet \&\fB's'\fR network mask
.br
range \&\fB'r'\fR begin end
.PP
The
.I dstlen
parameter of
.I rangetoa
specifies the size of the
.I dst
parameter;
under no circumstances are more than
.I dstlen
bytes written to
.IR dst .
A result which will not fit is truncated.
.I Dstlen
can be zero, in which case
.I dst
need not be valid and no result is written,
but the return value is unaffected;
in all other cases, the (possibly truncated) result is NUL-terminated.
The
.I freeswan.h
header file defines a constant,
.BR RANGETOA_BUF ,
which is the size of a buffer just large enough for worst-case results.
.PP
The
.I format
parameter of
.I rangetoa
specifies what format is to be used for the conversion.
The value
.B 0
(not the ASCII character
.BR '0' ,
but a zero value)
specifies a reasonable default,
and is in fact the only format currently available.
This parameter is a hedge against future needs.
.PP
.I Atoasr
returns NULL for success and
a pointer to a string-literal error message for failure;
see DIAGNOSTICS.
.I Rangetoa
returns
.B 0
for a failure, and otherwise
always returns the size of buffer which would
be needed to
accommodate the full conversion result, including terminating NUL;
it is the caller's responsibility to check this against the size of
the provided buffer to determine whether truncation has occurred.
.SH SEE ALSO
ipsec_atoaddr(3), ipsec_atosubnet(3)
.SH DIAGNOSTICS
Fatal errors in
.I atoasr
are:
empty input;
error in
.IR ipsec_atoaddr (3)
or
.IR ipsec_atosubnet (3)
during conversion;
begin address of range exceeds end address.
.PP
Fatal errors in
.I rangetoa
are:
unknown format.
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
The restriction of error reports to literal strings
(so that callers don't need to worry about freeing them or copying them)
does limit the precision of error reporting.
.PP
The error-reporting convention lends itself
to slightly obscure code,
because many readers will not think of NULL as signifying success.
A good way to make it clearer is to write something like:
.PP
.RS
.nf
.B "const char *error;"
.sp
.B "error = atoasr( /* ... */ );"
.B "if (error != NULL) {"
.B " /* something went wrong */"
.fi
.RE

View File

@ -1,210 +0,0 @@
/*
* convert from ASCII form of address/subnet/range to binary
* Copyright (C) 1998, 1999 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include "internal.h"
#include "freeswan.h"
/*
- atoasr - convert ASCII to address, subnet, or range
*/
const char * /* NULL for success, else string literal */
atoasr(src, srclen, typep, addrsp)
const char *src;
size_t srclen; /* 0 means "apply strlen" */
char *typep; /* return type code: 'a', 's', 'r' */
struct in_addr addrsp[2];
{
const char *punct;
const char *stop;
const char *oops;
if (srclen == 0)
srclen = strlen(src);
if (srclen == 0)
return "empty string";
/* subnet is easy to spot */
punct = memchr(src, '/', srclen);
if (punct != NULL) {
*typep = 's';
return atosubnet(src, srclen, &addrsp[0], &addrsp[1]);
}
/* try for a range */
stop = src + srclen;
for (punct = src; (punct = memchr(punct, '.', stop - punct)) != NULL;
punct++)
if (stop - punct > 3 && *(punct+1) == '.' && *(punct+2) == '.')
break; /* NOTE BREAK OUT */
if (punct == NULL) {
/* didn't find the range delimiter, must be plain address */
*typep = 'a';
return atoaddr(src, srclen, &addrsp[0]);
}
/* looks like a range */
*typep = 'r';
if (stop - punct > 4 && *(punct+3) == '.')
punct++; /* first dot is trailing dot of name */
oops = atoaddr(src, punct - src, &addrsp[0]);
if (oops != NULL)
return oops;
oops = atoaddr(punct+3, stop - (punct+3), &addrsp[1]);
if (oops != NULL)
return oops;
if (ntohl(addrsp[0].s_addr) > ntohl(addrsp[1].s_addr))
return "invalid range, begin > end";
return NULL;
}
#ifdef ATOASR_MAIN
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void regress(void);
int
main(int argc, char *argv[])
{
struct in_addr a[2];
char buf[100];
const char *oops;
size_t n;
char type;
if (argc < 2) {
fprintf(stderr, "Usage: %s {addr|net/mask|begin...end|-r}\n",
argv[0]);
exit(2);
}
if (strcmp(argv[1], "-r") == 0) {
regress();
fprintf(stderr, "regress() returned?!?\n");
exit(1);
}
oops = atoasr(argv[1], 0, &type, a);
if (oops != NULL) {
fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
exit(1);
}
switch (type) {
case 'a':
n = addrtoa(a[0], 0, buf, sizeof(buf));
break;
case 's':
n = subnettoa(a[0], a[1], 0, buf, sizeof(buf));
break;
case 'r':
n = rangetoa(a, 0, buf, sizeof(buf));
break;
default:
fprintf(stderr, "%s: unknown type '%c'\n", argv[0], type);
exit(1);
break;
}
if (n > sizeof(buf)) {
fprintf(stderr, "%s: reverse conversion of ", argv[0]);
fprintf(stderr, "%s ", inet_ntoa(a[0]));
fprintf(stderr, "%s", inet_ntoa(a[1]));
fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
(long)n, (long)sizeof(buf));
exit(1);
}
printf("%s\n", buf);
exit(0);
}
struct rtab {
char *input;
char *output; /* NULL means error expected */
} rtab[] = {
{"1.2.3.0", "1.2.3.0"},
{"1.2.3.0/255.255.255.0", "1.2.3.0/24"},
{"1.2.3.0...1.2.3.5", "1.2.3.0...1.2.3.5"},
{"1.2.3.4.5", NULL},
{"1.2.3.4/", NULL},
{"1.2.3.4...", NULL},
{"1.2.3.4....", NULL},
{"localhost/32", "127.0.0.1/32"},
{"localhost...127.0.0.3", "127.0.0.1...127.0.0.3"},
{"127.0.0.0...localhost", "127.0.0.0...127.0.0.1"},
{"127.0.0.3...localhost", NULL},
{NULL, NULL}
};
void
regress(void)
{
struct rtab *r;
int status = 0;
struct in_addr a[2];
char in[100];
char buf[100];
const char *oops;
size_t n;
char type;
for (r = rtab; r->input != NULL; r++) {
strcpy(in, r->input);
oops = atoasr(in, 0, &type, a);
if (oops != NULL && r->output == NULL)
{} /* okay, error expected */
else if (oops != NULL) {
printf("`%s' atoasr failed: %s\n", r->input, oops);
status = 1;
} else if (r->output == NULL) {
printf("`%s' atoasr succeeded unexpectedly '%c'\n",
r->input, type);
status = 1;
} else {
switch (type) {
case 'a':
n = addrtoa(a[0], 0, buf, sizeof(buf));
break;
case 's':
n = subnettoa(a[0], a[1], 0, buf, sizeof(buf));
break;
case 'r':
n = rangetoa(a, 0, buf, sizeof(buf));
break;
default:
fprintf(stderr, "`%s' unknown type '%c'\n",
r->input, type);
n = 0;
status = 1;
break;
}
if (n > sizeof(buf)) {
printf("`%s' '%c' reverse failed: need %ld\n",
r->input, type, (long)n);
status = 1;
} else if (n > 0 && strcmp(r->output, buf) != 0) {
printf("`%s' '%c' gave `%s', expected `%s'\n",
r->input, type, buf, r->output);
status = 1;
}
}
}
exit(status);
}
#endif /* ATOASR_MAIN */

View File

@ -1,214 +0,0 @@
/*
* convert from ASCII form of subnet specification to binary
* Copyright (C) 1998, 1999 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include "internal.h"
#include "freeswan.h"
#ifndef DEFAULTSUBNET
#define DEFAULTSUBNET "%default"
#endif
/*
- atosubnet - convert ASCII "addr/mask" to address and mask
* Mask can be integer bit count.
*/
const char * /* NULL for success, else string literal */
atosubnet(src, srclen, addrp, maskp)
const char *src;
size_t srclen; /* 0 means "apply strlen" */
struct in_addr *addrp;
struct in_addr *maskp;
{
const char *slash;
const char *mask;
size_t mlen;
const char *oops;
unsigned long bc;
static char def[] = DEFAULTSUBNET;
# define DEFLEN (sizeof(def) - 1) /* -1 for NUL */
static char defis[] = "0/0";
# define DEFILEN (sizeof(defis) - 1)
if (srclen == 0)
srclen = strlen(src);
if (srclen == 0)
return "empty string";
if (srclen == DEFLEN && strncmp(src, def, srclen) == 0) {
src = defis;
srclen = DEFILEN;
}
slash = memchr(src, '/', srclen);
if (slash == NULL)
return "no / in subnet specification";
mask = slash + 1;
mlen = srclen - (mask - src);
oops = atoaddr(src, slash-src, addrp);
if (oops != NULL)
return oops;
oops = atoul(mask, mlen, 10, &bc);
if (oops == NULL) {
/* atoul succeeded, it's a bit-count mask */
if (bc > ABITS)
return "bit-count mask too large";
#ifdef NOLEADINGZEROS
if (mlen > 1 && *mask == '0')
return "octal not allowed in mask";
#endif /* NOLEADINGZEROS */
*maskp = bitstomask((int)bc);
} else {
oops = atoaddr(mask, mlen, maskp);
if (oops != NULL)
return oops;
if (!goodmask(*maskp))
return "non-contiguous mask";
}
addrp->s_addr &= maskp->s_addr;
return NULL;
}
#ifdef ATOSUBNET_MAIN
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void regress(void);
int
main(int argc, char *argv[])
{
struct in_addr a;
struct in_addr m;
char buf[100];
const char *oops;
size_t n;
if (argc < 2) {
fprintf(stderr, "Usage: %s {addr/mask|-r}\n", argv[0]);
exit(2);
}
if (strcmp(argv[1], "-r") == 0) {
regress();
fprintf(stderr, "regress() returned?!?\n");
exit(1);
}
oops = atosubnet(argv[1], 0, &a, &m);
if (oops != NULL) {
fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
exit(1);
}
n = subnettoa(a, m, 0, buf, sizeof(buf));
if (n > sizeof(buf)) {
fprintf(stderr, "%s: reverse conversion of ", argv[0]);
fprintf(stderr, "%s/", inet_ntoa(a));
fprintf(stderr, "%s", inet_ntoa(m));
fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
(long)n, (long)sizeof(buf));
exit(1);
}
printf("%s\n", buf);
exit(0);
}
struct rtab {
char *input;
char *output; /* NULL means error expected */
} rtab[] = {
{"1.2.3.0/255.255.255.0", "1.2.3.0/24"},
{"1.2.3.0/24", "1.2.3.0/24"},
{"1.2.3.1/255.255.255.240", "1.2.3.0/28"},
{"1.2.3.1/32", "1.2.3.1/32"},
{"1.2.3.1/0", "0.0.0.0/0"},
/* "1.2.3.1/255.255.127.0", "1.2.3.0/255.255.127.0", */
{"1.2.3.1/255.255.127.0", NULL},
{"128.009.000.032/32", "128.9.0.32/32"},
{"128.0x9.0.32/32", NULL},
{"0x80090020/32", "128.9.0.32/32"},
{"0x800x0020/32", NULL},
{"128.9.0.32/0xffFF0000", "128.9.0.0/16"},
{"128.9.0.32/0xff0000FF", NULL},
{"128.9.0.32/0x0000ffFF", NULL},
{"128.9.0.32/0x00ffFF0000", NULL},
{"128.9.0.32/0xffFF", NULL},
{"128.9.0.32.27/32", NULL},
{"128.9.0k32/32", NULL},
{"328.9.0.32/32", NULL},
{"128.9..32/32", NULL},
{"10/8", "10.0.0.0/8"},
{"10.0/8", "10.0.0.0/8"},
{"10.0.0/8", "10.0.0.0/8"},
{"10.0.1/24", "10.0.1.0/24"},
{"_", NULL},
{"_/_", NULL},
{"1.2.3.1", NULL},
{"1.2.3.1/_", NULL},
{"1.2.3.1/24._", NULL},
{"1.2.3.1/99", NULL},
{"localhost/32", "127.0.0.1/32"},
{"%default", "0.0.0.0/0"},
{NULL, NULL}
};
void
regress()
{
struct rtab *r;
int status = 0;
struct in_addr a;
struct in_addr m;
char in[100];
char buf[100];
const char *oops;
size_t n;
for (r = rtab; r->input != NULL; r++) {
strcpy(in, r->input);
oops = atosubnet(in, 0, &a, &m);
if (oops != NULL && r->output == NULL)
{} /* okay, error expected */
else if (oops != NULL) {
printf("`%s' atosubnet failed: %s\n", r->input, oops);
status = 1;
} else if (r->output == NULL) {
printf("`%s' atosubnet succeeded unexpectedly\n",
r->input);
status = 1;
} else {
n = subnettoa(a, m, 0, buf, sizeof(buf));
if (n > sizeof(buf)) {
printf("`%s' subnettoa failed: need %ld\n",
r->input, (long)n);
status = 1;
} else if (strcmp(r->output, buf) != 0) {
printf("`%s' gave `%s', expected `%s'\n",
r->input, buf, r->output);
status = 1;
}
}
}
exit(status);
}
#endif /* ATOSUBNET_MAIN */

View File

@ -1,160 +0,0 @@
.TH IPSEC_ATOUL 3 "11 June 2001"
.SH NAME
ipsec atoul, ultoa \- convert unsigned-long numbers to and from ASCII
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "const char *atoul(const char *src, size_t srclen,"
.ti +1c
.B "int base, unsigned long *n);"
.br
.B "size_t ultoa(unsigned long n, int base, char *dst,"
.ti +1c
.B "size_t dstlen);"
.SH DESCRIPTION
These functions are obsolete; see
.IR ipsec_ttoul (3)
for their replacements.
.PP
.I Atoul
converts an ASCII number into a binary
.B "unsigned long"
value.
.I Ultoa
does the reverse conversion, back to an ASCII version.
.PP
Numbers are specified in ASCII as
decimal (e.g.
.BR 123 ),
octal with a leading zero (e.g.
.BR 012 ,
which has value 10),
or hexadecimal with a leading
.B 0x
(e.g.
.BR 0x1f ,
which has value 31)
in either upper or lower case.
.PP
The
.I srclen
parameter of
.I atoul
specifies the length of the ASCII string pointed to by
.IR src ;
it is an error for there to be anything else
(e.g., a terminating NUL) within that length.
As a convenience for cases where an entire NUL-terminated string is
to be converted,
a
.I srclen
value of
.B 0
is taken to mean
.BR strlen(src) .
.PP
The
.I base
parameter of
.I atoul
can be
.BR 8 ,
.BR 10 ,
or
.BR 16 ,
in which case the number supplied is assumed to be of that form
(and in the case of
.BR 16 ,
to lack any
.B 0x
prefix).
It can also be
.BR 0 ,
in which case the number is examined for a leading zero
or a leading
.B 0x
to determine its base,
or
.B 13
(halfway between 10 and 16),
which has the same effect as
.B 0
except that a non-hexadecimal
number is considered decimal regardless of any leading zero.
.PP
The
.I dstlen
parameter of
.I ultoa
specifies the size of the
.I dst
parameter;
under no circumstances are more than
.I dstlen
bytes written to
.IR dst .
A result which will not fit is truncated.
.I Dstlen
can be zero, in which case
.I dst
need not be valid and no result is written,
but the return value is unaffected;
in all other cases, the (possibly truncated) result is NUL-terminated.
.PP
The
.I base
parameter of
.I ultoa
must be
.BR 8 ,
.BR 10 ,
or
.BR 16 .
.PP
.I Atoul
returns NULL for success and
a pointer to a string-literal error message for failure;
see DIAGNOSTICS.
.I Ultoa
returns the size of buffer which would
be needed to
accommodate the full conversion result, including terminating NUL;
it is the caller's responsibility to check this against the size of
the provided buffer to determine whether truncation has occurred.
.SH SEE ALSO
atol(3), strtoul(3)
.SH DIAGNOSTICS
Fatal errors in
.I atoul
are:
empty input;
unknown
.IR base ;
non-digit character found;
number too large for an
.BR "unsigned long" .
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
There is no provision for reporting an invalid
.I base
parameter given to
.IR ultoa .
.PP
The restriction of error reports to literal strings
(so that callers don't need to worry about freeing them or copying them)
does limit the precision of error reporting.
.PP
The error-reporting convention lends itself to slightly obscure code,
because many readers will not think of NULL as signifying success.
A good way to make it clearer is to write something like:
.PP
.RS
.nf
.B "const char *error;"
.sp
.B "error = atoul( /* ... */ );"
.B "if (error != NULL) {"
.B " /* something went wrong */"
.fi
.RE

View File

@ -1,88 +0,0 @@
/*
* convert from ASCII form of unsigned long to binary
* Copyright (C) 1998, 1999 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include "internal.h"
#include "freeswan.h"
/*
- atoul - convert ASCII substring to unsigned long number
*/
const char * /* NULL for success, else string literal */
atoul(src, srclen, base, resultp)
const char *src;
size_t srclen; /* 0 means strlen(src) */
int base; /* 0 means figure it out */
unsigned long *resultp;
{
const char *stop;
static char hex[] = "0123456789abcdef";
static char uchex[] = "0123456789ABCDEF";
int d;
char c;
char *p;
unsigned long r;
unsigned long rlimit;
int dlimit;
if (srclen == 0)
srclen = strlen(src);
if (srclen == 0)
return "empty string";
if (base == 0 || base == 13) {
if (srclen > 2 && *src == '0' && CIEQ(*(src+1), 'x'))
return atoul(src+2, srclen-2, 16, resultp);
if (srclen > 1 && *src == '0' && base != 13)
return atoul(src+1, srclen-1, 8, resultp);
return atoul(src, srclen, 10, resultp);
}
if (base != 8 && base != 10 && base != 16)
return "unsupported number base";
r = 0;
stop = src + srclen;
if (base == 16) {
while (src < stop) {
c = *src++;
p = strchr(hex, c);
if (p != NULL)
d = p - hex;
else {
p = strchr(uchex, c);
if (p == NULL)
return "non-hex-digit in hex number";
d = p - uchex;
}
r = (r << 4) | d;
}
/* defer length check to catch invalid digits first */
if (srclen > sizeof(unsigned long) * 2)
return "hex number too long";
} else {
rlimit = ULONG_MAX / base;
dlimit = (int)(ULONG_MAX - rlimit*base);
while (src < stop) {
c = *src++;
d = c - '0';
if (d < 0 || d >= base)
return "non-digit in number";
if (r > rlimit || (r == rlimit && d > dlimit))
return "unsigned-long overflow";
r = r*base + d;
}
}
*resultp = r;
return NULL;
}

View File

@ -1,57 +0,0 @@
/*
* return IPsec copyright notice
* Copyright (C) 2001, 2002 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include "internal.h"
#include "freeswan.h"
static const char *co[] = {
"Copyright (C) 1999-2009 Henry Spencer, Richard Guy Briggs,",
" D. Hugh Redelmeier, Sandy Harris, Claudia Schmeing,",
" Michael Richardson, Angelos D. Keromytis, John Ioannidis,",
"",
" Ken Bantoft, Stephen J. Bevan, JuanJo Ciarlante, Mathieu Lafon,",
" Stephane Laroche, Kai Martius, Stephan Scholz, Tuomo Soini, Herbert Xu,",
"",
" Martin Berner, Marco Bertossa, David Buechi, Ueli Galizzi,",
" Christoph Gysin, Andreas Hess, Patric Lichtsteiner, Michael Meier,",
" Andreas Schleiss, Ariane Seiler, Mario Strasser, Lukas Suter,",
" Roger Wegmann, Simon Zwahlen,",
" ZHW Zuercher Hochschule Winterthur (Switzerland).",
"",
" Philip Boetschi, Tobias Brunner, Sansar Choinyambuu, Adrian Doerig,",
" Andreas Eigenmann, Fabian Hartmann, Noah Heusser, Jan Hutter,",
" Thomas Kallenberg, Daniel Roethlisberger, Joel Stillhart, Martin Willi,",
" Daniel Wydler, Andreas Steffen,",
" HSR Hochschule fuer Technik Rapperswil (Switzerland).",
"",
"This program is free software; you can redistribute it and/or modify it",
"under the terms of the GNU General Public License as published by the",
"Free Software Foundation; either version 2 of the License, or (at your",
"option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.",
"",
"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 (file COPYING in the distribution) for more details.",
NULL
};
/*
- ipsec_copyright_notice - return copyright notice, as a vector of strings
*/
const char **
ipsec_copyright_notice()
{
return co;
}

View File

@ -1,230 +0,0 @@
/*
* convert from binary data (e.g. key) to text form
* Copyright (C) 2000 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include "internal.h"
#include "freeswan.h"
static void convert(const char *src, size_t nreal, int format, char *out);
/*
- datatot - convert data bytes to text
*/
size_t /* true length (with NUL) for success */
datatot(src, srclen, format, dst, dstlen)
const char *src;
size_t srclen;
int format; /* character indicating what format */
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
size_t inblocksize; /* process this many bytes at a time */
size_t outblocksize; /* producing this many */
size_t breakevery; /* add a _ every this many (0 means don't) */
size_t sincebreak; /* output bytes since last _ */
char breakchar; /* character used to break between groups */
char inblock[10]; /* enough for any format */
char outblock[10]; /* enough for any format */
char fake[1]; /* fake output area for dstlen == 0 */
size_t needed; /* return value */
char *stop; /* where the terminating NUL will go */
size_t ntodo; /* remaining input */
size_t nreal;
char *out;
char *prefix;
breakevery = 0;
breakchar = '_';
switch (format) {
case 0:
case 'h':
format = 'x';
breakevery = 8;
/* FALLTHROUGH */
case 'x':
inblocksize = 1;
outblocksize = 2;
prefix = "0x";
break;
case ':':
breakevery = 2;
breakchar = ':';
/* FALLTHROUGH */
case 16:
inblocksize = 1;
outblocksize = 2;
prefix = "";
format = 'x';
break;
case 's':
inblocksize = 3;
outblocksize = 4;
prefix = "0s";
break;
case 64: /* beware, equals ' ' */
inblocksize = 3;
outblocksize = 4;
prefix = "";
format = 's';
break;
default:
return 0;
break;
}
assert(inblocksize < sizeof(inblock));
assert(outblocksize < sizeof(outblock));
assert(breakevery % outblocksize == 0);
if (srclen == 0)
return 0;
ntodo = srclen;
if (dstlen == 0) { /* dispose of awkward special case */
dst = fake;
dstlen = 1;
}
stop = dst + dstlen - 1;
nreal = strlen(prefix);
needed = nreal; /* for starters */
if (dstlen <= nreal) { /* prefix won't fit */
strncpy(dst, prefix, dstlen - 1);
dst += dstlen - 1;
} else {
strcpy(dst, prefix);
dst += nreal;
}
assert(dst <= stop);
sincebreak = 0;
while (ntodo > 0) {
if (ntodo < inblocksize) { /* incomplete input */
memset(inblock, 0, sizeof(inblock));
memcpy(inblock, src, ntodo);
src = inblock;
nreal = ntodo;
ntodo = inblocksize;
} else
nreal = inblocksize;
out = (outblocksize > stop - dst) ? outblock : dst;
convert(src, nreal, format, out);
needed += outblocksize;
sincebreak += outblocksize;
if (dst < stop) {
if (out != dst) {
assert(outblocksize > stop - dst);
memcpy(dst, out, stop - dst);
dst = stop;
} else
dst += outblocksize;
}
src += inblocksize;
ntodo -= inblocksize;
if (breakevery != 0 && sincebreak >= breakevery && ntodo > 0) {
if (dst < stop)
*dst++ = breakchar;
needed++;
sincebreak = 0;
}
}
assert(dst <= stop);
*dst++ = '\0';
needed++;
return needed;
}
/*
- convert - convert one input block to one output block
*/
static void
convert(src, nreal, format, out)
const char *src;
size_t nreal; /* how much of the input block is real */
int format;
char *out;
{
static char hex[] = "0123456789abcdef";
static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
unsigned char c;
unsigned char c1, c2, c3;
assert(nreal > 0);
switch (format) {
case 'x':
assert(nreal == 1);
c = (unsigned char)*src;
*out++ = hex[c >> 4];
*out++ = hex[c & 0xf];
break;
case 's':
c1 = (unsigned char)*src++;
c2 = (unsigned char)*src++;
c3 = (unsigned char)*src++;
*out++ = base64[c1 >> 2]; /* top 6 bits of c1 */
c = (c1 & 0x3) << 4; /* bottom 2 of c1... */
c |= c2 >> 4; /* ...top 4 of c2 */
*out++ = base64[c];
if (nreal == 1)
*out++ = '=';
else {
c = (c2 & 0xf) << 2; /* bottom 4 of c2... */
c |= c3 >> 6; /* ...top 2 of c3 */
*out++ = base64[c];
}
if (nreal <= 2)
*out++ = '=';
else
*out++ = base64[c3 & 0x3f]; /* bottom 6 of c3 */
break;
default:
assert(nreal == 0); /* unknown format */
break;
}
}
/*
- datatoa - convert data to ASCII
* backward-compatibility synonym for datatot
*/
size_t /* true length (with NUL) for success */
datatoa(src, srclen, format, dst, dstlen)
const char *src;
size_t srclen;
int format; /* character indicating what format */
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
return datatot(src, srclen, format, dst, dstlen);
}
/*
- bytestoa - convert data bytes to ASCII
* backward-compatibility synonym for datatot
*/
size_t /* true length (with NUL) for success */
bytestoa(src, srclen, format, dst, dstlen)
const char *src;
size_t srclen;
int format; /* character indicating what format */
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
return datatot(src, srclen, format, dst, dstlen);
}

View File

@ -1,371 +0,0 @@
#ifndef _FREESWAN_H
/*
* header file for FreeS/WAN library functions
* Copyright (C) 1998, 1999, 2000 Henry Spencer.
* Copyright (C) 1999, 2000, 2001 Richard Guy Briggs
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#define _FREESWAN_H /* seen it, no need to see it again */
# include <sys/types.h>
# include <stdio.h>
# include <netinet/in.h>
# define DEBUG_NO_STATIC static
#include <ipsec_param.h>
#include <utils.h>
/*
* We assume header files have IPv6 (i.e. kernel version >= 2.1.0)
*/
#define NET_21
#ifndef IPPROTO_COMP
# define IPPROTO_COMP 108
#endif /* !IPPROTO_COMP */
#ifndef IPPROTO_INT
# define IPPROTO_INT 61
#endif /* !IPPROTO_INT */
#ifdef CONFIG_IPSEC_DEBUG
# define DEBUG_NO_STATIC
#else /* CONFIG_IPSEC_DEBUG */
# define DEBUG_NO_STATIC static
#endif /* CONFIG_IPSEC_DEBUG */
#define ESPINUDP_WITH_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */
#define ESPINUDP_WITH_NON_ESP 2 /* draft-ietf-ipsec-nat-t-ike-02 */
/*
* Basic data types for the address-handling functions.
* ip_address and ip_subnet are supposed to be opaque types; do not
* use their definitions directly, they are subject to change!
*/
/* then the main types */
typedef struct {
union {
struct sockaddr_in v4;
struct sockaddr_in6 v6;
} u;
} ip_address;
typedef struct {
ip_address addr;
int maskbits;
} ip_subnet;
/* and the SA ID stuff */
typedef u_int32_t ipsec_spi_t;
typedef struct { /* to identify an SA, we need: */
ip_address dst; /* A. destination host */
ipsec_spi_t spi; /* B. 32-bit SPI, assigned by dest. host */
# define SPI_PASS 256 /* magic values... */
# define SPI_DROP 257 /* ...for use... */
# define SPI_REJECT 258 /* ...with SA_INT */
# define SPI_HOLD 259
# define SPI_TRAP 260
# define SPI_TRAPSUBNET 261
int proto; /* C. protocol */
# define SA_ESP 50 /* IPPROTO_ESP */
# define SA_AH 51 /* IPPROTO_AH */
# define SA_IPIP 4 /* IPPROTO_IPIP */
# define SA_COMP 108 /* IPPROTO_COMP */
# define SA_INT 61 /* IANA reserved for internal use */
} ip_said;
struct sa_id { /* old v4-only version */
struct in_addr dst;
ipsec_spi_t spi;
int proto;
};
/* misc */
struct prng { /* pseudo-random-number-generator guts */
unsigned char sbox[256];
int i, j;
unsigned long count;
};
/*
* definitions for user space, taken from freeswan/ipsec_sa.h
*/
typedef uint32_t IPsecSAref_t;
#define IPSEC_SA_REF_TABLE_NUM_ENTRIES (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH)
#define IPSEC_SA_REF_FIELD_WIDTH (8 * sizeof(IPsecSAref_t))
#define IPsecSAref2NFmark(x) ((x) << (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_TABLE_IDX_WIDTH))
#define NFmark2IPsecSAref(x) ((x) >> (IPSEC_SA_REF_FIELD_WIDTH - IPSEC_SA_REF_TABLE_IDX_WIDTH))
#define IPSEC_SAREF_NULL (~((IPsecSAref_t)0))
/* GCC magic for use in function definitions! */
#ifdef GCC_LINT
# define PRINTF_LIKE(n) __attribute__ ((format(printf, n, n+1)))
# define NEVER_RETURNS __attribute__ ((noreturn))
# define UNUSED __attribute__ ((unused))
# define BLANK_FORMAT " " /* GCC_LINT whines about empty formats */
#else
# define PRINTF_LIKE(n) /* ignore */
# define NEVER_RETURNS /* ignore */
# define UNUSED /* ignore */
# define BLANK_FORMAT ""
#endif
/*
* new IPv6-compatible functions
*/
/* text conversions */
err_t ttoul(const char *src, size_t srclen, int format, unsigned long *dst);
size_t ultot(unsigned long src, int format, char *buf, size_t buflen);
#define ULTOT_BUF (22+1) /* holds 64 bits in octal */
err_t ttoaddr(const char *src, size_t srclen, int af, ip_address *dst);
err_t tnatoaddr(const char *src, size_t srclen, int af, ip_address *dst);
size_t addrtot(const ip_address *src, int format, char *buf, size_t buflen);
/* RFC 1886 old IPv6 reverse-lookup format is the bulkiest */
#define ADDRTOT_BUF (32*2 + 3 + 1 + 3 + 1 + 1)
err_t ttosubnet(const char *src, size_t srclen, int af, ip_subnet *dst);
size_t subnettot(const ip_subnet *src, int format, char *buf, size_t buflen);
#define SUBNETTOT_BUF (ADDRTOT_BUF + 1 + 3)
err_t ttosa(const char *src, size_t srclen, ip_said *dst);
size_t satot(const ip_said *src, int format, char *bufptr, size_t buflen);
#define SATOT_BUF (5 + ULTOA_BUF + 1 + ADDRTOT_BUF)
err_t ttodata(const char *src, size_t srclen, int base, char *buf,
size_t buflen, size_t *needed);
err_t ttodatav(const char *src, size_t srclen, int base,
char *buf, size_t buflen, size_t *needed,
char *errp, size_t errlen, unsigned int flags);
#define TTODATAV_BUF 40 /* ttodatav's largest non-literal message */
#define TTODATAV_IGNORESPACE (1<<1) /* ignore spaces in base64 encodings*/
#define TTODATAV_SPACECOUNTS 0 /* do not ignore spaces in base64 */
size_t datatot(const char *src, size_t srclen, int format, char *buf,
size_t buflen);
err_t ttoprotoport(char *src, size_t src_len, u_int8_t *proto, u_int16_t *port,
bool *has_port_wildcard);
/* initializations */
void initsaid(const ip_address *addr, ipsec_spi_t spi, int proto, ip_said *dst);
err_t loopbackaddr(int af, ip_address *dst);
err_t unspecaddr(int af, ip_address *dst);
err_t anyaddr(int af, ip_address *dst);
err_t initaddr(const unsigned char *src, size_t srclen, int af, ip_address *dst);
err_t initsubnet(const ip_address *addr, int maskbits, int clash, ip_subnet *dst);
err_t addrtosubnet(const ip_address *addr, ip_subnet *dst);
/* misc. conversions and related */
err_t rangetosubnet(const ip_address *from, const ip_address *to, ip_subnet *dst);
int addrtypeof(const ip_address *src);
int subnettypeof(const ip_subnet *src);
size_t addrlenof(const ip_address *src);
size_t addrbytesptr(const ip_address *src, const unsigned char **dst);
size_t addrbytesof(const ip_address *src, unsigned char *dst, size_t dstlen);
int masktocount(const ip_address *src);
void networkof(const ip_subnet *src, ip_address *dst);
void maskof(const ip_subnet *src, ip_address *dst);
/* tests */
int sameaddr(const ip_address *a, const ip_address *b);
int addrcmp(const ip_address *a, const ip_address *b);
int samesubnet(const ip_subnet *a, const ip_subnet *b);
int addrinsubnet(const ip_address *a, const ip_subnet *s);
int subnetinsubnet(const ip_subnet *a, const ip_subnet *b);
int subnetishost(const ip_subnet *s);
int samesaid(const ip_said *a, const ip_said *b);
int sameaddrtype(const ip_address *a, const ip_address *b);
int samesubnettype(const ip_subnet *a, const ip_subnet *b);
int isanyaddr(const ip_address *src);
int isunspecaddr(const ip_address *src);
int isloopbackaddr(const ip_address *src);
/* low-level grot */
int portof(const ip_address *src);
void setportof(int port, ip_address *dst);
struct sockaddr *sockaddrof(ip_address *src);
size_t sockaddrlenof(const ip_address *src);
/* odds and ends */
const char **ipsec_copyright_notice(void);
const char *dns_string_rr(int rr, char *buf, int bufsize);
const char *dns_string_datetime(time_t seconds,
char *buf,
int bufsize);
/*
* old functions, to be deleted eventually
*/
/* unsigned long */
const char * /* NULL for success, else string literal */
atoul(
const char *src,
size_t srclen, /* 0 means strlen(src) */
int base, /* 0 means figure it out */
unsigned long *resultp
);
size_t /* space needed for full conversion */
ultoa(
unsigned long n,
int base,
char *dst,
size_t dstlen
);
#define ULTOA_BUF 21 /* just large enough for largest result, */
/* assuming 64-bit unsigned long! */
/* Internet addresses */
const char * /* NULL for success, else string literal */
atoaddr(
const char *src,
size_t srclen, /* 0 means strlen(src) */
struct in_addr *addr
);
size_t /* space needed for full conversion */
addrtoa(
struct in_addr addr,
int format, /* character; 0 means default */
char *dst,
size_t dstlen
);
#define ADDRTOA_BUF 16 /* just large enough for largest result */
/* subnets */
const char * /* NULL for success, else string literal */
atosubnet(
const char *src,
size_t srclen, /* 0 means strlen(src) */
struct in_addr *addr,
struct in_addr *mask
);
size_t /* space needed for full conversion */
subnettoa(
struct in_addr addr,
struct in_addr mask,
int format, /* character; 0 means default */
char *dst,
size_t dstlen
);
#define SUBNETTOA_BUF 32 /* large enough for worst case result */
/* ranges */
const char * /* NULL for success, else string literal */
atoasr(
const char *src,
size_t srclen, /* 0 means strlen(src) */
char *type, /* 'a', 's', 'r' */
struct in_addr *addrs /* two-element array */
);
size_t /* space needed for full conversion */
rangetoa(
struct in_addr *addrs, /* two-element array */
int format, /* character; 0 means default */
char *dst,
size_t dstlen
);
#define RANGETOA_BUF 34 /* large enough for worst case result */
/* generic data, e.g. keys */
const char * /* NULL for success, else string literal */
atobytes(
const char *src,
size_t srclen, /* 0 means strlen(src) */
char *dst,
size_t dstlen,
size_t *lenp /* NULL means don't bother telling me */
);
size_t /* 0 failure, else true size */
bytestoa(
const char *src,
size_t srclen,
int format, /* character; 0 means default */
char *dst,
size_t dstlen
);
/* old versions of generic-data functions; deprecated */
size_t /* 0 failure, else true size */
atodata(
const char *src,
size_t srclen, /* 0 means strlen(src) */
char *dst,
size_t dstlen
);
size_t /* 0 failure, else true size */
datatoa(
const char *src,
size_t srclen,
int format, /* character; 0 means default */
char *dst,
size_t dstlen
);
/* part extraction and special addresses */
struct in_addr
subnetof(
struct in_addr addr,
struct in_addr mask
);
struct in_addr
hostof(
struct in_addr addr,
struct in_addr mask
);
struct in_addr
broadcastof(
struct in_addr addr,
struct in_addr mask
);
/* mask handling */
int
goodmask(
struct in_addr mask
);
int
masktobits(
struct in_addr mask
);
struct in_addr
bitstomask(
int n
);
/*
* Debugging levels for pfkey_lib_debug
*/
#define PF_KEY_DEBUG_PARSE_NONE 0
#define PF_KEY_DEBUG_PARSE_PROBLEM 1
#define PF_KEY_DEBUG_PARSE_STRUCT 2
#define PF_KEY_DEBUG_PARSE_FLOW 4
#define PF_KEY_DEBUG_PARSE_MAX 7
extern unsigned int pfkey_lib_debug; /* bits selecting what to report */
/*
* pluto and lwdnsq need to know the maximum size of the commands to,
* and replies from lwdnsq.
*/
#define LWDNSQ_CMDBUF_LEN 1024
#define LWDNSQ_RESULT_LEN_MAX 4096
#endif /* _FREESWAN_H */

View File

@ -1,56 +0,0 @@
.TH IPSEC_GOODMASK 3 "11 June 2001"
.SH NAME
ipsec goodmask \- is this Internet subnet mask a valid one?
.br
ipsec masktobits \- convert Internet subnet mask to bit count
.br
ipsec bitstomask \- convert bit count to Internet subnet mask
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "int goodmask(struct in_addr mask);"
.br
.B "int masktobits(struct in_addr mask);"
.br
.B "struct in_addr bitstomask(int n);"
.SH DESCRIPTION
These functions are obsolete;
see
.IR ipsec_masktocount (3)
for a partial replacement.
.PP
.I Goodmask
reports whether the subnet
.I mask
is a valid one,
i.e. consists of a (possibly empty) sequence of
.BR 1 s
followed by a (possibly empty) sequence of
.BR 0 s.
.I Masktobits
takes a (valid) subnet mask and returns the number of
.B 1
bits in it.
.I Bitstomask
reverses this,
returning the subnet mask corresponding to bit count
.IR n .
.PP
All masks are in network byte order.
.SH SEE ALSO
inet(3), ipsec_atosubnet(3)
.SH DIAGNOSTICS
.I Masktobits
returns
.B \-1
for an invalid mask.
.I Bitstomask
returns an all-zeros mask for a negative or out-of-range
.IR n .
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
The error-reporting convention of
.I bitstomask
is less than ideal;
zero is sometimes a legitimate mask.

View File

@ -1,95 +0,0 @@
/*
* minor utilities for subnet-mask manipulation
* Copyright (C) 1998, 1999 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include "internal.h"
#include "freeswan.h"
/*
- goodmask - is this a good (^1*0*$) subnet mask?
* You are not expected to understand this. See Henry S. Warren Jr,
* "Functions realizable with word-parallel logical and two's-complement
* addition instructions", CACM 20.6 (June 1977), p.439.
*/
int /* predicate */
goodmask(mask)
struct in_addr mask;
{
unsigned long x = ntohl(mask.s_addr);
/* clear rightmost contiguous string of 1-bits */
# define CRCS1B(x) (((x|(x-1))+1)&x)
# define TOPBIT (1UL << 31)
/* either zero, or has one string of 1-bits which is left-justified */
if (x == 0 || (CRCS1B(x) == 0 && (x&TOPBIT)))
return 1;
return 0;
}
/*
- masktobits - how many bits in this mask?
* The algorithm is essentially a binary search, but highly optimized
* for this particular task.
*/
int /* -1 means !goodmask() */
masktobits(mask)
struct in_addr mask;
{
unsigned long m = ntohl(mask.s_addr);
int masklen;
if (!goodmask(mask))
return -1;
if (m&0x00000001UL)
return 32;
masklen = 0;
if (m&(0x0000ffffUL<<1)) { /* <<1 for 1-origin numbering */
masklen |= 0x10;
m <<= 16;
}
if (m&(0x00ff0000UL<<1)) {
masklen |= 0x08;
m <<= 8;
}
if (m&(0x0f000000UL<<1)) {
masklen |= 0x04;
m <<= 4;
}
if (m&(0x30000000UL<<1)) {
masklen |= 0x02;
m <<= 2;
}
if (m&(0x40000000UL<<1))
masklen |= 0x01;
return masklen;
}
/*
- bitstomask - return a mask with this many high bits on
*/
struct in_addr
bitstomask(n)
int n;
{
struct in_addr result;
if (n > 0 && n <= ABITS)
result.s_addr = htonl(~((1UL << (ABITS - n)) - 1));
else if (n == 0)
result.s_addr = 0;
else
result.s_addr = 0; /* best error report we can do */
return result;
}

View File

@ -1,128 +0,0 @@
.TH IPSEC_INITADDR 3 "11 Sept 2000"
.SH NAME
ipsec initaddr \- initialize an ip_address
.br
ipsec addrtypeof \- get address type of an ip_address
.br
ipsec addrlenof \- get length of address within an ip_address
.br
ipsec addrbytesof \- get copy of address within an ip_address
.br
ipsec addrbytesptr \- get pointer to address within an ip_address
.SH SYNOPSIS
.B "#include <freeswan.h>"
.sp
.B "const char *initaddr(const char *src, size_t srclen,"
.ti +1c
.B "int af, ip_address *dst);"
.br
.B "int addrtypeof(const ip_address *src);"
.br
.B "size_t addrlenof(const ip_address *src);"
.br
.B "size_t addrbytesof(const ip_address *src,"
.ti +1c
.B "unsigned char *dst, size_t dstlen);"
.br
.B "size_t addrbytesptr(const ip_address *src,"
.ti +1c
.B "const unsigned char **dst);"
.SH DESCRIPTION
The
.B <freeswan.h>
library uses an internal type
.I ip_address
to contain one of the (currently two) types of IP address.
These functions provide basic tools for creating and examining this type.
.PP
.I Initaddr
initializes a variable
.I *dst
of type
.I ip_address
from an address
(in network byte order,
indicated by a pointer
.I src
and a length
.IR srclen )
and an address family
.I af
(typically
.B AF_INET
or
.BR AF_INET6 ).
The length must be consistent with the address family.
.PP
.I Addrtypeof
returns the address type of an address,
normally
.B AF_INET
or
.BR AF_INET6 .
(The
.B <freeswan.h>
header file arranges to include the necessary headers for these
names to be known.)
.PP
.I Addrlenof
returns the size (in bytes) of the address within an
.IR ip_address ,
to permit storage allocation etc.
.PP
.I Addrbytesof
copies the address within the
.I ip_address
.I src
to the buffer indicated by the pointer
.I dst
and the length
.IR dstlen ,
and returns the address length (in bytes).
If the address will not fit,
as many bytes as will fit are copied;
the returned length is still the full length.
It is the caller's responsibility to check the
returned value to ensure that there was enough room.
.PP
.I Addrbytesptr
sets
.I *dst
to a pointer to the internal address within the
.IR ip_address ,
and returns the address length (in bytes).
If
.I dst
is
.BR NULL ,
it just returns the address length.
The pointer points to
.B const
to discourage misuse.
.PP
.I Initaddr
returns
.B NULL
for success and
a pointer to a string-literal error message for failure;
see DIAGNOSTICS.
.PP
The functions which return
.I size_t
return
.B 0
for a failure.
.SH SEE ALSO
inet(3), ipsec_ttoaddr(3)
.SH DIAGNOSTICS
An unknown address family is a fatal error for any of these functions
except
.IR addrtypeof .
An address-size mismatch is a fatal error for
.IR initaddr .
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
.I Addrtypeof
should probably have been named
.IR addrfamilyof .

View File

@ -1,51 +0,0 @@
/*
* initialize address structure
* Copyright (C) 2000 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include <sys/socket.h>
#include "internal.h"
#include "freeswan.h"
/*
- initaddr - initialize ip_address from bytes
*/
err_t /* NULL for success, else string literal */
initaddr(src, srclen, af, dst)
const unsigned char *src;
size_t srclen;
int af; /* address family */
ip_address *dst;
{
switch (af) {
case AF_INET:
if (srclen != 4)
return "IPv4 address must be exactly 4 bytes";
dst->u.v4.sin_family = af;
dst->u.v4.sin_port = 0; /* unused */
memcpy((char *)&dst->u.v4.sin_addr.s_addr, src, srclen);
break;
case AF_INET6:
if (srclen != 16)
return "IPv6 address must be exactly 16 bytes";
dst->u.v6.sin6_family = af;
dst->u.v6.sin6_flowinfo = 0; /* unused */
dst->u.v6.sin6_port = 0; /* unused */
memcpy((char *)&dst->u.v6.sin6_addr, src, srclen);
break;
default:
return "unknown address family in initaddr";
break;
}
return NULL;
}

View File

@ -1,31 +0,0 @@
/*
* initialize SA ID structure
* Copyright (C) 2000 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include "internal.h"
#include "freeswan.h"
/*
- initsaid - initialize SA ID from bits
*/
void
initsaid(addr, spi, proto, dst)
const ip_address *addr;
ipsec_spi_t spi;
int proto;
ip_said *dst;
{
dst->dst = *addr;
dst->spi = spi;
dst->proto = proto;
}

View File

@ -1,136 +0,0 @@
.TH IPSEC_INITSUBNET 3 "12 March 2002"
.SH NAME
ipsec initsubnet \- initialize an ip_subnet
.br
ipsec addrtosubnet \- initialize a singleton ip_subnet
.br
ipsec subnettypeof \- get address type of an ip_subnet
.br
ipsec masktocount \- convert subnet mask to bit count
.br
ipsec networkof \- get base address of an ip_subnet
.br
ipsec maskof \- get subnet mask of an ip_subnet
.SH SYNOPSIS
.B "#include <freeswan.h>"
.sp
.B "const char *initsubnet(const ip_address *addr,"
.ti +1c
.B "int maskbits, int clash, ip_subnet *dst);"
.br
.B "const char *addrtosubnet(const ip_address *addr,"
.ti +1c
.B "ip_subnet *dst);"
.sp
.B "int subnettypeof(const ip_subnet *src);"
.br
.B "int masktocount(const ip_address *src);"
.br
.B "void networkof(const ip_subnet *src, ip_address *dst);"
.br
.B "void maskof(const ip_subnet *src, ip_address *dst);"
.SH DESCRIPTION
The
.B <freeswan.h>
library uses an internal type
.I ip_subnet
to contain a description of an IP subnet
(base address plus mask).
These functions provide basic tools for creating and examining this type.
.PP
.I Initsubnet
initializes a variable
.I *dst
of type
.I ip_subnet
from a base address and
a count of mask bits.
The
.I clash
parameter specifies what to do if the base address includes
.B 1
bits outside the prefix specified by the mask
(that is, in the ``host number'' part of the address):
.RS
.IP '0' 5
zero out host-number bits
.IP 'x'
non-zero host-number bits are an error
.RE
.PP
.I Initsubnet
returns
.B NULL
for success and
a pointer to a string-literal error message for failure;
see DIAGNOSTICS.
.PP
.I Addrtosubnet
initializes an
.I ip_subnet
variable
.I *dst
to a ``singleton subnet'' containing the single address
.IR *addr .
It returns
.B NULL
for success and
a pointer to a string-literal error message for failure.
.PP
.I Subnettypeof
returns the address type of a subnet,
normally
.B AF_INET
or
.BR AF_INET6 .
(The
.B <freeswan.h>
header file arranges to include the necessary headers for these
names to be known.)
.PP
.I Masktocount
converts a subnet mask, expressed as an address, to a bit count
suitable for use with
.IR initsubnet .
It returns
.B \-1
for error; see DIAGNOSTICS.
.PP
.I Networkof
fills in
.I *dst
with the base address of subnet
.IR src .
.PP
.I Maskof
fills in
.I *dst
with the subnet mask of subnet
.IR src ,
expressed as an address.
.SH SEE ALSO
inet(3), ipsec_ttosubnet(3), ipsec_rangetosubnet(3)
.SH DIAGNOSTICS
Fatal errors in
.I initsubnet
are:
unknown address family;
unknown
.I clash
value;
impossible mask bit count;
non-zero host-number bits and
.I clash
is
.BR 'x' .
Fatal errors in
.I addrtosubnet
are:
unknown address family.
Fatal errors in
.I masktocount
are:
unknown address family;
mask bits not contiguous.
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.

View File

@ -1,93 +0,0 @@
/*
* initialize subnet structure
* Copyright (C) 2000, 2002 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include "internal.h"
#include "freeswan.h"
/*
- initsubnet - initialize ip_subnet from address and count
*
* The only hard part is checking for host-part bits turned on.
*/
err_t /* NULL for success, else string literal */
initsubnet(addr, count, clash, dst)
const ip_address *addr;
int count;
int clash; /* '0' zero host-part bits, 'x' die on them */
ip_subnet *dst;
{
unsigned char *p;
int n;
int c;
unsigned m;
int die;
dst->addr = *addr;
n = addrbytesptr(&dst->addr, (const unsigned char **)&p);
if (n == 0)
return "unknown address family";
switch (clash) {
case '0':
die = 0;
break;
case 'x':
die = 1;
break;
default:
return "unknown clash-control value in initsubnet";
break;
}
c = count / 8;
if (c > n)
return "impossible mask count";
p += c;
n -= c;
m = 0xff;
c = count % 8;
if (n > 0 && c != 0) /* partial byte */
m >>= c;
for (; n > 0; n--) {
if ((*p & m) != 0) {
if (die)
return "improper subnet, host-part bits on";
*p &= ~m;
}
m = 0xff;
p++;
}
dst->maskbits = count;
return NULL;
}
/*
- addrtosubnet - initialize ip_subnet from a single address
*/
err_t /* NULL for success, else string literal */
addrtosubnet(addr, dst)
const ip_address *addr;
ip_subnet *dst;
{
int n;
dst->addr = *addr;
n = addrbytesptr(&dst->addr, (const unsigned char **)NULL);
if (n == 0)
return "unknown address family";
dst->maskbits = n*8;
return NULL;
}

View File

@ -1,46 +0,0 @@
/*
* internal definitions for use within the library; do not export!
* Copyright (C) 1998, 1999 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#ifndef ABITS
#define ABITS 32 /* bits in an IPv4 address */
#endif
/* case-independent ASCII character equality comparison */
#define CIEQ(c1, c2) ( ((c1)&~040) == ((c2)&~040) )
/* syntax for passthrough SA */
#ifndef PASSTHROUGHNAME
#define PASSTHROUGHNAME "%passthrough"
#define PASSTHROUGH4NAME "%passthrough4"
#define PASSTHROUGH6NAME "%passthrough6"
#define PASSTHROUGHIS "tun0@0.0.0.0"
#define PASSTHROUGH4IS "tun0@0.0.0.0"
#define PASSTHROUGH6IS "tun0@::"
#define PASSTHROUGHTYPE "tun"
#define PASSTHROUGHSPI 0
#define PASSTHROUGHDST 0
#endif
#include <sys/types.h>
#include <netinet/in.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <limits.h>
#include <netdb.h>
#include <stdlib.h>
#define MALLOC(n) malloc(n)
#define FREE(p) free(p)

View File

@ -1,54 +0,0 @@
/*
* @(#) FreeSWAN tunable paramaters
*
* Copyright (C) 2001 Richard Guy Briggs <rgb@freeswan.org>
* and Michael Richardson <mcr@freeswan.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
/*
* This file provides a set of #define's which may be tuned by various
* people/configurations. It keeps all compile-time tunables in one place.
*
* This file should be included before all other IPsec kernel-only files.
*
*/
#ifndef _IPSEC_PARAM_H_
/*
* This is for the SA reference table. This number is related to the
* maximum number of SAs that KLIPS can concurrently deal with, plus enough
* space for keeping expired SAs around.
*
* TABLE_MAX_WIDTH is the number of bits that we will use.
* MAIN_TABLE_WIDTH is the number of bits used for the primary index table.
*
*/
#ifndef IPSEC_SA_REF_TABLE_IDX_WIDTH
# define IPSEC_SA_REF_TABLE_IDX_WIDTH 16
#endif
#ifndef IPSEC_SA_REF_MAINTABLE_IDX_WIDTH
# define IPSEC_SA_REF_MAINTABLE_IDX_WIDTH 4
#endif
#ifndef IPSEC_SA_REF_FREELIST_NUM_ENTRIES
# define IPSEC_SA_REF_FREELIST_NUM_ENTRIES 256
#endif
#ifndef IPSEC_SA_REF_CODE
# define IPSEC_SA_REF_CODE 1
#endif
#define _IPSEC_PARAM_H_
#endif /* _IPSEC_PARAM_H_ */

View File

@ -1,205 +0,0 @@
/*
* FreeS/WAN specific PF_KEY headers
* Copyright (C) 1999, 2000, 2001 Richard Guy Briggs.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef __NET_IPSEC_PF_KEY_H
#define __NET_IPSEC_PF_KEY_H
extern void (*pfkey_debug_func)(const char *message, ...);
extern uint8_t satype2proto(uint8_t satype);
extern uint8_t proto2satype(uint8_t proto);
extern char* satype2name(uint8_t satype);
extern char* proto2name(uint8_t proto);
struct key_opt
{
uint32_t key_pid; /* process ID */
struct sock *sk;
};
#define key_pid(sk) ((struct key_opt*)&((sk)->protinfo))->key_pid
#define IPSEC_PFKEYv2_ALIGN (sizeof(uint64_t)/sizeof(uint8_t))
#define BITS_PER_OCTET 8
#define OCTETBITS 8
#define PFKEYBITS 64
#define DIVUP(x,y) ((x + y -1) / y) /* divide, rounding upwards */
#define ALIGN_N(x,y) (DIVUP(x,y) * y) /* align on y boundary */
#define PFKEYv2_MAX_MSGSIZE 4096
/*
* PF_KEYv2 permitted and required extensions in and out bitmaps
*/
struct pf_key_ext_parsers_def {
int (*parser)(struct sadb_ext*);
char *parser_name;
};
extern unsigned int extensions_bitmaps[2/*in/out*/][2/*perm/req*/][SADB_MAX + 1/*ext*/];
#define EXT_BITS_IN 0
#define EXT_BITS_OUT 1
#define EXT_BITS_PERM 0
#define EXT_BITS_REQ 1
extern void pfkey_extensions_init(struct sadb_ext *extensions[SADB_EXT_MAX + 1]);
extern void pfkey_extensions_free(struct sadb_ext *extensions[SADB_EXT_MAX + 1]);
extern void pfkey_msg_free(struct sadb_msg **pfkey_msg);
extern int pfkey_msg_parse(struct sadb_msg *pfkey_msg,
struct pf_key_ext_parsers_def *ext_parsers[],
struct sadb_ext **extensions,
int dir);
/*
* PF_KEYv2 build function prototypes
*/
int
pfkey_msg_hdr_build(struct sadb_ext** pfkey_ext,
uint8_t msg_type,
uint8_t satype,
uint8_t msg_errno,
uint32_t seq,
uint32_t pid);
int
pfkey_sa_ref_build(struct sadb_ext ** pfkey_ext,
uint16_t exttype,
uint32_t spi, /* in network order */
uint8_t replay_window,
uint8_t sa_state,
uint8_t auth,
uint8_t encrypt,
uint32_t flags,
uint32_t/*IPsecSAref_t*/ ref);
int
pfkey_sa_build(struct sadb_ext ** pfkey_ext,
uint16_t exttype,
uint32_t spi, /* in network order */
uint8_t replay_window,
uint8_t sa_state,
uint8_t auth,
uint8_t encrypt,
uint32_t flags);
int
pfkey_lifetime_build(struct sadb_ext ** pfkey_ext,
uint16_t exttype,
uint32_t allocations,
uint64_t bytes,
uint64_t addtime,
uint64_t usetime,
uint32_t packets);
int
pfkey_address_build(struct sadb_ext** pfkey_ext,
uint16_t exttype,
uint8_t proto,
uint8_t prefixlen,
struct sockaddr* address);
int
pfkey_key_build(struct sadb_ext** pfkey_ext,
uint16_t exttype,
uint16_t key_bits,
char* key);
int
pfkey_ident_build(struct sadb_ext** pfkey_ext,
uint16_t exttype,
uint16_t ident_type,
uint64_t ident_id,
uint8_t ident_len,
char* ident_string);
int
pfkey_x_nat_t_type_build(struct sadb_ext** pfkey_ext,
uint8_t type);
int
pfkey_x_nat_t_port_build(struct sadb_ext** pfkey_ext,
uint16_t exttype,
uint16_t port);
int
pfkey_sens_build(struct sadb_ext** pfkey_ext,
uint32_t dpd,
uint8_t sens_level,
uint8_t sens_len,
uint64_t* sens_bitmap,
uint8_t integ_level,
uint8_t integ_len,
uint64_t* integ_bitmap);
int
pfkey_x_protocol_build(struct sadb_ext **, uint8_t);
int
pfkey_prop_build(struct sadb_ext** pfkey_ext,
uint8_t replay,
unsigned int comb_num,
struct sadb_comb* comb);
int
pfkey_supported_build(struct sadb_ext** pfkey_ext,
uint16_t exttype,
unsigned int alg_num,
struct sadb_alg* alg);
int
pfkey_spirange_build(struct sadb_ext** pfkey_ext,
uint16_t exttype,
uint32_t min,
uint32_t max);
int
pfkey_x_kmprivate_build(struct sadb_ext** pfkey_ext);
int
pfkey_x_satype_build(struct sadb_ext** pfkey_ext,
uint8_t satype);
int
pfkey_x_debug_build(struct sadb_ext** pfkey_ext,
uint32_t tunnel,
uint32_t netlink,
uint32_t xform,
uint32_t eroute,
uint32_t spi,
uint32_t radij,
uint32_t esp,
uint32_t ah,
uint32_t rcv,
uint32_t pfkey,
uint32_t ipcomp,
uint32_t verbose);
int
pfkey_msg_build(struct sadb_msg** pfkey_msg,
struct sadb_ext* extensions[],
int dir);
/* in pfkey_v2_debug.c - routines to decode numbers -> strings */
const char *
pfkey_v2_sadb_ext_string(int extnum);
const char *
pfkey_v2_sadb_type_string(int sadb_type);
#endif /* __NET_IPSEC_PF_KEY_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,104 +0,0 @@
/*
* @(#) pfkey version 2 debugging messages
*
* Copyright (C) 2001 Richard Guy Briggs <rgb@freeswan.org>
* and Michael Richardson <mcr@freeswan.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
# include <sys/types.h>
# include <errno.h>
#include "freeswan.h"
#include "pfkeyv2.h"
#include "pfkey.h"
/*
* This file provides ASCII translations of PF_KEY magic numbers.
*
*/
static char *pfkey_sadb_ext_strings[]={
"reserved", /* SADB_EXT_RESERVED 0 */
"security-association", /* SADB_EXT_SA 1 */
"lifetime-current", /* SADB_EXT_LIFETIME_CURRENT 2 */
"lifetime-hard", /* SADB_EXT_LIFETIME_HARD 3 */
"lifetime-soft", /* SADB_EXT_LIFETIME_SOFT 4 */
"source-address", /* SADB_EXT_ADDRESS_SRC 5 */
"destination-address", /* SADB_EXT_ADDRESS_DST 6 */
"proxy-address", /* SADB_EXT_ADDRESS_PROXY 7 */
"authentication-key", /* SADB_EXT_KEY_AUTH 8 */
"cipher-key", /* SADB_EXT_KEY_ENCRYPT 9 */
"source-identity", /* SADB_EXT_IDENTITY_SRC 10 */
"destination-identity", /* SADB_EXT_IDENTITY_DST 11 */
"sensitivity-label", /* SADB_EXT_SENSITIVITY 12 */
"proposal", /* SADB_EXT_PROPOSAL 13 */
"supported-auth", /* SADB_EXT_SUPPORTED_AUTH 14 */
"supported-cipher", /* SADB_EXT_SUPPORTED_ENCRYPT 15 */
"spi-range", /* SADB_EXT_SPIRANGE 16 */
"X-kmpprivate", /* SADB_X_EXT_KMPRIVATE 17 */
"X-satype2", /* SADB_X_EXT_SATYPE2 18 */
"X-security-association", /* SADB_X_EXT_SA2 19 */
"X-destination-address2", /* SADB_X_EXT_ADDRESS_DST2 20 */
"X-source-flow-address", /* SADB_X_EXT_ADDRESS_SRC_FLOW 21 */
"X-dest-flow-address", /* SADB_X_EXT_ADDRESS_DST_FLOW 22 */
"X-source-mask", /* SADB_X_EXT_ADDRESS_SRC_MASK 23 */
"X-dest-mask", /* SADB_X_EXT_ADDRESS_DST_MASK 24 */
"X-set-debug", /* SADB_X_EXT_DEBUG 25 */
"X-protocol", /* SADB_X_EXT_PROTOCOL 26 */
"X-NAT-T-type", /* SADB_X_EXT_NAT_T_TYPE 27 */
"X-NAT-T-sport", /* SADB_X_EXT_NAT_T_SPORT 28 */
"X-NAT-T-dport", /* SADB_X_EXT_NAT_T_DPORT 29 */
"X-NAT-T-OA", /* SADB_X_EXT_NAT_T_OA 30 */
};
const char *
pfkey_v2_sadb_ext_string(int ext)
{
if(ext <= SADB_EXT_MAX) {
return pfkey_sadb_ext_strings[ext];
} else {
return "unknown-ext";
}
}
static char *pfkey_sadb_type_strings[]={
"reserved", /* SADB_RESERVED */
"getspi", /* SADB_GETSPI */
"update", /* SADB_UPDATE */
"add", /* SADB_ADD */
"delete", /* SADB_DELETE */
"get", /* SADB_GET */
"acquire", /* SADB_ACQUIRE */
"register", /* SADB_REGISTER */
"expire", /* SADB_EXPIRE */
"flush", /* SADB_FLUSH */
"dump", /* SADB_DUMP */
"x-promisc", /* SADB_X_PROMISC */
"x-pchange", /* SADB_X_PCHANGE */
"x-groupsa", /* SADB_X_GRPSA */
"x-addflow(eroute)", /* SADB_X_ADDFLOW */
"x-delflow(eroute)", /* SADB_X_DELFLOW */
"x-debug", /* SADB_X_DEBUG */
"x-nat-t-new-mapping", /* SADB_X_NAT_T_NEW_MAPPING */
};
const char *
pfkey_v2_sadb_type_string(int sadb_type)
{
if(sadb_type <= SADB_MAX) {
return pfkey_sadb_type_strings[sadb_type];
} else {
return "unknown-sadb-type";
}
}

View File

@ -1,692 +0,0 @@
/*
* RFC2367 PF_KEYv2 Key management API message parser
* Copyright (C) 1999, 2000, 2001 Richard Guy Briggs.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
/*
* Template from klips/net/ipsec/ipsec/ipsec_parse.c.
*/
char pfkey_v2_ext_bits_c_version[] = "";
# include <sys/types.h>
# include <errno.h>
#include <freeswan.h>
#include <pfkeyv2.h>
#include <pfkey.h>
unsigned int extensions_bitmaps[2/*in/out*/][2/*perm/req*/][SADB_MAX + 1/*ext*/] = {
/* INBOUND EXTENSIONS */
{
/* PERMITTED IN */
{
/* SADB_RESERVED */
0
,
/* SADB_GETSPI */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_SPIRANGE
,
/* SADB_UPDATE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
| 1<<SADB_X_EXT_NAT_T_SPORT
| 1<<SADB_X_EXT_NAT_T_DPORT
,
/* SADB_ADD */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
| 1<<SADB_X_EXT_NAT_T_TYPE
| 1<<SADB_X_EXT_NAT_T_SPORT
| 1<<SADB_X_EXT_NAT_T_DPORT
| 1<<SADB_X_EXT_NAT_T_OA
,
/* SADB_DELETE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_GET */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_ACQUIRE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
| 1<<SADB_EXT_PROPOSAL
,
/* SADB_REGISTER */
1<<SADB_EXT_RESERVED
,
/* SADB_EXPIRE */
0
,
/* SADB_FLUSH */
1<<SADB_EXT_RESERVED
,
/* SADB_DUMP */
1<<SADB_EXT_RESERVED
,
/* SADB_X_PROMISC */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
| 1<<SADB_EXT_PROPOSAL
| 1<<SADB_EXT_SUPPORTED_AUTH
| 1<<SADB_EXT_SUPPORTED_ENCRYPT
| 1<<SADB_EXT_SPIRANGE
| 1<<SADB_X_EXT_KMPRIVATE
| 1<<SADB_X_EXT_SATYPE2
| 1<<SADB_X_EXT_SA2
| 1<<SADB_X_EXT_ADDRESS_DST2
,
/* SADB_X_PCHANGE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
| 1<<SADB_EXT_PROPOSAL
| 1<<SADB_EXT_SUPPORTED_AUTH
| 1<<SADB_EXT_SUPPORTED_ENCRYPT
| 1<<SADB_EXT_SPIRANGE
| 1<<SADB_X_EXT_KMPRIVATE
| 1<<SADB_X_EXT_SATYPE2
| 1<<SADB_X_EXT_SA2
| 1<<SADB_X_EXT_ADDRESS_DST2
,
/* SADB_X_GRPSA */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_X_EXT_SATYPE2
| 1<<SADB_X_EXT_SA2
| 1<<SADB_X_EXT_ADDRESS_DST2
,
/* SADB_X_ADDFLOW */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
| 1<<SADB_X_EXT_ADDRESS_DST_MASK
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_X_EXT_PROTOCOL
,
/* SADB_X_DELFLOW */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
| 1<<SADB_X_EXT_ADDRESS_DST_MASK
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_X_EXT_PROTOCOL
,
/* SADB_X_DEBUG */
1<<SADB_EXT_RESERVED
| 1<<SADB_X_EXT_DEBUG
,
/* SADB_X_NAT_T_NEW_MAPPING */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_X_EXT_NAT_T_SPORT
| 1<<SADB_X_EXT_NAT_T_DPORT
},
/* REQUIRED IN */
{
/* SADB_RESERVED */
0
,
/* SADB_GETSPI */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_SPIRANGE
,
/* SADB_UPDATE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
/*| 1<<SADB_EXT_KEY_AUTH*/
/*| 1<<SADB_EXT_KEY_ENCRYPT*/
,
/* SADB_ADD */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
/*| 1<<SADB_EXT_KEY_AUTH*/
/*| 1<<SADB_EXT_KEY_ENCRYPT*/
,
/* SADB_DELETE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_GET */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_ACQUIRE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_PROPOSAL
,
/* SADB_REGISTER */
1<<SADB_EXT_RESERVED
,
/* SADB_EXPIRE */
0
,
/* SADB_FLUSH */
1<<SADB_EXT_RESERVED
,
/* SADB_DUMP */
1<<SADB_EXT_RESERVED
,
/* SADB_X_PROMISC */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
| 1<<SADB_EXT_PROPOSAL
| 1<<SADB_EXT_SUPPORTED_AUTH
| 1<<SADB_EXT_SUPPORTED_ENCRYPT
| 1<<SADB_EXT_SPIRANGE
| 1<<SADB_X_EXT_KMPRIVATE
| 1<<SADB_X_EXT_SATYPE2
| 1<<SADB_X_EXT_SA2
| 1<<SADB_X_EXT_ADDRESS_DST2
,
/* SADB_X_PCHANGE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
| 1<<SADB_EXT_PROPOSAL
| 1<<SADB_EXT_SUPPORTED_AUTH
| 1<<SADB_EXT_SUPPORTED_ENCRYPT
| 1<<SADB_EXT_SPIRANGE
| 1<<SADB_X_EXT_KMPRIVATE
| 1<<SADB_X_EXT_SATYPE2
| 1<<SADB_X_EXT_SA2
| 1<<SADB_X_EXT_ADDRESS_DST2
,
/* SADB_X_GRPSA */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_DST
/*| 1<<SADB_X_EXT_SATYPE2*/
/*| 1<<SADB_X_EXT_SA2*/
/*| 1<<SADB_X_EXT_ADDRESS_DST2*/
,
/* SADB_X_ADDFLOW */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
| 1<<SADB_X_EXT_ADDRESS_DST_MASK
,
/* SADB_X_DELFLOW */
1<<SADB_EXT_RESERVED
/*| 1<<SADB_EXT_SA*/
#if 0 /* SADB_X_CLREROUTE doesn't need all these... */
| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
| 1<<SADB_X_EXT_ADDRESS_DST_MASK
#endif
,
/* SADB_X_DEBUG */
1<<SADB_EXT_RESERVED
| 1<<SADB_X_EXT_DEBUG
,
/* SADB_X_NAT_T_NEW_MAPPING */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_X_EXT_NAT_T_SPORT
| 1<<SADB_X_EXT_NAT_T_DPORT
}
},
/* OUTBOUND EXTENSIONS */
{
/* PERMITTED OUT */
{
/* SADB_RESERVED */
0
,
/* SADB_GETSPI */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_UPDATE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
,
/* SADB_ADD */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
| 1<<SADB_X_EXT_NAT_T_TYPE
| 1<<SADB_X_EXT_NAT_T_SPORT
| 1<<SADB_X_EXT_NAT_T_DPORT
| 1<<SADB_X_EXT_NAT_T_OA
,
/* SADB_DELETE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_GET */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
,
/* SADB_ACQUIRE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
| 1<<SADB_EXT_PROPOSAL
,
/* SADB_REGISTER */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SUPPORTED_AUTH
| 1<<SADB_EXT_SUPPORTED_ENCRYPT
,
/* SADB_EXPIRE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_FLUSH */
1<<SADB_EXT_RESERVED
,
/* SADB_DUMP */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
,
/* SADB_X_PROMISC */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
| 1<<SADB_EXT_PROPOSAL
| 1<<SADB_EXT_SUPPORTED_AUTH
| 1<<SADB_EXT_SUPPORTED_ENCRYPT
| 1<<SADB_EXT_SPIRANGE
| 1<<SADB_X_EXT_KMPRIVATE
| 1<<SADB_X_EXT_SATYPE2
| 1<<SADB_X_EXT_SA2
| 1<<SADB_X_EXT_ADDRESS_DST2
,
/* SADB_X_PCHANGE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
| 1<<SADB_EXT_PROPOSAL
| 1<<SADB_EXT_SUPPORTED_AUTH
| 1<<SADB_EXT_SUPPORTED_ENCRYPT
| 1<<SADB_EXT_SPIRANGE
| 1<<SADB_X_EXT_KMPRIVATE
| 1<<SADB_X_EXT_SATYPE2
| 1<<SADB_X_EXT_SA2
| 1<<SADB_X_EXT_ADDRESS_DST2
,
/* SADB_X_GRPSA */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_X_EXT_SATYPE2
| 1<<SADB_X_EXT_SA2
| 1<<SADB_X_EXT_ADDRESS_DST2
,
/* SADB_X_ADDFLOW */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
| 1<<SADB_X_EXT_ADDRESS_DST_MASK
| 1<<SADB_X_EXT_PROTOCOL
,
/* SADB_X_DELFLOW */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
| 1<<SADB_X_EXT_ADDRESS_DST_MASK
| 1<<SADB_X_EXT_PROTOCOL
,
/* SADB_X_DEBUG */
1<<SADB_EXT_RESERVED
| 1<<SADB_X_EXT_DEBUG
,
/* SADB_X_NAT_T_NEW_MAPPING */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_X_EXT_NAT_T_SPORT
| 1<<SADB_X_EXT_NAT_T_DPORT
},
/* REQUIRED OUT */
{
/* SADB_RESERVED */
0
,
/* SADB_GETSPI */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_UPDATE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_ADD */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_DELETE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_GET */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
/* | 1<<SADB_EXT_KEY_AUTH */
/* | 1<<SADB_EXT_KEY_ENCRYPT */
,
/* SADB_ACQUIRE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_PROPOSAL
,
/* SADB_REGISTER */
1<<SADB_EXT_RESERVED
/* | 1<<SADB_EXT_SUPPORTED_AUTH
| 1<<SADB_EXT_SUPPORTED_ENCRYPT */
,
/* SADB_EXPIRE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
/* | 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT */
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_FLUSH */
1<<SADB_EXT_RESERVED
,
/* SADB_DUMP */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
,
/* SADB_X_PROMISC */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
| 1<<SADB_EXT_PROPOSAL
| 1<<SADB_EXT_SUPPORTED_AUTH
| 1<<SADB_EXT_SUPPORTED_ENCRYPT
| 1<<SADB_EXT_SPIRANGE
| 1<<SADB_X_EXT_KMPRIVATE
| 1<<SADB_X_EXT_SATYPE2
| 1<<SADB_X_EXT_SA2
| 1<<SADB_X_EXT_ADDRESS_DST2
,
/* SADB_X_PCHANGE */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_LIFETIME_CURRENT
| 1<<SADB_EXT_LIFETIME_HARD
| 1<<SADB_EXT_LIFETIME_SOFT
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_EXT_ADDRESS_PROXY
| 1<<SADB_EXT_KEY_AUTH
| 1<<SADB_EXT_KEY_ENCRYPT
| 1<<SADB_EXT_IDENTITY_SRC
| 1<<SADB_EXT_IDENTITY_DST
| 1<<SADB_EXT_SENSITIVITY
| 1<<SADB_EXT_PROPOSAL
| 1<<SADB_EXT_SUPPORTED_AUTH
| 1<<SADB_EXT_SUPPORTED_ENCRYPT
| 1<<SADB_EXT_SPIRANGE
| 1<<SADB_X_EXT_KMPRIVATE
| 1<<SADB_X_EXT_SATYPE2
| 1<<SADB_X_EXT_SA2
| 1<<SADB_X_EXT_ADDRESS_DST2
,
/* SADB_X_GRPSA */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_DST
,
/* SADB_X_ADDFLOW */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
| 1<<SADB_X_EXT_ADDRESS_DST_MASK
,
/* SADB_X_DELFLOW */
1<<SADB_EXT_RESERVED
/*| 1<<SADB_EXT_SA*/
| 1<<SADB_X_EXT_ADDRESS_SRC_FLOW
| 1<<SADB_X_EXT_ADDRESS_DST_FLOW
| 1<<SADB_X_EXT_ADDRESS_SRC_MASK
| 1<<SADB_X_EXT_ADDRESS_DST_MASK
,
/* SADB_X_DEBUG */
1<<SADB_EXT_RESERVED
| 1<<SADB_X_EXT_DEBUG
,
/* SADB_X_NAT_T_NEW_MAPPING */
1<<SADB_EXT_RESERVED
| 1<<SADB_EXT_SA
| 1<<SADB_EXT_ADDRESS_SRC
| 1<<SADB_EXT_ADDRESS_DST
| 1<<SADB_X_EXT_NAT_T_SPORT
| 1<<SADB_X_EXT_NAT_T_DPORT
}
}
};

File diff suppressed because it is too large Load Diff

View File

@ -1,368 +0,0 @@
/*
RFC 2367 PF_KEY Key Management API July 1998
Appendix D: Sample Header File
This file defines structures and symbols for the PF_KEY Version 2
key management interface. It was written at the U.S. Naval Research
Laboratory. This file is in the public domain. The authors ask that
you leave this credit intact on any copies of this file.
*/
#ifndef __PFKEY_V2_H
#define __PFKEY_V2_H 1
#define PF_KEY_V2 2
#define PFKEYV2_REVISION 199806L
#define SADB_RESERVED 0
#define SADB_GETSPI 1
#define SADB_UPDATE 2
#define SADB_ADD 3
#define SADB_DELETE 4
#define SADB_GET 5
#define SADB_ACQUIRE 6
#define SADB_REGISTER 7
#define SADB_EXPIRE 8
#define SADB_FLUSH 9
#define SADB_DUMP 10
#define SADB_X_PROMISC 11
#define SADB_X_PCHANGE 12
#define SADB_X_GRPSA 13
#define SADB_X_ADDFLOW 14
#define SADB_X_DELFLOW 15
#define SADB_X_DEBUG 16
#define SADB_X_NAT_T_NEW_MAPPING 17
#define SADB_MAX 17
struct sadb_msg {
uint8_t sadb_msg_version;
uint8_t sadb_msg_type;
uint8_t sadb_msg_errno;
uint8_t sadb_msg_satype;
uint16_t sadb_msg_len;
uint16_t sadb_msg_reserved;
uint32_t sadb_msg_seq;
uint32_t sadb_msg_pid;
};
struct sadb_ext {
uint16_t sadb_ext_len;
uint16_t sadb_ext_type;
};
struct sadb_sa {
uint16_t sadb_sa_len;
uint16_t sadb_sa_exttype;
uint32_t sadb_sa_spi;
uint8_t sadb_sa_replay;
uint8_t sadb_sa_state;
uint8_t sadb_sa_auth;
uint8_t sadb_sa_encrypt;
uint32_t sadb_sa_flags;
uint32_t /*IPsecSAref_t*/ sadb_x_sa_ref; /* 32 bits */
uint8_t sadb_x_reserved[4];
};
struct sadb_sa_v1 {
uint16_t sadb_sa_len;
uint16_t sadb_sa_exttype;
uint32_t sadb_sa_spi;
uint8_t sadb_sa_replay;
uint8_t sadb_sa_state;
uint8_t sadb_sa_auth;
uint8_t sadb_sa_encrypt;
uint32_t sadb_sa_flags;
};
struct sadb_lifetime {
uint16_t sadb_lifetime_len;
uint16_t sadb_lifetime_exttype;
uint32_t sadb_lifetime_allocations;
uint64_t sadb_lifetime_bytes;
uint64_t sadb_lifetime_addtime;
uint64_t sadb_lifetime_usetime;
uint32_t sadb_x_lifetime_packets;
uint32_t sadb_x_lifetime_reserved;
};
struct sadb_address {
uint16_t sadb_address_len;
uint16_t sadb_address_exttype;
uint8_t sadb_address_proto;
uint8_t sadb_address_prefixlen;
uint16_t sadb_address_reserved;
};
struct sadb_key {
uint16_t sadb_key_len;
uint16_t sadb_key_exttype;
uint16_t sadb_key_bits;
uint16_t sadb_key_reserved;
};
struct sadb_ident {
uint16_t sadb_ident_len;
uint16_t sadb_ident_exttype;
uint16_t sadb_ident_type;
uint16_t sadb_ident_reserved;
uint64_t sadb_ident_id;
};
struct sadb_sens {
uint16_t sadb_sens_len;
uint16_t sadb_sens_exttype;
uint32_t sadb_sens_dpd;
uint8_t sadb_sens_sens_level;
uint8_t sadb_sens_sens_len;
uint8_t sadb_sens_integ_level;
uint8_t sadb_sens_integ_len;
uint32_t sadb_sens_reserved;
};
struct sadb_prop {
uint16_t sadb_prop_len;
uint16_t sadb_prop_exttype;
uint8_t sadb_prop_replay;
uint8_t sadb_prop_reserved[3];
};
struct sadb_comb {
uint8_t sadb_comb_auth;
uint8_t sadb_comb_encrypt;
uint16_t sadb_comb_flags;
uint16_t sadb_comb_auth_minbits;
uint16_t sadb_comb_auth_maxbits;
uint16_t sadb_comb_encrypt_minbits;
uint16_t sadb_comb_encrypt_maxbits;
uint32_t sadb_comb_reserved;
uint32_t sadb_comb_soft_allocations;
uint32_t sadb_comb_hard_allocations;
uint64_t sadb_comb_soft_bytes;
uint64_t sadb_comb_hard_bytes;
uint64_t sadb_comb_soft_addtime;
uint64_t sadb_comb_hard_addtime;
uint64_t sadb_comb_soft_usetime;
uint64_t sadb_comb_hard_usetime;
uint32_t sadb_x_comb_soft_packets;
uint32_t sadb_x_comb_hard_packets;
};
struct sadb_supported {
uint16_t sadb_supported_len;
uint16_t sadb_supported_exttype;
uint32_t sadb_supported_reserved;
};
struct sadb_alg {
uint8_t sadb_alg_id;
uint8_t sadb_alg_ivlen;
uint16_t sadb_alg_minbits;
uint16_t sadb_alg_maxbits;
uint16_t sadb_alg_reserved;
};
struct sadb_spirange {
uint16_t sadb_spirange_len;
uint16_t sadb_spirange_exttype;
uint32_t sadb_spirange_min;
uint32_t sadb_spirange_max;
uint32_t sadb_spirange_reserved;
};
struct sadb_x_kmprivate {
uint16_t sadb_x_kmprivate_len;
uint16_t sadb_x_kmprivate_exttype;
uint32_t sadb_x_kmprivate_reserved;
};
struct sadb_x_satype {
uint16_t sadb_x_satype_len;
uint16_t sadb_x_satype_exttype;
uint8_t sadb_x_satype_satype;
uint8_t sadb_x_satype_reserved[3];
};
struct sadb_x_policy {
uint16_t sadb_x_policy_len;
uint16_t sadb_x_policy_exttype;
uint16_t sadb_x_policy_type;
uint8_t sadb_x_policy_dir;
uint8_t sadb_x_policy_reserved;
uint32_t sadb_x_policy_id;
uint32_t sadb_x_policy_reserved2;
};
struct sadb_x_debug {
uint16_t sadb_x_debug_len;
uint16_t sadb_x_debug_exttype;
uint32_t sadb_x_debug_tunnel;
uint32_t sadb_x_debug_netlink;
uint32_t sadb_x_debug_xform;
uint32_t sadb_x_debug_eroute;
uint32_t sadb_x_debug_spi;
uint32_t sadb_x_debug_radij;
uint32_t sadb_x_debug_esp;
uint32_t sadb_x_debug_ah;
uint32_t sadb_x_debug_rcv;
uint32_t sadb_x_debug_pfkey;
uint32_t sadb_x_debug_ipcomp;
uint32_t sadb_x_debug_verbose;
uint8_t sadb_x_debug_reserved[4];
};
struct sadb_x_nat_t_type {
uint16_t sadb_x_nat_t_type_len;
uint16_t sadb_x_nat_t_type_exttype;
uint8_t sadb_x_nat_t_type_type;
uint8_t sadb_x_nat_t_type_reserved[3];
};
struct sadb_x_nat_t_port {
uint16_t sadb_x_nat_t_port_len;
uint16_t sadb_x_nat_t_port_exttype;
uint16_t sadb_x_nat_t_port_port;
uint16_t sadb_x_nat_t_port_reserved;
};
/*
* A protocol structure for passing through the transport level
* protocol. It contains more fields than are actually used/needed
* but it is this way to be compatible with the structure used in
* OpenBSD (http://www.openbsd.org/cgi-bin/cvsweb/src/sys/net/pfkeyv2.h)
*/
struct sadb_protocol {
uint16_t sadb_protocol_len;
uint16_t sadb_protocol_exttype;
uint8_t sadb_protocol_proto;
uint8_t sadb_protocol_direction;
uint8_t sadb_protocol_flags;
uint8_t sadb_protocol_reserved2;
};
#define SADB_EXT_RESERVED 0
#define SADB_EXT_SA 1
#define SADB_EXT_LIFETIME_CURRENT 2
#define SADB_EXT_LIFETIME_HARD 3
#define SADB_EXT_LIFETIME_SOFT 4
#define SADB_EXT_ADDRESS_SRC 5
#define SADB_EXT_ADDRESS_DST 6
#define SADB_EXT_ADDRESS_PROXY 7
#define SADB_EXT_KEY_AUTH 8
#define SADB_EXT_KEY_ENCRYPT 9
#define SADB_EXT_IDENTITY_SRC 10
#define SADB_EXT_IDENTITY_DST 11
#define SADB_EXT_SENSITIVITY 12
#define SADB_EXT_PROPOSAL 13
#define SADB_EXT_SUPPORTED_AUTH 14
#define SADB_EXT_SUPPORTED_ENCRYPT 15
#define SADB_EXT_SPIRANGE 16
#define SADB_X_EXT_KMPRIVATE 17
#define SADB_X_EXT_SATYPE2 18
#ifdef KERNEL26_HAS_KAME_DUPLICATES
#define SADB_X_EXT_POLICY 18
#endif
#define SADB_X_EXT_SA2 19
#define SADB_X_EXT_ADDRESS_DST2 20
#define SADB_X_EXT_ADDRESS_SRC_FLOW 21
#define SADB_X_EXT_ADDRESS_DST_FLOW 22
#define SADB_X_EXT_ADDRESS_SRC_MASK 23
#define SADB_X_EXT_ADDRESS_DST_MASK 24
#define SADB_X_EXT_DEBUG 25
#define SADB_X_EXT_PROTOCOL 26
#define SADB_X_EXT_NAT_T_TYPE 27
#define SADB_X_EXT_NAT_T_SPORT 28
#define SADB_X_EXT_NAT_T_DPORT 29
#define SADB_X_EXT_NAT_T_OA 30
#define SADB_EXT_MAX 30
/* SADB_X_DELFLOW required over and above SADB_X_SAFLAGS_CLEARFLOW */
#define SADB_X_EXT_ADDRESS_DELFLOW \
( (1<<SADB_X_EXT_ADDRESS_SRC_FLOW) \
| (1<<SADB_X_EXT_ADDRESS_DST_FLOW) \
| (1<<SADB_X_EXT_ADDRESS_SRC_MASK) \
| (1<<SADB_X_EXT_ADDRESS_DST_MASK))
#define SADB_SATYPE_UNSPEC 0
#define SADB_SATYPE_AH 2
#define SADB_SATYPE_ESP 3
#define SADB_SATYPE_RSVP 5
#define SADB_SATYPE_OSPFV2 6
#define SADB_SATYPE_RIPV2 7
#define SADB_SATYPE_MIP 8
#define SADB_X_SATYPE_IPIP 9
#ifdef KERNEL26_HAS_KAME_DUPLICATES
#define SADB_X_SATYPE_IPCOMP 9 /* ICK! */
#endif
#define SADB_X_SATYPE_COMP 10
#define SADB_X_SATYPE_INT 11
#define SADB_SATYPE_MAX 11
#define SADB_SASTATE_LARVAL 0
#define SADB_SASTATE_MATURE 1
#define SADB_SASTATE_DYING 2
#define SADB_SASTATE_DEAD 3
#define SADB_SASTATE_MAX 3
#define SADB_SAFLAGS_PFS 1
#define SADB_X_SAFLAGS_REPLACEFLOW 2
#define SADB_X_SAFLAGS_CLEARFLOW 4
#define SADB_X_SAFLAGS_INFLOW 8
/* Authentication algorithms */
#define SADB_AALG_NONE 0
#define SADB_AALG_MD5HMAC 2
#define SADB_AALG_SHA1HMAC 3
#define SADB_X_AALG_SHA2_256HMAC 5
#define SADB_X_AALG_SHA2_384HMAC 6
#define SADB_X_AALG_SHA2_512HMAC 7
#define SADB_X_AALG_RIPEMD160HMAC 8
#define SADB_X_AALG_AES_XCBC_MAC 9
#define SADB_X_AALG_NULL 251 /* kame */
#define SADB_X_AALG_SHA2_256_96HMAC 252
#define SADB_AALG_MAX 252
/* Encryption algorithms */
#define SADB_EALG_NONE 0
#define SADB_EALG_DESCBC 2
#define SADB_EALG_3DESCBC 3
#define SADB_X_EALG_CASTCBC 6
#define SADB_X_EALG_BLOWFISHCBC 7
#define SADB_EALG_NULL 11
#define SADB_X_EALG_AESCBC 12
#define SADB_X_EALG_AESCTR 13
#define SADB_X_EALG_AES_CCM_ICV8 14
#define SADB_X_EALG_AES_CCM_ICV12 15
#define SADB_X_EALG_AES_CCM_ICV16 16
#define SADB_X_EALG_AES_GCM_ICV8 18
#define SADB_X_EALG_AES_GCM_ICV12 19
#define SADB_X_EALG_AES_GCM_ICV16 20
#define SADB_X_EALG_CAMELLIACBC 22
#define SADB_X_EALG_NULL_AES_GMAC 23
#define SADB_EALG_MAX 253 /* last EALG */
/* private allocations should use 249-255 (RFC2407) */
#define SADB_X_EALG_SERPENTCBC 252 /* draft-ietf-ipsec-ciph-aes-cbc-00 */
#define SADB_X_EALG_TWOFISHCBC 253 /* draft-ietf-ipsec-ciph-aes-cbc-00 */
/* Compression algorithms */
#define SADB_X_CALG_NONE 0
#define SADB_X_CALG_OUI 1
#define SADB_X_CALG_DEFLATE 2
#define SADB_X_CALG_LZS 3
#define SADB_X_CALG_LZJH 4
#define SADB_X_CALG_MAX 4
#define SADB_X_TALG_NONE 0
#define SADB_X_TALG_IPv4_in_IPv4 1
#define SADB_X_TALG_IPv6_in_IPv4 2
#define SADB_X_TALG_IPv4_in_IPv6 3
#define SADB_X_TALG_IPv6_in_IPv6 4
#define SADB_X_TALG_MAX 4
/* Identity Extension values */
#define SADB_IDENTTYPE_RESERVED 0
#define SADB_IDENTTYPE_PREFIX 1
#define SADB_IDENTTYPE_FQDN 2
#define SADB_IDENTTYPE_USERFQDN 3
#define SADB_IDENTTYPE_MAX 3
#endif /* __PFKEY_V2_H */

View File

@ -1,69 +0,0 @@
.TH IPSEC_PORTOF 3 "8 Sept 2000"
.SH NAME
ipsec portof \- get port field of an ip_address
.br
ipsec setportof \- set port field of an ip_address
.br
ipsec sockaddrof \- get pointer to internal sockaddr of an ip_address
.br
ipsec sockaddrlenof \- get length of internal sockaddr of an ip_address
.SH SYNOPSIS
.B "#include <freeswan.h>"
.sp
.B "int portof(const ip_address *src);"
.br
.B "void setportof(int port, ip_address *dst);"
.br
.B "struct sockaddr *sockaddrof(ip_address *src);"
.br
.B "size_t sockaddrlenof(const ip_address *src);"
.SH DESCRIPTION
The
.B <freeswan.h>
internal type
.I ip_address
contains one of the
.I sockaddr
types internally.
\fIReliance on this feature is discouraged\fR,
but it may occasionally be necessary.
These functions provide low-level tools for this purpose.
.PP
.I Portof
and
.I setportof
respectively read and write the port-number field of the internal
.IR sockaddr .
The values are in network byte order.
.PP
.I Sockaddrof
returns a pointer to the internal
.IR sockaddr ,
for passing to other functions.
.PP
.I Sockaddrlenof
reports the size of the internal
.IR sockaddr ,
for use in storage allocation.
.SH SEE ALSO
inet(3), ipsec_initaddr(3)
.SH DIAGNOSTICS
.I Portof
returns
.BR \-1 ,
.I sockaddrof
returns
.BR NULL ,
and
.I sockaddrlenof
returns
.B 0
if an unknown address family is found within the
.IR ip_address .
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
These functions all depend on low-level details of the
.I ip_address
type, which are in principle subject to change.
Avoid using them unless really necessary.

View File

@ -1,96 +0,0 @@
/*
* low-level ip_address ugliness
* Copyright (C) 2000 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include <sys/socket.h>
#include "internal.h"
#include "freeswan.h"
/*
- portof - get the port field of an ip_address
*/
int /* network order */
portof(src)
const ip_address *src;
{
switch (src->u.v4.sin_family) {
case AF_INET:
return src->u.v4.sin_port;
break;
case AF_INET6:
return src->u.v6.sin6_port;
break;
default:
return -1; /* "can't happen" */
break;
}
}
/*
- setportof - set the port field of an ip_address
*/
void
setportof(port, dst)
int port; /* network order */
ip_address *dst;
{
switch (dst->u.v4.sin_family) {
case AF_INET:
dst->u.v4.sin_port = port;
break;
case AF_INET6:
dst->u.v6.sin6_port = port;
break;
}
}
/*
- sockaddrof - get a pointer to the sockaddr hiding inside an ip_address
*/
struct sockaddr *
sockaddrof(src)
ip_address *src;
{
switch (src->u.v4.sin_family) {
case AF_INET:
return (struct sockaddr *)&src->u.v4;
break;
case AF_INET6:
return (struct sockaddr *)&src->u.v6;
break;
default:
return NULL; /* "can't happen" */
break;
}
}
/*
- sockaddrlenof - get length of the sockaddr hiding inside an ip_address
*/
size_t /* 0 for error */
sockaddrlenof(src)
const ip_address *src;
{
switch (src->u.v4.sin_family) {
case AF_INET:
return sizeof(src->u.v4);
break;
case AF_INET6:
return sizeof(src->u.v6);
break;
default:
return 0;
break;
}
}

View File

@ -1,59 +0,0 @@
/*
* convert binary form of address range to ASCII
* Copyright (C) 1998, 1999 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include "internal.h"
#include "freeswan.h"
/*
- rangetoa - convert address range to ASCII
*/
size_t /* space needed for full conversion */
rangetoa(addrs, format, dst, dstlen)
struct in_addr addrs[2];
int format; /* character */
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
size_t len;
size_t rest;
int n;
char *p;
switch (format) {
case 0:
break;
default:
return 0;
break;
}
len = addrtoa(addrs[0], 0, dst, dstlen);
if (len < dstlen)
for (p = dst + len - 1, n = 3; len < dstlen && n > 0;
p++, len++, n--)
*p = '.';
else
p = NULL;
if (len < dstlen)
rest = dstlen - len;
else {
if (dstlen > 0)
*(dst + dstlen - 1) = '\0';
rest = 0;
}
len += addrtoa(addrs[1], 0, p, rest);
return len;
}

View File

@ -1,58 +0,0 @@
.TH IPSEC_RANGETOSUBNET 3 "8 Sept 2000"
.SH NAME
ipsec rangetosubnet \- convert address range to subnet
.SH SYNOPSIS
.B "#include <freeswan.h>"
.sp
.B "const char *rangetosubnet(const ip_address *start,"
.ti +1c
.B "const ip_address *stop, ip_subnet *dst);"
.SH DESCRIPTION
.I Rangetosubnet
accepts two IP addresses which define an address range,
from
.I start
to
.I stop
inclusive,
and converts this to a subnet if possible.
The addresses must both be IPv4 or both be IPv6,
and the address family of the resulting subnet is the same.
.PP
.I Rangetosubnet
returns NULL for success and
a pointer to a string-literal error message for failure;
see DIAGNOSTICS.
.SH SEE ALSO
ipsec_initsubnet(3), ipsec_ttosubnet(3)
.SH DIAGNOSTICS
Fatal errors in
.I rangetosubnet
are:
mixed address families;
unknown address family;
.I start
and
.I stop
do not define a subnet.
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
The restriction of error reports to literal strings
(so that callers don't need to worry about freeing them or copying them)
does limit the precision of error reporting.
.PP
The error-reporting convention lends itself
to slightly obscure code,
because many readers will not think of NULL as signifying success.
A good way to make it clearer is to write something like:
.PP
.RS
.nf
.B "const char *error;"
.sp
.B "error = rangetosubnet( /* ... */ );"
.B "if (error != NULL) {"
.B " /* something went wrong */"
.fi
.RE

View File

@ -1,224 +0,0 @@
/*
* express an address range as a subnet (if possible)
* Copyright (C) 2000 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include "internal.h"
#include "freeswan.h"
/*
- rangetosubnet - turn an address range into a subnet, if possible
*
* A range which is a valid subnet will have a network part which is the
* same in the from value and the to value, followed by a host part which
* is all 0 in the from value and all 1 in the to value.
*/
err_t
rangetosubnet(from, to, dst)
const ip_address *from;
const ip_address *to;
ip_subnet *dst;
{
unsigned const char *fp;
unsigned const char *tp;
unsigned fb;
unsigned tb;
unsigned const char *f;
unsigned const char *t;
size_t n;
size_t n2;
int i;
int nnet;
unsigned m;
if (addrtypeof(from) != addrtypeof(to))
return "mismatched address types";
n = addrbytesptr(from, &fp);
if (n == 0)
return "unknown address type";
n2 = addrbytesptr(to, &tp);
if (n != n2)
return "internal size mismatch in rangetosubnet";
f = fp;
t = tp;
nnet = 0;
for (i = n; i > 0 && *f == *t; i--, f++, t++)
nnet += 8;
if (i > 0 && !(*f == 0x00 && *t == 0xff)) { /* mid-byte bdry. */
fb = *f++;
tb = *t++;
i--;
m = 0x80;
while ((fb&m) == (tb&m)) {
fb &= ~m;
tb |= m;
m >>= 1;
nnet++;
}
if (fb != 0x00 || tb != 0xff)
return "not a valid subnet";
}
for (; i > 0 && *f == 0x00 && *t == 0xff; i--, f++, t++)
continue;
if (i != 0)
return "invalid subnet";
return initsubnet(from, nnet, 'x', dst);
}
#ifdef RANGETOSUBNET_MAIN
#include <stdio.h>
void regress(void);
int
main(int argc, char *argv[])
{
ip_address start;
ip_address stop;
ip_subnet sub;
char buf[100];
const char *oops;
size_t n;
int af;
int i;
if (argc == 2 && strcmp(argv[1], "-r") == 0) {
regress();
fprintf(stderr, "regress() returned?!?\n");
exit(1);
}
if (argc < 3) {
fprintf(stderr, "Usage: %s [-6] start stop\n", argv[0]);
fprintf(stderr, " or: %s -r\n", argv[0]);
exit(2);
}
af = AF_INET;
i = 1;
if (strcmp(argv[i], "-6") == 0) {
af = AF_INET6;
i++;
}
oops = ttoaddr(argv[i], 0, af, &start);
if (oops != NULL) {
fprintf(stderr, "%s: start conversion failed: %s\n", argv[0], oops);
exit(1);
}
oops = ttoaddr(argv[i+1], 0, af, &stop);
if (oops != NULL) {
fprintf(stderr, "%s: stop conversion failed: %s\n", argv[0], oops);
exit(1);
}
oops = rangetosubnet(&start, &stop, &sub);
if (oops != NULL) {
fprintf(stderr, "%s: rangetosubnet failed: %s\n", argv[0], oops);
exit(1);
}
n = subnettot(&sub, 0, buf, sizeof(buf));
if (n > sizeof(buf)) {
fprintf(stderr, "%s: reverse conversion", argv[0]);
fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
(long)n, (long)sizeof(buf));
exit(1);
}
printf("%s\n", buf);
exit(0);
}
struct rtab {
int family;
char *start;
char *stop;
char *output; /* NULL means error expected */
} rtab[] = {
{4, "1.2.3.0", "1.2.3.255", "1.2.3.0/24"},
{4, "1.2.3.0", "1.2.3.7", "1.2.3.0/29"},
{4, "1.2.3.240", "1.2.3.255", "1.2.3.240/28"},
{4, "0.0.0.0", "255.255.255.255", "0.0.0.0/0"},
{4, "1.2.3.4", "1.2.3.4", "1.2.3.4/32"},
{4, "1.2.3.0", "1.2.3.254", NULL},
{4, "1.2.3.0", "1.2.3.126", NULL},
{4, "1.2.3.0", "1.2.3.125", NULL},
{4, "1.2.0.0", "1.2.255.255", "1.2.0.0/16"},
{4, "1.2.0.0", "1.2.0.255", "1.2.0.0/24"},
{4, "1.2.255.0", "1.2.255.255", "1.2.255.0/24"},
{4, "1.2.255.0", "1.2.254.255", NULL},
{4, "1.2.255.1", "1.2.255.255", NULL},
{4, "1.2.0.1", "1.2.255.255", NULL},
{6, "1:2:3:4:5:6:7:0", "1:2:3:4:5:6:7:ffff", "1:2:3:4:5:6:7:0/112"},
{6, "1:2:3:4:5:6:7:0", "1:2:3:4:5:6:7:fff", "1:2:3:4:5:6:7:0/116"},
{6, "1:2:3:4:5:6:7:f0", "1:2:3:4:5:6:7:ff", "1:2:3:4:5:6:7:f0/124"},
{4, NULL, NULL, NULL},
};
void
regress()
{
struct rtab *r;
int status = 0;
ip_address start;
ip_address stop;
ip_subnet sub;
char buf[100];
const char *oops;
size_t n;
int af;
for (r = rtab; r->start != NULL; r++) {
af = (r->family == 4) ? AF_INET : AF_INET6;
oops = ttoaddr(r->start, 0, af, &start);
if (oops != NULL) {
printf("surprise failure converting `%s'\n", r->start);
exit(1);
}
oops = ttoaddr(r->stop, 0, af, &stop);
if (oops != NULL) {
printf("surprise failure converting `%s'\n", r->stop);
exit(1);
}
oops = rangetosubnet(&start, &stop, &sub);
if (oops != NULL && r->output == NULL)
{} /* okay, error expected */
else if (oops != NULL) {
printf("`%s'-`%s' rangetosubnet failed: %s\n",
r->start, r->stop, oops);
status = 1;
} else if (r->output == NULL) {
printf("`%s'-`%s' rangetosubnet succeeded unexpectedly\n",
r->start, r->stop);
status = 1;
} else {
n = subnettot(&sub, 0, buf, sizeof(buf));
if (n > sizeof(buf)) {
printf("`%s'-`%s' subnettot failed: need %ld\n",
r->start, r->stop, (long)n);
status = 1;
} else if (strcmp(r->output, buf) != 0) {
printf("`%s'-`%s' gave `%s', expected `%s'\n",
r->start, r->stop, buf, r->output);
status = 1;
}
}
}
exit(status);
}
#endif /* RANGETOSUBNET_MAIN */

View File

@ -1,164 +0,0 @@
.TH IPSEC_ANYADDR 3 "28 Nov 2000"
.SH NAME
ipsec sameaddr \- are two addresses the same?
.br
ipsec addrcmp \- ordered comparison of addresses
.br
ipsec samesubnet \- are two subnets the same?
.br
ipsec addrinsubnet \- is an address within a subnet?
.br
ipsec subnetinsubnet \- is a subnet within another subnet?
.br
ipsec subnetishost \- is a subnet a single host?
.br
ipsec samesaid \- are two SA IDs the same?
.br
ipsec sameaddrtype \- are two addresses of the same address family?
.br
ipsec samesubnettype \- are two subnets of the same address family?
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "int sameaddr(const ip_address *a, const ip_address *b);"
.br
.B "int addrcmp(const ip_address *a, const ip_address *b);"
.br
.B "int samesubnet(const ip_subnet *a, const ip_subnet *b);"
.br
.B "int addrinsubnet(const ip_address *a, const ip_subnet *s);"
.br
.B "int subnetinsubnet(const ip_subnet *a, const ip_subnet *b);"
.br
.B "int subnetishost(const ip_subnet *s);"
.br
.B "int samesaid(const ip_said *a, const ip_said *b);"
.br
.B "int sameaddrtype(const ip_address *a, const ip_address *b);"
.br
.B "int samesubnettype(const ip_subnet *a, const ip_subnet *b);"
.SH DESCRIPTION
These functions do various comparisons and tests on the
.I ip_address
type and
.I ip_subnet
types.
.PP
.I Sameaddr
returns
non-zero
if addresses
.I a
and
.IR b
are identical,
and
.B 0
otherwise.
Addresses of different families are never identical.
.PP
.I Addrcmp
returns
.BR \-1 ,
.BR 0 ,
or
.BR 1
respectively
if address
.I a
is less than, equal to, or greater than
.IR b .
If they are not of the same address family,
they are never equal;
the ordering reported in this case is arbitrary
(and probably not useful) but consistent.
.PP
.I Samesubnet
returns
non-zero
if subnets
.I a
and
.IR b
are identical,
and
.B 0
otherwise.
Subnets of different address families are never identical.
.PP
.I Addrinsubnet
returns
non-zero
if address
.I a
is within subnet
.IR s
and
.B 0
otherwise.
An address is never within a
subnet of a different address family.
.PP
.I Subnetinsubnet
returns
non-zero
if subnet
.I a
is a subset of subnet
.IR b
and
.B 0
otherwise.
A subnet is deemed to be a subset of itself.
A subnet is never a subset of another
subnet if their address families differ.
.PP
.I Subnetishost
returns
non-zero
if subnet
.I s
is in fact only a single host,
and
.B 0
otherwise.
.PP
.I Samesaid
returns
non-zero
if SA IDs
.I a
and
.IR b
are identical,
and
.B 0
otherwise.
.PP
.I Sameaddrtype
returns
non-zero
if addresses
.I a
and
.IR b
are of the same address family,
and
.B 0
otherwise.
.PP
.I Samesubnettype
returns
non-zero
if subnets
.I a
and
.IR b
are of the same address family,
and
.B 0
otherwise.
.SH SEE ALSO
inet(3), ipsec_initaddr(3)
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.

View File

@ -1,188 +0,0 @@
/*
* comparisons
* Copyright (C) 2000 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include "internal.h"
#include "freeswan.h"
static int samenbits(const ip_address *a, const ip_address *b, int n);
/*
- addrcmp - compare two addresses
* Caution, the order of the tests is subtle: doing type test before
* size test can yield cases where a<b, b<c, but a>c.
*/
int /* like memcmp */
addrcmp(a, b)
const ip_address *a;
const ip_address *b;
{
int at = addrtypeof(a);
int bt = addrtypeof(b);
const unsigned char *ap;
const unsigned char *bp;
size_t as = addrbytesptr(a, &ap);
size_t bs = addrbytesptr(b, &bp);
size_t n = (as < bs) ? as : bs; /* min(as, bs) */
int c = memcmp(ap, bp, n);
if (c != 0) /* bytes differ */
return (c < 0) ? -1 : 1;
if (as != bs) /* comparison incomplete: lexical order */
return (as < bs) ? -1 : 1;
if (at != bt) /* bytes same but not same type: break tie */
return (at < bt) ? -1 : 1;
return 0;
}
/*
- sameaddr - are two addresses the same?
*/
int
sameaddr(a, b)
const ip_address *a;
const ip_address *b;
{
return (addrcmp(a, b) == 0) ? 1 : 0;
}
/*
- samesubnet - are two subnets the same?
*/
int
samesubnet(a, b)
const ip_subnet *a;
const ip_subnet *b;
{
if (!sameaddr(&a->addr, &b->addr)) /* also does type check */
return 0;
if (a->maskbits != b->maskbits)
return 0;
return 1;
}
/*
- subnetishost - is a subnet in fact a single host?
*/
int
subnetishost(a)
const ip_subnet *a;
{
return (a->maskbits == addrlenof(&a->addr)*8) ? 1 : 0;
}
/*
- samesaid - are two SA IDs the same?
*/
int
samesaid(a, b)
const ip_said *a;
const ip_said *b;
{
if (a->spi != b->spi) /* test first, most likely to be different */
return 0;
if (!sameaddr(&a->dst, &b->dst))
return 0;
if (a->proto != b->proto)
return 0;
return 1;
}
/*
- sameaddrtype - do two addresses have the same type?
*/
int
sameaddrtype(a, b)
const ip_address *a;
const ip_address *b;
{
return (addrtypeof(a) == addrtypeof(b)) ? 1 : 0;
}
/*
- samesubnettype - do two subnets have the same type?
*/
int
samesubnettype(a, b)
const ip_subnet *a;
const ip_subnet *b;
{
return (subnettypeof(a) == subnettypeof(b)) ? 1 : 0;
}
/*
- addrinsubnet - is this address in this subnet?
*/
int
addrinsubnet(a, s)
const ip_address *a;
const ip_subnet *s;
{
if (addrtypeof(a) != subnettypeof(s))
return 0;
if (!samenbits(a, &s->addr, s->maskbits))
return 0;
return 1;
}
/*
- subnetinsubnet - is one subnet within another?
*/
int
subnetinsubnet(a, b)
const ip_subnet *a;
const ip_subnet *b;
{
if (subnettypeof(a) != subnettypeof(b))
return 0;
if (a->maskbits < b->maskbits) /* a is bigger than b */
return 0;
if (!samenbits(&a->addr, &b->addr, b->maskbits))
return 0;
return 1;
}
/*
- samenbits - do two addresses have the same first n bits?
*/
static int
samenbits(a, b, nbits)
const ip_address *a;
const ip_address *b;
int nbits;
{
const unsigned char *ap;
const unsigned char *bp;
size_t n;
int m;
if (addrtypeof(a) != addrtypeof(b))
return 0; /* arbitrary */
n = addrbytesptr(a, &ap);
if (n == 0)
return 0; /* arbitrary */
(void) addrbytesptr(b, &bp);
if (nbits > n*8)
return 0; /* "can't happen" */
for (; nbits >= 8 && *ap == *bp; nbits -= 8, ap++, bp++)
continue;
if (nbits >= 8)
return 0;
if (nbits > 0) { /* partial byte */
m = ~(0xff >> nbits);
if ((*ap & m) != (*bp & m))
return 0;
}
return 1;
}

View File

@ -1,132 +0,0 @@
/*
* convert from binary form of SA ID to text
* Copyright (C) 2000, 2001 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include <sys/socket.h>
#include "internal.h"
#include "freeswan.h"
static struct typename {
char type;
char *name;
} typenames[] = {
{ SA_AH, "ah" },
{ SA_ESP, "esp" },
{ SA_IPIP, "tun" },
{ SA_COMP, "comp" },
{ SA_INT, "int" },
{ 0, NULL }
};
/*
- satot - convert SA to text "ah507@1.2.3.4"
*/
size_t /* space needed for full conversion */
satot(sa, format, dst, dstlen)
const ip_said *sa;
int format; /* character */
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
size_t len = 0; /* 0 means "not recognized yet" */
int base;
int showversion; /* use delimiter to show IP version? */
struct typename *tn;
char *p;
char *pre;
char buf[10+1+ULTOT_BUF+ADDRTOT_BUF];
char unk[10];
switch (format) {
case 0:
base = 16;
showversion = 1;
break;
case 'f':
base = 17;
showversion = 1;
break;
case 'x':
base = 'x';
showversion = 0;
break;
case 'd':
base = 10;
showversion = 0;
break;
default:
return 0;
break;
}
pre = NULL;
for (tn = typenames; tn->name != NULL; tn++)
if (sa->proto == tn->type) {
pre = tn->name;
break; /* NOTE BREAK OUT */
}
if (pre == NULL) { /* unknown protocol */
strncpy(unk, "unk", sizeof(unk));
(void) ultot((unsigned char)sa->proto, 10, unk+strlen(unk),
sizeof(unk)-strlen(unk));
pre = unk;
}
if (strcmp(pre, PASSTHROUGHTYPE) == 0 &&
sa->spi == PASSTHROUGHSPI &&
isunspecaddr(&sa->dst)) {
strncpy(buf, (addrtypeof(&sa->dst) == AF_INET) ?
PASSTHROUGH4NAME :
PASSTHROUGH6NAME, sizeof(buf));
len = strlen(buf);
}
if (sa->proto == SA_INT && addrtypeof(&sa->dst) == AF_INET &&
isunspecaddr(&sa->dst)) {
switch (ntohl(sa->spi)) {
case SPI_PASS: p = "%pass"; break;
case SPI_DROP: p = "%drop"; break;
case SPI_REJECT: p = "%reject"; break;
case SPI_HOLD: p = "%hold"; break;
case SPI_TRAP: p = "%trap"; break;
case SPI_TRAPSUBNET: p = "%trapsubnet"; break;
default: p = NULL; break;
}
if (p != NULL) {
strncpy(buf, p, sizeof(buf));
len = strlen(buf);
}
}
if (len == 0) { /* general case needed */
strncpy(buf, pre, sizeof(buf));
len = strlen(buf);
if (showversion) {
*(buf+len) = (addrtypeof(&sa->dst) == AF_INET) ? '.' :
':';
len++;
*(buf+len) = '\0';
}
len += ultot(ntohl(sa->spi), base, buf+len, sizeof(buf)-len);
*(buf+len-1) = '@';
len += addrtot(&sa->dst, 0, buf+len, sizeof(buf)-len);
}
if (dst != NULL) {
if (len > dstlen)
*(buf+dstlen-1) = '\0';
strncpy(dst, buf, dstlen);
}
return len;
}

View File

@ -1,46 +0,0 @@
.TH IPSEC_SUBNETOF 3 "11 June 2001"
.SH NAME
ipsec subnetof \- given Internet address and subnet mask, return subnet number
.br
ipsec hostof \- given Internet address and subnet mask, return host part
.br
ipsec broadcastof \- given Internet address and subnet mask, return broadcast address
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "struct in_addr subnetof(struct in_addr addr,"
.ti +1c
.B "struct in_addr mask);"
.br
.B "struct in_addr hostof(struct in_addr addr,"
.ti +1c
.B "struct in_addr mask);"
.br
.B "struct in_addr broadcastof(struct in_addr addr,"
.ti +1c
.B "struct in_addr mask);"
.SH DESCRIPTION
These functions are obsolete; see
.IR ipsec_networkof (3)
for their replacements.
.PP
.I Subnetof
takes an Internet
.I address
and a subnet
.I mask
and returns the network part of the address
(all in network byte order).
.I Hostof
similarly returns the host part, and
.I broadcastof
returns the broadcast address (all-1s convention) for the network.
.PP
These functions are provided to hide the Internet bit-munging inside
an API, in hopes of easing the eventual transition to IPv6.
.SH SEE ALSO
inet(3), ipsec_atosubnet(3)
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
Calling functions for this is more costly than doing it yourself.

View File

@ -1,58 +0,0 @@
/*
* minor network-address manipulation utilities
* Copyright (C) 1998, 1999 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include "internal.h"
#include "freeswan.h"
/*
- subnetof - given address and mask, return subnet part
*/
struct in_addr
subnetof(addr, mask)
struct in_addr addr;
struct in_addr mask;
{
struct in_addr result;
result.s_addr = addr.s_addr & mask.s_addr;
return result;
}
/*
- hostof - given address and mask, return host part
*/
struct in_addr
hostof(addr, mask)
struct in_addr addr;
struct in_addr mask;
{
struct in_addr result;
result.s_addr = addr.s_addr & ~mask.s_addr;
return result;
}
/*
- broadcastof - given (network) address and mask, return broadcast address
*/
struct in_addr
broadcastof(addr, mask)
struct in_addr addr;
struct in_addr mask;
{
struct in_addr result;
result.s_addr = addr.s_addr | ~mask.s_addr;
return result;
}

View File

@ -1,60 +0,0 @@
/*
* convert binary form of subnet description to ASCII
* Copyright (C) 1998, 1999 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include "internal.h"
#include "freeswan.h"
/*
- subnettoa - convert address and mask to ASCII "addr/mask"
* Output expresses the mask as a bit count if possible, else dotted decimal.
*/
size_t /* space needed for full conversion */
subnettoa(addr, mask, format, dst, dstlen)
struct in_addr addr;
struct in_addr mask;
int format; /* character */
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
size_t len;
size_t rest;
int n;
char *p;
switch (format) {
case 0:
break;
default:
return 0;
break;
}
len = addrtoa(addr, 0, dst, dstlen);
if (len < dstlen) {
dst[len - 1] = '/';
p = dst + len;
rest = dstlen - len;
} else {
p = NULL;
rest = 0;
}
n = masktobits(mask);
if (n >= 0)
len += ultoa((unsigned long)n, 10, p, rest);
else
len += addrtoa(mask, 0, p, rest);
return len;
}

View File

@ -1,54 +0,0 @@
/*
* convert binary form of subnet description to text
* Copyright (C) 2000 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include "internal.h"
#include "freeswan.h"
/*
- subnettot - convert subnet to text "addr/bitcount"
*/
size_t /* space needed for full conversion */
subnettot(sub, format, dst, dstlen)
const ip_subnet *sub;
int format; /* character */
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
size_t len;
size_t rest;
char *p;
switch (format) {
case 0:
break;
default:
return 0;
break;
}
len = addrtot(&sub->addr, format, dst, dstlen);
if (len < dstlen) {
dst[len - 1] = '/';
p = dst + len;
rest = dstlen - len;
} else {
p = NULL;
rest = 0;
}
len += ultoa((unsigned long)sub->maskbits, 10, p, rest);
return len;
}

View File

@ -1,107 +0,0 @@
/*
* extract parts of an ip_subnet, and related
* Copyright (C) 2000 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include "internal.h"
#include "freeswan.h"
/*
- subnettypeof - get the address type of an ip_subnet
*/
int
subnettypeof(src)
const ip_subnet *src;
{
return src->addr.u.v4.sin_family;
}
/*
- networkof - get the network address of a subnet
*/
void
networkof(src, dst)
const ip_subnet *src;
ip_address *dst;
{
*dst = src->addr;
}
/*
- maskof - get the mask of a subnet, as an address
*/
void
maskof(src, dst)
const ip_subnet *src;
ip_address *dst;
{
int b;
unsigned char buf[16];
size_t n = addrlenof(&src->addr);
unsigned char *p;
if (src->maskbits > n*8 || n > sizeof(buf))
return; /* "can't happen" */
p = buf;
for (b = src->maskbits; b >= 8; b -= 8)
*p++ = 0xff;
if (b != 0)
*p++ = (0xff << (8 - b)) & 0xff;
while (p - buf < n)
*p++ = 0;
(void) initaddr(buf, n, addrtypeof(&src->addr), dst);
}
/*
- masktocount - convert a mask, expressed as an address, to a bit count
*/
int /* -1 if not valid mask */
masktocount(src)
const ip_address *src;
{
int b;
unsigned const char *bp;
size_t n;
unsigned const char *p;
unsigned const char *stop;
n = addrbytesptr(src, &bp);
if (n == 0)
return -1;
p = bp;
stop = bp + n;
n = 0;
while (p < stop && *p == 0xff) {
p++;
n += 8;
}
if (p < stop && *p != 0) { /* boundary in mid-byte */
b = *p++;
while (b&0x80) {
b <<= 1;
n++;
}
if ((b&0xff) != 0)
return -1; /* bits not contiguous */
}
while (p < stop && *p == 0)
p++;
if (p != stop)
return -1;
return n;
}

View File

@ -1,374 +0,0 @@
.TH IPSEC_TTOADDR 3 "28 Sept 2001"
.SH NAME
ipsec ttoaddr, tnatoaddr, addrtot \- convert Internet addresses to and from text
.br
ipsec ttosubnet, subnettot \- convert subnet/mask text form to and from addresses
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "const char *ttoaddr(const char *src, size_t srclen,"
.ti +1c
.B "int af, ip_address *addr);"
.br
.B "const char *tnatoaddr(const char *src, size_t srclen,"
.ti +1c
.B "int af, ip_address *addr);"
.br
.B "size_t addrtot(const ip_address *addr, int format,"
.ti +1c
.B "char *dst, size_t dstlen);"
.sp
.B "const char *ttosubnet(const char *src, size_t srclen,"
.ti +1c
.B "int af, ip_subnet *dst);"
.br
.B "size_t subnettot(const ip_subnet *sub, int format,"
.ti +1c
.B "char *dst, size_t dstlen);"
.SH DESCRIPTION
.I Ttoaddr
converts a text-string name or numeric address into a binary address
(in network byte order).
.I Tnatoaddr
does the same conversion,
but the only text forms it accepts are
the ``official'' forms of
numeric address (dotted-decimal for IPv4, colon-hex for IPv6).
.I Addrtot
does the reverse conversion, from binary address back to a text form.
.I Ttosubnet
and
.I subnettot
do likewise for the ``address/mask'' form used to write a
specification of a subnet.
.PP
An IPv4 address is specified in text as a
dotted-decimal address (e.g.
.BR 1.2.3.4 ),
an eight-digit network-order hexadecimal number with the usual C prefix (e.g.
.BR 0x01020304 ,
which is synonymous with
.BR 1.2.3.4 ),
an eight-digit host-order hexadecimal number with a
.B 0h
prefix (e.g.
.BR 0h01020304 ,
which is synonymous with
.B 1.2.3.4
on a big-endian host and
.B 4.3.2.1
on a little-endian host),
a DNS name to be looked up via
.IR getaddrinfo (3),
or an old-style network name to be looked up via
.IR getnetbyname (3).
.PP
A dotted-decimal address may be incomplete, in which case
text-to-binary conversion implicitly appends
as many instances of
.B .0
as necessary to bring it up to four components.
The components of a dotted-decimal address are always taken as
decimal, and leading zeros are ignored.
For example,
.B 10
is synonymous with
.BR 10.0.0.0 ,
and
.B 128.009.000.032
is synonymous with
.BR 128.9.0.32
(the latter example is verbatim from RFC 1166).
The result of applying
.I addrtot
to an IPv4 address is always complete and does not contain leading zeros.
.PP
Use of hexadecimal addresses is
.B strongly
.BR discouraged ;
they are included only to save hassles when dealing with
the handful of perverted programs which already print
network addresses in hexadecimal.
.PP
An IPv6 address is specified in text with
colon-hex notation (e.g.
.BR 0:56:78ab:22:33:44:55:66 ),
colon-hex with
.B ::
abbreviating at most one subsequence of multiple zeros (e.g.
.BR 99:ab::54:068 ,
which is synonymous with
.BR 99:ab:0:0:0:0:54:68 ),
or a DNS name to be looked up via
.IR getaddrinfo (3).
The result of applying
.I addrtot
to an IPv6 address will use
.B ::
abbreviation if possible,
and will not contain leading zeros.
.PP
The letters in hexadecimal
may be uppercase or lowercase or any mixture thereof.
.PP
DNS names may be complete (optionally terminated with a ``.'')
or incomplete, and are looked up as specified by local system configuration
(see
.IR resolver (5)).
The first value returned by
.IR getaddrinfo (3)
is used,
so with current DNS implementations,
the result when the name corresponds to more than one address is
difficult to predict.
IPv4 name lookup resorts to
.IR getnetbyname (3)
only if
.IR getaddrinfo (3)
fails.
.PP
A subnet specification is of the form \fInetwork\fB/\fImask\fR.
The
.I network
and
.I mask
can be any form acceptable to
.IR ttoaddr .
In addition, and preferably, the
.I mask
can be a decimal integer (leading zeros ignored) giving a bit count,
in which case
it stands for a mask with that number of high bits on and all others off
(e.g.,
.B 24
in IPv4 means
.BR 255.255.255.0 ).
In any case, the mask must be contiguous
(a sequence of high bits on and all remaining low bits off).
As a special case, the subnet specification
.B %default
is a synonym for
.B 0.0.0.0/0
or
.B ::/0
in IPv4 or IPv6 respectively.
.PP
.I Ttosubnet
ANDs the mask with the address before returning,
so that any non-network bits in the address are turned off
(e.g.,
.B 10.1.2.3/24
is synonymous with
.BR 10.1.2.0/24 ).
.I Subnettot
always generates the decimal-integer-bit-count
form of the mask,
with no leading zeros.
.PP
The
.I srclen
parameter of
.I ttoaddr
and
.I ttosubnet
specifies the length of the text string pointed to by
.IR src ;
it is an error for there to be anything else
(e.g., a terminating NUL) within that length.
As a convenience for cases where an entire NUL-terminated string is
to be converted,
a
.I srclen
value of
.B 0
is taken to mean
.BR strlen(src) .
.PP
The
.I af
parameter of
.I ttoaddr
and
.I ttosubnet
specifies the address family of interest.
It should be either
.B AF_INET
or
.BR AF_INET6 .
.PP
The
.I dstlen
parameter of
.I addrtot
and
.I subnettot
specifies the size of the
.I dst
parameter;
under no circumstances are more than
.I dstlen
bytes written to
.IR dst .
A result which will not fit is truncated.
.I Dstlen
can be zero, in which case
.I dst
need not be valid and no result is written,
but the return value is unaffected;
in all other cases, the (possibly truncated) result is NUL-terminated.
The
.I freeswan.h
header file defines constants,
.B ADDRTOT_BUF
and
.BR SUBNETTOT_BUF ,
which are the sizes of buffers just large enough for worst-case results.
.PP
The
.I format
parameter of
.I addrtot
and
.I subnettot
specifies what format is to be used for the conversion.
The value
.B 0
(not the character
.BR '0' ,
but a zero value)
specifies a reasonable default,
and is in fact the only format currently available in
.IR subnettot .
.I Addrtot
also accepts format values
.B 'r'
(signifying a text form suitable for DNS reverse lookups,
e.g.
.B 4.3.2.1.IN-ADDR.ARPA.
for IPv4 and
RFC 2874 format for IPv6),
and
.B 'R'
(signifying an alternate reverse-lookup form,
an error for IPv4 and RFC 1886 format for IPv6).
Reverse-lookup names always end with a ``.''.
.PP
The text-to-binary functions return NULL for success and
a pointer to a string-literal error message for failure;
see DIAGNOSTICS.
The binary-to-text functions return
.B 0
for a failure, and otherwise
always return the size of buffer which would
be needed to
accommodate the full conversion result, including terminating NUL;
it is the caller's responsibility to check this against the size of
the provided buffer to determine whether truncation has occurred.
.SH SEE ALSO
inet(3)
.SH DIAGNOSTICS
Fatal errors in
.I ttoaddr
are:
empty input;
unknown address family;
attempt to allocate temporary storage for a very long name failed;
name lookup failed;
syntax error in dotted-decimal or colon-hex form;
dotted-decimal or colon-hex component too large.
.PP
Fatal errors in
.I ttosubnet
are:
no
.B /
in
.IR src ;
.I ttoaddr
error in conversion of
.I network
or
.IR mask ;
bit-count mask too big;
mask non-contiguous.
.PP
Fatal errors in
.I addrtot
and
.I subnettot
are:
unknown format.
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
The interpretation of incomplete dotted-decimal addresses
(e.g.
.B 10/24
means
.BR 10.0.0.0/24 )
differs from that of some older conversion
functions, e.g. those of
.IR inet (3).
The behavior of the older functions has never been
particularly consistent or particularly useful.
.PP
Ignoring leading zeros in dotted-decimal components and bit counts
is arguably the most useful behavior in this application,
but it might occasionally cause confusion with the historical use of leading
zeros to denote octal numbers.
.PP
.I Ttoaddr
does not support the mixed colon-hex-dotted-decimal
convention used to embed an IPv4 address in an IPv6 address.
.PP
.I Addrtot
always uses the
.B ::
abbreviation (which can appear only once in an address) for the
.I first
sequence of multiple zeros in an IPv6 address.
One can construct addresses (unlikely ones) in which this is suboptimal.
.PP
.I Addrtot
.B 'r'
conversion of an IPv6 address uses lowercase hexadecimal,
not the uppercase used in RFC 2874's examples.
It takes careful reading of RFCs 2874, 2673, and 2234 to realize
that lowercase is technically legitimate here,
and there may be software which botches this
and hence would have trouble with lowercase hex.
.PP
Possibly
.I subnettot
ought to recognize the
.B %default
case and generate that string as its output.
Currently it doesn't.
.PP
It is barely possible that somebody, somewhere,
might have a legitimate use for non-contiguous subnet masks.
.PP
.IR Getnetbyname (3)
is a historical dreg.
.PP
.I Tnatoaddr
probably should enforce completeness of dotted-decimal addresses.
.PP
The restriction of text-to-binary error reports to literal strings
(so that callers don't need to worry about freeing them or copying them)
does limit the precision of error reporting.
.PP
The text-to-binary error-reporting convention lends itself
to slightly obscure code,
because many readers will not think of NULL as signifying success.
A good way to make it clearer is to write something like:
.PP
.RS
.nf
.B "const char *error;"
.sp
.B "error = ttoaddr( /* ... */ );"
.B "if (error != NULL) {"
.B " /* something went wrong */"
.fi
.RE

View File

@ -1,471 +0,0 @@
/*
* conversion from text forms of addresses to internal ones
* Copyright (C) 2000 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include <sys/socket.h>
#include "internal.h"
#include "freeswan.h"
/*
* Legal ASCII characters in a domain name. Underscore technically is not,
* but is a common misunderstanding. Non-ASCII characters are simply
* exempted from checking at the moment, to allow for UTF-8 encoded stuff;
* the purpose of this check is merely to catch blatant errors.
*/
static const char namechars[] = "abcdefghijklmnopqrstuvwxyz0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ-_.";
#define ISASCII(c) (((c) & 0x80) == 0)
static err_t tryname(const char *, size_t, int, int, ip_address *);
static err_t tryhex(const char *, size_t, int, ip_address *);
static err_t trydotted(const char *, size_t, ip_address *);
static err_t getbyte(const char **, const char *, int *);
static err_t colon(const char *, size_t, ip_address *);
static err_t getpiece(const char **, const char *, unsigned *);
/*
- ttoaddr - convert text name or dotted-decimal address to binary address
*/
err_t /* NULL for success, else string literal */
ttoaddr(src, srclen, af, dst)
const char *src;
size_t srclen; /* 0 means "apply strlen" */
int af; /* address family */
ip_address *dst;
{
err_t oops;
# define HEXLEN 10 /* strlen("0x11223344") */
int nultermd;
if (srclen == 0) {
srclen = strlen(src);
if (srclen == 0)
return "empty string";
nultermd = 1;
} else
nultermd = 0; /* at least, not *known* to be terminated */
switch (af) {
case AF_INET:
case AF_INET6:
case 0: /* guess */
break;
default:
return "invalid address family";
}
if (af == AF_INET && srclen == HEXLEN && *src == '0') {
if (*(src+1) == 'x' || *(src+1) == 'X')
return tryhex(src+2, srclen-2, 'x', dst);
if (*(src+1) == 'h' || *(src+1) == 'H')
return tryhex(src+2, srclen-2, 'h', dst);
}
if (memchr(src, ':', srclen) != NULL) {
if(af == 0)
{
af = AF_INET6;
}
if (af != AF_INET6)
return "non-ipv6 address may not contain `:'";
return colon(src, srclen, dst);
}
if (af == 0 || af == AF_INET) {
oops = trydotted(src, srclen, dst);
if (oops == NULL)
return NULL; /* it worked */
if (*oops != '?')
return oops; /* probably meant as d-d */
}
return tryname(src, srclen, nultermd, af, dst);
}
/*
- tnatoaddr - convert text numeric address (only) to binary address
*/
err_t /* NULL for success, else string literal */
tnatoaddr(src, srclen, af, dst)
const char *src;
size_t srclen; /* 0 means "apply strlen" */
int af; /* address family */
ip_address *dst;
{
err_t oops;
if (srclen == 0) {
srclen = strlen(src);
if (srclen == 0)
return "empty string";
}
switch (af) {
case 0: /* guess */
oops = colon(src, srclen, dst);
if(oops == NULL)
{
return NULL;
}
oops = trydotted(src, srclen, dst);
if(oops == NULL)
{
return NULL;
}
return "does not appear to be either IPv4 or IPv6 numeric address";
break;
case AF_INET6:
return colon(src, srclen, dst);
break;
case AF_INET:
oops = trydotted(src, srclen, dst);
if (oops == NULL)
return NULL; /* it worked */
if (*oops != '?')
return oops; /* probably meant as d-d */
return "does not appear to be numeric address";
break;
default:
return "unknown address family in tnatoaddr";
break;
}
}
/*
- tryname - try it as a name
* Slightly complicated by lack of reliable NUL termination in source.
*/
static err_t
tryname(src, srclen, nultermd, af, dst)
const char *src;
size_t srclen;
int nultermd; /* is it known to be NUL-terminated? */
int af;
ip_address *dst;
{
struct addrinfo hints, *res;
struct netent *ne = NULL;
char namebuf[100]; /* enough for most DNS names */
const char *cp;
char *p = namebuf;
unsigned char *addr = NULL;
size_t n;
int error;
err_t err = NULL;
for (cp = src, n = srclen; n > 0; cp++, n--)
if (ISASCII(*cp) && strchr(namechars, *cp) == NULL)
return "illegal (non-DNS-name) character in name";
if (nultermd)
cp = src;
else {
if (srclen+1 > sizeof(namebuf)) {
p = (char *) MALLOC(srclen+1);
if (p == NULL)
return "unable to get temporary space for name";
}
p[0] = '\0'; /* strncpy semantics are wrong */
strncat(p, src, srclen);
cp = (const char *)p;
}
memset(&hints, 0, sizeof(hints));
hints.ai_family = af;
error = getaddrinfo(cp, NULL, &hints, &res);
if (error != 0)
{ /* getaddrinfo failed, try getnetbyname */
if (af == AF_INET)
{
ne = getnetbyname(cp);
if (ne != NULL)
{
ne->n_net = htonl(ne->n_net);
addr = (unsigned char*)&ne->n_net;
err = initaddr(addr, sizeof(ne->n_net), af, dst);
}
}
}
else
{
struct addrinfo *r = res;
while (r)
{
size_t addr_len;
switch (r->ai_family)
{
case AF_INET:
{
struct sockaddr_in *in = (struct sockaddr_in*)r->ai_addr;
addr_len = 4;
addr = (unsigned char*)&in->sin_addr.s_addr;
break;
}
case AF_INET6:
{
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)r->ai_addr;
addr_len = 16;
addr = (unsigned char*)&in6->sin6_addr.s6_addr;
break;
}
default:
{ /* unknown family, try next result */
r = r->ai_next;
continue;
}
}
err = initaddr(addr, addr_len, r->ai_family, dst);
break;
}
freeaddrinfo(res);
}
if (p != namebuf)
{
FREE(p);
}
if (addr == NULL)
{
return "does not look numeric and name lookup failed";
}
return err;
}
/*
- tryhex - try conversion as an eight-digit hex number (AF_INET only)
*/
static err_t
tryhex(src, srclen, flavor, dst)
const char *src;
size_t srclen; /* should be 8 */
int flavor; /* 'x' for network order, 'h' for host order */
ip_address *dst;
{
err_t oops;
unsigned long ul;
union {
uint32_t addr;
unsigned char buf[4];
} u;
if (srclen != 8)
return "internal error, tryhex called with bad length";
oops = ttoul(src, srclen, 16, &ul);
if (oops != NULL)
return oops;
u.addr = (flavor == 'h') ? ul : htonl(ul);
return initaddr(u.buf, sizeof(u.buf), AF_INET, dst);
}
/*
- trydotted - try conversion as dotted decimal (AF_INET only)
*
* If the first char of a complaint is '?', that means "didn't look like
* dotted decimal at all".
*/
static err_t
trydotted(src, srclen, dst)
const char *src;
size_t srclen;
ip_address *dst;
{
const char *stop = src + srclen; /* just past end */
int byte;
err_t oops;
# define NBYTES 4
unsigned char buf[NBYTES];
int i;
memset(buf, 0, sizeof(buf));
for (i = 0; i < NBYTES && src < stop; i++) {
oops = getbyte(&src, stop, &byte);
if (oops != NULL) {
if (*oops != '?')
return oops; /* bad number */
if (i > 1)
return oops+1; /* failed number */
return oops; /* with leading '?' */
}
buf[i] = byte;
if (i < 3 && src < stop && *src++ != '.') {
if (i == 0)
return "?syntax error in dotted-decimal address";
else
return "syntax error in dotted-decimal address";
}
}
if (src != stop)
return "extra garbage on end of dotted-decimal address";
return initaddr(buf, sizeof(buf), AF_INET, dst);
}
/*
- getbyte - try to scan a byte in dotted decimal
* A subtlety here is that all this arithmetic on ASCII digits really is
* highly portable -- ANSI C guarantees that digits 0-9 are contiguous.
* It's easier to just do it ourselves than set up for a call to ttoul().
*
* If the first char of a complaint is '?', that means "didn't look like a
* number at all".
*/
err_t
getbyte(srcp, stop, retp)
const char **srcp; /* *srcp is updated */
const char *stop; /* first untouchable char */
int *retp; /* return-value pointer */
{
char c;
const char *p;
int no;
if (*srcp >= stop)
return "?empty number in dotted-decimal address";
no = 0;
p = *srcp;
while (p < stop && no <= 255 && (c = *p) >= '0' && c <= '9') {
no = no*10 + (c - '0');
p++;
}
if (p == *srcp)
return "?non-numeric component in dotted-decimal address";
*srcp = p;
if (no > 255)
return "byte overflow in dotted-decimal address";
*retp = no;
return NULL;
}
/*
- colon - convert IPv6 "numeric" address
*/
static err_t
colon(src, srclen, dst)
const char *src;
size_t srclen; /* known to be >0 */
ip_address *dst;
{
const char *stop = src + srclen; /* just past end */
unsigned piece = 0;
int gapat; /* where was empty piece seen */
err_t oops;
# define NPIECES 8
unsigned char buf[NPIECES*2]; /* short may have wrong byte order */
int i;
int j;
# define IT "IPv6 numeric address"
int naftergap;
/* leading or trailing :: becomes single empty field */
if (*src == ':') { /* legal only if leading :: */
if (srclen == 1 || *(src+1) != ':')
return "illegal leading `:' in " IT;
if (srclen == 2) {
unspecaddr(AF_INET6, dst);
return NULL;
}
src++; /* past first but not second */
srclen--;
}
if (*(stop-1) == ':') { /* legal only if trailing :: */
if (srclen == 1 || *(stop-2) != ':')
return "illegal trailing `:' in " IT;
srclen--; /* leave one */
}
gapat = -1;
for (i = 0; i < NPIECES && src < stop; i++) {
oops = getpiece(&src, stop, &piece);
if (oops != NULL && *oops == ':') { /* empty field */
if (gapat >= 0)
return "more than one :: in " IT;
gapat = i;
} else if (oops != NULL)
return oops;
buf[2*i] = piece >> 8;
buf[2*i + 1] = piece & 0xff;
if (i < NPIECES-1) { /* there should be more input */
if (src == stop && gapat < 0)
return IT " ends prematurely";
if (src != stop && *src++ != ':')
return "syntax error in " IT;
}
}
if (src != stop)
return "extra garbage on end of " IT;
if (gapat < 0 && i < NPIECES) /* should have been caught earlier */
return "incomplete " IT " (internal error)";
if (gapat >= 0 && i == NPIECES)
return "non-abbreviating empty field in " IT;
if (gapat >= 0) {
naftergap = i - (gapat + 1);
for (i--, j = NPIECES-1; naftergap > 0; i--, j--, naftergap--) {
buf[2*j] = buf[2*i];
buf[2*j + 1] = buf[2*i + 1];
}
for (; j >= gapat; j--)
buf[2*j] = buf[2*j + 1] = 0;
}
return initaddr(buf, sizeof(buf), AF_INET6, dst);
}
/*
- getpiece - try to scan one 16-bit piece of an IPv6 address
*/
err_t /* ":" means "empty field seen" */
getpiece(srcp, stop, retp)
const char **srcp; /* *srcp is updated */
const char *stop; /* first untouchable char */
unsigned *retp; /* return-value pointer */
{
const char *p;
# define NDIG 4
int d;
unsigned long ret;
err_t oops;
if (*srcp >= stop || **srcp == ':') { /* empty field */
*retp = 0;
return ":";
}
p = *srcp;
d = 0;
while (p < stop && d < NDIG && isxdigit(*p)) {
p++;
d++;
}
if (d == 0)
return "non-hex field in IPv6 numeric address";
if (p < stop && d == NDIG && isxdigit(*p))
return "field in IPv6 numeric address longer than 4 hex digits";
oops = ttoul(*srcp, d, 16, &ret);
if (oops != NULL) /* shouldn't happen, really... */
return oops;
*srcp = p;
*retp = ret;
return NULL;
}

View File

@ -1,280 +0,0 @@
.TH IPSEC_TTODATA 3 "16 August 2003"
.SH NAME
ipsec ttodata, datatot \- convert binary data bytes from and to text formats
.SH SYNOPSIS
.B "#include <freeswan.h>"
.sp
.B "const char *ttodata(const char *src, size_t srclen,"
.ti +1c
.B "int base, char *dst, size_t dstlen, size_t *lenp);"
.br
.B "const char *ttodatav(const char *src, size_t srclen,"
.ti +1c
.B "int base, char *dst, size_t dstlen, size_t *lenp,"
.ti +1c
.B "char *errp, size_t errlen, int flags);"
.br
.B "size_t datatot(const char *src, size_t srclen,"
.ti +1c
.B "int format, char *dst, size_t dstlen);"
.SH DESCRIPTION
.IR Ttodata ,
.IR ttodatav ,
and
.I datatot
convert arbitrary binary data (e.g. encryption or authentication keys)
from and to more-or-less human-readable text formats.
.PP
Currently supported formats are hexadecimal, base64, and characters.
.PP
A hexadecimal text value begins with a
.B 0x
(or
.BR 0X )
prefix and continues with two-digit groups
of hexadecimal digits (0-9, and a-f or A-F),
each group encoding the value of one binary byte, high-order digit first.
A single
.B _
(underscore)
between consecutive groups is ignored, permitting punctuation to improve
readability; doing this every eight digits seems about right.
.PP
A base64 text value begins with a
.B 0s
(or
.BR 0S )
prefix
and continues with four-digit groups of base64 digits (A-Z, a-z, 0-9, +, and /),
each group encoding the value of three binary bytes as described in
section 6.8 of RFC 2045.
If
.B flags
has the
.B TTODATAV_IGNORESPACE
bit on, blanks are ignore (after the prefix).
Note that the last one or two digits of a base64 group can be
.B =
to indicate that fewer than three binary bytes are encoded.
.PP
A character text value begins with a
.B 0t
(or
.BR 0T )
prefix
and continues with text characters, each being the value of one binary byte.
.PP
All these functions basically copy data from
.I src
(whose size is specified by
.IR srclen )
to
.I dst
(whose size is specified by
.IR dstlen ),
doing the conversion en route.
If the result will not fit in
.IR dst ,
it is truncated;
under no circumstances are more than
.I dstlen
bytes of result written to
.IR dst .
.I Dstlen
can be zero, in which case
.I dst
need not be valid and no result bytes are written at all.
.PP
The
.I base
parameter of
.I ttodata
and
.I ttodatav
specifies what format the input is in;
normally it should be
.B 0
to signify that this gets figured out from the prefix.
Values of
.BR 16 ,
.BR 64 ,
and
.BR 256
respectively signify hexadecimal, base64, and character-text formats
without prefixes.
.PP
The
.I format
parameter of
.IR datatot ,
a single character used as a type code,
specifies which text format is wanted.
The value
.B 0
(not ASCII
.BR '0' ,
but a zero value) specifies a reasonable default.
Other currently-supported values are:
.RS 2
.TP 4
.B 'x'
continuous lower-case hexadecimal with a
.B 0x
prefix
.TP
.B 'h'
lower-case hexadecimal with a
.B 0x
prefix and a
.B _
every eight digits
.TP
.B ':'
lower-case hexadecimal with no prefix and a
.B :
(colon) every two digits
.TP
.B 16
lower-case hexadecimal with no prefix or
.B _
.TP
.B 's'
continuous base64 with a
.B 0s
prefix
.TP
.B 64
continuous base64 with no prefix
.RE
.PP
The default format is currently
.BR 'h' .
.PP
.I Ttodata
returns NULL for success and
a pointer to a string-literal error message for failure;
see DIAGNOSTICS.
On success,
if and only if
.I lenp
is non-NULL,
.B *lenp
is set to the number of bytes required to contain the full untruncated result.
It is the caller's responsibility to check this against
.I dstlen
to determine whether he has obtained a complete result.
The
.B *lenp
value is correct even if
.I dstlen
is zero, which offers a way to determine how much space would be needed
before having to allocate any.
.PP
.I Ttodatav
is just like
.I ttodata
except that in certain cases,
if
.I errp
is non-NULL,
the buffer pointed to by
.I errp
(whose length is given by
.IR errlen )
is used to hold a more detailed error message.
The return value is NULL for success,
and is either
.I errp
or a pointer to a string literal for failure.
If the size of the error-message buffer is
inadequate for the desired message,
.I ttodatav
will fall back on returning a pointer to a literal string instead.
The
.I freeswan.h
header file defines a constant
.B TTODATAV_BUF
which is the size of a buffer large enough for worst-case results.
.PP
The normal return value of
.IR datatot
is the number of bytes required
to contain the full untruncated result.
It is the caller's responsibility to check this against
.I dstlen
to determine whether he has obtained a complete result.
The return value is correct even if
.I dstlen
is zero, which offers a way to determine how much space would be needed
before having to allocate any.
A return value of
.B 0
signals a fatal error of some kind
(see DIAGNOSTICS).
.PP
A zero value for
.I srclen
in
.I ttodata
(but not
.IR datatot !)
is synonymous with
.BR strlen(src) .
A non-zero
.I srclen
in
.I ttodata
must not include the terminating NUL.
.PP
Unless
.I dstlen
is zero,
the result supplied by
.I datatot
is always NUL-terminated,
and its needed-size return value includes space for the terminating NUL.
.PP
Several obsolete variants of these functions
.RI ( atodata ,
.IR datatoa ,
.IR atobytes ,
and
.IR bytestoa )
are temporarily also supported.
.SH SEE ALSO
sprintf(3), ipsec_atoaddr(3)
.SH DIAGNOSTICS
Fatal errors in
.I ttodata
and
.I ttodatav
are:
unknown characters in the input;
unknown or missing prefix;
unknown base;
incomplete digit group;
non-zero padding in a base64 less-than-three-bytes digit group;
zero-length input.
.PP
Fatal errors in
.I datatot
are:
unknown format code;
zero-length input.
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
.I Datatot
should have a format code to produce character-text output.
.PP
The
.B 0s
and
.B 0t
prefixes are the author's inventions and are not a standard
of any kind.
They have been chosen to avoid collisions with existing practice
(some C implementations use
.B 0b
for binary)
and possible confusion with unprefixed hexadecimal.

View File

@ -1,720 +0,0 @@
/*
* convert from text form of arbitrary data (e.g., keys) to binary
* Copyright (C) 2000 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include "internal.h"
#include "freeswan.h"
/* converters and misc */
static int unhex(const char *, char *, size_t);
static int unb64(const char *, char *, size_t);
static int untext(const char *, char *, size_t);
static const char *badch(const char *, int, char *, size_t);
/* internal error codes for converters */
#define SHORT (-2) /* internal buffer too short */
#define BADPAD (-3) /* bad base64 padding */
#define BADCH0 (-4) /* invalid character 0 */
#define BADCH1 (-5) /* invalid character 1 */
#define BADCH2 (-6) /* invalid character 2 */
#define BADCH3 (-7) /* invalid character 3 */
#define BADOFF(code) (BADCH0-(code))
/*
- ttodatav - convert text to data, with verbose error reports
* If some of this looks slightly odd, it's because it has changed
* repeatedly (from the original atodata()) without a major rewrite.
*/
const char * /* NULL on success, else literal or errp */
ttodatav(src, srclen, base, dst, dstlen, lenp, errp, errlen, flags)
const char *src;
size_t srclen; /* 0 means apply strlen() */
int base; /* 0 means figure it out */
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
size_t *lenp; /* where to record length (NULL is nowhere) */
char *errp; /* error buffer */
size_t errlen;
unsigned int flags;
{
size_t ingroup; /* number of input bytes converted at once */
char buf[4]; /* output from conversion */
int nbytes; /* size of output */
int (*decode)(const char *, char *, size_t);
char *stop;
int ndone;
int i;
int underscoreok;
int skipSpace = 0;
if (srclen == 0)
srclen = strlen(src);
if (dstlen == 0)
dst = buf; /* point it somewhere valid */
stop = dst + dstlen;
if (base == 0) {
if (srclen < 2)
return "input too short to be valid";
if (*src++ != '0')
return "input does not begin with format prefix";
switch (*src++) {
case 'x':
case 'X':
base = 16;
break;
case 's':
case 'S':
base = 64;
break;
case 't':
case 'T':
base = 256;
break;
default:
return "unknown format prefix";
}
srclen -= 2;
}
switch (base) {
case 16:
decode = unhex;
underscoreok = 1;
ingroup = 2;
break;
case 64:
decode = unb64;
underscoreok = 0;
ingroup = 4;
if(flags & TTODATAV_IGNORESPACE) {
skipSpace = 1;
}
break;
case 256:
decode = untext;
ingroup = 1;
underscoreok = 0;
break;
default:
return "unknown base";
}
/* proceed */
ndone = 0;
while (srclen > 0) {
char stage[4]; /* staging area for group */
size_t sl = 0;
/* Grab ingroup characters into stage,
* squeezing out blanks if we are supposed to ignore them.
*/
for (sl = 0; sl < ingroup; src++, srclen--) {
if (srclen == 0)
return "input ends in mid-byte, perhaps truncated";
else if (!(skipSpace && (*src == ' ' || *src == '\t')))
stage[sl++] = *src;
}
nbytes = (*decode)(stage, buf, sizeof(buf));
switch (nbytes) {
case BADCH0:
case BADCH1:
case BADCH2:
case BADCH3:
return badch(stage, nbytes, errp, errlen);
case SHORT:
return "internal buffer too short (\"can't happen\")";
case BADPAD:
return "bad (non-zero) padding at end of base64 input";
}
if (nbytes <= 0)
return "unknown internal error";
for (i = 0; i < nbytes; i++) {
if (dst < stop)
*dst++ = buf[i];
ndone++;
}
while (srclen >= 1 && skipSpace && (*src == ' ' || *src == '\t')){
src++;
srclen--;
}
if (underscoreok && srclen > 1 && *src == '_') {
/* srclen > 1 means not last character */
src++;
srclen--;
}
}
if (ndone == 0)
return "no data bytes specified by input";
if (lenp != NULL)
*lenp = ndone;
return NULL;
}
/*
- ttodata - convert text to data
*/
const char * /* NULL on success, else literal */
ttodata(src, srclen, base, dst, dstlen, lenp)
const char *src;
size_t srclen; /* 0 means apply strlen() */
int base; /* 0 means figure it out */
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
size_t *lenp; /* where to record length (NULL is nowhere) */
{
return ttodatav(src, srclen, base, dst, dstlen, lenp, (char *)NULL,
(size_t)0, TTODATAV_SPACECOUNTS);
}
/*
- atodata - convert ASCII to data
* backward-compatibility interface
*/
size_t /* 0 for failure, true length for success */
atodata(src, srclen, dst, dstlen)
const char *src;
size_t srclen;
char *dst;
size_t dstlen;
{
size_t len;
const char *err;
err = ttodata(src, srclen, 0, dst, dstlen, &len);
if (err != NULL)
return 0;
return len;
}
/*
- atobytes - convert ASCII to data bytes
* another backward-compatibility interface
*/
const char *
atobytes(src, srclen, dst, dstlen, lenp)
const char *src;
size_t srclen;
char *dst;
size_t dstlen;
size_t *lenp;
{
return ttodata(src, srclen, 0, dst, dstlen, lenp);
}
/*
- unhex - convert two ASCII hex digits to byte
*/
static int /* number of result bytes, or error code */
unhex(src, dst, dstlen)
const char *src; /* known to be full length */
char *dst;
size_t dstlen; /* not large enough is a failure */
{
char *p;
unsigned byte;
static char hex[] = "0123456789abcdef";
if (dstlen < 1)
return SHORT;
p = strchr(hex, *src);
if (p == NULL)
p = strchr(hex, tolower(*src));
if (p == NULL)
return BADCH0;
byte = (p - hex) << 4;
src++;
p = strchr(hex, *src);
if (p == NULL)
p = strchr(hex, tolower(*src));
if (p == NULL)
return BADCH1;
byte |= (p - hex);
*dst = byte;
return 1;
}
/*
- unb64 - convert four ASCII base64 digits to three bytes
* Note that a base64 digit group is padded out with '=' if it represents
* less than three bytes: one byte is dd==, two is ddd=, three is dddd.
*/
static int /* number of result bytes, or error code */
unb64(src, dst, dstlen)
const char *src; /* known to be full length */
char *dst;
size_t dstlen;
{
char *p;
unsigned byte1;
unsigned byte2;
static char base64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
if (dstlen < 3)
return SHORT;
p = strchr(base64, *src++);
if (p == NULL)
return BADCH0;
byte1 = (p - base64) << 2; /* first six bits */
p = strchr(base64, *src++);
if (p == NULL) {
return BADCH1;
}
byte2 = p - base64; /* next six: two plus four */
*dst++ = byte1 | (byte2 >> 4);
byte1 = (byte2 & 0xf) << 4;
p = strchr(base64, *src++);
if (p == NULL) {
if (*(src-1) == '=' && *src == '=') {
if (byte1 != 0) /* bad padding */
return BADPAD;
return 1;
}
return BADCH2;
}
byte2 = p - base64; /* next six: four plus two */
*dst++ = byte1 | (byte2 >> 2);
byte1 = (byte2 & 0x3) << 6;
p = strchr(base64, *src++);
if (p == NULL) {
if (*(src-1) == '=') {
if (byte1 != 0) /* bad padding */
return BADPAD;
return 2;
}
return BADCH3;
}
byte2 = p - base64; /* last six */
*dst++ = byte1 | byte2;
return 3;
}
/*
- untext - convert one ASCII character to byte
*/
static int /* number of result bytes, or error code */
untext(src, dst, dstlen)
const char *src; /* known to be full length */
char *dst;
size_t dstlen; /* not large enough is a failure */
{
if (dstlen < 1)
return SHORT;
*dst = *src;
return 1;
}
/*
- badch - produce a nice complaint about an unknown character
*
* If the compiler complains that the array bigenough[] has a negative
* size, that means the TTODATAV_BUF constant has been set too small.
*/
static const char * /* literal or errp */
badch(src, errcode, errp, errlen)
const char *src;
int errcode;
char *errp; /* might be NULL */
size_t errlen;
{
static const char pre[] = "unknown character (`";
static const char suf[] = "') in input";
char buf[5];
# define REQD (sizeof(pre) - 1 + sizeof(buf) - 1 + sizeof(suf))
struct sizecheck {
char bigenough[TTODATAV_BUF - REQD]; /* see above */
};
char ch;
if (errp == NULL || errlen < REQD)
return "unknown character in input";
strcpy(errp, pre);
ch = *(src + BADOFF(errcode));
if (isprint(ch)) {
buf[0] = ch;
buf[1] = '\0';
} else {
buf[0] = '\\';
buf[1] = ((ch & 0700) >> 6) + '0';
buf[2] = ((ch & 0070) >> 3) + '0';
buf[3] = ((ch & 0007) >> 0) + '0';
buf[4] = '\0';
}
strcat(errp, buf);
strcat(errp, suf);
return (const char *)errp;
}
#ifdef TTODATA_MAIN
#include <stdio.h>
struct artab;
static void check(struct artab *r, char *buf, size_t n, err_t oops, int *status);
static void regress(char *pgm);
static void hexout(const char *s, size_t len, FILE *f);
/*
- main - convert first argument to hex, or run regression
*/
int
main(int argc, char *argv[])
{
char buf[1024];
char buf2[1024];
char err[512];
size_t n;
size_t i;
char *p = buf;
char *p2 = buf2;
char *pgm = argv[0];
const char *oops;
if (argc < 2) {
fprintf(stderr, "Usage: %s {0x<hex>|0s<base64>|-r}\n", pgm);
exit(2);
}
if (strcmp(argv[1], "-r") == 0) {
regress(pgm); /* should not return */
fprintf(stderr, "%s: regress() returned?!?\n", pgm);
exit(1);
}
oops = ttodatav(argv[1], 0, 0, buf, sizeof(buf), &n,
err, sizeof(err), TTODATAV_IGNORESPACE);
if (oops != NULL) {
fprintf(stderr, "%s: ttodata error `%s' in `%s'\n", pgm,
oops, argv[1]);
exit(1);
}
if (n > sizeof(buf)) {
p = (char *)malloc((size_t)n);
if (p == NULL) {
fprintf(stderr,
"%s: unable to malloc %d bytes for result\n",
pgm, n);
exit(1);
}
oops = ttodata(argv[1], 0, 0, p, n, &n);
if (oops != NULL) {
fprintf(stderr, "%s: error `%s' in ttodata retry?!?\n",
pgm, oops);
exit(1);
}
}
hexout(p, n, stdout);
printf("\n");
i = datatot(buf, n, 'h', buf2, sizeof(buf2));
if (i == 0) {
fprintf(stderr, "%s: datatot reports error in `%s'\n", pgm,
argv[1]);
exit(1);
}
if (i > sizeof(buf2)) {
p2 = (char *)malloc((size_t)i);
if (p == NULL) {
fprintf(stderr,
"%s: unable to malloc %d bytes for result\n",
pgm, i);
exit(1);
}
i = datatot(buf, n, 'h', p2, i);
if (i == 0) {
fprintf(stderr, "%s: error in datatoa retry?!?\n", pgm);
exit(1);
}
}
printf("%s\n", p2);
exit(0);
}
/*
- hexout - output an arbitrary-length string in hex
*/
static void
hexout(s, len, f)
const char *s;
size_t len;
FILE *f;
{
size_t i;
fprintf(f, "0x");
for (i = 0; i < len; i++)
fprintf(f, "%02x", (unsigned char)s[i]);
}
struct artab {
int base;
# define IGNORESPACE_BIAS 1000
char *ascii; /* NULL for end */
char *data; /* NULL for error expected */
} atodatatab[] = {
{ 0, "", NULL, },
{ 0, "0", NULL, },
{ 0, "0x", NULL, },
{ 0, "0xa", NULL, },
{ 0, "0xab", "\xab", },
{ 0, "0xabc", NULL, },
{ 0, "0xabcd", "\xab\xcd", },
{ 0, "0x0123456789", "\x01\x23\x45\x67\x89", },
{ 0, "0x01x", NULL, },
{ 0, "0xabcdef", "\xab\xcd\xef", },
{ 0, "0xABCDEF", "\xab\xcd\xef", },
{ 0, "0XaBc0eEd81f", "\xab\xc0\xee\xd8\x1f", },
{ 0, "0XaBc0_eEd8", "\xab\xc0\xee\xd8", },
{ 0, "0XaBc0_", NULL, },
{ 0, "0X_aBc0", NULL, },
{ 0, "0Xa_Bc0", NULL, },
{ 16, "aBc0eEd8", "\xab\xc0\xee\xd8", },
{ 0, "0s", NULL, },
{ 0, "0sA", NULL, },
{ 0, "0sBA", NULL, },
{ 0, "0sCBA", NULL, },
{ 0, "0sDCBA", "\x0c\x20\x40", },
{ 0, "0SDCBA", "\x0c\x20\x40", },
{ 0, "0sDA==", "\x0c", },
{ 0, "0sDC==", NULL, },
{ 0, "0sDCA=", "\x0c\x20", },
{ 0, "0sDCB=", NULL, },
{ 0, "0sDCAZ", "\x0c\x20\x19", },
{ 0, "0sDCAa", "\x0c\x20\x1a", },
{ 0, "0sDCAz", "\x0c\x20\x33", },
{ 0, "0sDCA0", "\x0c\x20\x34", },
{ 0, "0sDCA9", "\x0c\x20\x3d", },
{ 0, "0sDCA+", "\x0c\x20\x3e", },
{ 0, "0sDCA/", "\x0c\x20\x3f", },
{ 0, "0sAbraCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0s AbraCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sA braCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAb raCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbr aCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbra Cadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbraC adabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbraCa dabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbraCad abra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbraCada bra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbraCadab ra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbraCadabr a+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbraCadabra +", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbraCadabra+ ", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ 0, "0t", NULL, },
{ 0, "0tabc_xyz", "abc_xyz", },
{ 256, "abc_xyz", "abc_xyz", },
{ 0, NULL, NULL, },
};
struct drtab {
char *data; /* input; NULL for end */
char format;
int buflen; /* -1 means big buffer */
int outlen; /* -1 means strlen(ascii)+1 */
char *ascii; /* NULL for error expected */
} datatoatab[] = {
{ "", 'x', -1, -1, NULL, },
{ "", 'X', -1, -1, NULL, },
{ "", 'n', -1, -1, NULL, },
{ "0", 'x', -1, -1, "0x30", },
{ "0", 'x', 0, 5, "---", },
{ "0", 'x', 1, 5, "", },
{ "0", 'x', 2, 5, "0", },
{ "0", 'x', 3, 5, "0x", },
{ "0", 'x', 4, 5, "0x3", },
{ "0", 'x', 5, 5, "0x30", },
{ "0", 'x', 6, 5, "0x30", },
{ "\xab\xcd", 'x', -1, -1, "0xabcd", },
{ "\x01\x23\x45\x67\x89", 'x', -1, -1, "0x0123456789", },
{ "\xab\xcd\xef", 'x', -1, -1, "0xabcdef", },
{ "\xab\xc0\xee\xd8\x1f", 'x', -1, -1, "0xabc0eed81f", },
{ "\x01\x02", 'h', -1, -1, "0x0102", },
{ "\x01\x02\x03\x04\x05\x06", 'h', -1, -1, "0x01020304_0506", },
{ "\xab\xc0\xee\xd8\x1f", 16, -1, -1, "abc0eed81f", },
{ "\x0c\x20\x40", 's', -1, -1, "0sDCBA", },
{ "\x0c\x20\x40", 's', 0, 7, "---", },
{ "\x0c\x20\x40", 's', 1, 7, "", },
{ "\x0c\x20\x40", 's', 2, 7, "0", },
{ "\x0c\x20\x40", 's', 3, 7, "0s", },
{ "\x0c\x20\x40", 's', 4, 7, "0sD", },
{ "\x0c\x20\x40", 's', 5, 7, "0sDC", },
{ "\x0c\x20\x40", 's', 6, 7, "0sDCB", },
{ "\x0c\x20\x40", 's', 7, 7, "0sDCBA", },
{ "\x0c\x20\x40", 's', 8, 7, "0sDCBA", },
{ "\x0c", 's', -1, -1, "0sDA==", },
{ "\x0c\x20", 's', -1, -1, "0sDCA=", },
{ "\x0c\x20\x19", 's', -1, -1, "0sDCAZ", },
{ "\x0c\x20\x1a", 's', -1, -1, "0sDCAa", },
{ "\x0c\x20\x33", 's', -1, -1, "0sDCAz", },
{ "\x0c\x20\x34", 's', -1, -1, "0sDCA0", },
{ "\x0c\x20\x3d", 's', -1, -1, "0sDCA9", },
{ "\x0c\x20\x3e", 's', -1, -1, "0sDCA+", },
{ "\x0c\x20\x3f", 's', -1, -1, "0sDCA/", },
{ "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", 's', -1, -1, "0sAbraCadabra+", },
{ "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", 64, -1, -1, "AbraCadabra+", },
{ NULL, 'x', -1, -1, NULL, },
};
/*
- regress - regression-test ttodata() and datatot()
*/
static void
check(r, buf, n, oops, status)
struct artab *r;
char *buf;
size_t n;
err_t oops;
int *status;
{
if (oops != NULL && r->data == NULL)
{} /* error expected */
else if (oops != NULL) {
printf("`%s' gave error `%s', expecting %d `", r->ascii,
oops, strlen(r->data));
hexout(r->data, strlen(r->data), stdout);
printf("'\n");
*status = 1;
} else if (r->data == NULL) {
printf("`%s' gave %d `", r->ascii, n);
hexout(buf, n, stdout);
printf("', expecting error\n");
*status = 1;
} else if (n != strlen(r->data)) {
printf("length wrong in `%s': got %d `", r->ascii, n);
hexout(buf, n, stdout);
printf("', expecting %d `", strlen(r->data));
hexout(r->data, strlen(r->data), stdout);
printf("'\n");
*status = 1;
} else if (memcmp(buf, r->data, n) != 0) {
printf("`%s' gave %d `", r->ascii, n);
hexout(buf, n, stdout);
printf("', expecting %d `", strlen(r->data));
hexout(r->data, strlen(r->data), stdout);
printf("'\n");
*status = 1;
}
fflush(stdout);
}
static void /* should not return at all, in fact */
regress(pgm)
char *pgm;
{
struct artab *r;
struct drtab *dr;
char buf[100];
size_t n;
int status = 0;
for (r = atodatatab; r->ascii != NULL; r++) {
int base = r->base;
int xbase = 0;
if ((base == 0 || base == IGNORESPACE_BIAS + 0) && r->ascii[0] == '0') {
switch (r->ascii[1]) {
case 'x':
case 'X':
xbase = 16;
break;
case 's':
case 'S':
xbase = 64;
break;
case 't':
case 'T':
xbase = 256;
break;
}
}
if (base >= IGNORESPACE_BIAS) {
base = base - IGNORESPACE_BIAS;
check(r, buf, n, ttodatav(r->ascii, 0, base, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
if (xbase != 0)
check(r, buf, n, ttodatav(r->ascii+2, 0, xbase, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
} else {
check(r, buf, n, ttodata(r->ascii, 0, base, buf, sizeof(buf), &n), &status);
if (base == 64 || xbase == 64)
check(r, buf, n, ttodatav(r->ascii, 0, base, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
if (xbase != 0) {
check(r, buf, n, ttodata(r->ascii+2, 0, xbase, buf, sizeof(buf), &n), &status);
if (base == 64 || xbase == 64)
check(r, buf, n, ttodatav(r->ascii+2, 0, xbase, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
}
}
}
for (dr = datatoatab; dr->data != NULL; dr++) {
size_t should;
strcpy(buf, "---");
n = datatot(dr->data, strlen(dr->data), dr->format, buf,
(dr->buflen == -1) ? sizeof(buf) : dr->buflen);
should = (dr->ascii == NULL) ? 0 : strlen(dr->ascii) + 1;
if (dr->outlen != -1)
should = dr->outlen;
if (n == 0 && dr->ascii == NULL)
{} /* error expected */
else if (n == 0) {
printf("`");
hexout(dr->data, strlen(dr->data), stdout);
printf("' %c gave error, expecting %d `%s'\n",
dr->format, should, dr->ascii);
status = 1;
} else if (dr->ascii == NULL) {
printf("`");
hexout(dr->data, strlen(dr->data), stdout);
printf("' %c gave %d `%.*s', expecting error\n",
dr->format, n, (int)n, buf);
status = 1;
} else if (n != should) {
printf("length wrong in `");
hexout(dr->data, strlen(dr->data), stdout);
printf("': got %d `%s'", n, buf);
printf(", expecting %d `%s'\n", should, dr->ascii);
status = 1;
} else if (strcmp(buf, dr->ascii) != 0) {
printf("`");
hexout(dr->data, strlen(dr->data), stdout);
printf("' gave %d `%s'", n, buf);
printf(", expecting %d `%s'\n", should, dr->ascii);
status = 1;
}
fflush(stdout);
}
exit(status);
}
#endif /* TTODATA_MAIN */

View File

@ -1,101 +0,0 @@
/*
* conversion from protocol/port string to protocol and port
* Copyright (C) 2002 Mario Strasser <mast@gmx.net>,
* Zuercher Hochschule Winterthur,
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include "internal.h"
#include "freeswan.h"
/*
* ttoprotoport - converts from protocol/port string to protocol and port
*/
err_t
ttoprotoport(src, src_len, proto, port, has_port_wildcard)
char *src; /* input string */
size_t src_len; /* length of input string, use strlen() if 0 */
u_int8_t *proto; /* extracted protocol number */
u_int16_t *port; /* extracted port number if it exists */
bool *has_port_wildcard; /* set if port is %any */
{
char *end, *service_name;
char proto_name[16];
int proto_len;
long int l;
struct protoent *protocol;
struct servent *service;
/* get the length of the string */
if (!src_len) src_len = strlen(src);
/* locate delimiter '/' between protocol and port */
end = strchr(src, '/');
if (end != NULL) {
proto_len = end - src;
service_name = end + 1;
} else {
proto_len = src_len;
service_name = src + src_len;
}
/* copy protocol name*/
memset(proto_name, '\0', sizeof(proto_name));
memcpy(proto_name, src, proto_len);
/* extract protocol by trying to resolve it by name */
protocol = getprotobyname(proto_name);
if (protocol != NULL) {
*proto = protocol->p_proto;
}
else /* failed, now try it by number */
{
l = strtol(proto_name, &end, 0);
if (*proto_name && *end)
return "<protocol> is neither a number nor a valid name";
if (l < 0 || l > 0xff)
return "<protocol> must be between 0 and 255";
*proto = (u_int8_t)l;
}
/* is there a port wildcard? */
*has_port_wildcard = (strcmp(service_name, "%any") == 0);
if (*has_port_wildcard)
{
*port = 0;
return NULL;
}
/* extract port by trying to resolve it by name */
service = getservbyname(service_name, NULL);
if (service != NULL) {
*port = ntohs(service->s_port);
}
else /* failed, now try it by number */
{
l = strtol(service_name, &end, 0);
if (*service_name && *end)
return "<port> is neither a number nor a valid name";
if (l < 0 || l > 0xffff)
return "<port> must be between 0 and 65535";
*port = (u_int16_t)l;
}
return NULL;
}

View File

@ -1,287 +0,0 @@
.TH IPSEC_TTOSA 3 "26 Nov 2001"
.SH NAME
ipsec ttosa, satot \- convert IPsec Security Association IDs to and from text
.br
ipsec initsaid \- initialize an SA ID
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "typedef struct {"
.ti +1c
.B "ip_address dst;"
.ti +1c
.B "ipsec_spi_t spi;"
.ti +1c
.B "int proto;"
.br
.B "} ip_said;"
.sp
.B "const char *ttosa(const char *src, size_t srclen,"
.ti +1c
.B "ip_said *sa);
.br
.B "size_t satot(const ip_said *sa, int format,"
.ti +1c
.B "char *dst, size_t dstlen);"
.br
.B "void initsaid(const ip_address *addr, ipsec_spi_t spi,"
.ti +1c
.B "int proto, ip_said *dst);"
.SH DESCRIPTION
.I Ttosa
converts an ASCII Security Association (SA) specifier into an
.B ip_said
structure (containing
a destination-host address
in network byte order,
an SPI number in network byte order, and
a protocol code).
.I Satot
does the reverse conversion, back to a text SA specifier.
.I Initsaid
initializes an
.B ip_said
from separate items of information.
.PP
An SA is specified in text with a mail-like syntax, e.g.
.BR esp.5a7@1.2.3.4 .
An SA specifier contains
a protocol prefix (currently
.BR ah ,
.BR esp ,
.BR tun ,
.BR comp ,
or
.BR int ),
a single character indicating the address family
.RB ( .
for IPv4,
.B :
for IPv6),
an unsigned integer SPI number in hexadecimal (with no
.B 0x
prefix),
and an IP address.
The IP address can be any form accepted by
.IR ipsec_ttoaddr (3),
e.g. dotted-decimal IPv4 address,
colon-hex IPv6 address,
or DNS name.
.PP
As a special case, the SA specifier
.B %passthrough4
or
.B %passthrough6
signifies the special SA used to indicate that packets should be
passed through unaltered.
(At present, these are synonyms for
.B tun.0@0.0.0.0
and
.B tun:0@::
respectively,
but that is subject to change without notice.)
.B %passthrough
is a historical synonym for
.BR %passthrough4 .
These forms are known to both
.I ttosa
and
.IR satot ,
so the internal representation is never visible.
.PP
Similarly, the SA specifiers
.BR %pass ,
.BR %drop ,
.BR %reject ,
.BR %hold ,
.BR %trap ,
and
.BR %trapsubnet
signify special ``magic'' SAs used to indicate that packets should be
passed, dropped, rejected (dropped with ICMP notification),
held,
and trapped (sent up to
.IR ipsec_pluto (8),
with either of two forms of
.B %hold
automatically installed)
respectively.
These forms too are known to both routines,
so the internal representation of the magic SAs should never be visible.
.PP
The
.B <freeswan.h>
header file supplies the
.B ip_said
structure, as well as a data type
.B ipsec_spi_t
which is an unsigned 32-bit integer.
(There is no consistency between kernel and user on what such a type
is called, hence the header hides the differences.)
.PP
The protocol code uses the same numbers that IP does.
For user convenience, given the difficulty in acquiring the exact set of
protocol names used by the kernel,
.B <freeswan.h>
defines the names
.BR SA_ESP ,
.BR SA_AH ,
.BR SA_IPIP ,
and
.BR SA_COMP
to have the same values as the kernel names
.BR IPPROTO_ESP ,
.BR IPPROTO_AH ,
.BR IPPROTO_IPIP ,
and
.BR IPPROTO_COMP .
.PP
.B <freeswan.h>
also defines
.BR SA_INT
to have the value
.BR 61
(reserved by IANA for ``any host internal protocol'')
and
.BR SPI_PASS ,
.BR SPI_DROP ,
.BR SPI_REJECT ,
.BR SPI_HOLD ,
and
.B SPI_TRAP
to have the values 256-260 (in \fIhost\fR byte order) respectively.
These are used in constructing the magic SAs
(which always have address
.BR 0.0.0.0 ).
.PP
If
.I satot
encounters an unknown protocol code, e.g. 77,
it yields output using a prefix
showing the code numerically, e.g. ``unk77''.
This form is
.I not
recognized by
.IR ttosa .
.PP
The
.I srclen
parameter of
.I ttosa
specifies the length of the string pointed to by
.IR src ;
it is an error for there to be anything else
(e.g., a terminating NUL) within that length.
As a convenience for cases where an entire NUL-terminated string is
to be converted,
a
.I srclen
value of
.B 0
is taken to mean
.BR strlen(src) .
.PP
The
.I dstlen
parameter of
.I satot
specifies the size of the
.I dst
parameter;
under no circumstances are more than
.I dstlen
bytes written to
.IR dst .
A result which will not fit is truncated.
.I Dstlen
can be zero, in which case
.I dst
need not be valid and no result is written,
but the return value is unaffected;
in all other cases, the (possibly truncated) result is NUL-terminated.
The
.B <freeswan.h>
header file defines a constant,
.BR SATOT_BUF ,
which is the size of a buffer just large enough for worst-case results.
.PP
The
.I format
parameter of
.I satot
specifies what format is to be used for the conversion.
The value
.B 0
(not the ASCII character
.BR '0' ,
but a zero value)
specifies a reasonable default
(currently
lowercase protocol prefix, lowercase hexadecimal SPI,
dotted-decimal or colon-hex address).
The value
.B 'f'
is similar except that the SPI is padded with
.BR 0 s
to a fixed 32-bit width, to ease aligning displayed tables.
.PP
.I Ttosa
returns
.B NULL
for success and
a pointer to a string-literal error message for failure;
see DIAGNOSTICS.
.I Satot
returns
.B 0
for a failure, and otherwise
always returns the size of buffer which would
be needed to
accommodate the full conversion result, including terminating NUL;
it is the caller's responsibility to check this against the size of
the provided buffer to determine whether truncation has occurred.
.PP
There is also, temporarily, support for some obsolete
forms of SA specifier which lack the address-family indicator.
.SH SEE ALSO
ipsec_ttoul(3), ipsec_ttoaddr(3), ipsec_samesaid(3), inet(3)
.SH DIAGNOSTICS
Fatal errors in
.I ttosa
are:
empty input;
input too small to be a legal SA specifier;
no
.B @
in input;
unknown protocol prefix;
conversion error in
.I ttoul
or
.IR ttoaddr .
.PP
Fatal errors in
.I satot
are:
unknown format.
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
The restriction of text-to-binary error reports to literal strings
(so that callers don't need to worry about freeing them or copying them)
does limit the precision of error reporting.
.PP
The text-to-binary error-reporting convention lends itself
to slightly obscure code,
because many readers will not think of NULL as signifying success.
A good way to make it clearer is to write something like:
.PP
.RS
.nf
.B "const char *error;"
.sp
.B "error = ttosa( /* ... */ );"
.B "if (error != NULL) {"
.B " /* something went wrong */"
.fi
.RE

View File

@ -1,280 +0,0 @@
/*
* convert from text form of SA ID to binary
* Copyright (C) 2000, 2001 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include <sys/socket.h>
#include "internal.h"
#include "freeswan.h"
static struct satype {
char *prefix;
size_t prelen; /* strlen(prefix) */
int proto;
} satypes[] = {
{ "ah", 2, SA_AH },
{ "esp", 3, SA_ESP },
{ "tun", 3, SA_IPIP },
{ "comp", 4, SA_COMP },
{ "int", 3, SA_INT },
{ NULL, 0, 0, }
};
static struct magic {
char *name;
char *really;
} magic[] = {
{ PASSTHROUGHNAME, PASSTHROUGH4IS },
{ PASSTHROUGH4NAME, PASSTHROUGH4IS },
{ PASSTHROUGH6NAME, PASSTHROUGH6IS },
{ "%pass", "int256@0.0.0.0" },
{ "%drop", "int257@0.0.0.0" },
{ "%reject", "int258@0.0.0.0" },
{ "%hold", "int259@0.0.0.0" },
{ "%trap", "int260@0.0.0.0" },
{ "%trapsubnet", "int261@0.0.0.0" },
{ NULL, NULL }
};
/*
- ttosa - convert text "ah507@10.0.0.1" to SA identifier
*/
err_t /* NULL for success, else string literal */
ttosa(src, srclen, sa)
const char *src;
size_t srclen; /* 0 means "apply strlen" */
ip_said *sa;
{
const char *at;
const char *addr;
size_t alen;
const char *spi = NULL;
struct satype *sat;
unsigned long ul;
const char *oops;
struct magic *mp;
size_t nlen;
# define MINLEN 5 /* ah0@0 is as short as it can get */
int af;
int base;
if (srclen == 0)
srclen = strlen(src);
if (srclen == 0)
return "empty string";
if (srclen < MINLEN)
return "string too short to be SA identifier";
if (*src == '%') {
for (mp = magic; mp->name != NULL; mp++) {
nlen = strlen(mp->name);
if (srclen == nlen && memcmp(src, mp->name, nlen) == 0)
break;
}
if (mp->name == NULL)
return "unknown % keyword";
src = mp->really;
srclen = strlen(src);
}
at = memchr(src, '@', srclen);
if (at == NULL)
return "no @ in SA specifier";
for (sat = satypes; sat->prefix != NULL; sat++)
if (sat->prelen < srclen &&
strncmp(src, sat->prefix, sat->prelen) == 0) {
sa->proto = sat->proto;
spi = src + sat->prelen;
break; /* NOTE BREAK OUT */
}
if (sat->prefix == NULL)
return "SA specifier lacks valid protocol prefix";
if (spi >= at)
return "no SPI in SA specifier";
switch (*spi) {
case '.':
af = AF_INET;
spi++;
base = 16;
break;
case ':':
af = AF_INET6;
spi++;
base = 16;
break;
default:
af = AF_UNSPEC; /* not known yet */
base = 0;
break;
}
if (spi >= at)
return "no SPI found in SA specifier";
oops = ttoul(spi, at - spi, base, &ul);
if (oops != NULL)
return oops;
sa->spi = htonl(ul);
addr = at + 1;
alen = srclen - (addr - src);
if (af == AF_UNSPEC)
af = (memchr(addr, ':', alen) != NULL) ? AF_INET6 : AF_INET;
oops = ttoaddr(addr, alen, af, &sa->dst);
if (oops != NULL)
return oops;
return NULL;
}
#ifdef TTOSA_MAIN
#include <stdio.h>
void regress(void);
int
main(int argc, char *argv[])
{
ip_said sa;
char buf[100];
char buf2[100];
const char *oops;
size_t n;
if (argc < 2) {
fprintf(stderr, "Usage: %s {ahnnn@aaa|-r}\n", argv[0]);
exit(2);
}
if (strcmp(argv[1], "-r") == 0) {
regress();
fprintf(stderr, "regress() returned?!?\n");
exit(1);
}
oops = ttosa(argv[1], 0, &sa);
if (oops != NULL) {
fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
exit(1);
}
n = satot(&sa, 0, buf, sizeof(buf));
if (n > sizeof(buf)) {
fprintf(stderr, "%s: reverse conv of `%d'", argv[0], sa.proto);
fprintf(stderr, "%lx@", (long unsigned int)sa.spi);
(void) addrtot(&sa.dst, 0, buf2, sizeof(buf2));
fprintf(stderr, "%s", buf2);
fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
(long)n, (long)sizeof(buf));
exit(1);
}
printf("%s\n", buf);
exit(0);
}
struct rtab {
int format;
# define FUDGE 0x1000
char *input;
char *output; /* NULL means error expected */
} rtab[] = {
{0, "esp257@1.2.3.0", "esp.101@1.2.3.0"},
{0, "ah0x20@1.2.3.4", "ah.20@1.2.3.4"},
{0, "tun20@1.2.3.4", "tun.14@1.2.3.4"},
{0, "comp20@1.2.3.4", "comp.14@1.2.3.4"},
{0, "esp257@::1", "esp:101@::1"},
{0, "esp257@0bc:12de::1", "esp:101@bc:12de::1"},
{0, "esp78@1049:1::8007:2040", "esp:4e@1049:1::8007:2040"},
{0, "esp0x78@1049:1::8007:2040", "esp:78@1049:1::8007:2040"},
{0, "ah78@1049:1::8007:2040", "ah:4e@1049:1::8007:2040"},
{0, "ah0x78@1049:1::8007:2040", "ah:78@1049:1::8007:2040"},
{0, "tun78@1049:1::8007:2040", "tun:4e@1049:1::8007:2040"},
{0, "tun0x78@1049:1::8007:2040", "tun:78@1049:1::8007:2040"},
{0, "duk99@3ffe:370:400:ff::9001:3001", NULL},
{0, "esp78x@1049:1::8007:2040", NULL},
{0, "esp0x78@1049:1:0xfff::8007:2040", NULL},
{0, "es78@1049:1::8007:2040", NULL},
{0, "", NULL},
{0, "_", NULL},
{0, "ah2.2", NULL},
{0, "goo2@1.2.3.4", NULL},
{0, "esp9@1.2.3.4", "esp.9@1.2.3.4"},
{'f', "esp0xa9@1.2.3.4", "esp.000000a9@1.2.3.4"},
{0, "espp9@1.2.3.4", NULL},
{0, "es9@1.2.3.4", NULL},
{0, "ah@1.2.3.4", NULL},
{0, "esp7x7@1.2.3.4", NULL},
{0, "esp77@1.0x2.3.4", NULL},
{0, PASSTHROUGHNAME, PASSTHROUGH4NAME},
{0, PASSTHROUGH6NAME, PASSTHROUGH6NAME},
{0, "%pass", "%pass"},
{0, "int256@0.0.0.0", "%pass"},
{0, "%drop", "%drop"},
{0, "int257@0.0.0.0", "%drop"},
{0, "%reject", "%reject"},
{0, "int258@0.0.0.0", "%reject"},
{0, "%hold", "%hold"},
{0, "int259@0.0.0.0", "%hold"},
{0, "%trap", "%trap"},
{0, "int260@0.0.0.0", "%trap"},
{0, "%trapsubnet", "%trapsubnet"},
{0, "int261@0.0.0.0", "%trapsubnet"},
{0, "int262@0.0.0.0", "int.106@0.0.0.0"},
{FUDGE, "esp9@1.2.3.4", "unk77.9@1.2.3.4"},
{0, NULL, NULL}
};
void
regress(void)
{
struct rtab *r;
int status = 0;
ip_said sa;
char in[100];
char buf[100];
const char *oops;
size_t n;
for (r = rtab; r->input != NULL; r++) {
strcpy(in, r->input);
oops = ttosa(in, 0, &sa);
if (oops != NULL && r->output == NULL)
{} /* okay, error expected */
else if (oops != NULL) {
printf("`%s' ttosa failed: %s\n", r->input, oops);
status = 1;
} else if (r->output == NULL) {
printf("`%s' ttosa succeeded unexpectedly\n",
r->input);
status = 1;
} else {
if (r->format&FUDGE)
sa.proto = 77;
n = satot(&sa, (char)r->format, buf, sizeof(buf));
if (n > sizeof(buf)) {
printf("`%s' satot failed: need %ld\n",
r->input, (long)n);
status = 1;
} else if (strcmp(r->output, buf) != 0) {
printf("`%s' gave `%s', expected `%s'\n",
r->input, buf, r->output);
status = 1;
}
}
}
exit(status);
}
#endif /* TTOSA_MAIN */

View File

@ -1,296 +0,0 @@
/*
* convert from text form of subnet specification to binary
* Copyright (C) 2000 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include <sys/socket.h>
#include "internal.h"
#include "freeswan.h"
#ifndef DEFAULTSUBNET
#define DEFAULTSUBNET "%default"
#endif
/*
- ttosubnet - convert text "addr/mask" to address and mask
* Mask can be integer bit count.
*/
err_t
ttosubnet(src, srclen, af, dst)
const char *src;
size_t srclen; /* 0 means "apply strlen" */
int af; /* AF_INET or AF_INET6 */
ip_subnet *dst;
{
const char *slash;
const char *colon;
const char *mask;
size_t mlen;
const char *oops;
unsigned long bc;
static char def[] = DEFAULTSUBNET;
# define DEFLEN (sizeof(def) - 1) /* -1 for NUL */
static char defis4[] = "0/0";
# define DEFIS4LEN (sizeof(defis4) - 1)
static char defis6[] = "::/0";
# define DEFIS6LEN (sizeof(defis6) - 1)
ip_address addrtmp;
ip_address masktmp;
int nbits;
int i;
if (srclen == 0)
srclen = strlen(src);
if (srclen == 0)
return "empty string";
switch (af) {
case AF_INET:
nbits = 32;
break;
case AF_INET6:
nbits = 128;
break;
default:
return "unknown address family in ttosubnet";
break;
}
if (srclen == DEFLEN && strncmp(src, def, srclen) == 0) {
src = (af == AF_INET) ? defis4 : defis6;
srclen = (af == AF_INET) ? DEFIS4LEN : DEFIS6LEN;
}
slash = memchr(src, '/', srclen);
if (slash == NULL)
return "no / in subnet specification";
mask = slash + 1;
mlen = srclen - (mask - src);
oops = ttoaddr(src, slash-src, af, &addrtmp);
if (oops != NULL)
return oops;
/* extract port */
colon = memchr(mask, ':', mlen);
if (colon == 0)
{
setportof(0, &addrtmp);
}
else
{
long port;
oops = ttoul(colon+1, mlen-(colon-mask+1), 10, &port);
if (oops != NULL)
return oops;
setportof(htons(port), &addrtmp);
mlen = colon - mask;
}
/*extract mask */
oops = ttoul(mask, mlen, 10, &bc);
if (oops == NULL) {
/* ttoul succeeded, it's a bit-count mask */
if (bc > nbits)
return "subnet mask bit count too large";
i = bc;
} else {
oops = ttoaddr(mask, mlen, af, &masktmp);
if (oops != NULL)
return oops;
i = masktocount(&masktmp);
if (i < 0)
return "non-contiguous or otherwise erroneous mask";
}
return initsubnet(&addrtmp, i, '0', dst);
}
#ifdef TTOSUBNET_MAIN
#include <stdio.h>
void regress(void);
int main(int argc, char *argv[])
{
ip_subnet s;
char buf[100];
char buf2[100];
const char *oops;
size_t n;
int af;
char *p;
if (argc < 2) {
fprintf(stderr, "Usage: %s [-6] addr/mask\n", argv[0]);
fprintf(stderr, " or: %s -r\n", argv[0]);
exit(2);
}
if (strcmp(argv[1], "-r") == 0) {
regress();
fprintf(stderr, "regress() returned?!?\n");
exit(1);
}
af = AF_INET;
p = argv[1];
if (strcmp(argv[1], "-6") == 0) {
af = AF_INET6;
p = argv[2];
} else if (strchr(argv[1], ':') != NULL)
af = AF_INET6;
oops = ttosubnet(p, 0, af, &s);
if (oops != NULL) {
fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops);
exit(1);
}
n = subnettot(&s, 0, buf, sizeof(buf));
if (n > sizeof(buf)) {
fprintf(stderr, "%s: reverse conversion of ", argv[0]);
(void) addrtot(&s.addr, 0, buf2, sizeof(buf2));
fprintf(stderr, "%s/", buf2);
fprintf(stderr, "%d", s.maskbits);
fprintf(stderr, " failed: need %ld bytes, have only %ld\n",
(long)n, (long)sizeof(buf));
exit(1);
}
printf("%s\n", buf);
exit(0);
}
struct rtab {
int family;
char *input;
char *output; /* NULL means error expected */
} rtab[] = {
{4, "1.2.3.0/255.255.255.0", "1.2.3.0/24"},
{4, "1.2.3.0/24", "1.2.3.0/24"},
{4, "1.2.3.0/24:10", "1.2.3.0/24:10"},
{4, "1.2.3.0/24:-1", NULL},
{4, "1.2.3.0/24:none", NULL},
{4, "1.2.3.0/24:", NULL},
{4, "1.2.3.0/24:0x10", "1.2.3.0/24:16"},
{4, "1.2.3.0/24:0X10", "1.2.3.0/24:16"},
{4, "1.2.3.0/24:010", "1.2.3.0/24:8"},
{4, "1.2.3.1/255.255.255.240", "1.2.3.0/28"},
{4, "1.2.3.1/32", "1.2.3.1/32"},
{4, "1.2.3.1/0", "0.0.0.0/0"},
/* {4, "1.2.3.1/255.255.127.0", "1.2.3.0/255.255.127.0"}, */
{4, "1.2.3.1/255.255.127.0", NULL},
{4, "128.009.000.032/32", "128.9.0.32/32"},
{4, "128.0x9.0.32/32", NULL},
{4, "0x80090020/32", "128.9.0.32/32"},
{4, "0x800x0020/32", NULL},
{4, "128.9.0.32/0xffFF0000", "128.9.0.0/16"},
{4, "128.9.0.32/0xff0000FF", NULL},
{4, "128.9.0.32/0x0000ffFF", NULL},
{4, "128.9.0.32/0x00ffFF0000", NULL},
{4, "128.9.0.32/0xffFF", NULL},
{4, "128.9.0.32.27/32", NULL},
{4, "128.9.0k32/32", NULL},
{4, "328.9.0.32/32", NULL},
{4, "128.9..32/32", NULL},
{4, "10/8", "10.0.0.0/8"},
{4, "10.0/8", "10.0.0.0/8"},
{4, "10.0.0/8", "10.0.0.0/8"},
{4, "10.0.1/24", "10.0.1.0/24"},
{4, "_", NULL},
{4, "_/_", NULL},
{4, "1.2.3.1", NULL},
{4, "1.2.3.1/_", NULL},
{4, "1.2.3.1/24._", NULL},
{4, "1.2.3.1/99", NULL},
{4, "localhost/32", "127.0.0.1/32"},
{4, "%default", "0.0.0.0/0"},
{6, "3049:1::8007:2040/0", "::/0"},
{6, "3049:1::8007:2040/128", "3049:1::8007:2040/128"},
{6, "3049:1::192.168.0.1/128", NULL}, /*"3049:1::c0a8:1/128",*/
{6, "3049:1::8007::2040/128", NULL},
{6, "3049:1::8007:2040/ffff::0", "3049::/16"},
{6, "3049:1::8007:2040/64", "3049:1::/64"},
{6, "3049:1::8007:2040/ffff::", "3049::/16"},
{6, "3049:1::8007:2040/0000:ffff::0", NULL},
{6, "3049:1::8007:2040/ff1f::0", NULL},
{6, "3049:1::8007:x:2040/128", NULL},
{6, "3049:1t::8007:2040/128", NULL},
{6, "3049:1::80071:2040/128", NULL},
{6, "::/21", "::/21"},
{6, "::1/128", "::1/128"},
{6, "1::/21", "1::/21"},
{6, "1::2/128", "1::2/128"},
{6, "1:0:0:0:0:0:0:2/128", "1::2/128"},
{6, "1:0:0:0:3:0:0:2/128", "1::3:0:0:2/128"},
{6, "1:0:0:3:0:0:0:2/128", "1::3:0:0:0:2/128"},
{6, "1:0:3:0:0:0:0:2/128", "1:0:3::2/128"},
{6, "abcd:ef01:2345:6789:0:00a:000:20/128", "abcd:ef01:2345:6789:0:a:0:20/128"},
{6, "3049:1::8007:2040/ffff:ffff:", NULL},
{6, "3049:1::8007:2040/ffff:88::", NULL},
{6, "3049:12::9000:3200/ffff:fff0::", "3049:10::/28"},
{6, "3049:12::9000:3200/28", "3049:10::/28"},
{6, "3049:12::9000:3200/ff00:::", NULL},
{6, "3049:12::9000:3200/ffff:::", NULL},
{6, "3049:12::9000:3200/128_", NULL},
{6, "3049:12::9000:3200/", NULL},
{6, "%default", "::/0"},
{4, NULL, NULL}
};
void
regress(void)
{
struct rtab *r;
int status = 0;
ip_subnet s;
char in[100];
char buf[100];
const char *oops;
size_t n;
int af;
for (r = rtab; r->input != NULL; r++) {
af = (r->family == 4) ? AF_INET : AF_INET6;
strcpy(in, r->input);
oops = ttosubnet(in, 0, af, &s);
if (oops != NULL && r->output == NULL)
{} /* okay, error expected */
else if (oops != NULL) {
printf("`%s' ttosubnet failed: %s\n", r->input, oops);
status = 1;
} else if (r->output == NULL) {
printf("`%s' ttosubnet succeeded unexpectedly\n",
r->input);
status = 1;
} else {
n = subnettot(&s, 0, buf, sizeof(buf));
if (n > sizeof(buf)) {
printf("`%s' subnettot failed: need %ld\n",
r->input, (long)n);
status = 1;
} else if (strcmp(r->output, buf) != 0) {
printf("`%s' gave `%s', expected `%s'\n",
r->input, buf, r->output);
status = 1;
}
}
}
exit(status);
}
#endif /* TTOSUBNET_MAIN */

View File

@ -1,191 +0,0 @@
.TH IPSEC_TTOUL 3 "16 Aug 2000"
.SH NAME
ipsec ttoul, ultot \- convert unsigned-long numbers to and from text
.SH SYNOPSIS
.B "#include <freeswan.h>
.sp
.B "const char *ttoul(const char *src, size_t srclen,"
.ti +1c
.B "int base, unsigned long *n);"
.br
.B "size_t ultot(unsigned long n, int format, char *dst,"
.ti +1c
.B "size_t dstlen);"
.SH DESCRIPTION
.I Ttoul
converts a text-string number into a binary
.B "unsigned long"
value.
.I Ultot
does the reverse conversion, back to a text version.
.PP
Numbers are specified in text as
decimal (e.g.
.BR 123 ),
octal with a leading zero (e.g.
.BR 012 ,
which has value 10),
or hexadecimal with a leading
.B 0x
(e.g.
.BR 0x1f ,
which has value 31)
in either upper or lower case.
.PP
The
.I srclen
parameter of
.I ttoul
specifies the length of the string pointed to by
.IR src ;
it is an error for there to be anything else
(e.g., a terminating NUL) within that length.
As a convenience for cases where an entire NUL-terminated string is
to be converted,
a
.I srclen
value of
.B 0
is taken to mean
.BR strlen(src) .
.PP
The
.I base
parameter of
.I ttoul
can be
.BR 8 ,
.BR 10 ,
or
.BR 16 ,
in which case the number supplied is assumed to be of that form
(and in the case of
.BR 16 ,
to lack any
.B 0x
prefix).
It can also be
.BR 0 ,
in which case the number is examined for a leading zero
or a leading
.B 0x
to determine its base.
.PP
The
.I dstlen
parameter of
.I ultot
specifies the size of the
.I dst
parameter;
under no circumstances are more than
.I dstlen
bytes written to
.IR dst .
A result which will not fit is truncated.
.I Dstlen
can be zero, in which case
.I dst
need not be valid and no result is written,
but the return value is unaffected;
in all other cases, the (possibly truncated) result is NUL-terminated.
The
.I freeswan.h
header file defines a constant,
.BR ULTOT_BUF ,
which is the size of a buffer just large enough for worst-case results.
.PP
The
.I format
parameter of
.I ultot
must be one of:
.RS
.IP \fB'o'\fR 4
octal conversion with leading
.B 0
.IP \fB\ 8\fR
octal conversion with no leading
.B 0
.IP \fB'd'\fR
decimal conversion
.IP \fB10\fR
same as
.B d
.IP \fB'x'\fR
hexadecimal conversion, including leading
.B 0x
.IP \fB16\fR
hexadecimal conversion with no leading
.B 0x
.IP \fB17\fR
like
.B 16
except padded on left with
.BR 0 s
to eight digits (full width of a 32-bit number)
.RE
.PP
.I Ttoul
returns NULL for success and
a pointer to a string-literal error message for failure;
see DIAGNOSTICS.
.I Ultot
returns
.B 0
for a failure, and otherwise
returns the size of buffer which would
be needed to
accommodate the full conversion result, including terminating NUL
(it is the caller's responsibility to check this against the size of
the provided buffer to determine whether truncation has occurred).
.SH SEE ALSO
atol(3), strtoul(3)
.SH DIAGNOSTICS
Fatal errors in
.I ttoul
are:
empty input;
unknown
.IR base ;
non-digit character found;
number too large for an
.BR "unsigned long" .
.PP
Fatal errors in
.I ultot
are:
unknown
.IR format .
.SH HISTORY
Written for the FreeS/WAN project by Henry Spencer.
.SH BUGS
Conversion of
.B 0
with format
.B o
yields
.BR 00 .
.PP
.I Ultot
format
.B 17
is a bit of a kludge.
.PP
The restriction of error reports to literal strings
(so that callers don't need to worry about freeing them or copying them)
does limit the precision of error reporting.
.PP
The error-reporting convention lends itself to slightly obscure code,
because many readers will not think of NULL as signifying success.
A good way to make it clearer is to write something like:
.PP
.RS
.nf
.B "const char *error;"
.sp
.B "error = ttoul( /* ... */ );"
.B "if (error != NULL) {"
.B " /* something went wrong */"
.fi
.RE

View File

@ -1,89 +0,0 @@
/*
* convert from text form of unsigned long to binary
* Copyright (C) 2000 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include "internal.h"
#include "freeswan.h"
/*
- ttoul - convert text substring to unsigned long number
*/
const char * /* NULL for success, else string literal */
ttoul(src, srclen, base, resultp)
const char *src;
size_t srclen; /* 0 means strlen(src) */
int base; /* 0 means figure it out */
unsigned long *resultp;
{
const char *stop;
static char hex[] = "0123456789abcdef";
static char uchex[] = "0123456789ABCDEF";
int d;
char c;
char *p;
unsigned long r;
unsigned long rlimit;
int dlimit;
if (srclen == 0)
srclen = strlen(src);
if (srclen == 0)
return "empty string";
if (base == 0) {
if (srclen > 2 && *src == '0' &&
(*(src+1) == 'x' || *(src+1) == 'X'))
return ttoul(src+2, srclen-2, 16, resultp);
if (srclen > 1 && *src == '0')
return ttoul(src+1, srclen-1, 8, resultp);
return ttoul(src, srclen, 10, resultp);
}
if (base != 8 && base != 10 && base != 16)
return "unsupported number base";
r = 0;
stop = src + srclen;
if (base == 16) {
while (src < stop) {
c = *src++;
p = strchr(hex, c);
if (p != NULL)
d = p - hex;
else {
p = strchr(uchex, c);
if (p == NULL)
return "non-hex digit in hex number";
d = p - uchex;
}
r = (r << 4) | d;
}
/* defer length check to catch invalid digits first */
if (srclen > sizeof(unsigned long) * 2)
return "hex number too long";
} else {
rlimit = ULONG_MAX / base;
dlimit = (int)(ULONG_MAX - rlimit*base);
while (src < stop) {
c = *src++;
d = c - '0';
if (d < 0 || d >= base)
return "non-digit in number";
if (r > rlimit || (r == rlimit && d > dlimit))
return "unsigned-long overflow";
r = r*base + d;
}
}
*resultp = r;
return NULL;
}

View File

@ -1,65 +0,0 @@
/*
* convert unsigned long to ASCII
* Copyright (C) 1998, 1999 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include "internal.h"
#include "freeswan.h"
/*
- ultoa - convert unsigned long to decimal ASCII
*/
size_t /* length required for full conversion */
ultoa(n, base, dst, dstlen)
unsigned long n;
int base;
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
char buf[3*sizeof(unsigned long) + 1];
char *bufend = buf + sizeof(buf);
size_t len;
char *p;
static char hex[] = "0123456789abcdef";
p = bufend;
*--p = '\0';
if (base == 10) {
do {
*--p = n%10 + '0';
n /= 10;
} while (n != 0);
} else if (base == 16) {
do {
*--p = hex[n&0xf];
n >>= 4;
} while (n != 0);
*--p = 'x';
*--p = '0';
} else if (base == 8) {
do {
*--p = (n&07) + '0';
n >>= 3;
} while (n != 0);
*--p = '0';
} else
*--p = '?';
len = bufend - p;
if (dstlen > 0) {
if (len > dstlen)
*(p + dstlen - 1) = '\0';
strcpy(dst, p);
}
return len;
}

View File

@ -1,81 +0,0 @@
/*
* convert unsigned long to text
* Copyright (C) 2000 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library 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 Library General Public
* License for more details.
*/
#include "internal.h"
#include "freeswan.h"
/*
- ultot - convert unsigned long to text
*/
size_t /* length required for full conversion */
ultot(n, base, dst, dstlen)
unsigned long n;
int base;
char *dst; /* need not be valid if dstlen is 0 */
size_t dstlen;
{
char buf[3*sizeof(unsigned long) + 1];
char *bufend = buf + sizeof(buf);
size_t len;
char *p;
static char hex[] = "0123456789abcdef";
# define HEX32 (32/4)
p = bufend;
*--p = '\0';
switch (base) {
case 10:
case 'd':
do {
*--p = n%10 + '0';
n /= 10;
} while (n != 0);
break;
case 16:
case 17:
case 'x':
do {
*--p = hex[n&0xf];
n >>= 4;
} while (n != 0);
if (base == 17)
while (bufend - p < HEX32 + 1)
*--p = '0';
if (base == 'x') {
*--p = 'x';
*--p = '0';
}
break;
case 8:
case 'o':
do {
*--p = (n&07) + '0';
n >>= 3;
} while (n != 0);
if (base == 'o')
*--p = '0';
break;
default:
return 0;
break;
}
len = bufend - p;
if (dstlen > 0) {
if (len > dstlen)
*(p + dstlen - 1) = '\0';
strcpy(dst, p);
}
return len;
}

View File

@ -1,2 +0,0 @@
pluto
_pluto_adns

View File

@ -1,80 +0,0 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# copy-n-paste from Makefile.am
LOCAL_SRC_FILES := \
ac.c ac.h \
alg_info.c alg_info.h \
ca.c ca.h \
certs.c certs.h \
connections.c connections.h \
constants.c constants.h \
cookie.c cookie.h \
crl.c crl.h \
crypto.c crypto.h \
db_ops.c db_ops.h \
defs.c defs.h \
demux.c demux.h \
event_queue.c event_queue.h \
fetch.c fetch.h \
foodgroups.c foodgroups.h \
ike_alg.c ike_alg.h \
ipsec_doi.c ipsec_doi.h \
kameipsec.h \
kernel.c kernel.h \
kernel_alg.c kernel_alg.h \
kernel_pfkey.c kernel_pfkey.h \
keys.c keys.h \
lex.c lex.h \
log.c log.h \
myid.c myid.h \
modecfg.c modecfg.h \
nat_traversal.c nat_traversal.h \
ocsp.c ocsp.h \
packet.c packet.h \
pkcs7.c pkcs7.h \
plugin_list.c plugin_list.h \
pluto.c pluto.h \
plutomain.c \
rcv_whack.c rcv_whack.h \
server.c server.h \
smartcard.c smartcard.h \
spdb.c spdb.h \
state.c state.h \
timer.c timer.h \
vendor.c vendor.h \
virtual.c virtual.h \
whack_attribute.c whack_attribute.h \
xauth/xauth_manager.c xauth/xauth_manager.h \
xauth/xauth_provider.h xauth/xauth_verifier.h \
x509.c x509.h \
builder.c builder.h \
rsaref/pkcs11t.h rsaref/pkcs11.h rsaref/unix.h rsaref/pkcs11f.h
LOCAL_SRC_FILES += $(call add_plugin, xauth)
# build pluto ------------------------------------------------------------------
LOCAL_C_INCLUDES += \
$(libvstr_PATH) \
$(strongswan_PATH)/src/libhydra \
$(strongswan_PATH)/src/libstrongswan \
$(strongswan_PATH)/src/libfreeswan \
$(strongswan_PATH)/src/whack
LOCAL_CFLAGS := $(strongswan_CFLAGS) \
-DPLUTO -DVENDORID -DXAUTH_VID -DCISCO_QUIRKS \
-DTHREADS -DKERNEL26_HAS_KAME_DUPLICATES \
-DPLUGINS='"$(strongswan_PLUTO_PLUGINS)"'
LOCAL_MODULE := pluto
LOCAL_MODULE_TAGS := optional
LOCAL_ARM_MODE := arm
LOCAL_PRELINK_MODULE := false
LOCAL_SHARED_LIBRARIES += libstrongswan libhydra libfreeswan libcutils
include $(BUILD_EXECUTABLE)

View File

@ -1,155 +0,0 @@
# Makefile.am was ported from the old Makefile the most
# painless way. Only the most important options are included,
# further work may be necessary here...
ipsec_PROGRAMS = pluto
if USE_ADNS
ipsec_PROGRAMS += _pluto_adns
endif
pluto_SOURCES = \
ac.c ac.h \
alg_info.c alg_info.h \
ca.c ca.h \
certs.c certs.h \
connections.c connections.h \
constants.c constants.h \
cookie.c cookie.h \
crl.c crl.h \
crypto.c crypto.h \
db_ops.c db_ops.h \
defs.c defs.h \
demux.c demux.h \
event_queue.c event_queue.h \
fetch.c fetch.h \
foodgroups.c foodgroups.h \
ike_alg.c ike_alg.h \
ipsec_doi.c ipsec_doi.h \
kameipsec.h \
kernel.c kernel.h \
kernel_alg.c kernel_alg.h \
kernel_pfkey.c kernel_pfkey.h \
keys.c keys.h \
lex.c lex.h \
log.c log.h \
myid.c myid.h \
modecfg.c modecfg.h \
nat_traversal.c nat_traversal.h \
ocsp.c ocsp.h \
packet.c packet.h \
pkcs7.c pkcs7.h \
plugin_list.c plugin_list.h \
pluto.c pluto.h \
plutomain.c \
rcv_whack.c rcv_whack.h \
server.c server.h \
smartcard.c smartcard.h \
spdb.c spdb.h \
state.c state.h \
timer.c timer.h \
vendor.c vendor.h \
virtual.c virtual.h \
whack_attribute.c whack_attribute.h \
xauth/xauth_manager.c xauth/xauth_manager.h \
xauth/xauth_provider.h xauth/xauth_verifier.h \
x509.c x509.h \
builder.c builder.h \
rsaref/pkcs11t.h rsaref/pkcs11.h rsaref/unix.h rsaref/pkcs11f.h
if USE_ADNS
pluto_SOURCES += \
dnskey.c dnskey.h
_pluto_adns_SOURCES = \
adns.c adns.h
endif
plutomain.o : $(top_builddir)/config.status
LIBSTRONGSWANDIR=$(top_builddir)/src/libstrongswan
LIBFREESWANDIR=$(top_builddir)/src/libfreeswan
LIBHYDRADIR=$(top_builddir)/src/libhydra
INCLUDES = \
-I${linux_headers} \
-I$(top_srcdir)/src/libstrongswan \
-I$(top_srcdir)/src/libfreeswan \
-I$(top_srcdir)/src/libhydra \
-I$(top_srcdir)/src/whack
AM_CFLAGS = -rdynamic \
-DIPSEC_DIR=\"${ipsecdir}\" \
-DIPSEC_CONFDIR=\"${sysconfdir}\" \
-DIPSEC_PIDDIR=\"${piddir}\" \
-DSHARED_SECRETS_FILE=\"${sysconfdir}/ipsec.secrets\" \
-DPLUGINS=\""${pluto_plugins}\"" \
-DPKCS11_DEFAULT_LIB=\"${default_pkcs11}\" \
-DKERNEL26_HAS_KAME_DUPLICATES \
-DPLUTO -DDEBUG
pluto_LDADD = \
$(LIBSTRONGSWANDIR)/libstrongswan.la \
$(LIBFREESWANDIR)/libfreeswan.a \
$(LIBHYDRADIR)/libhydra.la \
-lresolv $(PTHREADLIB) $(DLLIB)
if USE_ADNS
_pluto_adns_LDADD = \
$(LIBFREESWANDIR)/libfreeswan.a \
-lresolv $(DLLIB)
endif
dist_man_MANS = pluto.8
EXTRA_DIST = Android.mk
# compile options
#################
# This compile option activates the sending of a strongSwan VID
if USE_VENDORID
AM_CFLAGS += -DVENDORID
endif
# This compile option activates the sending of the XAUTH VID
if USE_XAUTH_VID
AM_CFLAGS += -DXAUTH_VID
endif
# This compile option activates the support of the Cisco VPN client
if USE_CISCO_QUIRKS
AM_CFLAGS += -DCISCO_QUIRKS
endif
# This compile option activates NAT traversal with IPSec transport mode
if USE_NAT_TRANSPORT
AM_CFLAGS += -DI_KNOW_TRANSPORT_MODE_HAS_SECURITY_CONCERN_BUT_I_WANT_IT
endif
# This compile option activates smartcard support
if USE_SMARTCARD
AM_CFLAGS += -DSMARTCARD
endif
if USE_LIBCAP
pluto_LDADD += -lcap
endif
if USE_THREADS
AM_CFLAGS += -DTHREADS
endif
if USE_ADNS
AM_CFLAGS += -DADNS
endif
# build optional plugins
########################
SUBDIRS = .
if USE_XAUTH
SUBDIRS += plugins/xauth
endif

View File

@ -1,298 +0,0 @@
/* Support of X.509 attribute certificates
* Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
* Copyright (C) 2003 Martin Berner, Lukas Suter
* Copyright (C) 2009 Andreas Steffen
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <sys/stat.h>
#include <time.h>
#include <debug.h>
#include <utils/enumerator.h>
#include <utils/linked_list.h>
#include <credentials/certificates/ac.h>
#include "ac.h"
#include "ca.h"
#include "certs.h"
#include "fetch.h"
#include "log.h"
/**
* Chained list of X.509 attribute certificates
*/
static linked_list_t *acerts = NULL;
/**
* Initialize the linked list of attribute certificates
*/
void ac_initialize(void)
{
acerts = linked_list_create();
}
/**
* Free the linked list of attribute certificates
*/
void ac_finalize(void)
{
if (acerts)
{
acerts->destroy_offset(acerts, offsetof(certificate_t, destroy));
}
}
/**
* Get a X.509 attribute certificate for a given holder
*/
certificate_t* ac_get_cert(identification_t *issuer, chunk_t serial)
{
enumerator_t *enumerator;
certificate_t *cert, *found = NULL;
enumerator = acerts->create_enumerator(acerts);
while (enumerator->enumerate(enumerator, &cert))
{
ac_t *ac = (ac_t*)cert;
if (issuer->equals(issuer, ac->get_holderIssuer(ac)) &&
chunk_equals(serial, ac->get_holderSerial(ac)))
{
found = cert;
break;
}
}
enumerator->destroy(enumerator);
return found;
}
/**
* Verifies a X.509 attribute certificate
*/
bool ac_verify_cert(certificate_t *cert, bool strict)
{
ac_t *ac = (ac_t*)cert;
identification_t *subject = cert->get_subject(cert);
identification_t *issuer = cert->get_issuer(cert);
chunk_t authKeyID = ac->get_authKeyIdentifier(ac);
cert_t *aacert;
time_t notBefore, valid_until;
DBG1(DBG_LIB, "holder: '%Y'", subject);
DBG1(DBG_LIB, "issuer: '%Y'", issuer);
if (!cert->get_validity(cert, NULL, NULL, &valid_until))
{
DBG1(DBG_LIB, "attribute certificate is invalid (valid from %T to %T)",
&notBefore, FALSE, &valid_until, FALSE);
return FALSE;
}
DBG1(DBG_LIB, "attribute certificate is valid until %T", &valid_until,
FALSE);
lock_authcert_list("verify_x509acert");
aacert = get_authcert(issuer, authKeyID, X509_AA);
unlock_authcert_list("verify_x509acert");
if (aacert == NULL)
{
DBG1(DBG_LIB, "issuer aacert not found");
return FALSE;
}
DBG2(DBG_LIB, "issuer aacert found");
if (!cert->issued_by(cert, aacert->cert))
{
DBG1(DBG_LIB, "attribute certificate signature is invalid");
return FALSE;
}
DBG1(DBG_LIB, "attribute certificate signature is valid");
return verify_x509cert(aacert, strict, &valid_until);
}
/**
* Add a X.509 attribute certificate to the chained list
*/
static void ac_add_cert(certificate_t *cert)
{
ac_t *ac = (ac_t*)cert;
identification_t *hIssuer = ac->get_holderIssuer(ac);
chunk_t hSerial = ac->get_holderSerial(ac);
enumerator_t *enumerator;
certificate_t *cert_old;
enumerator = acerts->create_enumerator(acerts);
while (enumerator->enumerate(enumerator, &cert_old))
{
ac_t *ac_old = (ac_t*)cert_old;
if (hIssuer->equals(hIssuer, ac_old->get_holderIssuer(ac_old)) &&
chunk_equals(hSerial, ac_old->get_holderSerial(ac_old)))
{
if (certificate_is_newer(cert, cert_old))
{
acerts->remove_at(acerts, enumerator);
cert_old->destroy(cert_old);
}
else
{
cert->destroy(cert);
cert = NULL;
}
break;
}
}
enumerator->destroy(enumerator);
if (cert)
{
acerts->insert_last(acerts, cert);
}
}
/**
* Check if at least one peer attribute matches a connection attribute
*/
bool match_group_membership(ietf_attributes_t *peer_attributes, char *conn,
ietf_attributes_t *conn_attributes)
{
bool match;
if (conn_attributes == NULL)
{
return TRUE;
}
match = conn_attributes->matches(conn_attributes, peer_attributes);
DBG1(DBG_LIB, "%s: peer with attributes '%s' is %sa member of the "
"groups '%s'", conn, peer_attributes->get_string(peer_attributes),
match ? "" : "not ", conn_attributes->get_string(conn_attributes));
return match;
}
/**
* Loads X.509 attribute certificates
*/
void ac_load_certs(void)
{
enumerator_t *enumerator;
struct stat st;
char *file;
DBG1(DBG_LIB, "loading attribute certificates from '%s'", A_CERT_PATH);
enumerator = enumerator_create_directory(A_CERT_PATH);
if (!enumerator)
{
return;
}
while (enumerator->enumerate(enumerator, NULL, &file, &st))
{
certificate_t *cert;
if (!S_ISREG(st.st_mode))
{
/* skip special file */
continue;
}
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_AC,
BUILD_FROM_FILE, file, BUILD_END);
if (cert)
{
DBG1(DBG_LIB, " loaded attribute certificate from '%s'", file);
ac_add_cert(cert);
}
}
enumerator->destroy(enumerator);
}
/**
* List all X.509 attribute certificates in the chained list
*/
void ac_list_certs(bool utc)
{
enumerator_t *enumerator;
certificate_t *cert;
time_t now;
/* determine the current time */
time(&now);
if (acerts->get_count(acerts) > 0)
{
whack_log(RC_COMMENT, " ");
whack_log(RC_COMMENT, "List of X.509 Attribute Certificates:");
}
enumerator = acerts->create_enumerator(acerts);
while (enumerator->enumerate(enumerator, &cert))
{
ac_t *ac = (ac_t*)cert;
identification_t *entityName, *holderIssuer, *issuer;
chunk_t holderSerial, serial, authKeyID;
time_t notBefore, notAfter;
ietf_attributes_t *groups;
whack_log(RC_COMMENT, " ");
entityName = cert->get_subject(cert);
if (entityName)
{
whack_log(RC_COMMENT, " holder: \"%Y\"", entityName);
}
holderIssuer = ac->get_holderIssuer(ac);
if (holderIssuer)
{
whack_log(RC_COMMENT, " hissuer: \"%Y\"", holderIssuer);
}
holderSerial = chunk_skip_zero(ac->get_holderSerial(ac));
if (holderSerial.ptr)
{
whack_log(RC_COMMENT, " hserial: %#B", &holderSerial);
}
groups = ac->get_groups(ac);
if (groups)
{
whack_log(RC_COMMENT, " groups: %s", groups->get_string(groups));
groups->destroy(groups);
}
issuer = cert->get_issuer(cert);
whack_log(RC_COMMENT, " issuer: \"%Y\"", issuer);
serial = chunk_skip_zero(ac->get_serial(ac));
whack_log(RC_COMMENT, " serial: %#B", &serial);
cert->get_validity(cert, &now, &notBefore, &notAfter);
whack_log(RC_COMMENT, " validity: not before %T %s",
&notBefore, utc,
(notBefore < now)?"ok":"fatal (not valid yet)");
whack_log(RC_COMMENT, " not after %T %s", &notAfter, utc,
check_expiry(notAfter, ACERT_WARNING_INTERVAL, TRUE));
authKeyID = ac->get_authKeyIdentifier(ac);
if (authKeyID.ptr)
{
whack_log(RC_COMMENT, " authkey: %#B", &authKeyID);
}
}
enumerator->destroy(enumerator);
}

View File

@ -1,39 +0,0 @@
/* Support of X.509 attribute certificates
* Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
* Copyright (C) 2003 Martin Berner, Lukas Suter
* Copyright (C) 2009 Andreas Steffen
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef _AC_H
#define _AC_H
#include <utils/identification.h>
#include <credentials/certificates/certificate.h>
#include <credentials/ietf_attributes/ietf_attributes.h>
/* access structure for an X.509 attribute certificate */
extern void ac_initialize(void);
extern void ac_finalize(void);
extern void ac_load_certs(void);
extern void ac_list_certs(bool utc);
extern certificate_t* ac_get_cert(identification_t *issuer, chunk_t serial);
extern bool ac_verify_cert(certificate_t *ac, bool strict);
extern bool match_group_membership(ietf_attributes_t *peer_attributes,
char *conn,
ietf_attributes_t *conn_attributes);
#endif /* _AC_H */

View File

@ -1,610 +0,0 @@
/* Pluto Asynchronous DNS Helper Program -- for internal use only!
* Copyright (C) 2002 D. Hugh Redelmeier.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
/* This program executes as multiple processes. The Master process
* receives queries (struct adns_query messages) from Pluto and distributes
* them amongst Worker processes. These Worker processes are created
* by the Master whenever a query arrives and no existing Worker is free.
* At most MAX_WORKERS will be created; after that, the Master will queue
* queries until a Worker becomes free. When a Worker has an answer from
* the resolver, it sends the answer as a struct adns_answer message to the
* Master. The Master then forwards the answer to Pluto, noting that
* the Worker is free to accept another query.
*
* The protocol is simple: Pluto sends a sequence of queries and receives
* a sequence of answers. select(2) is used by Pluto and by the Master
* process to decide when to read, but writes are done without checking
* for readiness. Communications is via pipes. Since only one process
* can write to each pipe, messages will not be interleaved. Fixed length
* records are used for simplicity.
*
* Pluto needs a way to indicate to the Master when to shut down
* and the Master needs to indicate this to each worker. EOF on the pipe
* signifies this.
*
* The interfaces between these components are considered private to
* Pluto. This allows us to get away with less checking. This is a
* reason to use pipes instead of TCP/IP.
*
* Although the code uses plain old UNIX processes, it could be modified
* to use threads. That might reduce resource requirements. It would
* preclude running on systems without thread-safe resolvers.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <netdb.h> /* ??? for h_errno */
#include <freeswan.h>
/* GCC magic! */
#ifdef GCC_LINT
# define UNUSED __attribute__ ((unused))
#else
# define UNUSED /* ignore */
#endif
#include "constants.h"
#include "adns.h" /* needs <resolv.h> */
/* shared by all processes */
static const char *name; /* program name, for messages */
static bool debug = FALSE;
/* Read a variable-length record from a pipe (and no more!).
* First bytes must be a size_t containing the length.
* HES_CONTINUE if record read
* HES_OK if EOF
* HES_IO_ERROR_IN if errno tells the tale.
* Others are errors.
*/
static enum helper_exit_status
read_pipe(int fd, unsigned char *stuff, size_t minlen, size_t maxlen)
{
size_t n = 0;
size_t goal = minlen;
do {
ssize_t m = read(fd, stuff + n, goal - n);
if (m == -1)
{
if (errno != EINTR)
{
syslog(LOG_ERR, "Input error on pipe: %s", strerror(errno));
return HES_IO_ERROR_IN;
}
}
else if (m == 0)
{
return HES_OK; /* treat empty message as EOF */
}
else
{
n += m;
if (n >= sizeof(size_t))
{
goal = *(size_t *)(void *)stuff;
if (goal < minlen || maxlen < goal)
{
if (debug)
fprintf(stderr, "%lu : [%lu, %lu]\n"
, (unsigned long)goal
, (unsigned long)minlen, (unsigned long)maxlen);
return HES_BAD_LEN;
}
}
}
} while (n < goal);
return HES_CONTINUE;
}
/* Write a variable-length record to a pipe.
* First bytes must be a size_t containing the length.
* HES_CONTINUE if record written
* Others are errors.
*/
static enum helper_exit_status
write_pipe(int fd, const unsigned char *stuff)
{
size_t len = *(const size_t *)(const void *)stuff;
size_t n = 0;
do {
ssize_t m = write(fd, stuff + n, len - n);
if (m == -1)
{
/* error, but ignore and retry if EINTR */
if (errno != EINTR)
{
syslog(LOG_ERR, "Output error from master: %s", strerror(errno));
return HES_IO_ERROR_OUT;
}
}
else
{
n += m;
}
} while (n != len);
return HES_CONTINUE;
}
/**************** worker process ****************/
/* The interface in RHL6.x and BIND distribution 8.2.2 are different,
* so we build some of our own :-(
*/
/* Support deprecated interface to allow for older releases of the resolver.
* Fake new interface!
* See resolver(3) bind distribution (should be in RHL6.1, but isn't).
* __RES was 19960801 in RHL6.2, an old resolver.
*/
#if (__RES) <= 19960801
# define OLD_RESOLVER 1
#endif
#ifdef OLD_RESOLVER
# define res_ninit(statp) res_init()
# define res_nquery(statp, dname, class, type, answer, anslen) \
res_query(dname, class, type, answer, anslen)
# define res_nclose(statp) res_close()
static struct __res_state *statp = &_res;
#else /* !OLD_RESOLVER */
static struct __res_state my_res_state /* = { 0 } */;
static res_state statp = &my_res_state;
#endif /* !OLD_RESOLVER */
static int
worker(int qfd, int afd)
{
{
int r = res_ninit(statp);
if (r != 0)
{
syslog(LOG_ERR, "cannot initialize resolver");
return HES_RES_INIT;
}
#ifndef OLD_RESOLVER
statp->options |= RES_ROTATE;
#endif
statp->options |= RES_DEBUG;
}
for (;;)
{
struct adns_query q;
struct adns_answer a;
enum helper_exit_status r = read_pipe(qfd, (unsigned char *)&q
, sizeof(q), sizeof(q));
if (r != HES_CONTINUE)
return r; /* some kind of exit */
if (q.qmagic != ADNS_Q_MAGIC)
{
syslog(LOG_ERR, "error in input from master: bad magic");
return HES_BAD_MAGIC;
}
a.amagic = ADNS_A_MAGIC;
a.serial = q.serial;
a.continuation = NULL;
a.result = res_nquery(statp, q.name_buf, C_IN, q.type, a.ans, sizeof(a.ans));
a.h_errno_val = h_errno;
a.len = offsetof(struct adns_answer, ans) + (a.result < 0? 0 : a.result);
#ifdef DEBUG
if (((q.debugging & IMPAIR_DELAY_ADNS_KEY_ANSWER) && q.type == T_KEY)
|| ((q.debugging & IMPAIR_DELAY_ADNS_TXT_ANSWER) && q.type == T_TXT))
sleep(30); /* delay the answer */
#endif
/* write answer, possibly a bit at a time */
r = write_pipe(afd, (const unsigned char *)&a);
if (r != HES_CONTINUE)
return r; /* some kind of exit */
}
}
/**************** master process ****************/
bool eof_from_pluto = FALSE;
#define PLUTO_QFD 0 /* queries come on stdin */
#define PLUTO_AFD 1 /* answers go out on stdout */
#ifndef MAX_WORKERS
# define MAX_WORKERS 10 /* number of in-flight queries */
#endif
struct worker_info {
int qfd; /* query pipe's file descriptor */
int afd; /* answer pipe's file descriptor */
pid_t pid;
bool busy;
void *continuation; /* of outstanding request */
};
static struct worker_info wi[MAX_WORKERS];
static struct worker_info *wi_roof = wi;
/* request FIFO */
struct query_list {
struct query_list *next;
struct adns_query aq;
};
static struct query_list *oldest_query = NULL;
static struct query_list *newest_query; /* undefined when oldest == NULL */
static struct query_list *free_queries = NULL;
static bool
spawn_worker(void)
{
int qfds[2];
int afds[2];
pid_t p;
if (pipe(qfds) != 0 || pipe(afds) != 0)
{
syslog(LOG_ERR, "pipe(2) failed: %s", strerror(errno));
exit(HES_PIPE);
}
wi_roof->qfd = qfds[1]; /* write end of query pipe */
wi_roof->afd = afds[0]; /* read end of answer pipe */
p = fork();
if (p == -1)
{
/* fork failed: ignore if at least one worker exists */
if (wi_roof == wi)
{
syslog(LOG_ERR, "fork(2) error creating first worker: %s", strerror(errno));
exit(HES_FORK);
}
close(qfds[0]);
close(qfds[1]);
close(afds[0]);
close(afds[1]);
return FALSE;
}
else if (p == 0)
{
/* child */
struct worker_info *w;
close(PLUTO_QFD);
close(PLUTO_AFD);
/* close all master pipes, including ours */
for (w = wi; w <= wi_roof; w++)
{
close(w->qfd);
close(w->afd);
}
exit(worker(qfds[0], afds[1]));
}
else
{
/* parent */
struct worker_info *w = wi_roof++;
w->pid = p;
w->busy = FALSE;
close(qfds[0]);
close(afds[1]);
return TRUE;
}
}
static void
send_eof(struct worker_info *w)
{
pid_t p;
int status;
close(w->qfd);
w->qfd = NULL_FD;
close(w->afd);
w->afd = NULL_FD;
/* reap child */
p = waitpid(w->pid, &status, 0);
/* ignore result -- what could we do with it? */
}
static void
forward_query(struct worker_info *w)
{
struct query_list *q = oldest_query;
if (q == NULL)
{
if (eof_from_pluto)
send_eof(w);
}
else
{
enum helper_exit_status r
= write_pipe(w->qfd, (const unsigned char *) &q->aq);
if (r != HES_CONTINUE)
exit(r);
w->busy = TRUE;
oldest_query = q->next;
q->next = free_queries;
free_queries = q;
}
}
static void
query(void)
{
struct query_list *q = free_queries;
enum helper_exit_status r;
/* find an unused queue entry */
if (q == NULL)
{
q = malloc(sizeof(*q));
if (q == NULL)
{
syslog(LOG_ERR, "malloc(3) failed");
exit(HES_MALLOC);
}
}
else
{
free_queries = q->next;
}
r = read_pipe(PLUTO_QFD, (unsigned char *)&q->aq
, sizeof(q->aq), sizeof(q->aq));
if (r == HES_OK)
{
/* EOF: we're done, except for unanswered queries */
struct worker_info *w;
eof_from_pluto = TRUE;
q->next = free_queries;
free_queries = q;
/* Send bye-bye to unbusy processes.
* Note that if there are queued queries, there won't be
* any non-busy workers.
*/
for (w = wi; w != wi_roof; w++)
if (!w->busy)
send_eof(w);
}
else if (r != HES_CONTINUE)
{
exit(r);
}
else if (q->aq.qmagic != ADNS_Q_MAGIC)
{
syslog(LOG_ERR, "error in query from Pluto: bad magic");
exit(HES_BAD_MAGIC);
}
else
{
struct worker_info *w;
/* got a query */
/* add it to FIFO */
q->next = NULL;
if (oldest_query == NULL)
oldest_query = q;
else
newest_query->next = q;
newest_query = q;
/* See if any worker available */
for (w = wi; ; w++)
{
if (w == wi_roof)
{
/* no free worker */
if (w == wi + MAX_WORKERS)
break; /* no more to be created */
/* make a new one */
if (!spawn_worker())
break; /* cannot create one at this time */
}
if (!w->busy)
{
/* assign first to free worker */
forward_query(w);
break;
}
}
}
return;
}
static void
answer(struct worker_info *w)
{
struct adns_answer a;
enum helper_exit_status r = read_pipe(w->afd, (unsigned char *)&a
, offsetof(struct adns_answer, ans), sizeof(a));
if (r == HES_OK)
{
/* unexpected EOF */
syslog(LOG_ERR, "unexpected EOF from worker");
exit(HES_IO_ERROR_IN);
}
else if (r != HES_CONTINUE)
{
exit(r);
}
else if (a.amagic != ADNS_A_MAGIC)
{
syslog(LOG_ERR, "Input from worker error: bad magic");
exit(HES_BAD_MAGIC);
}
else if (a.continuation != w->continuation)
{
/* answer doesn't match query */
syslog(LOG_ERR, "Input from worker error: continuation mismatch");
exit(HES_SYNC);
}
else
{
/* pass the answer on to Pluto */
enum helper_exit_status r
= write_pipe(PLUTO_AFD, (const unsigned char *) &a);
if (r != HES_CONTINUE)
exit(r);
w->busy = FALSE;
forward_query(w);
}
}
/* assumption: input limited; accept blocking on output */
static int
master(void)
{
for (;;)
{
fd_set readfds;
int maxfd = PLUTO_QFD; /* approximate lower bound */
int ndes = 0;
struct worker_info *w;
FD_ZERO(&readfds);
if (!eof_from_pluto)
{
FD_SET(PLUTO_QFD, &readfds);
ndes++;
}
for (w = wi; w != wi_roof; w++)
{
if (w->busy)
{
FD_SET(w->afd, &readfds);
ndes++;
if (maxfd < w->afd)
maxfd = w->afd;
}
}
if (ndes == 0)
return HES_OK; /* done! */
do {
ndes = select(maxfd + 1, &readfds, NULL, NULL, NULL);
} while (ndes == -1 && errno == EINTR);
if (ndes == -1)
{
syslog(LOG_ERR, "select(2) error: %s", strerror(errno));
exit(HES_IO_ERROR_SELECT);
}
else if (ndes > 0)
{
if (FD_ISSET(PLUTO_QFD, &readfds))
{
query();
ndes--;
}
for (w = wi; ndes > 0 && w != wi_roof; w++)
{
if (w->busy && FD_ISSET(w->afd, &readfds))
{
answer(w);
ndes--;
}
}
}
}
}
/* Not to be invoked by strangers -- user hostile.
* Mandatory args: query-fd answer-fd
* Optional arg: -d, signifying "debug".
*/
static void
adns_usage(const char *fmt, const char *arg)
{
const char **sp = ipsec_copyright_notice();
fprintf(stderr, "INTERNAL TO PLUTO: DO NOT EXECUTE\n");
fprintf(stderr, fmt, arg);
fprintf(stderr, "\nstrongSwan "VERSION"\n");
for (; *sp != NULL; sp++)
fprintf(stderr, "%s\n", *sp);
syslog(LOG_ERR, fmt, arg);
exit(HES_INVOCATION);
}
int
main(int argc UNUSED, char **argv)
{
int i = 1;
name = argv[0];
while (i < argc)
{
if (streq(argv[i], "-d"))
{
i++;
debug = TRUE;
}
else
{
adns_usage("unexpected argument \"%s\"", argv[i]);
/*NOTREACHED*/
}
}
return master();
}

View File

@ -1,78 +0,0 @@
/* Pluto Asynchronous DNS Helper Program's Header
* Copyright (C) 2002 D. Hugh Redelmeier.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef ADNS
/* dummy struct to make compilers happy */
struct adns_query {
};
#else /* rest of file */
/* The interface in RHL6.x and BIND distribution 8.2.2 are different,
* so we build some of our own :-(
*/
# ifndef NS_MAXDNAME
# define NS_MAXDNAME MAXDNAME /* I hope this is long enough for IPv6 */
# endif
# ifndef NS_PACKETSZ
# define NS_PACKETSZ PACKETSZ
# endif
/* protocol version */
#define ADNS_Q_MAGIC (((((('d' << 8) + 'n') << 8) + 's') << 8) + 4)
#define ADNS_A_MAGIC (((((('d' << 8) + 'n') << 8) + 's') << 8) + 128 + 4)
/* note: both struct adns_query and struct adns_answer must start with
* size_t len;
*/
struct adns_query {
size_t len;
unsigned int qmagic;
unsigned long serial;
lset_t debugging; /* only used #ifdef DEBUG, but don't want layout to change */
u_char name_buf[NS_MAXDNAME + 2];
int type; /* T_KEY or T_TXT */
};
struct adns_answer {
size_t len;
unsigned int amagic;
unsigned long serial;
struct adns_continuation *continuation;
int result;
int h_errno_val;
u_char ans[NS_PACKETSZ * 10]; /* very probably bigger than necessary */
};
enum helper_exit_status {
HES_CONTINUE = -1, /* not an exit */
HES_OK = 0, /* all's well that ends well (perhaps EOF) */
HES_INVOCATION, /* improper invocation */
HES_IO_ERROR_SELECT, /* IO error in select() */
HES_MALLOC, /* malloc failed */
HES_IO_ERROR_IN, /* error reading pipe */
HES_IO_ERROR_OUT, /* error reading pipe */
HES_PIPE, /* pipe(2) failed */
HES_SYNC, /* answer from worker doesn't match query */
HES_FORK, /* fork(2) failed */
HES_RES_INIT, /* resolver initialization failed */
HES_BAD_LEN, /* implausible .len field */
HES_BAD_MAGIC, /* .magic field wrong */
};
#endif /* ADNS */

View File

@ -1,683 +0,0 @@
/*
* Algorithm info parsing and creation functions
* Copyright (C) JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
* Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <freeswan.h>
#include <pfkeyv2.h>
#include <utils.h>
#include <utils/lexparser.h>
#include <crypto/diffie_hellman.h>
#include <crypto/transform.h>
#include <crypto/proposal/proposal_keywords.h>
#include "alg_info.h"
#include "constants.h"
#include "defs.h"
#include "log.h"
#include "whack.h"
#include "crypto.h"
#include "kernel_alg.h"
#include "ike_alg.h"
/*
* sadb/ESP aa attrib converters
*/
int alg_info_esp_aa2sadb(int auth)
{
int sadb_aalg = 0;
switch(auth)
{
case AUTH_ALGORITHM_HMAC_MD5:
case AUTH_ALGORITHM_HMAC_SHA1:
sadb_aalg = auth + 1;
break;
default:
sadb_aalg = auth;
}
return sadb_aalg;
}
int alg_info_esp_sadb2aa(int sadb_aalg)
{
int auth = 0;
switch(sadb_aalg)
{
case SADB_AALG_MD5HMAC:
case SADB_AALG_SHA1HMAC:
auth = sadb_aalg - 1;
break;
default:
auth = sadb_aalg;
}
return auth;
}
void alg_info_free(struct alg_info *alg_info)
{
free(alg_info);
}
/*
* Raw add routine: only checks for no duplicates
*/
static void __alg_info_esp_add(struct alg_info_esp *alg_info, int ealg_id,
unsigned ek_bits, int aalg_id, unsigned ak_bits)
{
struct esp_info *esp_info = alg_info->esp;
unsigned cnt = alg_info->alg_info_cnt, i;
/* check for overflows */
passert(cnt < countof(alg_info->esp));
/* dont add duplicates */
for (i = 0; i < cnt; i++)
{
if (esp_info[i].esp_ealg_id == ealg_id
&& (!ek_bits || esp_info[i].esp_ealg_keylen == ek_bits)
&& esp_info[i].esp_aalg_id == aalg_id
&& (!ak_bits || esp_info[i].esp_aalg_keylen == ak_bits))
{
return;
}
}
esp_info[cnt].esp_ealg_id = ealg_id;
esp_info[cnt].esp_ealg_keylen = ek_bits;
esp_info[cnt].esp_aalg_id = aalg_id;
esp_info[cnt].esp_aalg_keylen = ak_bits;
/* sadb values */
esp_info[cnt].encryptalg = ealg_id;
esp_info[cnt].authalg = alg_info_esp_aa2sadb(aalg_id);
alg_info->alg_info_cnt++;
DBG(DBG_CRYPT,
DBG_log("esp alg added: %s_%d/%s, cnt=%d",
enum_show(&esp_transform_names, ealg_id), ek_bits,
enum_show(&auth_alg_names, aalg_id),
alg_info->alg_info_cnt)
)
}
/**
* Returns true if the given alg is an authenticated encryption algorithm
*/
static bool is_authenticated_encryption(int ealg_id)
{
switch (ealg_id)
{
case ESP_AES_CCM_8:
case ESP_AES_CCM_12:
case ESP_AES_CCM_16:
case ESP_AES_GCM_8:
case ESP_AES_GCM_12:
case ESP_AES_GCM_16:
case ESP_AES_GMAC:
return TRUE;
}
return FALSE;
}
/*
* Add ESP alg info _with_ logic (policy):
*/
static void alg_info_esp_add(struct alg_info *alg_info, int ealg_id,
int ek_bits, int aalg_id, int ak_bits)
{
/* Policy: default to 3DES */
if (ealg_id == 0)
{
ealg_id = ESP_3DES;
}
if (ealg_id > 0)
{
if (is_authenticated_encryption(ealg_id))
{
__alg_info_esp_add((struct alg_info_esp *)alg_info,
ealg_id, ek_bits,
AUTH_ALGORITHM_NONE, 0);
}
else if (aalg_id > 0)
{
__alg_info_esp_add((struct alg_info_esp *)alg_info,
ealg_id, ek_bits,
aalg_id, ak_bits);
}
else
{
/* Policy: default to SHA-1 and MD5 */
__alg_info_esp_add((struct alg_info_esp *)alg_info,
ealg_id, ek_bits,
AUTH_ALGORITHM_HMAC_SHA1, ak_bits);
__alg_info_esp_add((struct alg_info_esp *)alg_info,
ealg_id, ek_bits,
AUTH_ALGORITHM_HMAC_MD5, ak_bits);
}
}
}
static void __alg_info_ike_add (struct alg_info_ike *alg_info, int ealg_id,
unsigned ek_bits, int aalg_id, unsigned ak_bits,
int modp_id)
{
struct ike_info *ike_info = alg_info->ike;
unsigned cnt = alg_info->alg_info_cnt;
unsigned i;
/* check for overflows */
passert(cnt < countof(alg_info->ike));
/* dont add duplicates */
for (i = 0; i < cnt; i++)
{
if (ike_info[i].ike_ealg == ealg_id
&& (!ek_bits || ike_info[i].ike_eklen == ek_bits)
&& ike_info[i].ike_halg == aalg_id
&& (!ak_bits || ike_info[i].ike_hklen == ak_bits)
&& ike_info[i].ike_modp==modp_id)
return;
}
ike_info[cnt].ike_ealg = ealg_id;
ike_info[cnt].ike_eklen = ek_bits;
ike_info[cnt].ike_halg = aalg_id;
ike_info[cnt].ike_hklen = ak_bits;
ike_info[cnt].ike_modp = modp_id;
alg_info->alg_info_cnt++;
DBG(DBG_CRYPT,
DBG_log("ikg alg added: %s_%d/%s/%s, cnt=%d",
enum_show(&oakley_enc_names, ealg_id), ek_bits,
enum_show(&oakley_hash_names, aalg_id),
enum_show(&oakley_group_names, modp_id),
alg_info->alg_info_cnt)
)
}
/*
* Proposals will be built by looping over default_ike_groups array and
* merging alg_info (ike_info) contents
*/
static int default_ike_groups[] = {
MODP_1536_BIT,
MODP_1024_BIT
};
/*
* Add IKE alg info _with_ logic (policy):
*/
static void alg_info_ike_add (struct alg_info *alg_info, int ealg_id,
int ek_bits, int aalg_id, int ak_bits, int modp_id)
{
int i = 0;
int n_groups = countof(default_ike_groups);
/* if specified modp_id avoid loop over default_ike_groups */
if (modp_id)
{
n_groups=0;
goto in_loop;
}
for (; n_groups--; i++)
{
modp_id = default_ike_groups[i];
in_loop:
/* Policy: default to 3DES */
if (ealg_id == 0)
{
ealg_id = OAKLEY_3DES_CBC;
}
if (ealg_id > 0)
{
if (aalg_id > 0)
{
__alg_info_ike_add((struct alg_info_ike *)alg_info,
ealg_id, ek_bits,
aalg_id, ak_bits,
modp_id);
}
else
{
/* Policy: default to MD5 and SHA */
__alg_info_ike_add((struct alg_info_ike *)alg_info,
ealg_id, ek_bits,
OAKLEY_MD5, ak_bits,
modp_id);
__alg_info_ike_add((struct alg_info_ike *)alg_info,
ealg_id, ek_bits,
OAKLEY_SHA, ak_bits,
modp_id);
}
}
}
}
static status_t alg_info_add(chunk_t alg, unsigned protoid,
int *ealg, size_t *ealg_keysize,
int *aalg, size_t *aalg_keysize, int *dh_group)
{
const proposal_token_t *token = proposal_get_token(alg.ptr, alg.len);
if (token == NULL)
{
return FAILED;
}
switch (token->type)
{
case ENCRYPTION_ALGORITHM:
if (*ealg != 0)
{
return FAILED;
}
*ealg = (protoid == PROTO_ISAKMP) ?
oakley_from_encryption_algorithm(token->algorithm) :
esp_from_encryption_algorithm(token->algorithm);
if (*ealg == 0)
{
return FAILED;
}
*ealg_keysize = token->keysize;
break;
case INTEGRITY_ALGORITHM:
if (*aalg != 0)
{
return FAILED;
}
*aalg = (protoid == PROTO_ISAKMP) ?
oakley_from_integrity_algorithm(token->algorithm) :
esp_from_integrity_algorithm(token->algorithm);
if (*aalg == 0)
{
return FAILED;
}
*aalg_keysize = token->keysize;
break;
case DIFFIE_HELLMAN_GROUP:
if (protoid == PROTO_ISAKMP)
{
if (*dh_group != 0)
{
return FAILED;
}
*dh_group = token->algorithm;
}
break;
default:
return FAILED;
}
return SUCCESS;
}
static status_t alg_info_parse_str(struct alg_info *alg_info, char *alg_str)
{
char *strict, *single;
status_t status = SUCCESS;
strict = alg_str + strlen(alg_str) - 1;
if (*strict == '!')
{
alg_info->alg_info_flags |= ALG_INFO_F_STRICT;
*strict = '\0';
}
while ((single = strsep(&alg_str, ",")))
{
chunk_t string = { (u_char *)single, strlen(single) };
int ealg = 0;
int aalg = 0;
int dh_group = 0;
size_t ealg_keysize = 0;
size_t aalg_keysize = 0;
eat_whitespace(&string);
if (string.len > 0)
{
chunk_t alg;
/* get all token, separated by '-' */
while (extract_token(&alg, '-', &string))
{
status |= alg_info_add(alg, alg_info->alg_info_protoid,
&ealg, &ealg_keysize,
&aalg, &aalg_keysize, &dh_group);
}
if (string.len)
{
status |= alg_info_add(string, alg_info->alg_info_protoid,
&ealg, &ealg_keysize,
&aalg, &aalg_keysize, &dh_group);
}
}
if (status == SUCCESS)
{
switch (alg_info->alg_info_protoid)
{
case PROTO_IPSEC_ESP:
alg_info_esp_add(alg_info, ealg, ealg_keysize,
aalg, aalg_keysize);
break;
case PROTO_ISAKMP:
alg_info_ike_add(alg_info, ealg, ealg_keysize,
aalg, aalg_keysize,
dh_group);
break;
default:
break;
}
}
}
return status;
}
struct alg_info_esp *alg_info_esp_create_from_str(char *alg_str)
{
struct alg_info_esp *alg_info_esp;
char esp_buf[BUF_LEN];
char *pfs_name;
status_t status = SUCCESS;
/*
* alg_info storage should be sized dynamically
* but this may require 2passes to know
* transform count in advance.
*/
alg_info_esp = malloc_thing (struct alg_info_esp);
zero(alg_info_esp);
pfs_name=strchr(alg_str, ';');
if (pfs_name)
{
memcpy(esp_buf, alg_str, pfs_name-alg_str);
esp_buf[pfs_name-alg_str] = 0;
alg_str = esp_buf;
pfs_name++;
/* if pfs strings AND first char is not '0' */
if (*pfs_name && pfs_name[0] != '0')
{
const proposal_token_t *token;
token = proposal_get_token(pfs_name, strlen(pfs_name));
if (token == NULL || token->type != DIFFIE_HELLMAN_GROUP)
{
/* Bomb if pfsgroup not found */
DBG(DBG_CRYPT,
DBG_log("alg_info_esp_create_from_str(): pfsgroup \"%s\" not found"
, pfs_name)
)
status = FAILED;
goto out;
}
alg_info_esp->esp_pfsgroup = token->algorithm;
}
}
else
{
alg_info_esp->esp_pfsgroup = 0;
}
alg_info_esp->alg_info_protoid = PROTO_IPSEC_ESP;
status = alg_info_parse_str((struct alg_info *)alg_info_esp, alg_str);
out:
if (status == SUCCESS)
{
alg_info_esp->ref_cnt = 1;
return alg_info_esp;
}
else
{
free(alg_info_esp);
return NULL;
}
}
struct alg_info_ike *alg_info_ike_create_from_str(char *alg_str)
{
struct alg_info_ike *alg_info_ike;
/*
* alg_info storage should be sized dynamically
* but this may require 2passes to know
* transform count in advance.
*/
alg_info_ike = malloc_thing (struct alg_info_ike);
zero(alg_info_ike);
alg_info_ike->alg_info_protoid = PROTO_ISAKMP;
if (alg_info_parse_str((struct alg_info *)alg_info_ike, alg_str) == SUCCESS)
{
alg_info_ike->ref_cnt = 1;
return alg_info_ike;
}
else
{
free(alg_info_ike);
return NULL;
}
}
/*
* alg_info struct can be shared by
* several connections instances,
* handle free() with ref_cnts
*/
void
alg_info_addref(struct alg_info *alg_info)
{
if (alg_info != NULL)
{
alg_info->ref_cnt++;
}
}
void
alg_info_delref(struct alg_info **alg_info_p)
{
struct alg_info *alg_info = *alg_info_p;
if (alg_info != NULL)
{
passert(alg_info->ref_cnt != 0);
alg_info->ref_cnt--;
if (alg_info->ref_cnt == 0)
{
alg_info_free(alg_info);
}
*alg_info_p = NULL;
}
}
/* snprint already parsed transform list (alg_info) */
int
alg_info_snprint(char *buf, int buflen, struct alg_info *alg_info)
{
char *ptr = buf;
int np = 0;
struct esp_info *esp_info;
struct ike_info *ike_info;
int cnt;
switch (alg_info->alg_info_protoid) {
case PROTO_IPSEC_ESP:
{
struct alg_info_esp *alg_info_esp = (struct alg_info_esp *)alg_info;
ALG_INFO_ESP_FOREACH(alg_info_esp, esp_info, cnt)
{
np = snprintf(ptr, buflen, "%s",
enum_show(&esp_transform_names, esp_info->esp_ealg_id));
ptr += np;
buflen -= np;
if (esp_info->esp_ealg_keylen)
{
np = snprintf(ptr, buflen, "_%zu", esp_info->esp_ealg_keylen);
ptr += np;
buflen -= np;
}
np = snprintf(ptr, buflen, "/%s, ",
enum_show(&auth_alg_names, esp_info->esp_aalg_id));
ptr += np;
buflen -= np;
if (buflen < 0)
goto out;
}
if (alg_info_esp->esp_pfsgroup)
{
np = snprintf(ptr, buflen, "; pfsgroup=%s; ",
enum_show(&oakley_group_names, alg_info_esp->esp_pfsgroup));
ptr += np;
buflen -= np;
if (buflen < 0)
goto out;
}
break;
}
case PROTO_ISAKMP:
ALG_INFO_IKE_FOREACH((struct alg_info_ike *)alg_info, ike_info, cnt)
{
np = snprintf(ptr, buflen, "%s",
enum_show(&oakley_enc_names, ike_info->ike_ealg));
ptr += np;
buflen -= np;
if (ike_info->ike_eklen)
{
np = snprintf(ptr, buflen, "_%zu", ike_info->ike_eklen);
ptr += np;
buflen -= np;
}
np = snprintf(ptr, buflen, "/%s/%s, ",
enum_show(&oakley_hash_names, ike_info->ike_halg),
enum_show(&oakley_group_names, ike_info->ike_modp));
ptr += np;
buflen -= np;
if (buflen < 0)
goto out;
}
break;
default:
np = snprintf(buf, buflen, "INVALID protoid=%d\n"
, alg_info->alg_info_protoid);
ptr += np;
buflen -= np;
goto out;
}
np = snprintf(ptr, buflen, "%s"
, alg_info->alg_info_flags & ALG_INFO_F_STRICT?
"strict":"");
ptr += np;
buflen -= np;
out:
if (buflen < 0)
{
loglog(RC_LOG_SERIOUS
, "buffer space exhausted in alg_info_snprint_ike(), buflen=%d"
, buflen);
}
return ptr - buf;
}
int alg_info_snprint_esp(char *buf, int buflen, struct alg_info_esp *alg_info)
{
char *ptr = buf;
int cnt = alg_info->alg_info_cnt;
struct esp_info *esp_info = alg_info->esp;
while (cnt--)
{
if (kernel_alg_esp_enc_ok(esp_info->esp_ealg_id, 0, NULL)
&& kernel_alg_esp_auth_ok(esp_info->esp_aalg_id, NULL))
{
u_int eklen = (esp_info->esp_ealg_keylen)
? esp_info->esp_ealg_keylen
: kernel_alg_esp_enc_keylen(esp_info->esp_ealg_id)
* BITS_PER_BYTE;
u_int aklen = esp_info->esp_aalg_keylen
? esp_info->esp_aalg_keylen
: kernel_alg_esp_auth_keylen(esp_info->esp_aalg_id)
* BITS_PER_BYTE;
int ret = snprintf(ptr, buflen, "%d_%03d-%d_%03d, ",
esp_info->esp_ealg_id, eklen,
esp_info->esp_aalg_id, aklen);
ptr += ret;
buflen -= ret;
if (buflen < 0)
break;
}
esp_info++;
}
return ptr - buf;
}
int alg_info_snprint_ike(char *buf, int buflen, struct alg_info_ike *alg_info)
{
char *ptr = buf;
int cnt = alg_info->alg_info_cnt;
struct ike_info *ike_info = alg_info->ike;
while (cnt--)
{
struct encrypt_desc *enc_desc = ike_alg_get_crypter(ike_info->ike_ealg);
struct hash_desc *hash_desc = ike_alg_get_hasher(ike_info->ike_halg);
struct dh_desc *dh_desc = ike_alg_get_dh_group(ike_info->ike_modp);
if (enc_desc && hash_desc && dh_desc)
{
u_int eklen = (ike_info->ike_eklen)
? ike_info->ike_eklen
: enc_desc->keydeflen;
u_int aklen = (ike_info->ike_hklen)
? ike_info->ike_hklen
: hash_desc->hash_digest_size * BITS_PER_BYTE;
int ret = snprintf(ptr, buflen, "%d_%03d-%d_%03d-%d, ",
ike_info->ike_ealg, eklen,
ike_info->ike_halg, aklen,
ike_info->ike_modp);
ptr += ret;
buflen -= ret;
if (buflen < 0)
break;
}
ike_info++;
}
return ptr - buf;
}

View File

@ -1,80 +0,0 @@
/* Algorithm info parsing and creation functions
* Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef ALG_INFO_H
#define ALG_INFO_H
struct esp_info {
u_int8_t transid; /* ESP transform */
u_int16_t auth; /* AUTH */
size_t enckeylen; /* keylength for ESP transform */
size_t authkeylen; /* keylength for AUTH */
u_int8_t encryptalg; /* normally encryptalg=transid */
u_int8_t authalg; /* normally authalg=auth+1 */
};
struct ike_info {
u_int16_t ike_ealg; /* high 16 bit nums for reserved */
u_int8_t ike_halg;
size_t ike_eklen;
size_t ike_hklen;
u_int16_t ike_modp;
};
#define ALG_INFO_COMMON \
int alg_info_cnt; \
int ref_cnt; \
unsigned alg_info_flags; \
unsigned alg_info_protoid
struct alg_info {
ALG_INFO_COMMON;
};
struct alg_info_esp {
ALG_INFO_COMMON;
struct esp_info esp[64];
int esp_pfsgroup;
};
struct alg_info_ike {
ALG_INFO_COMMON;
struct ike_info ike[64];
};
#define esp_ealg_id transid
#define esp_aalg_id auth
#define esp_ealg_keylen enckeylen /* bits */
#define esp_aalg_keylen authkeylen /* bits */
/* alg_info_flags bits */
#define ALG_INFO_F_STRICT 0x01
extern int alg_info_esp_aa2sadb(int auth);
extern int alg_info_esp_sadb2aa(int sadb_aalg);
extern void alg_info_free(struct alg_info *alg_info);
extern void alg_info_addref(struct alg_info *alg_info);
extern void alg_info_delref(struct alg_info **alg_info);
extern struct alg_info_esp* alg_info_esp_create_from_str(char *alg_str);
extern struct alg_info_ike* alg_info_ike_create_from_str(char *alg_str);
extern int alg_info_parse(const char *str);
extern int alg_info_snprint(char *buf, int buflen, struct alg_info *alg_info);
extern int alg_info_snprint_esp(char *buf, int buflen
, struct alg_info_esp *alg_info);
extern int alg_info_snprint_ike(char *buf, int buflen
, struct alg_info_ike *alg_info);
#define ALG_INFO_ESP_FOREACH(ai, ai_esp, i) \
for (i=(ai)->alg_info_cnt,ai_esp=(ai)->esp; i--; ai_esp++)
#define ALG_INFO_IKE_FOREACH(ai, ai_ike, i) \
for (i=(ai)->alg_info_cnt,ai_ike=(ai)->ike; i--; ai_ike++)
#endif /* ALG_INFO_H */

View File

@ -1,150 +0,0 @@
/* Pluto certificate/CRL/AC builder hooks.
* Copyright (C) 2002-2009 Andreas Steffen
* Copyright (C) 2009 Martin Willi
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include "builder.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <freeswan.h>
#include <library.h>
#include <credentials/certificates/certificate.h>
#include "constants.h"
#include "defs.h"
#include "log.h"
#include "certs.h"
#include "crl.h"
/**
* Load a certificate
*/
static cert_t *builder_load_cert(certificate_type_t type, va_list args)
{
x509_flag_t flags = 0;
chunk_t blob = chunk_empty;
bool pgp = FALSE;
while (TRUE)
{
switch (va_arg(args, builder_part_t))
{
case BUILD_BLOB_PGP:
pgp = TRUE;
/* FALL */
case BUILD_BLOB_ASN1_DER:
blob = va_arg(args, chunk_t);
continue;
case BUILD_X509_FLAG:
flags |= va_arg(args, x509_flag_t);
continue;
case BUILD_END:
break;
default:
return NULL;
}
break;
}
if (blob.ptr)
{
cert_t *cert = malloc_thing(cert_t);
*cert = cert_empty;
if (pgp)
{
cert->cert = lib->creds->create(lib->creds,
CRED_CERTIFICATE, CERT_GPG,
BUILD_BLOB_PGP, blob,
BUILD_END);
}
else
{
cert->cert = lib->creds->create(lib->creds,
CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_ASN1_DER, blob,
BUILD_X509_FLAG, flags,
BUILD_END);
}
if (cert->cert)
{
return cert;
}
plog(" error in X.509 certificate");
cert_free(cert);
}
return NULL;
}
/**
* Load a CRL
*/
static x509crl_t *builder_load_crl(certificate_type_t type, va_list args)
{
chunk_t blob = chunk_empty;
x509crl_t *crl;
while (TRUE)
{
switch (va_arg(args, builder_part_t))
{
case BUILD_BLOB_ASN1_DER:
blob = va_arg(args, chunk_t);
continue;
case BUILD_END:
break;
default:
return NULL;
}
break;
}
if (blob.ptr)
{
crl = malloc_thing(x509crl_t);
crl->next = NULL;
crl->distributionPoints = linked_list_create();
crl->crl = lib->creds->create(lib->creds,
CRED_CERTIFICATE, CERT_X509_CRL,
BUILD_BLOB_ASN1_DER, blob,
BUILD_END);
if (crl->crl)
{
return crl;
}
plog(" error in X.509 crl");
free_crl(crl);
}
return NULL;
}
void init_builder(void)
{
lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_CERT, FALSE,
(builder_function_t)builder_load_cert);
lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_CRL, FALSE,
(builder_function_t)builder_load_crl);
}
void free_builder(void)
{
lib->creds->remove_builder(lib->creds, (builder_function_t)builder_load_cert);
lib->creds->remove_builder(lib->creds, (builder_function_t)builder_load_crl);
}

View File

@ -1,24 +0,0 @@
/* Pluto certificate/CRL/AC builder hooks.
* Copyright (C) 2009 Martin Willi
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef _BUILDER_H
#define _BUILDER_H
/* register credential builder hooks */
extern void init_builder();
/* unregister credential builder hooks */
extern void free_builder();
#endif /* _BUILDER_H */

View File

@ -1,712 +0,0 @@
/* Certification Authority (CA) support for IKE authentication
* Copyright (C) 2002-2004 Andreas Steffen, Zuercher Hochschule Winterthur
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <debug.h>
#include <utils/enumerator.h>
#include <credentials/certificates/x509.h>
#include <freeswan.h>
#include "constants.h"
#include "defs.h"
#include "log.h"
#include "x509.h"
#include "ca.h"
#include "certs.h"
#include "whack.h"
#include "fetch.h"
#include "smartcard.h"
/* chained list of X.509 authority certificates (ca, aa, and ocsp) */
static cert_t *x509authcerts = NULL;
/* chained list of X.509 certification authority information records */
static ca_info_t *ca_infos = NULL;
/*
* Checks if CA a is trusted by CA b
*/
bool trusted_ca(identification_t *a, identification_t *b, int *pathlen)
{
bool match = FALSE;
/* no CA b specified -> any CA a is accepted */
if (b == NULL)
{
*pathlen = (a == NULL) ? 0 : X509_MAX_PATH_LEN;
return TRUE;
}
/* no CA a specified -> trust cannot be established */
if (a == NULL)
{
*pathlen = X509_MAX_PATH_LEN;
return FALSE;
}
*pathlen = 0;
/* CA a equals CA b -> we have a match */
if (a->equals(a, b))
{
return TRUE;
}
/* CA a might be a subordinate CA of b */
lock_authcert_list("trusted_ca");
while ((*pathlen)++ < X509_MAX_PATH_LEN)
{
certificate_t *certificate;
identification_t *issuer;
cert_t *cacert;
cacert = get_authcert(a, chunk_empty, X509_CA);
if (cacert == NULL)
{
break;
}
certificate = cacert->cert;
/* is the certificate self-signed? */
{
x509_t *x509 = (x509_t*)certificate;
if (x509->get_flags(x509) & X509_SELF_SIGNED)
{
break;
}
}
/* does the issuer of CA a match CA b? */
issuer = certificate->get_issuer(certificate);
match = b->equals(b, issuer);
/* we have a match and exit the loop */
if (match)
{
break;
}
/* go one level up in the CA chain */
a = issuer;
}
unlock_authcert_list("trusted_ca");
return match;
}
/*
* does our CA match one of the requested CAs?
*/
bool match_requested_ca(linked_list_t *requested_ca, identification_t *our_ca,
int *our_pathlen)
{
identification_t *ca;
enumerator_t *enumerator;
/* if no ca is requested than any ca will match */
if (requested_ca == NULL || requested_ca->get_count(requested_ca) == 0)
{
*our_pathlen = 0;
return TRUE;
}
*our_pathlen = X509_MAX_PATH_LEN + 1;
enumerator = requested_ca->create_enumerator(requested_ca);
while (enumerator->enumerate(enumerator, &ca))
{
int pathlen;
if (trusted_ca(our_ca, ca, &pathlen) && pathlen < *our_pathlen)
{
*our_pathlen = pathlen;
}
}
enumerator->destroy(enumerator);
if (*our_pathlen > X509_MAX_PATH_LEN)
{
*our_pathlen = X509_MAX_PATH_LEN;
return FALSE;
}
else
{
return TRUE;
}
}
/*
* free the first authority certificate in the chain
*/
static void free_first_authcert(void)
{
cert_t *first = x509authcerts;
x509authcerts = first->next;
cert_free(first);
}
/*
* free all CA certificates
*/
void free_authcerts(void)
{
lock_authcert_list("free_authcerts");
while (x509authcerts != NULL)
{
free_first_authcert();
}
unlock_authcert_list("free_authcerts");
}
/*
* get a X.509 authority certificate with a given subject or keyid
*/
cert_t* get_authcert(identification_t *subject, chunk_t keyid,
x509_flag_t auth_flags)
{
cert_t *cert, *prev_cert = NULL;
/* the authority certificate list is empty */
if (x509authcerts == NULL)
{
return NULL;
}
for (cert = x509authcerts; cert != NULL; prev_cert = cert, cert = cert->next)
{
certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate;
/* skip non-matching types of authority certificates */
if (!(x509->get_flags(x509) & auth_flags))
{
continue;
}
/* compare the keyid with the certificate's subjectKeyIdentifier */
if (keyid.ptr)
{
chunk_t subjectKeyId;
subjectKeyId = x509->get_subjectKeyIdentifier(x509);
if (subjectKeyId.ptr && !chunk_equals(keyid, subjectKeyId))
{
continue;
}
}
/* compare the subjectDistinguishedNames */
if (!(subject && certificate->has_subject(certificate, subject)) &&
(subject || !keyid.ptr))
{
continue;
}
/* found the authcert */
if (cert != x509authcerts)
{
/* bring the certificate up front */
prev_cert->next = cert->next;
cert->next = x509authcerts;
x509authcerts = cert;
}
return cert;
}
return NULL;
}
/*
* add an authority certificate to the chained list
*/
cert_t* add_authcert(cert_t *cert, x509_flag_t auth_flags)
{
certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate;
cert_t *old_cert;
lock_authcert_list("add_authcert");
old_cert = get_authcert(certificate->get_subject(certificate),
x509->get_subjectKeyIdentifier(x509),
auth_flags);
if (old_cert)
{
if (certificate->equals(certificate, old_cert->cert))
{
DBG(DBG_CONTROL | DBG_PARSING ,
DBG_log(" authcert is already present and identical")
)
unlock_authcert_list("add_authcert");
cert_free(cert);
return old_cert;
}
else
{
/* cert is already present but will be replaced by new cert */
free_first_authcert();
DBG(DBG_CONTROL | DBG_PARSING ,
DBG_log(" existing authcert deleted")
)
}
}
/* add new authcert to chained list */
cert->next = x509authcerts;
x509authcerts = cert;
cert_share(cert); /* set count to one */
DBG(DBG_CONTROL | DBG_PARSING,
DBG_log(" authcert inserted")
)
unlock_authcert_list("add_authcert");
return cert;
}
/*
* Loads authority certificates
*/
void load_authcerts(char *type, char *path, x509_flag_t auth_flags)
{
enumerator_t *enumerator;
struct stat st;
char *file;
DBG1(DBG_LIB, "loading %s certificates from '%s'", type, path);
enumerator = enumerator_create_directory(path);
if (!enumerator)
{
DBG1(DBG_LIB, " reading directory '%s' failed", path);
return;
}
while (enumerator->enumerate(enumerator, NULL, &file, &st))
{
cert_t *cert;
if (!S_ISREG(st.st_mode))
{
/* skip special file */
continue;
}
cert = load_cert(file, type, auth_flags);
if (cert)
{
add_authcert(cert, auth_flags);
}
}
enumerator->destroy(enumerator);
}
/*
* list all X.509 authcerts with given auth flags in a chained list
*/
void list_authcerts(const char *caption, x509_flag_t auth_flags, bool utc)
{
lock_authcert_list("list_authcerts");
list_x509cert_chain(caption, x509authcerts, auth_flags, utc);
unlock_authcert_list("list_authcerts");
}
/*
* get a cacert with a given subject or keyid from an alternative list
*/
static const cert_t* get_alt_cacert(identification_t *subject, chunk_t keyid,
const cert_t *cert)
{
if (cert == NULL)
{
return NULL;
}
for (; cert != NULL; cert = cert->next)
{
certificate_t *certificate = cert->cert;
/* compare the keyid with the certificate's subjectKeyIdentifier */
if (keyid.ptr)
{
x509_t *x509 = (x509_t*)certificate;
chunk_t subjectKeyId;
subjectKeyId = x509->get_subjectKeyIdentifier(x509);
if (subjectKeyId.ptr && !chunk_equals(keyid, subjectKeyId))
{
continue;
}
}
/* compare the subjectDistinguishedNames */
if (!certificate->has_subject(certificate, subject))
{
continue;
}
/* we found the cacert */
return cert;
}
return NULL;
}
/* establish trust into a candidate authcert by going up the trust chain.
* validity and revocation status are not checked.
*/
bool trust_authcert_candidate(const cert_t *cert, const cert_t *alt_chain)
{
int pathlen;
lock_authcert_list("trust_authcert_candidate");
for (pathlen = 0; pathlen < X509_MAX_PATH_LEN; pathlen++)
{
certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate;
identification_t *subject = certificate->get_subject(certificate);
identification_t *issuer = certificate->get_issuer(certificate);
chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
const cert_t *authcert = NULL;
DBG(DBG_CONTROL,
DBG_log("subject: '%Y'", subject);
DBG_log("issuer: '%Y'", issuer);
if (authKeyID.ptr != NULL)
{
DBG_log("authkey: %#B", &authKeyID);
}
)
/* search in alternative chain first */
authcert = get_alt_cacert(issuer, authKeyID, alt_chain);
if (authcert != NULL)
{
DBG(DBG_CONTROL,
DBG_log("issuer cacert found in alternative chain")
)
}
else
{
/* search in trusted chain */
authcert = get_authcert(issuer, authKeyID, X509_CA);
if (authcert != NULL)
{
DBG(DBG_CONTROL,
DBG_log("issuer cacert found")
)
}
else
{
plog("issuer cacert not found");
unlock_authcert_list("trust_authcert_candidate");
return FALSE;
}
}
if (!certificate->issued_by(certificate, authcert->cert))
{
plog("certificate signature is invalid");
unlock_authcert_list("trust_authcert_candidate");
return FALSE;
}
DBG(DBG_CONTROL,
DBG_log("certificate signature is valid")
)
/* check if cert is a self-signed root ca */
if (pathlen > 0 && (x509->get_flags(x509) & X509_SELF_SIGNED))
{
DBG(DBG_CONTROL,
DBG_log("reached self-signed root ca")
)
unlock_authcert_list("trust_authcert_candidate");
return TRUE;
}
/* go up one step in the trust chain */
cert = authcert;
}
plog("maximum ca path length of %d levels exceeded", X509_MAX_PATH_LEN);
unlock_authcert_list("trust_authcert_candidate");
return FALSE;
}
/*
* get a CA info record with a given authName or authKeyID
*/
ca_info_t* get_ca_info(identification_t *name, chunk_t keyid)
{
ca_info_t *ca= ca_infos;
while (ca != NULL)
{
if ((keyid.ptr) ? same_keyid(keyid, ca->authKeyID)
: name->equals(name, ca->authName))
{
return ca;
}
ca = ca->next;
}
return NULL;
}
/*
* free the dynamic memory used by a ca_info record
*/
static void
free_ca_info(ca_info_t* ca_info)
{
if (ca_info == NULL)
{
return;
}
ca_info->crluris->destroy_function(ca_info->crluris, free);
DESTROY_IF(ca_info->authName);
free(ca_info->name);
free(ca_info->ldaphost);
free(ca_info->ldapbase);
free(ca_info->ocspuri);
free(ca_info->authKeyID.ptr);
free(ca_info);
}
/*
* free all CA certificates
*/
void free_ca_infos(void)
{
while (ca_infos != NULL)
{
ca_info_t *ca = ca_infos;
ca_infos = ca_infos->next;
free_ca_info(ca);
}
}
/*
* find a CA information record by name and optionally delete it
*/
bool find_ca_info_by_name(const char *name, bool delete)
{
ca_info_t **ca_p = &ca_infos;
ca_info_t *ca = *ca_p;
while (ca != NULL)
{
/* is there already an entry? */
if (streq(name, ca->name))
{
if (delete)
{
lock_ca_info_list("find_ca_info_by_name");
*ca_p = ca->next;
free_ca_info(ca);
plog("deleting ca description \"%s\"", name);
unlock_ca_info_list("find_ca_info_by_name");
}
return TRUE;
}
ca_p = &ca->next;
ca = *ca_p;
}
return FALSE;
}
/*
* Create an empty ca_info_t record
*/
ca_info_t* create_ca_info(void)
{
ca_info_t *ca_info = malloc_thing(ca_info_t);
memset(ca_info, 0, sizeof(ca_info_t));
ca_info->crluris = linked_list_create();
return ca_info;
}
/**
* Adds a CA description to a chained list
*/
void add_ca_info(const whack_message_t *msg)
{
smartcard_t *sc = NULL;
cert_t *cert = NULL;
bool cached_cert = FALSE;
if (find_ca_info_by_name(msg->name, FALSE))
{
loglog(RC_DUPNAME, "attempt to redefine ca record \"%s\"", msg->name);
return;
}
if (scx_on_smartcard(msg->cacert))
{
/* load CA cert from smartcard */
cert = scx_load_cert(msg->cacert, &sc, &cached_cert);
}
else
{
/* load CA cert from file */
cert = load_ca_cert(msg->cacert);
}
if (cert)
{
certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate;
identification_t *subject = certificate->get_subject(certificate);
chunk_t subjectKeyID = x509->get_subjectKeyIdentifier(x509);
ca_info_t *ca = NULL;
/* does the authname already exist? */
ca = get_ca_info(subject, subjectKeyID);
if (ca != NULL)
{
/* ca_info is already present */
loglog(RC_DUPNAME, " duplicate ca information in record \"%s\" found,"
"ignoring \"%s\"", ca->name, msg->name);
cert_free(cert);
return;
}
plog("added ca description \"%s\"", msg->name);
/* create and initialize new ca_info record */
ca = create_ca_info();
/* name */
ca->name = clone_str(msg->name);
/* authName */
ca->authName = subject->clone(subject);
DBG(DBG_CONTROL,
DBG_log("authname: '%Y'", subject)
)
/* authKeyID */
if (subjectKeyID.ptr)
{
ca->authKeyID = chunk_clone(subjectKeyID);
DBG(DBG_CONTROL | DBG_PARSING ,
DBG_log("authkey: %#B", &subjectKeyID)
)
}
/* ldaphost */
ca->ldaphost = clone_str(msg->ldaphost);
/* ldapbase */
ca->ldapbase = clone_str(msg->ldapbase);
/* ocspuri */
if (msg->ocspuri != NULL)
{
if (strncasecmp(msg->ocspuri, "http", 4) == 0)
ca->ocspuri = clone_str(msg->ocspuri);
else
plog(" ignoring ocspuri with unknown protocol");
}
/* add crl uris */
add_distribution_point(ca->crluris, msg->crluri);
add_distribution_point(ca->crluris, msg->crluri2);
/* strictrlpolicy */
ca->strictcrlpolicy = msg->whack_strict;
/* insert ca_info record into the chained list */
lock_ca_info_list("add_ca_info");
ca->next = ca_infos;
ca_infos = ca;
unlock_ca_info_list("add_ca_info");
/* add cacert to list of authcerts */
cert = add_authcert(cert, X509_CA);
if (!cached_cert && sc != NULL)
{
if (sc->last_cert != NULL)
{
sc->last_cert->count--;
}
sc->last_cert = cert;
cert_share(sc->last_cert);
}
if (sc != NULL)
time(&sc->last_load);
}
}
/*
* list all ca_info records in the chained list
*/
void list_ca_infos(bool utc)
{
ca_info_t *ca = ca_infos;
if (ca != NULL)
{
whack_log(RC_COMMENT, " ");
whack_log(RC_COMMENT, "List of X.509 CA Information Records:");
}
while (ca != NULL)
{
/* strictpolicy per CA not supported yet
*
whack_log(RC_COMMENT, "%T, \"%s\", strictcrlpolicy: %s"
, &ca->installed, utc, ca->name
, ca->strictcrlpolicy? "yes":"no");
*/
whack_log(RC_COMMENT, " ");
whack_log(RC_COMMENT, " authname: \"%Y\"", ca->authName);
if (ca->ldaphost)
{
whack_log(RC_COMMENT, " ldaphost: '%s'", ca->ldaphost);
}
if (ca->ldapbase)
{
whack_log(RC_COMMENT, " ldapbase: '%s'", ca->ldapbase);
}
if (ca->ocspuri)
{
whack_log(RC_COMMENT, " ocspuri: '%s'", ca->ocspuri);
}
list_distribution_points(ca->crluris);
if (ca->authKeyID.ptr)
{
whack_log(RC_COMMENT, " authkey: %#B", &ca->authKeyID);
}
ca = ca->next;
}
}

View File

@ -1,58 +0,0 @@
/* Certification Authority (CA) support for IKE authentication
* Copyright (C) 2002-2004 Andreas Steffen, Zuercher Hochschule Winterthur
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef _CA_H
#define _CA_H
#include <utils/linked_list.h>
#include <utils/identification.h>
#include "certs.h"
#include "whack.h"
/* CA info structures */
typedef struct ca_info ca_info_t;
struct ca_info {
ca_info_t *next;
char *name;
identification_t *authName;
chunk_t authKeyID;
char *ldaphost;
char *ldapbase;
char *ocspuri;
linked_list_t *crluris;
bool strictcrlpolicy;
};
extern bool trusted_ca(identification_t *a, identification_t *b, int *pathlen);
extern bool match_requested_ca(linked_list_t *requested_ca,
identification_t *our_ca, int *our_pathlen);
extern cert_t* get_authcert(identification_t *subject, chunk_t keyid,
x509_flag_t auth_flags);
extern void load_authcerts(char *type, char *path, x509_flag_t auth_flags);
extern cert_t* add_authcert(cert_t *cert, x509_flag_t auth_flags);
extern void free_authcerts(void);
extern void list_authcerts(const char *caption, x509_flag_t auth_flags, bool utc);
extern bool trust_authcert_candidate(const cert_t *cert, const cert_t *alt_chain);
extern ca_info_t* get_ca_info(identification_t *name, chunk_t keyid);
extern bool find_ca_info_by_name(const char *name, bool delete);
extern void add_ca_info(const whack_message_t *msg);
extern void delete_ca_info(const char *name);
extern void free_ca_infos(void);
extern void list_ca_infos(bool utc);
#endif /* _CA_H */

View File

@ -1,268 +0,0 @@
/* Certificate support for IKE authentication
* Copyright (C) 2002-2009 Andreas Steffen
*
* HSR - Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <freeswan.h>
#include <library.h>
#include <asn1/asn1.h>
#include <credentials/certificates/certificate.h>
#include <credentials/certificates/pgp_certificate.h>
#include "constants.h"
#include "defs.h"
#include "log.h"
#include "certs.h"
#include "whack.h"
#include "fetch.h"
#include "keys.h"
#include "builder.h"
/**
* Initialization
*/
const cert_t cert_empty = {
NULL , /* cert */
NULL , /* *next */
0 , /* count */
FALSE /* smartcard */
};
/**
* Chained lists of X.509 and PGP end entity certificates
*/
static cert_t *certs = NULL;
/**
* Free a pluto certificate
*/
void cert_free(cert_t *cert)
{
if (cert)
{
certificate_t *certificate = cert->cert;
if (certificate)
{
certificate->destroy(certificate);
}
free(cert);
}
}
/**
* Add a pluto end entity certificate to the chained list
*/
cert_t* cert_add(cert_t *cert)
{
certificate_t *certificate = cert->cert;
cert_t *c;
lock_certs_and_keys("cert_add");
for (c = certs; c != NULL; c = c->next)
{
if (certificate->equals(certificate, c->cert))
{ /* already in chain, free cert */
unlock_certs_and_keys("cert_add");
cert_free(cert);
return c;
}
}
/* insert new cert at the root of the chain */
cert->next = certs;
certs = cert;
DBG(DBG_CONTROL | DBG_PARSING,
DBG_log(" cert inserted")
)
unlock_certs_and_keys("cert_add");
return cert;
}
/**
* Loads a X.509 or OpenPGP certificate
*/
cert_t* load_cert(char *filename, const char *label, x509_flag_t flags)
{
cert_t *cert;
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_CERT,
BUILD_FROM_FILE, filename,
BUILD_X509_FLAG, flags,
BUILD_END);
if (cert)
{
plog(" loaded %s certificate from '%s'", label, filename);
}
return cert;
}
/**
* Loads a host certificate
*/
cert_t* load_host_cert(char *filename)
{
char *path = concatenate_paths(HOST_CERT_PATH, filename);
return load_cert(path, "host", X509_NONE);
}
/**
* Loads a CA certificate
*/
cert_t* load_ca_cert(char *filename)
{
char *path = concatenate_paths(CA_CERT_PATH, filename);
return load_cert(path, "CA", X509_NONE);
}
/**
* for each link pointing to the certificate increase the count by one
*/
void cert_share(cert_t *cert)
{
if (cert != NULL)
{
cert->count++;
}
}
/* release of a certificate decreases the count by one
* the certificate is freed when the counter reaches zero
*/
void cert_release(cert_t *cert)
{
if (cert && --cert->count == 0)
{
cert_t **pp = &certs;
while (*pp != cert)
{
pp = &(*pp)->next;
}
*pp = cert->next;
cert_free(cert);
}
}
/**
* Get a X.509 certificate with a given issuer found at a certain position
*/
cert_t* get_x509cert(identification_t *issuer, chunk_t keyid, cert_t *chain)
{
cert_t *cert = chain ? chain->next : certs;
while (cert)
{
certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate;
chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
if (keyid.ptr ? same_keyid(keyid, authKeyID) :
certificate->has_issuer(certificate, issuer))
{
return cert;
}
cert = cert->next;
}
return NULL;
}
/**
* List all PGP end certificates in a chained list
*/
void list_pgp_end_certs(bool utc)
{
cert_t *cert = certs;
time_t now = time(NULL);
bool first = TRUE;
while (cert != NULL)
{
certificate_t *certificate = cert->cert;
if (certificate->get_type(certificate) == CERT_GPG)
{
time_t created, until;
public_key_t *key;
identification_t *userid = certificate->get_subject(certificate);
pgp_certificate_t *pgp_cert = (pgp_certificate_t*)certificate;
chunk_t fingerprint = pgp_cert->get_fingerprint(pgp_cert);
if (first)
{
whack_log(RC_COMMENT, " ");
whack_log(RC_COMMENT, "List of PGP End Entity Certificates:");
first = false;
}
whack_log(RC_COMMENT, " ");
whack_log(RC_COMMENT, " userid: '%Y'", userid);
whack_log(RC_COMMENT, " digest: %#B", &fingerprint);
/* list validity */
certificate->get_validity(certificate, &now, &created, &until);
whack_log(RC_COMMENT, " created: %T", &created, utc);
whack_log(RC_COMMENT, " until: %T %s%s", &until, utc,
check_expiry(until, CA_CERT_WARNING_INTERVAL, TRUE),
(until == TIME_32_BIT_SIGNED_MAX) ? " (expires never)":"");
key = certificate->get_public_key(certificate);
if (key)
{
chunk_t keyid;
whack_log(RC_COMMENT, " pubkey: %N %4d bits%s",
key_type_names, key->get_type(key),
key->get_keysize(key),
has_private_key(cert)? ", has private key" : "");
if (key->get_fingerprint(key, KEYID_PUBKEY_INFO_SHA1, &keyid))
{
whack_log(RC_COMMENT, " keyid: %#B", &keyid);
}
if (key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &keyid))
{
whack_log(RC_COMMENT, " subjkey: %#B", &keyid);
}
}
}
cert = cert->next;
}
}
/**
* List all X.509 end certificates in a chained list
*/
void list_x509_end_certs(bool utc)
{
list_x509cert_chain("End Entity", certs, X509_NONE, utc);
}
/**
* list all X.509 and OpenPGP end certificates
*/
void cert_list(bool utc)
{
list_x509_end_certs(utc);
list_pgp_end_certs(utc);
}

View File

@ -1,80 +0,0 @@
/* Certificate support for IKE authentication
* Copyright (C) 2002-2009 Andreas Steffen
*
* HSR - Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef _CERTS_H
#define _CERTS_H
#include <credentials/keys/private_key.h>
#include <credentials/certificates/certificate.h>
#include <credentials/certificates/x509.h>
#include <freeswan.h>
#include "defs.h"
/* path definitions for private keys, end certs,
* cacerts, attribute certs and crls
*/
#define PRIVATE_KEY_PATH IPSEC_CONFDIR "/ipsec.d/private"
#define HOST_CERT_PATH IPSEC_CONFDIR "/ipsec.d/certs"
#define CA_CERT_PATH IPSEC_CONFDIR "/ipsec.d/cacerts"
#define A_CERT_PATH IPSEC_CONFDIR "/ipsec.d/acerts"
#define AA_CERT_PATH IPSEC_CONFDIR "/ipsec.d/aacerts"
#define OCSP_CERT_PATH IPSEC_CONFDIR "/ipsec.d/ocspcerts"
#define CRL_PATH IPSEC_CONFDIR "/ipsec.d/crls"
#define REQ_PATH IPSEC_CONFDIR "/ipsec.d/reqs"
/* advance warning of imminent expiry of
* cacerts, public keys, and crls
*/
#define CA_CERT_WARNING_INTERVAL 30 /* days */
#define OCSP_CERT_WARNING_INTERVAL 30 /* days */
#define PUBKEY_WARNING_INTERVAL 7 /* days */
#define CRL_WARNING_INTERVAL 7 /* days */
#define ACERT_WARNING_INTERVAL 1 /* day */
/* access structure for a pluto certificate */
typedef struct cert_t cert_t;
struct cert_t {
certificate_t *cert;
cert_t *next;
int count;
bool smartcard;
};
/* used for initialization */
extern const cert_t cert_empty;
/* do not send certificate requests
* flag set in plutomain.c and used in ipsec_doi.c
*/
extern bool no_cr_send;
extern cert_t* load_cert(char *filename, const char *label, x509_flag_t flags);
extern cert_t* load_host_cert(char *filename);
extern cert_t* load_ca_cert(char *filename);
extern cert_t* cert_add(cert_t *cert);
extern void cert_free(cert_t *cert);
extern void cert_share(cert_t *cert);
extern void cert_release(cert_t *cert);
extern void cert_list(bool utc);
extern cert_t* get_x509cert(identification_t *issuer, chunk_t keyid, cert_t* chain);
#endif /* _CERTS_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,366 +0,0 @@
/* information about connections between hosts and clients
* Copyright (C) 1998-2001 D. Hugh Redelmeier
* Copyright (C) 2009-2010 Andreas Steffen - Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef _CONNECTIONS_H
#define _CONNECTIONS_H
#include <sys/queue.h>
#include <utils/host.h>
#include <utils/linked_list.h>
#include <utils/identification.h>
#include <credentials/ietf_attributes/ietf_attributes.h>
#include "certs.h"
#include "smartcard.h"
#include "whack.h"
/* There are two kinds of connections:
* - ISAKMP connections, between hosts (for IKE communication)
* - IPsec connections, between clients (for secure IP communication)
*
* An ISAKMP connection looks like:
* host<--->host
*
* An IPsec connection looks like:
* client-subnet<-->host<->nexthop<--->nexthop<->host<-->client-subnet
*
* For the connection to be relevant to this instance of Pluto,
* exactly one of the hosts must be a public interface of our machine
* known to this instance.
*
* The client subnet might simply be the host -- this is a
* representation of "host mode".
*
* Each nexthop defaults to the neighbouring host's IP address.
* The nexthop is a property of the pair of hosts, not each
* individually. It is only needed for IPsec because of the
* way IPsec is mixed into the kernel routing logic. Furthermore,
* only this end's nexthop is actually used. Eventually, nexthop
* will be unnecessary.
*
* Other information represented:
* - each connection has a name: a chunk of uninterpreted text
* that is unique for each connection.
* - security requirements (currently just the "policy" flags from
* the whack command to initiate the connection, but eventually
* much more. Different for ISAKMP and IPsec connections.
* - rekeying parameters:
* + time an SA may live
* + time before SA death that a rekeying should be attempted
* (only by the initiator)
* + number of times to attempt rekeying
* - With the current KLIPS, we must route packets for a client
* subnet through the ipsec interface (ipsec0). Only one
* gateway can get traffic for a specific (client) subnet.
* Furthermore, if the routing isn't in place, packets will
* be sent in the clear.
* "routing" indicates whether the routing has been done for
* this connection. Note that several connections may claim
* the same routing, as long as they agree about where the
* packets are to be sent.
* - With the current KLIPS, only one outbound IPsec SA bundle can be
* used for a particular client. This is due to a limitation
* of using only routing for selection. So only one IPsec state (SA)
* may "own" the eroute. "eroute_owner" is the serial number of
* this state, SOS_NOBODY if there is none. "routing" indicates
* what kind of erouting has been done for this connection, if any.
*
* Details on routing is in constants.h
*
* Operations on Connections:
*
* - add a new connection (with all details) [whack command]
* - delete a connection (by name) [whack command]
* - initiate a connection (by name) [whack command]
* - find a connection (by IP addresses of hosts)
* [response to peer request; finding ISAKMP connection for IPsec connection]
*
* Some connections are templates, missing the address of the peer
* (represented by INADDR_ANY). These are always arranged so that the
* missing end is "that" (there can only be one missing end). These can
* be instantiated (turned into real connections) by Pluto in one of two
* different ways: Road Warrior Instantiation or Opportunistic
* Instantiation. A template connection is marked for Opportunistic
* Instantiation by specifying the peer client as 0.0.0.0/32 (or the IPV6
* equivalent). Otherwise, it is suitable for Road Warrior Instantiation.
*
* Instantiation creates a new temporary connection, with the missing
* details filled in. The resulting template lasts only as long as there
* is a state that uses it.
*/
/* connection policy priority: how important this policy is
* - used to implement eroute-like precedence (augmented by a small
* bonus for a routed connection).
* - a whole number
* - larger is more important
* - three subcomponents. In order of decreasing significance:
* + length of source subnet mask (8 bits)
* + length of destination subnet mask (8 bits)
* + bias (8 bit)
* - a bias of 1 is added to allow prio BOTTOM_PRIO to be less than all
* normal priorities
* - other bias values are created on the fly to give mild preference
* to certaion conditions (eg. routedness)
* - priority is inherited -- an instance of a policy has the same priority
* as the original policy, even though its subnets might be smaller.
* - display format: n,m
*/
typedef unsigned long policy_prio_t;
#define BOTTOM_PRIO ((policy_prio_t)0) /* smaller than any real prio */
#define set_policy_prio(c) { (c)->prio = \
((policy_prio_t)(c)->spd.this.client.maskbits << 16) \
| ((policy_prio_t)(c)->spd.that.client.maskbits << 8) \
| (policy_prio_t)1; }
#define POLICY_PRIO_BUF (3+1+3+1)
extern void fmt_policy_prio(policy_prio_t pp, char buf[POLICY_PRIO_BUF]);
struct virtual_t;
struct end {
identification_t *id;
ip_address host_addr, host_nexthop;
host_t *host_srcip;
ip_subnet client;
bool is_left;
bool key_from_DNS_on_demand;
bool has_client;
bool has_client_wildcard;
bool has_port_wildcard;
bool has_id_wildcards;
bool has_natip;
char *updown;
u_int16_t host_port; /* host order */
u_int16_t port; /* host order */
u_int8_t protocol;
cert_t *cert; /* end certificate */
identification_t *ca; /* CA distinguished name */
ietf_attributes_t *groups; /* access control groups */
smartcard_t *sc; /* smartcard reader and key info */
struct virtual_t *virt;
bool modecfg; /* this end: request local address from server */
/* that end: give local addresses to clients */
char *pool; /* name of an associated virtual IP address pool */
bool hostaccess; /* allow access to host via iptables INPUT/OUTPUT */
/* rules if client behind host is a subnet */
bool allow_any; /* IP address is subject to change */
certpolicy_t sendcert; /* whether or not to send the certificate */
};
struct spd_route {
struct spd_route *next;
struct end this;
struct end that;
so_serial_t eroute_owner;
enum routing_t routing; /* level of routing in place */
uint32_t reqid;
mark_t mark_in;
mark_t mark_out;
};
typedef struct connection connection_t;
struct connection {
char *name;
bool ikev1;
lset_t policy;
time_t sa_ike_life_seconds;
time_t sa_ipsec_life_seconds;
time_t sa_rekey_margin;
unsigned long sa_rekey_fuzz;
unsigned long sa_keying_tries;
identification_t *xauth_identity; /* XAUTH identity */
/* RFC 3706 DPD */
time_t dpd_delay;
time_t dpd_timeout;
dpd_action_t dpd_action;
char *log_file_name; /* name of log file */
FILE *log_file; /* possibly open FILE */
TAILQ_ENTRY(connection) log_link; /* linked list of open conns */
bool log_file_err; /* only bitch once */
struct spd_route spd;
/* internal fields: */
unsigned long instance_serial;
policy_prio_t prio;
bool instance_initiation_ok; /* this is an instance of a policy that mandates initiate */
enum connection_kind kind;
const struct iface *interface; /* filled in iff oriented */
so_serial_t /* state object serial number */
newest_isakmp_sa,
newest_ipsec_sa;
#ifdef DEBUG
lset_t extra_debugging;
#endif
/* note: if the client is the gateway, the following must be equal */
sa_family_t addr_family; /* between gateways */
sa_family_t tunnel_addr_family; /* between clients */
connection_t *policy_next; /* if multiple policies,
next one to apply */
struct gw_info *gw_info;
struct alg_info_esp *alg_info_esp;
struct alg_info_ike *alg_info_ike;
struct host_pair *host_pair;
connection_t *hp_next; /* host pair list link */
connection_t *ac_next; /* all connections list link */
linked_list_t *requested_ca; /* collected certificate requests */
linked_list_t *requested; /* requested attributes with handlers */
linked_list_t *attributes; /* configuration attributes with handlers */
bool got_certrequest;
};
#define oriented(c) ((c).interface != NULL)
extern bool orient(connection_t *c);
extern bool same_peer_ids(const connection_t *c, const connection_t *d,
identification_t *his_id);
/* Format the topology of a connection end, leaving out defaults.
* Largest left end looks like: client === host : port [ host_id ] --- hop
* Note: if that==NULL, skip nexthop
*/
#define END_BUF (SUBNETTOT_BUF + ADDRTOT_BUF + IDTOA_BUF + ADDRTOT_BUF + 10)
extern size_t format_end(char *buf, size_t buf_len, const struct end *this,
const struct end *that, bool is_left, lset_t policy);
extern void add_connection(const whack_message_t *wm);
extern void initiate_connection(const char *name, int whackfd);
extern void initiate_opportunistic(const ip_address *our_client,
const ip_address *peer_client,
int transport_proto, bool held, int whackfd);
extern void terminate_connection(const char *nm);
extern void release_connection(connection_t *c, bool relations);
extern void delete_connection(connection_t *c, bool relations);
extern void delete_connections_by_name(const char *name, bool strict);
extern void delete_every_connection(void);
extern char *add_group_instance(connection_t *group, const ip_subnet *target);
extern void remove_group_instance(const connection_t *group, const char *name);
extern void release_dead_interfaces(void);
extern void check_orientations(void);
extern connection_t *route_owner(connection_t *c, struct spd_route **srp,
connection_t **erop, struct spd_route **esrp);
extern connection_t *shunt_owner(const ip_subnet *ours, const ip_subnet *his);
extern bool uniqueIDs; /* --uniqueids? */
extern void ISAKMP_SA_established(connection_t *c, so_serial_t serial);
#define id_is_ipaddr(id) ((id)->get_type(id) == ID_IPV4_ADDR || \
(id)->get_type(id) == ID_IPV6_ADDR)
extern bool his_id_was_instantiated(const connection_t *c);
struct state; /* forward declaration of tag (defined in state.h) */
extern connection_t* con_by_name(const char *nm, bool strict);
extern connection_t* find_host_connection(const ip_address *me,
u_int16_t my_port,
const ip_address *him,
u_int16_t his_port, lset_t policy);
extern connection_t* refine_host_connection(const struct state *st,
identification_t *id,
identification_t *peer_ca);
extern connection_t* find_client_connection(connection_t *c,
const ip_subnet *our_net,
const ip_subnet *peer_net,
const u_int8_t our_protocol,
const u_int16_t out_port,
const u_int8_t peer_protocol,
const u_int16_t peer_port);
extern connection_t* find_connection_by_reqid(uint32_t reqid);
extern connection_t* find_connection_for_clients(struct spd_route **srp,
const ip_address *our_client,
const ip_address *peer_client,
int transport_proto);
extern void get_peer_ca_and_groups(connection_t *c,
identification_t **peer_ca,
ietf_attributes_t **peer_attributes);
/* instantiating routines
* Note: connection_discard() is in state.h because all its work
* is looking through state objects.
*/
struct gw_info; /* forward declaration of tag (defined in dnskey.h) */
struct alg_info; /* forward declaration of tag (defined in alg_info.h) */
extern connection_t *rw_instantiate(connection_t *c,
const ip_address *him,
u_int16_t his_port,
const ip_subnet *his_net,
identification_t *his_id);
extern connection_t *oppo_instantiate(connection_t *c,
const ip_address *him,
identification_t *his_id,
struct gw_info *gw,
const ip_address *our_client,
const ip_address *peer_client);
extern connection_t
*build_outgoing_opportunistic_connection(struct gw_info *gw,
const ip_address *our_client,
const ip_address *peer_client);
#define CONN_INST_BUF BUF_LEN
extern void fmt_conn_instance(const connection_t *c, char buf[CONN_INST_BUF]);
/* operations on "pending", the structure representing Quick Mode
* negotiations delayed until a Keying Channel has been negotiated.
*/
struct pending; /* forward declaration (opaque outside connections.c) */
extern void add_pending(int whack_sock, struct state *isakmp_sa,
connection_t *c, lset_t policy, unsigned long try,
so_serial_t replacing);
extern void release_pending_whacks(struct state *st, err_t story);
extern void unpend(struct state *st);
extern void update_pending(struct state *os, struct state *ns);
extern void flush_pending_by_state(struct state *st);
extern void show_pending_phase2(const struct host_pair *hp, const struct state *st);
extern void connection_discard(connection_t *c);
/* A template connection's eroute can be eclipsed by
* either a %hold or an eroute for an instance iff
* the template is a /32 -> /32. This requires some special casing.
*/
#define eclipsable(sr) (subnetishost(&(sr)->this.client) && subnetishost(&(sr)->that.client))
extern long eclipse_count;
extern connection_t *eclipsed(connection_t *c, struct spd_route **);
/* print connection status */
extern void show_connections_status(bool all, const char *name);
extern int connection_compare(const connection_t *ca
, const connection_t *cb);
extern void update_host_pair(const char *why, connection_t *c
, const ip_address *myaddr, u_int16_t myport
, const ip_address *hisaddr, u_int16_t hisport);
#endif /* _CONNECTIONS_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,73 +0,0 @@
/* cookie generation/verification routines.
* Copyright (C) 1997 Angelos D. Keromytis.
* Copyright (C) 1998-2002 D. Hugh Redelmeier.
* Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <freeswan.h>
#include <library.h>
#include <crypto/rngs/rng.h>
#include "constants.h"
#include "defs.h"
#include "cookie.h"
const u_char zero_cookie[COOKIE_SIZE]; /* guaranteed 0 */
/* Generate a cookie.
* First argument is true if we're to create an Initiator cookie.
* Length SHOULD be a multiple of sizeof(u_int32_t).
*/
void get_cookie(bool initiator, u_int8_t *cookie, int length, ip_address *addr)
{
hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
u_char buffer[HASH_SIZE_SHA1];
do {
if (initiator)
{
rng_t *rng;
rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
rng->get_bytes(rng, length, cookie);
rng->destroy(rng);
}
else /* Responder cookie */
{
chunk_t addr_chunk, secret_chunk, counter_chunk;
size_t addr_len;
static u_int32_t counter = 0;
unsigned char addr_buf[
sizeof(union {struct in_addr A; struct in6_addr B;})];
addr_len = addrbytesof(addr, addr_buf, sizeof(addr_buf));
addr_chunk = chunk_create(addr_buf, addr_len);
secret_chunk = chunk_create(secret_of_the_day, HASH_SIZE_SHA1);
counter++;
counter_chunk = chunk_create((void *) &counter, sizeof(counter));
hasher->get_hash(hasher, addr_chunk, NULL);
hasher->get_hash(hasher, secret_chunk, NULL);
hasher->get_hash(hasher, counter_chunk, buffer);
memcpy(cookie, buffer, length);
}
} while (is_zero_cookie(cookie)); /* probably never loops */
hasher->destroy(hasher);
}

View File

@ -1,22 +0,0 @@
/* cookie generation/verification routines.
* Copyright (C) 1998-2002 D. Hugh Redelmeier.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <freeswan.h>
extern const u_char zero_cookie[COOKIE_SIZE]; /* guaranteed 0 */
extern void get_cookie(bool initiator, u_int8_t *cookie, int length,
ip_address *addr);
#define is_zero_cookie(cookie) all_zero((cookie), COOKIE_SIZE)

View File

@ -1,541 +0,0 @@
/* Support of X.509 certificate revocation lists (CRLs)
* Copyright (C) 2000-2009 Andreas Steffen
*
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <time.h>
#include <sys/types.h>
#include <freeswan.h>
#include "constants.h"
#include "defs.h"
#include "log.h"
#include "x509.h"
#include "crl.h"
#include "ca.h"
#include "certs.h"
#include "keys.h"
#include "whack.h"
#include "fetch.h"
#include "builder.h"
/* chained lists of X.509 crls */
static x509crl_t *x509crls = NULL;
/**
* Get the X.509 CRL with a given issuer
*/
static x509crl_t* get_x509crl(identification_t *issuer, chunk_t keyid)
{
x509crl_t *x509crl = x509crls;
x509crl_t *prev_crl = NULL;
while (x509crl != NULL)
{
certificate_t *cert_crl = x509crl->crl;
crl_t *crl = (crl_t*)cert_crl;
identification_t *crl_issuer = cert_crl->get_issuer(cert_crl);
chunk_t authKeyID = crl->get_authKeyIdentifier(crl);
if ((keyid.ptr && authKeyID.ptr)? same_keyid(keyid, authKeyID) :
issuer->equals(issuer, crl_issuer))
{
if (x509crl != x509crls)
{
/* bring the CRL up front */
prev_crl->next = x509crl->next;
x509crl->next = x509crls;
x509crls = x509crl;
}
return x509crl;
}
prev_crl = x509crl;
x509crl = x509crl->next;
}
return NULL;
}
/**
* Free the dynamic memory used to store CRLs
*/
void free_crl(x509crl_t *crl)
{
DESTROY_IF(crl->crl);
crl->distributionPoints->destroy_function(crl->distributionPoints, free);
free(crl);
}
static void free_first_crl(void)
{
x509crl_t *crl = x509crls;
x509crls = crl->next;
free_crl(crl);
}
void free_crls(void)
{
lock_crl_list("free_crls");
while (x509crls != NULL)
{
free_first_crl();
}
unlock_crl_list("free_crls");
}
/**
* Insert X.509 CRL into chained list
*/
bool insert_crl(x509crl_t *x509crl, char *crl_uri, bool cache_crl)
{
certificate_t *cert_crl = x509crl->crl;
crl_t *crl = (crl_t*)cert_crl;
identification_t *issuer = cert_crl->get_issuer(cert_crl);
chunk_t authKeyID = crl->get_authKeyIdentifier(crl);
cert_t *issuer_cert;
x509crl_t *oldcrl;
time_t now, nextUpdate;
bool valid_sig;
/* add distribution point */
add_distribution_point(x509crl->distributionPoints, crl_uri);
lock_authcert_list("insert_crl");
/* get the issuer cacert */
issuer_cert = get_authcert(issuer, authKeyID, X509_CA);
if (issuer_cert == NULL)
{
plog("crl issuer cacert not found");
free_crl(x509crl);
unlock_authcert_list("insert_crl");
return FALSE;
}
DBG(DBG_CONTROL,
DBG_log("crl issuer cacert found")
)
/* check the issuer's signature of the crl */
valid_sig = cert_crl->issued_by(cert_crl, issuer_cert->cert);
unlock_authcert_list("insert_crl");
if (!valid_sig)
{
free_crl(x509crl);
return FALSE;
}
DBG(DBG_CONTROL,
DBG_log("crl signature is valid")
)
/* note the current time */
time(&now);
lock_crl_list("insert_crl");
oldcrl = get_x509crl(issuer, authKeyID);
if (oldcrl != NULL)
{
certificate_t *old_cert_crl = oldcrl->crl;
if (crl_is_newer((crl_t*)cert_crl, (crl_t*)old_cert_crl))
{
/* keep any known CRL distribution points */
add_distribution_points(x509crl->distributionPoints,
oldcrl->distributionPoints);
/* now delete the old CRL */
free_first_crl();
DBG(DBG_CONTROL,
DBG_log("thisUpdate is newer - existing crl deleted")
)
}
else
{
unlock_crl_list("insert_crls");
DBG(DBG_CONTROL,
DBG_log("thisUpdate is not newer - existing crl not replaced");
)
free_crl(x509crl);
old_cert_crl->get_validity(old_cert_crl, &now, NULL, &nextUpdate);
return nextUpdate - now > 2*crl_check_interval;
}
}
/* insert new CRL */
x509crl->next = x509crls;
x509crls = x509crl;
unlock_crl_list("insert_crl");
/* If crl caching is enabled then the crl is saved locally.
* Only http or ldap URIs are cached but not local file URIs.
* The CRL's authorityKeyIdentifier is used as a unique filename
*/
if (cache_crl && strncasecmp(crl_uri, "file", 4) != 0)
{
char buf[BUF_LEN];
chunk_t hex, encoding;
hex = chunk_to_hex(crl->get_authKeyIdentifier(crl), NULL, FALSE);
snprintf(buf, sizeof(buf), "%s/%s.crl", CRL_PATH, hex.ptr);
free(hex.ptr);
if (cert_crl->get_encoding(cert_crl, CERT_ASN1_DER, &encoding))
{
chunk_write(encoding, buf, "crl", 022, TRUE);
free(encoding.ptr);
}
}
/* is the fetched crl valid? */
cert_crl->get_validity(cert_crl, &now, NULL, &nextUpdate);
return nextUpdate - now > 2*crl_check_interval;
}
/**
* Loads CRLs
*/
void load_crls(void)
{
struct dirent **filelist;
u_char buf[BUF_LEN];
u_char *save_dir;
int n;
/* change directory to specified path */
save_dir = getcwd(buf, BUF_LEN);
if (chdir(CRL_PATH))
{
plog("Could not change to directory '%s'", CRL_PATH);
}
else
{
plog("Changing to directory '%s'", CRL_PATH);
n = scandir(CRL_PATH, &filelist, file_select, alphasort);
if (n < 0)
plog(" scandir() error");
else
{
while (n--)
{
char *filename = filelist[n]->d_name;
x509crl_t *x509crl;
x509crl = lib->creds->create(lib->creds, CRED_CERTIFICATE,
CERT_PLUTO_CRL,
BUILD_FROM_FILE, filename, BUILD_END);
if (x509crl)
{
char crl_uri[BUF_LEN];
plog(" loaded crl from '%s'", filename);
snprintf(crl_uri, BUF_LEN, "file://%s/%s", CRL_PATH, filename);
insert_crl(x509crl, crl_uri, FALSE);
}
free(filelist[n]);
}
free(filelist);
}
}
/* restore directory path */
ignore_result(chdir(save_dir));
}
/* Checks if the current certificate is revoked. It goes through the
* list of revoked certificates of the corresponding crl. Either the
* status CERT_GOOD or CERT_REVOKED is returned
*/
static cert_status_t check_revocation(crl_t *crl, chunk_t cert_serial,
time_t *revocationDate,
crl_reason_t *revocationReason)
{
enumerator_t *enumerator;
cert_status_t status;
chunk_t serial;
DBG(DBG_CONTROL,
DBG_log("serial number: %#B", &cert_serial)
)
*revocationDate = UNDEFINED_TIME;
*revocationReason = CRL_REASON_UNSPECIFIED;
status = CERT_GOOD;
enumerator = crl->create_enumerator(crl);
while (enumerator->enumerate(enumerator, &serial,
revocationDate, revocationReason))
{
if (chunk_equals(serial, cert_serial))
{
status = CERT_REVOKED;
break;
}
}
enumerator->destroy(enumerator);
return status;
}
/*
* check if any crls are about to expire
*/
void check_crls(void)
{
x509crl_t *x509crl;
time_t now, nextUpdate, time_left;
lock_crl_list("check_crls");
time(&now);
x509crl = x509crls;
while (x509crl != NULL)
{
certificate_t *cert_crl = x509crl->crl;
crl_t *crl = (crl_t*)cert_crl;
identification_t *issuer = cert_crl->get_issuer(cert_crl);
chunk_t authKeyID = crl->get_authKeyIdentifier(crl);
cert_crl->get_validity(cert_crl, &now, NULL, &nextUpdate);
time_left = nextUpdate - now;
DBG(DBG_CONTROL,
DBG_log("issuer: '%Y'", issuer);
if (authKeyID.ptr)
{
DBG_log("authkey: %#B", &authKeyID);
}
DBG_log("%ld seconds left", time_left)
)
if (time_left < 2*crl_check_interval)
{
fetch_req_t *req = build_crl_fetch_request(issuer, authKeyID,
x509crl->distributionPoints);
add_crl_fetch_request(req);
}
x509crl = x509crl->next;
}
unlock_crl_list("check_crls");
}
/*
* verify if a cert hasn't been revoked by a crl
*/
cert_status_t verify_by_crl(cert_t *cert, time_t *until, time_t *revocationDate,
crl_reason_t *revocationReason)
{
certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate;
identification_t *issuer = certificate->get_issuer(certificate);
chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
x509crl_t *x509crl;
ca_info_t *ca;
enumerator_t *enumerator;
x509_cdp_t *cdp;
ca = get_ca_info(issuer, authKeyID);
*revocationDate = UNDEFINED_TIME;
*revocationReason = CRL_REASON_UNSPECIFIED;
lock_crl_list("verify_by_crl");
x509crl = get_x509crl(issuer, authKeyID);
if (x509crl == NULL)
{
linked_list_t *crluris;
unlock_crl_list("verify_by_crl");
plog("crl not found");
crluris = linked_list_create();
if (ca)
{
add_distribution_points(crluris, ca->crluris);
}
enumerator = x509->create_crl_uri_enumerator(x509);
while (enumerator->enumerate(enumerator, &cdp))
{
add_distribution_point(crluris, cdp->uri);
}
enumerator->destroy(enumerator);
if (crluris->get_count(crluris) > 0)
{
fetch_req_t *req;
req = build_crl_fetch_request(issuer, authKeyID, crluris);
crluris->destroy_function(crluris, free);
add_crl_fetch_request(req);
wake_fetch_thread("verify_by_crl");
return CERT_UNKNOWN;
}
else
{
crluris->destroy(crluris);
return CERT_UNDEFINED;
}
}
else
{
certificate_t *cert_crl = x509crl->crl;
crl_t *crl = (crl_t*)cert_crl;
chunk_t authKeyID = crl->get_authKeyIdentifier(crl);
cert_t *issuer_cert;
bool trusted, valid;
DBG(DBG_CONTROL,
DBG_log("crl found")
)
if (ca)
{
add_distribution_points(x509crl->distributionPoints, ca->crluris);
}
enumerator = x509->create_crl_uri_enumerator(x509);
while (enumerator->enumerate(enumerator, &cdp))
{
add_distribution_point(x509crl->distributionPoints, cdp->uri);
}
enumerator->destroy(enumerator);
lock_authcert_list("verify_by_crl");
issuer_cert = get_authcert(issuer, authKeyID, X509_CA);
trusted = issuer_cert ? cert_crl->issued_by(cert_crl, issuer_cert->cert)
: FALSE;
unlock_authcert_list("verify_by_crl");
if (trusted)
{
cert_status_t status;
DBG(DBG_CONTROL,
DBG_log("crl signature is valid")
)
/* return the expiration date */
valid = cert_crl->get_validity(cert_crl, NULL, NULL, until);
/* has the certificate been revoked? */
status = check_revocation(crl, x509->get_serial(x509), revocationDate
, revocationReason);
if (valid)
{
unlock_crl_list("verify_by_crl");
DBG(DBG_CONTROL,
DBG_log("crl is valid: until %T", until, FALSE)
)
}
else
{
fetch_req_t *req;
DBG(DBG_CONTROL,
DBG_log("crl is stale: since %T", until, FALSE)
)
/* try to fetch a crl update */
req = build_crl_fetch_request(issuer, authKeyID,
x509crl->distributionPoints);
unlock_crl_list("verify_by_crl");
add_crl_fetch_request(req);
wake_fetch_thread("verify_by_crl");
}
return status;
}
else
{
unlock_crl_list("verify_by_crl");
plog("crl signature is invalid");
return CERT_UNKNOWN;
}
}
}
/*
* list all X.509 crls in the chained list
*/
void list_crls(bool utc, bool strict)
{
x509crl_t *x509crl;
lock_crl_list("list_crls");
x509crl = x509crls;
if (x509crl)
{
whack_log(RC_COMMENT, " ");
whack_log(RC_COMMENT, "List of X.509 CRLs:");
}
while (x509crl)
{
certificate_t *cert_crl = x509crl->crl;
crl_t *crl = (crl_t*)cert_crl;
chunk_t serial, authKeyID;
time_t thisUpdate, nextUpdate;
u_int revoked = 0;
enumerator_t *enumerator;
whack_log(RC_COMMENT, " ");
whack_log(RC_COMMENT, " issuer: \"%Y\"",
cert_crl->get_issuer(cert_crl));
serial = chunk_skip_zero(crl->get_serial(crl));
if (serial.ptr)
{
whack_log(RC_COMMENT, " serial: %#B", &serial);
}
/* count number of revoked certificates in CRL */
enumerator = crl->create_enumerator(crl);
while (enumerator->enumerate(enumerator, NULL, NULL, NULL))
{
revoked++;
}
enumerator->destroy(enumerator);
whack_log(RC_COMMENT, " revoked: %d certificates", revoked);
list_distribution_points(x509crl->distributionPoints);
cert_crl->get_validity(cert_crl, NULL, &thisUpdate, &nextUpdate);
whack_log(RC_COMMENT, " updates: this %T", &thisUpdate, utc);
whack_log(RC_COMMENT, " next %T %s", &nextUpdate, utc,
check_expiry(nextUpdate, CRL_WARNING_INTERVAL, strict));
authKeyID = crl->get_authKeyIdentifier(crl);
if (authKeyID.ptr)
{
whack_log(RC_COMMENT, " authkey: %#B", &authKeyID);
}
x509crl = x509crl->next;
}
unlock_crl_list("list_crls");
}

View File

@ -1,53 +0,0 @@
/* Support of X.509 certificate revocation lists (CRLs)
* Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include "constants.h"
#include <utils/linked_list.h>
#include <credentials/certificates/certificate.h>
#include <credentials/certificates/crl.h>
/* storage structure for an X.509 CRL */
typedef struct x509crl x509crl_t;
struct x509crl {
certificate_t *crl;
x509crl_t *next;
linked_list_t *distributionPoints;
};
/* apply a strict CRL policy
* flag set in plutomain.c and used in ipsec_doi.c and rcv_whack.c
*/
extern bool strict_crl_policy;
/*
* cache the retrieved CRLs by storing them locally as a file
*/
extern bool cache_crls;
/*
* check periodically for expired crls
*/
extern long crl_check_interval;
extern void load_crls(void);
extern void check_crls(void);
extern bool insert_crl(x509crl_t *crl, char *crl_uri, bool cache_crl);
extern cert_status_t verify_by_crl(cert_t *cert, time_t *until,
time_t *revocationDate,
crl_reason_t *revocationReason);
extern void list_crls(bool utc, bool strict);
extern void free_crls(void);
extern void free_crl(x509crl_t *crl);

View File

@ -1,698 +0,0 @@
/* crypto interfaces
*
* Copyright (C) 2010 Tobias Brunner
* Copyright (C) 2007-2009 Andreas Steffen
* Hochschule fuer Technik Rapperswil
*
* Copyright (C) 1998-2001 D. Hugh Redelmeier
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <freeswan.h>
#include "constants.h"
#include "defs.h"
#include "crypto.h"
#include "log.h"
static struct encrypt_desc encrypt_desc_3des =
{
algo_type: IKE_ALG_ENCRYPT,
algo_id: OAKLEY_3DES_CBC,
plugin_name: NULL,
algo_next: NULL,
enc_blocksize: DES_BLOCK_SIZE,
keydeflen: DES_BLOCK_SIZE * 3 * BITS_PER_BYTE,
keyminlen: DES_BLOCK_SIZE * 3 * BITS_PER_BYTE,
keymaxlen: DES_BLOCK_SIZE * 3 * BITS_PER_BYTE,
};
#define AES_KEY_MIN_LEN 128
#define AES_KEY_DEF_LEN 128
#define AES_KEY_MAX_LEN 256
static struct encrypt_desc encrypt_desc_aes =
{
algo_type: IKE_ALG_ENCRYPT,
algo_id: OAKLEY_AES_CBC,
plugin_name: NULL,
algo_next: NULL,
enc_blocksize: AES_BLOCK_SIZE,
keyminlen: AES_KEY_MIN_LEN,
keydeflen: AES_KEY_DEF_LEN,
keymaxlen: AES_KEY_MAX_LEN,
};
#define CAMELLIA_KEY_MIN_LEN 128
#define CAMELLIA_KEY_DEF_LEN 128
#define CAMELLIA_KEY_MAX_LEN 256
static struct encrypt_desc encrypt_desc_camellia =
{
algo_type: IKE_ALG_ENCRYPT,
algo_id: OAKLEY_CAMELLIA_CBC,
plugin_name: NULL,
algo_next: NULL,
enc_blocksize: CAMELLIA_BLOCK_SIZE,
keyminlen: CAMELLIA_KEY_MIN_LEN,
keydeflen: CAMELLIA_KEY_DEF_LEN,
keymaxlen: CAMELLIA_KEY_MAX_LEN,
};
#define BLOWFISH_KEY_MIN_LEN 128
#define BLOWFISH_KEY_MAX_LEN 448
static struct encrypt_desc encrypt_desc_blowfish =
{
algo_type: IKE_ALG_ENCRYPT,
algo_id: OAKLEY_BLOWFISH_CBC,
plugin_name: NULL,
algo_next: NULL,
enc_blocksize: BLOWFISH_BLOCK_SIZE,
keyminlen: BLOWFISH_KEY_MIN_LEN,
keydeflen: BLOWFISH_KEY_MIN_LEN,
keymaxlen: BLOWFISH_KEY_MAX_LEN,
};
#define SERPENT_KEY_MIN_LEN 128
#define SERPENT_KEY_DEF_LEN 128
#define SERPENT_KEY_MAX_LEN 256
static struct encrypt_desc encrypt_desc_serpent =
{
algo_type: IKE_ALG_ENCRYPT,
algo_id: OAKLEY_SERPENT_CBC,
plugin_name: NULL,
algo_next: NULL,
enc_blocksize: SERPENT_BLOCK_SIZE,
keyminlen: SERPENT_KEY_MIN_LEN,
keydeflen: SERPENT_KEY_DEF_LEN,
keymaxlen: SERPENT_KEY_MAX_LEN,
};
#define TWOFISH_KEY_MIN_LEN 128
#define TWOFISH_KEY_DEF_LEN 128
#define TWOFISH_KEY_MAX_LEN 256
static struct encrypt_desc encrypt_desc_twofish =
{
algo_type: IKE_ALG_ENCRYPT,
algo_id: OAKLEY_TWOFISH_CBC,
plugin_name: NULL,
algo_next: NULL,
enc_blocksize: TWOFISH_BLOCK_SIZE,
keydeflen: TWOFISH_KEY_MIN_LEN,
keyminlen: TWOFISH_KEY_DEF_LEN,
keymaxlen: TWOFISH_KEY_MAX_LEN,
};
static struct encrypt_desc encrypt_desc_twofish_ssh =
{
algo_type: IKE_ALG_ENCRYPT,
algo_id: OAKLEY_TWOFISH_CBC_SSH,
plugin_name: NULL,
algo_next: NULL,
enc_blocksize: TWOFISH_BLOCK_SIZE,
keydeflen: TWOFISH_KEY_MIN_LEN,
keyminlen: TWOFISH_KEY_DEF_LEN,
keymaxlen: TWOFISH_KEY_MAX_LEN,
};
static struct hash_desc hash_desc_md5 =
{
algo_type: IKE_ALG_HASH,
algo_id: OAKLEY_MD5,
plugin_name: NULL,
algo_next: NULL,
hash_digest_size: HASH_SIZE_MD5,
};
static struct hash_desc hash_desc_sha1 =
{
algo_type: IKE_ALG_HASH,
algo_id: OAKLEY_SHA,
plugin_name: NULL,
algo_next: NULL,
hash_digest_size: HASH_SIZE_SHA1,
};
static struct hash_desc hash_desc_sha2_256 = {
algo_type: IKE_ALG_HASH,
algo_id: OAKLEY_SHA2_256,
plugin_name: NULL,
algo_next: NULL,
hash_digest_size: HASH_SIZE_SHA256,
};
static struct hash_desc hash_desc_sha2_384 = {
algo_type: IKE_ALG_HASH,
algo_id: OAKLEY_SHA2_384,
plugin_name: NULL,
algo_next: NULL,
hash_digest_size: HASH_SIZE_SHA384,
};
static struct hash_desc hash_desc_sha2_512 = {
algo_type: IKE_ALG_HASH,
algo_id: OAKLEY_SHA2_512,
plugin_name: NULL,
algo_next: NULL,
hash_digest_size: HASH_SIZE_SHA512,
};
const struct dh_desc unset_group = {
algo_type: IKE_ALG_DH_GROUP,
algo_id: MODP_NONE,
plugin_name: NULL,
algo_next: NULL,
ke_size: 0
};
static struct dh_desc dh_desc_modp_1024 = {
algo_type: IKE_ALG_DH_GROUP,
algo_id: MODP_1024_BIT,
plugin_name: NULL,
algo_next: NULL,
ke_size: 1024 / BITS_PER_BYTE
};
static struct dh_desc dh_desc_modp_1536 = {
algo_type: IKE_ALG_DH_GROUP,
algo_id: MODP_1536_BIT,
plugin_name: NULL,
algo_next: NULL,
ke_size: 1536 / BITS_PER_BYTE
};
static struct dh_desc dh_desc_modp_2048 = {
algo_type: IKE_ALG_DH_GROUP,
algo_id: MODP_2048_BIT,
algo_next: NULL,
ke_size: 2048 / BITS_PER_BYTE
};
static struct dh_desc dh_desc_modp_3072 = {
algo_type: IKE_ALG_DH_GROUP,
algo_id: MODP_3072_BIT,
plugin_name: NULL,
algo_next: NULL,
ke_size: 3072 / BITS_PER_BYTE
};
static struct dh_desc dh_desc_modp_4096 = {
algo_type: IKE_ALG_DH_GROUP,
algo_id: MODP_4096_BIT,
plugin_name: NULL,
algo_next: NULL,
ke_size: 4096 / BITS_PER_BYTE
};
static struct dh_desc dh_desc_modp_6144 = {
algo_type: IKE_ALG_DH_GROUP,
algo_id: MODP_6144_BIT,
plugin_name: NULL,
algo_next: NULL,
ke_size: 6144 / BITS_PER_BYTE
};
static struct dh_desc dh_desc_modp_8192 = {
algo_type: IKE_ALG_DH_GROUP,
algo_id: MODP_8192_BIT,
plugin_name: NULL,
algo_next: NULL,
ke_size: 8192 / BITS_PER_BYTE
};
static struct dh_desc dh_desc_ecp_256 = {
algo_type: IKE_ALG_DH_GROUP,
algo_id: ECP_256_BIT,
plugin_name: NULL,
algo_next: NULL,
ke_size: 2*256 / BITS_PER_BYTE
};
static struct dh_desc dh_desc_ecp_384 = {
algo_type: IKE_ALG_DH_GROUP,
algo_id: ECP_384_BIT,
plugin_name: NULL,
algo_next: NULL,
ke_size: 2*384 / BITS_PER_BYTE
};
static struct dh_desc dh_desc_ecp_521 = {
algo_type: IKE_ALG_DH_GROUP,
algo_id: ECP_521_BIT,
plugin_name: NULL,
algo_next: NULL,
ke_size: 2*528 / BITS_PER_BYTE
};
static struct dh_desc dh_desc_modp_1024_160 = {
algo_type: IKE_ALG_DH_GROUP,
algo_id: MODP_1024_160,
plugin_name: NULL,
algo_next: NULL,
ke_size: 1024 / BITS_PER_BYTE
};
static struct dh_desc dh_desc_modp_2048_224 = {
algo_type: IKE_ALG_DH_GROUP,
algo_id: MODP_2048_224,
plugin_name: NULL,
algo_next: NULL,
ke_size: 2048 / BITS_PER_BYTE
};
static struct dh_desc dh_desc_modp_2048_256 = {
algo_type: IKE_ALG_DH_GROUP,
algo_id: MODP_2048_256,
plugin_name: NULL,
algo_next: NULL,
ke_size: 2048 / BITS_PER_BYTE
};
static struct dh_desc dh_desc_ecp_192 = {
algo_type: IKE_ALG_DH_GROUP,
algo_id: ECP_192_BIT,
plugin_name: NULL,
algo_next: NULL,
ke_size: 2*192 / BITS_PER_BYTE
};
static struct dh_desc dh_desc_ecp_224 = {
algo_type: IKE_ALG_DH_GROUP,
algo_id: ECP_224_BIT,
plugin_name: NULL,
algo_next: NULL,
ke_size: 2*224 / BITS_PER_BYTE
};
bool init_crypto(void)
{
enumerator_t *enumerator;
encryption_algorithm_t encryption_alg;
hash_algorithm_t hash_alg;
diffie_hellman_group_t dh_group;
const char *plugin_name;
bool no_md5 = TRUE;
bool no_sha1 = TRUE;
enumerator = lib->crypto->create_hasher_enumerator(lib->crypto);
while (enumerator->enumerate(enumerator, &hash_alg, &plugin_name))
{
const struct hash_desc *desc;
switch (hash_alg)
{
case HASH_SHA1:
desc = &hash_desc_sha1;
no_sha1 = FALSE;
break;
case HASH_SHA256:
desc = &hash_desc_sha2_256;
break;
case HASH_SHA384:
desc = &hash_desc_sha2_384;
break;
case HASH_SHA512:
desc = &hash_desc_sha2_512;
break;
case HASH_MD5:
desc = &hash_desc_md5;
no_md5 = FALSE;
break;
default:
continue;
}
ike_alg_add((struct ike_alg *)desc, plugin_name);
}
enumerator->destroy(enumerator);
if (no_sha1 || no_md5)
{
plog("pluto cannot run without a %s%s%s hasher",
(no_sha1) ? "SHA-1" : "",
(no_sha1 && no_md5) ? " and " : "",
(no_md5) ? "MD5" : "");
return FALSE;
}
enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
while (enumerator->enumerate(enumerator, &encryption_alg, &plugin_name))
{
const struct encrypt_desc *desc;
switch (encryption_alg)
{
case ENCR_3DES:
desc = &encrypt_desc_3des;
break;
case ENCR_BLOWFISH:
desc = &encrypt_desc_blowfish;
break;
case ENCR_AES_CBC:
desc = &encrypt_desc_aes;
break;
case ENCR_CAMELLIA_CBC:
desc = &encrypt_desc_camellia;
break;
case ENCR_TWOFISH_CBC:
desc = &encrypt_desc_twofish;
ike_alg_add((struct ike_alg *)&encrypt_desc_twofish_ssh,
plugin_name);
break;
case ENCR_SERPENT_CBC:
desc = &encrypt_desc_serpent;
break;
default:
continue;
}
ike_alg_add((struct ike_alg *)desc, plugin_name);
}
enumerator->destroy(enumerator);
enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
while (enumerator->enumerate(enumerator, &dh_group, &plugin_name))
{
const struct dh_desc *desc;
switch (dh_group)
{
case MODP_1024_BIT:
desc = &dh_desc_modp_1024;
break;
case MODP_1536_BIT:
desc = &dh_desc_modp_1536;
break;
case MODP_2048_BIT:
desc = &dh_desc_modp_2048;
break;
case MODP_3072_BIT:
desc = &dh_desc_modp_3072;
break;
case MODP_4096_BIT:
desc = &dh_desc_modp_4096;
break;
case MODP_6144_BIT:
desc = &dh_desc_modp_6144;
break;
case MODP_8192_BIT:
desc = &dh_desc_modp_8192;
break;
case ECP_256_BIT:
desc = &dh_desc_ecp_256;
break;
case ECP_384_BIT:
desc = &dh_desc_ecp_384;
break;
case ECP_521_BIT:
desc = &dh_desc_ecp_521;
break;
case MODP_1024_160:
desc = &dh_desc_modp_1024_160;
break;
case MODP_2048_224:
desc = &dh_desc_modp_2048_224;
break;
case MODP_2048_256:
desc = &dh_desc_modp_2048_256;
break;
case ECP_192_BIT:
desc = &dh_desc_ecp_192;
break;
case ECP_224_BIT:
desc = &dh_desc_ecp_224;
break;
default:
continue;
}
ike_alg_add((struct ike_alg *)desc, plugin_name);
}
enumerator->destroy(enumerator);
return TRUE;
}
void free_crypto(void)
{
/* currently nothing to do */
}
/**
* Converts IKEv1 encryption algorithm name to crypter name
*/
encryption_algorithm_t oakley_to_encryption_algorithm(int alg)
{
switch (alg)
{
case OAKLEY_DES_CBC:
return ENCR_DES;
case OAKLEY_IDEA_CBC:
return ENCR_IDEA;
case OAKLEY_BLOWFISH_CBC:
return ENCR_BLOWFISH;
case OAKLEY_RC5_R16_B64_CBC:
return ENCR_RC5;
case OAKLEY_3DES_CBC:
return ENCR_3DES;
case OAKLEY_CAST_CBC:
return ENCR_CAST;
case OAKLEY_AES_CBC:
return ENCR_AES_CBC;
case OAKLEY_CAMELLIA_CBC:
return ENCR_CAMELLIA_CBC;
case OAKLEY_SERPENT_CBC:
return ENCR_SERPENT_CBC;
case OAKLEY_TWOFISH_CBC:
case OAKLEY_TWOFISH_CBC_SSH:
return ENCR_TWOFISH_CBC;
default:
return ENCR_UNDEFINED;
}
}
/**
* Converts IKEv1 hash algorithm name to hasher name
*/
hash_algorithm_t oakley_to_hash_algorithm(int alg)
{
switch (alg)
{
case OAKLEY_MD5:
return HASH_MD5;
case OAKLEY_SHA:
return HASH_SHA1;
case OAKLEY_SHA2_256:
return HASH_SHA256;
case OAKLEY_SHA2_384:
return HASH_SHA384;
case OAKLEY_SHA2_512:
return HASH_SHA512;
default:
return HASH_UNKNOWN;
}
}
/**
* Converts IKEv1 hash algorithm name to IKEv2 prf name
*/
pseudo_random_function_t oakley_to_prf(int alg)
{
switch (alg)
{
case OAKLEY_MD5:
return PRF_HMAC_MD5;
case OAKLEY_SHA:
return PRF_HMAC_SHA1;
case OAKLEY_SHA2_256:
return PRF_HMAC_SHA2_256;
case OAKLEY_SHA2_384:
return PRF_HMAC_SHA2_384;
case OAKLEY_SHA2_512:
return PRF_HMAC_SHA2_512;
default:
return PRF_UNDEFINED;
}
}
/**
* Maps IKEv1 authentication method to IKEv2 signature scheme
*/
signature_scheme_t oakley_to_signature_scheme(int method)
{
switch (method)
{
case OAKLEY_RSA_SIG:
case XAUTHInitRSA:
case XAUTHRespRSA:
return SIGN_RSA_EMSA_PKCS1_NULL;
case OAKLEY_ECDSA_256:
case OAKLEY_ECDSA_384:
case OAKLEY_ECDSA_521:
return SIGN_ECDSA_WITH_NULL;
default:
return SIGN_UNKNOWN;
}
}
/**
* Table to map IKEv2 encryption algorithms to IKEv1 (or IKEv1 ESP) and back
*/
struct {
encryption_algorithm_t alg;
int oakley;
int esp;
} encr_map[] = {
{ENCR_DES, OAKLEY_DES_CBC, ESP_DES },
{ENCR_3DES, OAKLEY_3DES_CBC, ESP_3DES },
{ENCR_RC5, OAKLEY_RC5_R16_B64_CBC, ESP_RC5 },
{ENCR_IDEA, OAKLEY_IDEA_CBC, ESP_IDEA },
{ENCR_CAST, OAKLEY_CAST_CBC, ESP_CAST },
{ENCR_BLOWFISH, OAKLEY_BLOWFISH_CBC, ESP_BLOWFISH },
{ENCR_AES_CBC, OAKLEY_AES_CBC, ESP_AES },
{ENCR_CAMELLIA_CBC, OAKLEY_CAMELLIA_CBC, ESP_CAMELLIA },
{ENCR_SERPENT_CBC, OAKLEY_SERPENT_CBC, ESP_SERPENT },
{ENCR_TWOFISH_CBC, OAKLEY_TWOFISH_CBC, ESP_TWOFISH },
{ENCR_NULL, 0, ESP_NULL },
{ENCR_AES_CTR, 0, ESP_AES_CTR },
{ENCR_AES_CCM_ICV8, 0, ESP_AES_CCM_8 },
{ENCR_AES_CCM_ICV12, 0, ESP_AES_CCM_12},
{ENCR_AES_CCM_ICV16, 0, ESP_AES_CCM_16},
{ENCR_AES_GCM_ICV8, 0, ESP_AES_GCM_8 },
{ENCR_AES_GCM_ICV12, 0, ESP_AES_GCM_12},
{ENCR_AES_GCM_ICV16, 0, ESP_AES_GCM_16},
{ENCR_NULL_AUTH_AES_GMAC, 0, ESP_AES_GMAC },
};
/**
* Converts IKEv2 encryption to IKEv1 encryption algorithm
*/
int oakley_from_encryption_algorithm(encryption_algorithm_t alg)
{
int i;
for (i = 0; i < countof(encr_map); i++)
{
if (encr_map[i].alg == alg)
{
return encr_map[i].oakley;
}
}
return 0;
}
/**
* Converts IKEv2 encryption to IKEv1 ESP encryption algorithm
*/
int esp_from_encryption_algorithm(encryption_algorithm_t alg)
{
int i;
for (i = 0; i < countof(encr_map); i++)
{
if (encr_map[i].alg == alg)
{
return encr_map[i].esp;
}
}
return 0;
}
/**
* Converts IKEv1 ESP encryption to IKEv2 algorithm
*/
encryption_algorithm_t encryption_algorithm_from_esp(int esp)
{
int i;
for (i = 0; i < countof(encr_map); i++)
{
if (encr_map[i].esp == esp)
{
return encr_map[i].alg;
}
}
return 0;
}
/**
* Table to map IKEv2 integrity algorithms to IKEv1 (or IKEv1 ESP) and back
*/
struct {
integrity_algorithm_t alg;
int oakley;
int esp;
} auth_map[] = {
{AUTH_HMAC_MD5_96, OAKLEY_MD5, AUTH_ALGORITHM_HMAC_MD5 },
{AUTH_HMAC_SHA1_96, OAKLEY_SHA, AUTH_ALGORITHM_HMAC_SHA1 },
{AUTH_HMAC_SHA2_256_96, 0, AUTH_ALGORITHM_HMAC_SHA2_256_96},
{AUTH_HMAC_SHA2_256_128, OAKLEY_SHA2_256, AUTH_ALGORITHM_HMAC_SHA2_256 },
{AUTH_HMAC_SHA2_384_192, OAKLEY_SHA2_384, AUTH_ALGORITHM_HMAC_SHA2_384 },
{AUTH_HMAC_SHA2_512_256, OAKLEY_SHA2_512, AUTH_ALGORITHM_HMAC_SHA2_512 },
{AUTH_AES_XCBC_96, 0, AUTH_ALGORITHM_AES_XCBC_MAC },
{AUTH_AES_128_GMAC, 0, AUTH_ALGORITHM_AES_128_GMAC },
{AUTH_AES_192_GMAC, 0, AUTH_ALGORITHM_AES_192_GMAC },
{AUTH_AES_256_GMAC, 0, AUTH_ALGORITHM_AES_256_GMAC },
};
/**
* Converts IKEv2 integrity to IKEv1 hash algorithm
*/
int oakley_from_integrity_algorithm(integrity_algorithm_t alg)
{
int i;
for (i = 0; i < countof(auth_map); i++)
{
if (auth_map[i].alg == alg)
{
return auth_map[i].oakley;
}
}
return 0;
}
/**
* Converts IKEv2 integrity to IKEv1 ESP authentication algorithm
*/
int esp_from_integrity_algorithm(integrity_algorithm_t alg)
{
int i;
for (i = 0; i < countof(auth_map); i++)
{
if (auth_map[i].alg == alg)
{
return auth_map[i].esp;
}
}
return 0;
}
/**
* Converts IKEv1 ESP authentication to IKEv2 integrity algorithm
*/
integrity_algorithm_t integrity_algorithm_from_esp(int esp)
{
int i;
for (i = 0; i < countof(auth_map); i++)
{
if (auth_map[i].esp == esp)
{
return auth_map[i].alg;
}
}
return 0;
}

View File

@ -1,64 +0,0 @@
/* crypto interfaces
*
* Copyright (C) 2010 Tobias Brunner
* Copyright (C) 2009 Andreas Steffen
* Hochschule fuer Technik Rapperswil
*
* Copyright (C) 1998, 1999 D. Hugh Redelmeier.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <crypto/crypters/crypter.h>
#include <crypto/signers/signer.h>
#include <crypto/hashers/hasher.h>
#include <crypto/prfs/prf.h>
#include <credentials/keys/public_key.h>
#include "ike_alg.h"
extern bool init_crypto(void);
extern void free_crypto(void);
extern const struct dh_desc unset_group; /* magic signifier */
/* unification of cryptographic encoding/decoding algorithms
* The IV is taken from and returned to st->st_new_iv.
* This allows the old IV to be retained.
* Use update_iv to commit to the new IV (for example, once a packet has
* been validated).
*/
#define MAX_OAKLEY_KEY_LEN0 (3 * DES_CBC_BLOCK_SIZE)
#define MAX_OAKLEY_KEY_LEN (256/BITS_PER_BYTE)
struct state; /* forward declaration, dammit */
#define update_iv(st) memcpy((st)->st_iv, (st)->st_new_iv \
, (st)->st_iv_len = (st)->st_new_iv_len)
#define set_ph1_iv(st, iv) \
passert((st)->st_ph1_iv_len <= sizeof((st)->st_ph1_iv)); \
memcpy((st)->st_ph1_iv, (iv), (st)->st_ph1_iv_len);
/* unification of cryptographic hashing mechanisms */
extern encryption_algorithm_t oakley_to_encryption_algorithm(int alg);
extern hash_algorithm_t oakley_to_hash_algorithm(int alg);
extern pseudo_random_function_t oakley_to_prf(int alg);
extern signature_scheme_t oakley_to_signature_scheme(int method);
extern int oakley_from_encryption_algorithm(encryption_algorithm_t alg);
extern int oakley_from_integrity_algorithm(integrity_algorithm_t alg);
extern int esp_from_encryption_algorithm(encryption_algorithm_t alg);
extern int esp_from_integrity_algorithm(integrity_algorithm_t alg);
extern encryption_algorithm_t encryption_algorithm_from_esp(int esp);
extern integrity_algorithm_t integrity_algorithm_from_esp(int esp);

View File

@ -1,412 +0,0 @@
/* Dynamic db (proposal, transforms, attributes) handling.
* Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
/*
* The stratedy is to have (full contained) struct db_prop in db_context
* pointing to ONE dynamically sizable transform vector (trans0).
* Each transform stores attrib. in ONE dyn. sizable attribute vector (attrs0)
* in a "serialized" way (attributes storage is used in linear sequence for
* subsecuent transforms).
*
* Resizing for both trans0 and attrs0 is supported:
* - For trans0: quite simple, just allocate and copy trans. vector content
* also update trans_cur (by offset)
* - For attrs0: after allocating and copying attrs, I must rewrite each
* trans->attrs present in trans0; to achieve this, calculate
* attrs pointer offset (new minus old) and iterate over
* each transform "adding" this difference.
* also update attrs_cur (by offset)
*
* db_context structure:
* +---------------------+
* | prop |
* | .protoid |
* | .trans | --+
* | .trans_cnt | |
* +---------------------+ <-+
* | trans0 | ----> { trans#1 | ... | trans#i | ... }
* +---------------------+ ^
* | trans_cur | ----------------------' current transf.
* +---------------------+
* | attrs0 | ----> { attr#1 | ... | attr#j | ... }
* +---------------------+ ^
* | attrs_cur | ---------------------' current attr.
* +---------------------+
* | max_trans,max_attrs | max_trans/attrs: number of elem. of each vector
* +---------------------+
*
* See testing examples at end for interface usage.
*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <malloc.h>
#include <sys/types.h>
#include <freeswan.h>
#include "constants.h"
#include "defs.h"
#include "state.h"
#include "packet.h"
#include "spdb.h"
#include "db_ops.h"
#include "log.h"
#include "whack.h"
#include <assert.h>
#ifdef NOT_YET
/*
* Allocator cache:
* Because of the single-threaded nature of pluto/spdb.c,
* alloc()/free() is exercised many times with very small
* lifetime objects.
* Just caching last object (currently it will select the
* largest) will avoid this allocation mas^Wperturbations
*
*/
struct db_ops_alloc_cache {
void *ptr;
int size;
};
#endif
#ifndef NO_DB_OPS_STATS
/*
* stats: do account for allocations
* displayed in db_ops_show_status()
*/
struct db_ops_stats {
int st_curr_cnt; /* current number of allocations */
int st_total_cnt; /* total allocations so far */
size_t st_maxsz; /* max. size requested */
};
#define DB_OPS_ZERO { 0, 0, 0};
#define DB_OPS_STATS_DESC "{curr_cnt, total_cnt, maxsz}"
#define DB_OPS_STATS_STR(name) name "={%d,%d,%d} "
#define DB_OPS_STATS_F(st) (st).st_curr_cnt, (st).st_total_cnt, (int)(st).st_maxsz
static struct db_ops_stats db_context_st = DB_OPS_ZERO;
static struct db_ops_stats db_trans_st = DB_OPS_ZERO;
static struct db_ops_stats db_attrs_st = DB_OPS_ZERO;
static __inline__ void *malloc_bytes_st(size_t size, struct db_ops_stats *st)
{
void *ptr = malloc(size);
if (ptr)
{
st->st_curr_cnt++;
st->st_total_cnt++;
if (size > st->st_maxsz) st->st_maxsz=size;
}
return ptr;
}
#define ALLOC_BYTES_ST(z,st) malloc_bytes_st(z, &st);
#define PFREE_ST(p,st) do { st.st_curr_cnt--; free(p); } while (0);
#else
#define ALLOC_BYTES_ST(z,n) malloc(z);
#define PFREE_ST(p,n) free(p);
#endif /* NO_DB_OPS_STATS */
/* Initialize db object
* max_trans and max_attrs can be 0, will be dynamically expanded
* as a result of "add" operations
*/
int
db_prop_init(struct db_context *ctx, u_int8_t protoid, int max_trans, int max_attrs)
{
ctx->trans0 = NULL;
ctx->attrs0 = NULL;
if (max_trans > 0) { /* quite silly if not */
ctx->trans0 = ALLOC_BYTES_ST ( sizeof(struct db_trans) * max_trans,
db_trans_st);
memset(ctx->trans0, '\0', sizeof(struct db_trans) * max_trans);
}
if (max_attrs > 0) { /* quite silly if not */
ctx->attrs0 = ALLOC_BYTES_ST (sizeof(struct db_attr) * max_attrs,
db_attrs_st);
memset(ctx->attrs0, '\0', sizeof(struct db_attr) * max_attrs);
}
ctx->max_trans = max_trans;
ctx->max_attrs = max_attrs;
ctx->trans_cur = ctx->trans0;
ctx->attrs_cur = ctx->attrs0;
ctx->prop.protoid = protoid;
ctx->prop.trans = ctx->trans0;
ctx->prop.trans_cnt = 0;
return 0;
}
/* Expand storage for transforms by number delta_trans */
static int
db_trans_expand(struct db_context *ctx, int delta_trans)
{
int ret = -1;
struct db_trans *new_trans, *old_trans;
int max_trans = ctx->max_trans + delta_trans;
int offset;
old_trans = ctx->trans0;
new_trans = ALLOC_BYTES_ST ( sizeof (struct db_trans) * max_trans,
db_trans_st);
if (!new_trans)
goto out;
memcpy(new_trans, old_trans, ctx->max_trans * sizeof(struct db_trans));
/* update trans0 (obviously) */
ctx->trans0 = ctx->prop.trans = new_trans;
/* update trans_cur (by offset) */
offset = (char *)(new_trans) - (char *)(old_trans);
{
char *cctx = (char *)(ctx->trans_cur);
cctx += offset;
ctx->trans_cur = (struct db_trans *)cctx;
}
/* update elem count */
ctx->max_trans = max_trans;
PFREE_ST(old_trans, db_trans_st);
ret = 0;
out:
return ret;
}
/*
* Expand storage for attributes by delta_attrs number AND
* rewrite trans->attr pointers
*/
static int
db_attrs_expand(struct db_context *ctx, int delta_attrs)
{
int ret = -1;
struct db_attr *new_attrs, *old_attrs;
struct db_trans *t;
int ti;
int max_attrs = ctx->max_attrs + delta_attrs;
int offset;
old_attrs = ctx->attrs0;
new_attrs = ALLOC_BYTES_ST ( sizeof (struct db_attr) * max_attrs,
db_attrs_st);
if (!new_attrs)
goto out;
memcpy(new_attrs, old_attrs, ctx->max_attrs * sizeof(struct db_attr));
/* update attrs0 and attrs_cur (obviously) */
offset = (char *)(new_attrs) - (char *)(old_attrs);
{
char *actx = (char *)(ctx->attrs0);
actx += offset;
ctx->attrs0 = (struct db_attr *)actx;
actx = (char *)ctx->attrs_cur;
actx += offset;
ctx->attrs_cur = (struct db_attr *)actx;
}
/* for each transform, rewrite attrs pointer by offsetting it */
for (t=ctx->prop.trans, ti=0; ti < ctx->prop.trans_cnt; t++, ti++) {
char *actx = (char *)(t->attrs);
actx += offset;
t->attrs = (struct db_attr *)actx;
}
/* update elem count */
ctx->max_attrs = max_attrs;
PFREE_ST(old_attrs, db_attrs_st);
ret = 0;
out:
return ret;
}
/* Allocate a new db object */
struct db_context *
db_prop_new(u_int8_t protoid, int max_trans, int max_attrs)
{
struct db_context *ctx;
ctx = ALLOC_BYTES_ST ( sizeof (struct db_context), db_context_st);
if (!ctx) goto out;
if (db_prop_init(ctx, protoid, max_trans, max_attrs) < 0) {
PFREE_ST(ctx, db_context_st);
ctx=NULL;
}
out:
return ctx;
}
/* Free a db object */
void
db_destroy(struct db_context *ctx)
{
if (ctx->trans0) PFREE_ST(ctx->trans0, db_trans_st);
if (ctx->attrs0) PFREE_ST(ctx->attrs0, db_attrs_st);
PFREE_ST(ctx, db_context_st);
}
/* Start a new transform, expand trans0 is needed */
int
db_trans_add(struct db_context *ctx, u_int8_t transid)
{
/* skip incrementing current trans pointer the 1st time*/
if (ctx->trans_cur && ctx->trans_cur->attr_cnt)
ctx->trans_cur++;
/*
* Strategy: if more space is needed, expand by
* <current_size>/2 + 1
*
* This happens to produce a "reasonable" sequence
* after few allocations, eg.:
* 0,1,2,4,8,13,20,31,47
*/
if ((ctx->trans_cur - ctx->trans0) >= ctx->max_trans) {
/* XXX:jjo if fails should shout and flag it */
if (db_trans_expand(ctx, ctx->max_trans/2 + 1)<0)
return -1;
}
ctx->trans_cur->transid = transid;
ctx->trans_cur->attrs=ctx->attrs_cur;
ctx->trans_cur->attr_cnt = 0;
ctx->prop.trans_cnt++;
return 0;
}
/* Add attr copy to current transform, expanding attrs0 if needed */
int
db_attr_add(struct db_context *ctx, const struct db_attr *a)
{
/*
* Strategy: if more space is needed, expand by
* <current_size>/2 + 1
*/
if ((ctx->attrs_cur - ctx->attrs0) >= ctx->max_attrs) {
/* XXX:jjo if fails should shout and flag it */
if (db_attrs_expand(ctx, ctx->max_attrs/2 + 1) < 0)
return -1;
}
*ctx->attrs_cur++=*a;
ctx->trans_cur->attr_cnt++;
return 0;
}
/* Add attr copy (by value) to current transform,
* expanding attrs0 if needed, just calls db_attr_add().
*/
int
db_attr_add_values(struct db_context *ctx, u_int16_t type, u_int16_t val)
{
struct db_attr attr;
attr.type = type;
attr.val = val;
return db_attr_add (ctx, &attr);
}
#ifndef NO_DB_OPS_STATS
int
db_ops_show_status(void)
{
whack_log(RC_COMMENT, "stats " __FILE__ ": "
DB_OPS_STATS_DESC " :"
DB_OPS_STATS_STR("context")
DB_OPS_STATS_STR("trans")
DB_OPS_STATS_STR("attrs"),
DB_OPS_STATS_F(db_context_st),
DB_OPS_STATS_F(db_trans_st),
DB_OPS_STATS_F(db_attrs_st)
);
return 0;
}
#endif /* NO_DB_OPS_STATS */
/*
* From below to end just testing stuff ....
*/
#ifdef TEST
static void db_prop_print(struct db_prop *p)
{
struct db_trans *t;
struct db_attr *a;
int ti, ai;
enum_names *n, *n_at, *n_av;
printf("protoid=\"%s\"\n", enum_name(&protocol_names, p->protoid));
for (ti=0, t=p->trans; ti< p->trans_cnt; ti++, t++) {
switch( t->transid) {
case PROTO_ISAKMP:
n=&isakmp_transformid_names;break;
case PROTO_IPSEC_ESP:
n=&esp_transformid_names;break;
default:
continue;
}
printf(" transid=\"%s\"\n",
enum_name(n, t->transid));
for (ai=0, a=t->attrs; ai < t->attr_cnt; ai++, a++) {
int i;
switch( t->transid) {
case PROTO_ISAKMP:
n_at=&oakley_attr_names;
i=a->type|ISAKMP_ATTR_AF_TV;
n_av=oakley_attr_val_descs[(i)&ISAKMP_ATTR_RTYPE_MASK];
break;
case PROTO_IPSEC_ESP:
n_at=&ipsec_attr_names;
i=a->type|ISAKMP_ATTR_AF_TV;
n_av=ipsec_attr_val_descs[(i)&ISAKMP_ATTR_RTYPE_MASK];
break;
default:
continue;
}
printf(" type=\"%s\" value=\"%s\"\n",
enum_name(n_at, i),
enum_name(n_av, a->val));
}
}
}
static void db_print(struct db_context *ctx)
{
printf("trans_cur diff=%d, attrs_cur diff=%d\n",
ctx->trans_cur - ctx->trans0,
ctx->attrs_cur - ctx->attrs0);
db_prop_print(&ctx->prop);
}
void
passert_fail(const char *pred_str, const char *file_str, unsigned long line_no);
void abort(void);
void
passert_fail(const char *pred_str, const char *file_str, unsigned long line_no)
{
fprintf(stderr, "ASSERTION FAILED at %s:%lu: %s", file_str, line_no, pred_str);
abort(); /* exiting correctly doesn't always work */
}
int main(void) {
struct db_context *ctx=db_prop_new(PROTO_ISAKMP, 0, 0);
db_trans_add(ctx, KEY_IKE);
db_attr_add_values(ctx, OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC);
db_attr_add_values(ctx, OAKLEY_HASH_ALGORITHM, OAKLEY_MD5);
db_attr_add_values(ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG);
db_attr_add_values(ctx, OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024);
db_trans_add(ctx, KEY_IKE);
db_attr_add_values(ctx, OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_AES_CBC);
db_attr_add_values(ctx, OAKLEY_HASH_ALGORITHM, OAKLEY_MD5);
db_attr_add_values(ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY);
db_attr_add_values(ctx, OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536);
db_trans_add(ctx, ESP_3DES);
db_attr_add_values(ctx, AUTH_ALGORITHM, AUTH_ALGORITHM_HMAC_SHA1);
db_print(ctx);
db_destroy(ctx);
return 0;
}
#endif

View File

@ -1,54 +0,0 @@
/* Dynamic db (proposal, transforms, attributes) handling.
* Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef _DB_OPS_H
#define _DB_OPS_H
/*
* Main db object, (quite proposal "oriented")
*/
#ifndef NO_DB_CONTEXT
struct db_context {
struct db_prop prop; /* proposal buffer (not pointer) */
struct db_trans *trans0; /* transf. list, dynamically sized */
struct db_trans *trans_cur; /* current transform ptr */
struct db_attr *attrs0; /* attr. list, dynamically sized */
struct db_attr *attrs_cur; /* current attribute ptr */
int max_trans; /* size of trans list */
int max_attrs; /* size of attrs list */
};
/*
* Allocate a new db object
*/
struct db_context * db_prop_new(u_int8_t protoid, int max_trans, int max_attrs);
/* Initialize object for proposal building */
int db_prop_init(struct db_context *ctx, u_int8_t protoid, int max_trans, int max_attrs);
/* Free all resourses for this db */
void db_destroy(struct db_context *ctx);
/* Start a new transform */
int db_trans_add(struct db_context *ctx, u_int8_t transid);
/* Add a new attribute by copying db_attr content */
int db_attr_add(struct db_context *db_ctx, const struct db_attr *attr);
/* Add a new attribute by value */
int db_attr_add_values(struct db_context *ctx, u_int16_t type, u_int16_t val);
/* Get proposal from db object */
static __inline__ struct db_prop *db_prop_get(struct db_context *ctx) {
return &ctx->prop;
}
/* Show stats (allocation, etc) */
#endif /* NO_DB_CONTEXT */
int db_ops_show_status(void);
#endif /* _DB_OPS_H */

View File

@ -1,145 +0,0 @@
/* misc. universal things
* Copyright (C) 1998-2001 D. Hugh Redelmeier.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <dirent.h>
#include <inttypes.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <freeswan.h>
#include "constants.h"
#include "defs.h"
#include "log.h"
#include "whack.h" /* for RC_LOG_SERIOUS */
bool
all_zero(const unsigned char *m, size_t len)
{
size_t i;
for (i = 0; i != len; i++)
if (m[i] != '\0')
return FALSE;
return TRUE;
}
/* Note that there may be as many as six IDs that are temporary at
* one time before unsharing the two ends of a connection. So we need
* at least six temporary buffers for DER_ASN1_DN IDs.
* We rotate them. Be careful!
*/
#define MAX_BUF 10
char*
temporary_cyclic_buffer(void)
{
static char buf[MAX_BUF][BUF_LEN]; /* MAX_BUF internal buffers */
static int counter = 0; /* cyclic counter */
if (++counter == MAX_BUF) counter = 0; /* next internal buffer */
return buf[counter]; /* assign temporary buffer */
}
/* concatenates two sub paths into a string with a maximum size of BUF_LEN
* use for temporary storage only
*/
char* concatenate_paths(char *a, char *b)
{
char *c;
if (*b == '/' || *b == '.')
return b;
c = temporary_cyclic_buffer();
snprintf(c, BUF_LEN, "%s/%s", a, b);
return c;
}
/* moves a chunk to a memory position, chunk is freed afterwards
* position pointer is advanced after the insertion point
*/
void
mv_chunk(u_char **pos, chunk_t content)
{
if (content.len > 0)
{
chunkcpy(*pos, content);
free(content.ptr);
}
}
/* checks if the expiration date has been reached and
* warns during the warning_interval of the imminent
* expiry. strict=TRUE declares a fatal error,
* strict=FALSE issues a warning upon expiry.
*/
const char*
check_expiry(time_t expiration_date, int warning_interval, bool strict)
{
time_t now, time_left;
if (expiration_date == UNDEFINED_TIME)
return "ok (expires never)";
/* determine the current time */
time(&now);
time_left = (expiration_date - now);
if (time_left < 0)
return strict? "fatal (expired)" : "warning (expired)";
if (time_left > 86400*warning_interval)
return "ok";
{
static char buf[35]; /* temporary storage */
const char* unit = "second";
if (time_left > 172800)
{
time_left /= 86400;
unit = "day";
}
else if (time_left > 7200)
{
time_left /= 3600;
unit = "hour";
}
else if (time_left > 120)
{
time_left /= 60;
unit = "minute";
}
snprintf(buf, 35, "warning (expires in %" PRIu64 " %s%s)",
(u_int64_t)time_left, unit, (time_left == 1) ? "" : "s");
return buf;
}
}
/*
* Filter eliminating the directory entries '.' and '..'
*/
int
file_select(const struct dirent *entry)
{
return strcmp(entry->d_name, "." ) &&
strcmp(entry->d_name, "..");
}

View File

@ -1,79 +0,0 @@
/* misc. universal things
* Copyright (C) 1997 Angelos D. Keromytis.
* Copyright (C) 1998-2001 D. Hugh Redelmeier.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef _DEFS_H
#define _DEFS_H
#include <string.h>
#include <sys/types.h>
#include <chunk.h>
#ifdef DEBUG
# define USED_BY_DEBUG /* ignore */
#else
# define USED_BY_DEBUG UNUSED
#endif
/* type of serial number of a state object
* Needed in connections.h and state.h; here to simplify dependencies.
*/
typedef unsigned long so_serial_t;
#define SOS_NOBODY 0 /* null serial number */
#define SOS_FIRST 1 /* first normal serial number */
/* memory allocation */
#define clone_thing(orig) clalloc((void *)&(orig), sizeof(orig))
#define clone_str(str) \
((str) == NULL? NULL : strdup(str))
#define replace(p, q) \
{ free(p); (p) = (q); }
#define chunkcpy(dst, chunk) \
{ memcpy(dst, chunk.ptr, chunk.len); dst += chunk.len;}
extern char* temporary_cyclic_buffer(void);
extern char* concatenate_paths(char *a, char *b);
/* move a chunk to a memory position and free it after insertion */
extern void mv_chunk(u_char **pos, chunk_t content);
/* warns a predefined interval before expiry */
extern const char* check_expiry(time_t expiration_date,
int warning_interval, bool strict);
#define MAX_PROMPT_PASS_TRIALS 5
#define PROMPT_PASS_LEN 64
/* filter eliminating the directory entries '.' and '..' */
typedef struct dirent dirent_t;
extern int file_select(const dirent_t *entry);
/* cleanly exit Pluto */
extern void exit_pluto(int /*status*/) NEVER_RETURNS;
/* zero all bytes */
#define zero(x) memset((x), '\0', sizeof(*(x)))
/* are all bytes 0? */
extern bool all_zero(const unsigned char *m, size_t len);
/* pad_up(n, m) is the amount to add to n to make it a multiple of m */
#define pad_up(n, m) (((m) - 1) - (((n) + (m) - 1) % (m)))
#endif /* _DEFS_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,97 +0,0 @@
/* demultiplex incoming IKE messages
* Copyright (C) 1998-2002 D. Hugh Redelmeier.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#ifndef _DEMUX_H
#define _DEMUX_H
#include "packet.h"
#include "state.h"
extern void init_demux(void);
extern bool send_packet(struct state *st, const char *where);
extern void comm_handle(const struct iface *ifp);
extern u_int8_t reply_buffer[MAX_OUTPUT_UDP_SIZE];
/* State transition function infrastructure
*
* com_handle parses a message, decides what state object it applies to,
* and calls the appropriate state transition function (STF).
* These declarations define the interface to these functions.
*
* Each STF must be able to be restarted up to any failure point:
* a later message will cause the state to be re-entered. This
* explains the use of the replace macro and the care in handling
* MP_INT members of struct state.
*/
struct payload_digest {
pb_stream pbs;
union payload payload;
struct payload_digest *next; /* of same kind */
};
/* message digest
* Note: raw_packet and packet_pbs are "owners" of space on heap.
*/
struct msg_digest {
struct msg_digest *next; /* for free list */
chunk_t raw_packet; /* if encrypted, received packet before decryption */
const struct iface *iface; /* interface on which message arrived */
ip_address sender; /* where message came from */
u_int16_t sender_port; /* host order */
pb_stream packet_pbs; /* whole packet */
pb_stream message_pbs; /* message to be processed */
struct isakmp_hdr hdr; /* message's header */
bool encrypted; /* was it encrypted? */
enum state_kind from_state; /* state we started in */
const struct state_microcode *smc; /* microcode for initial state */
struct state *st; /* current state object */
pb_stream reply; /* room for reply */
pb_stream rbody; /* room for reply body (after header) */
notification_t note; /* reason for failure */
bool dpd; /* peer supports RFC 3706 DPD */
bool openpgp; /* peer supports OpenPGP certificates */
bool ms_nt5; /* peer is a windows 2000+ host */
# define PAYLIMIT 40
struct payload_digest
digest[PAYLIMIT],
*digest_roof,
*chain[ISAKMP_NEXT_ROOF];
unsigned short nat_traversal_vid;
};
extern void release_md(struct msg_digest *md);
/* status for state-transition-function
* Note: STF_FAIL + notification_t means fail with that notification
*/
typedef enum {
STF_IGNORE, /* don't respond */
STF_SUSPEND, /* unfinished -- don't release resources */
STF_OK, /* success */
STF_INTERNAL_ERROR, /* discard everything, we failed */
STF_FAIL /* discard everything, something failed. notification_t added. */
} stf_status;
typedef stf_status state_transition_fn(struct msg_digest *md);
extern void complete_state_transition(struct msg_digest **mdp, stf_status result);
extern void free_md_pool(void);
#endif /* _DEMUX_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,75 +0,0 @@
/* Find public key in DNS
* Copyright (C) 2000-2002 D. Hugh Redelmeier.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <utils/identification.h>
extern int adns_qfd; /* file descriptor for sending queries to adns */
extern int adns_afd; /* file descriptor for receiving answers from adns */
extern const char *pluto_adns_option; /* path from --pluto_adns */
extern void init_adns(void);
extern void stop_adns(void);
extern void handle_adns_answer(void);
extern bool unsent_ADNS_queries;
extern void send_unsent_ADNS_queries(void);
/* (common prefix of) stuff remembered between async query and answer.
* Filled in by start_adns_query.
* Freed by call to release_adns_continuation.
*/
struct adns_continuation; /* forward declaration (not far!) */
typedef void (*cont_fn_t)(struct adns_continuation *cr, err_t ugh);
struct adns_continuation {
unsigned long qtid; /* query transaction id number */
int type; /* T_TXT or T_KEY, selecting rr type of interest */
cont_fn_t cont_fn; /* function to carry on suspended work */
identification_t *id; /* subject of query */
bool sgw_specified;
identification_t *sgw_id; /* peer, if constrained */
lset_t debugging; /* only used #ifdef DEBUG, but don't want layout to change */
struct gw_info *gateways_from_dns; /* answer, if looking for our TXT rrs */
#ifdef USE_KEYRR
struct pubkey_list *keys_from_dns; /* answer, if looking for KEY rrs */
#endif
struct adns_continuation *previous, *next;
struct pubkey *last_info; /* the last structure we accumulated */
struct adns_query query;
};
extern err_t start_adns_query(identification_t *id /* domain to query */
, identification_t *sgw_id /* if non-null, any accepted gw_info must match */
, int type /* T_TXT or T_KEY, selecting rr type of interest */
, cont_fn_t cont_fn /* continuation function */
, struct adns_continuation *cr);
/* Gateway info gleaned from reverse DNS of client */
struct gw_info {
unsigned refcnt; /* reference counted! */
unsigned pref; /* preference: lower is better */
#define NO_TIME ((time_t) -2) /* time_t value meaning "not_yet" */
identification_t* client_id; /* id of client of peer */
identification_t* gw_id; /* id of peer (if id_is_ipaddr, .ip_addr is address) */
bool gw_key_present;
struct pubkey *key;
struct gw_info *next;
};
extern void gw_addref(struct gw_info *gw);
extern void gw_delref(struct gw_info **gwp);
extern void reset_adns_restart_count(void);

View File

@ -1,195 +0,0 @@
/*
* Copyright (C) 2010 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <unistd.h>
#include <fcntl.h>
#include "event_queue.h"
#include <debug.h>
#include <threading/mutex.h>
#include <utils/linked_list.h>
typedef struct private_event_queue_t private_event_queue_t;
/**
* Private data of event_queue_t class.
*/
struct private_event_queue_t {
/**
* Public event_queue_t interface.
*/
event_queue_t public;
/**
* List of queued events (event_t*).
*/
linked_list_t *events;
/**
* Mutex for event list.
*/
mutex_t *mutex;
/**
* Read end of the notification pipe.
*/
int read_fd;
/**
* Write end of the notification pipe.
*/
int write_fd;
};
typedef struct event_t event_t;
struct event_t {
/**
* Callback function.
*/
void (*callback)(void *data);
/**
* Data to supply to the callback.
*/
void *data;
/**
* Cleanup function.
*/
void (*cleanup)(void *data);
};
static event_t *event_create(void (*callback)(void *data), void *data,
void (*cleanup)(void *data))
{
event_t *this;
INIT(this,
.callback = callback,
.data = data,
.cleanup = cleanup,
);
return this;
}
static void event_destroy(event_t *this)
{
if (this->cleanup)
{
this->cleanup(this->data);
}
free(this);
}
METHOD(event_queue_t, get_event_fd, int,
private_event_queue_t *this)
{
return this->read_fd;
}
METHOD(event_queue_t, handle, void,
private_event_queue_t *this)
{
char buf[10];
linked_list_t *events;
event_t *event;
this->mutex->lock(this->mutex);
/* flush pipe */
while (read(this->read_fd, &buf, sizeof(buf)) == sizeof(buf));
/* replace the list, so we can unlock the mutex while executing the jobs */
events = this->events;
this->events = linked_list_create();
this->mutex->unlock(this->mutex);
while (events->remove_first(events, (void**)&event) == SUCCESS)
{
event->callback(event->data);
event_destroy(event);
}
events->destroy(events);
}
METHOD(event_queue_t, queue, void,
private_event_queue_t *this, void (*callback)(void *data), void *data,
void (*cleanup)(void *data))
{
event_t *event = event_create(callback, data, cleanup);
char c = 0;
this->mutex->lock(this->mutex);
this->events->insert_last(this->events, event);
ignore_result(write(this->write_fd, &c, 1));
this->mutex->unlock(this->mutex);
}
METHOD(event_queue_t, destroy, void,
private_event_queue_t *this)
{
this->mutex->lock(this->mutex);
this->events->destroy_function(this->events, (void*)event_destroy);
this->mutex->unlock(this->mutex);
this->mutex->destroy(this->mutex);
close(this->read_fd);
close(this->write_fd);
free(this);
}
static bool set_nonblock(int socket)
{
int flags = fcntl(socket, F_GETFL);
return flags != -1 && fcntl(socket, F_SETFL, flags | O_NONBLOCK) != -1;
}
static bool set_cloexec(int socket)
{
int flags = fcntl(socket, F_GETFD);
return flags != -1 && fcntl(socket, F_SETFD, flags | FD_CLOEXEC) != -1;
}
/*
* Described in header.
*/
event_queue_t *event_queue_create()
{
private_event_queue_t *this;
int fd[2];
INIT(this,
.public = {
.get_event_fd = _get_event_fd,
.handle = _handle,
.queue = _queue,
.destroy = _destroy,
},
.events = linked_list_create(),
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
);
if (pipe(fd) == -1 ||
!set_nonblock(fd[0]) || !set_cloexec(fd[0]) ||
!set_nonblock(fd[1]) || !set_cloexec(fd[1]))
{
DBG1(DBG_JOB, "failed to create pipe for job queue");
_destroy(this);
return NULL;
}
this->read_fd = fd[0];
this->write_fd = fd[1];
return &this->public;
}

View File

@ -1,69 +0,0 @@
/*
* Copyright (C) 2010 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
/**
* @defgroup event_queue event_queue
* @{ @ingroup pluto
*/
#ifndef EVENT_QUEUE_H_
#define EVENT_QUEUE_H_
typedef struct event_queue_t event_queue_t;
/**
* The event queue facility can be used to synchronize thread-pool threads
* with the pluto main thread. That is, all queued callbacks are executed
* asynchronously by the pluto main thread.
*/
struct event_queue_t {
/**
* Returns the file descriptor used to notify the main thread.
*
* @return fd to use in the main thread
*/
int (*get_event_fd) (event_queue_t *this);
/**
* Handle all queued events.
*/
void (*handle) (event_queue_t *this);
/**
* Add an event to the queue.
*
* @param callback callback function to add to the queue
* @param data data supplied to the callback function
* @param cleanup optional cleanup function
*/
void (*queue) (event_queue_t *this, void (*callback)(void *data),
void *data, void (*cleanup)(void *data));
/**
* Destroy this instance.
*/
void (*destroy) (event_queue_t *this);
};
/**
* Create the event queue.
*
* @return created object
*/
event_queue_t *event_queue_create();
#endif /** EVENT_QUEUE_H_ @}*/

View File

@ -1,766 +0,0 @@
/* Dynamic fetching of X.509 CRLs
* Copyright (C) 2002 Stephane Laroche <stephane.laroche@colubris.com>
* Copyright (C) 2002-2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <stdlib.h>
#include <errno.h>
#include <sys/time.h>
#include <time.h>
#include <string.h>
#ifdef THREADS
#include <pthread.h>
#endif
#include <freeswan.h>
#include <library.h>
#include <debug.h>
#include <asn1/asn1.h>
#include <credentials/certificates/certificate.h>
#ifdef THREADS
#include <threading/thread.h>
#endif
#include "constants.h"
#include "defs.h"
#include "log.h"
#include "x509.h"
#include "ca.h"
#include "whack.h"
#include "ocsp.h"
#include "crl.h"
#include "fetch.h"
#include "builder.h"
fetch_req_t empty_fetch_req = {
NULL , /* next */
0 , /* trials */
NULL , /* issuer */
{ NULL, 0}, /* authKeyID */
NULL /* distributionPoints */
};
/* chained list of crl fetch requests */
static fetch_req_t *crl_fetch_reqs = NULL;
/* chained list of ocsp fetch requests */
static ocsp_location_t *ocsp_fetch_reqs = NULL;
#ifdef THREADS
static thread_t *thread;
static pthread_mutex_t certs_and_keys_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t authcert_list_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t crl_list_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t ocsp_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t ca_info_list_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t crl_fetch_list_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t ocsp_fetch_list_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t fetch_wake_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t fetch_wake_cond = PTHREAD_COND_INITIALIZER;
/**
* lock access to my certs and keys
*/
void lock_certs_and_keys(const char *who)
{
pthread_mutex_lock(&certs_and_keys_mutex);
DBG(DBG_CONTROLMORE,
DBG_log("certs and keys locked by '%s'", who)
)
}
/**
* Unlock access to my certs and keys
*/
void unlock_certs_and_keys(const char *who)
{
DBG(DBG_CONTROLMORE,
DBG_log("certs and keys unlocked by '%s'", who)
)
pthread_mutex_unlock(&certs_and_keys_mutex);
}
/**
* Lock access to the chained authcert list
*/
void lock_authcert_list(const char *who)
{
pthread_mutex_lock(&authcert_list_mutex);
DBG(DBG_CONTROLMORE,
DBG_log("authcert list locked by '%s'", who)
)
}
/**
* Unlock access to the chained authcert list
*/
void unlock_authcert_list(const char *who)
{
DBG(DBG_CONTROLMORE,
DBG_log("authcert list unlocked by '%s'", who)
)
pthread_mutex_unlock(&authcert_list_mutex);
}
/**
* Lock access to the chained crl list
*/
void lock_crl_list(const char *who)
{
pthread_mutex_lock(&crl_list_mutex);
DBG(DBG_CONTROLMORE,
DBG_log("crl list locked by '%s'", who)
)
}
/**
* Unlock access to the chained crl list
*/
void unlock_crl_list(const char *who)
{
DBG(DBG_CONTROLMORE,
DBG_log("crl list unlocked by '%s'", who)
)
pthread_mutex_unlock(&crl_list_mutex);
}
/**
* Lock access to the ocsp cache
*/
extern void lock_ocsp_cache(const char *who)
{
pthread_mutex_lock(&ocsp_cache_mutex);
DBG(DBG_CONTROLMORE,
DBG_log("ocsp cache locked by '%s'", who)
)
}
/**
* Unlock access to the ocsp cache
*/
extern void unlock_ocsp_cache(const char *who)
{
DBG(DBG_CONTROLMORE,
DBG_log("ocsp cache unlocked by '%s'", who)
)
pthread_mutex_unlock(&ocsp_cache_mutex);
}
/**
* Lock access to the ca info list
*/
extern void lock_ca_info_list(const char *who)
{
pthread_mutex_lock(&ca_info_list_mutex);
DBG(DBG_CONTROLMORE,
DBG_log("ca info list locked by '%s'", who)
)
}
/**
* Unlock access to the ca info list
*/
extern void unlock_ca_info_list(const char *who)
{
DBG(DBG_CONTROLMORE,
DBG_log("ca info list unlocked by '%s'", who)
)
pthread_mutex_unlock(&ca_info_list_mutex);
}
/**
* Lock access to the chained crl fetch request list
*/
static void lock_crl_fetch_list(const char *who)
{
pthread_mutex_lock(&crl_fetch_list_mutex);
DBG(DBG_CONTROLMORE,
DBG_log("crl fetch request list locked by '%s'", who)
)
}
/**
* Unlock access to the chained crl fetch request list
*/
static void unlock_crl_fetch_list(const char *who)
{
DBG(DBG_CONTROLMORE,
DBG_log("crl fetch request list unlocked by '%s'", who)
)
pthread_mutex_unlock(&crl_fetch_list_mutex);
}
/**
* Lock access to the chained ocsp fetch request list
*/
static void lock_ocsp_fetch_list(const char *who)
{
pthread_mutex_lock(&ocsp_fetch_list_mutex);
DBG(DBG_CONTROLMORE,
DBG_log("ocsp fetch request list locked by '%s'", who)
)
}
/**
* Unlock access to the chained ocsp fetch request list
*/
static void unlock_ocsp_fetch_list(const char *who)
{
DBG(DBG_CONTROLMORE,
DBG_log("ocsp fetch request list unlocked by '%s'", who)
)
pthread_mutex_unlock(&ocsp_fetch_list_mutex);
}
/**
* Wakes up the sleeping fetch thread
*/
void wake_fetch_thread(const char *who)
{
if (crl_check_interval > 0)
{
DBG(DBG_CONTROLMORE,
DBG_log("fetch thread wake call by '%s'", who)
)
pthread_mutex_lock(&fetch_wake_mutex);
pthread_cond_signal(&fetch_wake_cond);
pthread_mutex_unlock(&fetch_wake_mutex);
}
}
#else /* !THREADS */
#define lock_crl_fetch_list(who) /* do nothing */
#define unlock_crl_fetch_list(who) /* do nothing */
#define lock_ocsp_fetch_list(who) /* do nothing */
#define unlock_ocsp_fetch_list(who) /* do nothing */
#endif /* !THREADS */
/**
* Free the dynamic memory used to store fetch requests
*/
static void free_fetch_request(fetch_req_t *req)
{
req->distributionPoints->destroy_function(req->distributionPoints, free);
DESTROY_IF(req->issuer);
free(req->authKeyID.ptr);
free(req);
}
#ifdef THREADS
/**
* Fetch an ASN.1 blob coded in PEM or DER format from a URL
*/
x509crl_t* fetch_crl(char *url)
{
x509crl_t *crl;
chunk_t blob;
DBG1(DBG_LIB, " fetching crl from '%s' ...", url);
if (lib->fetcher->fetch(lib->fetcher, url, &blob, FETCH_END) != SUCCESS)
{
DBG1(DBG_LIB, "crl fetching failed");
return FALSE;
}
crl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_CRL,
BUILD_BLOB_PEM, blob, BUILD_END);
free(blob.ptr);
if (!crl)
{
DBG1(DBG_LIB, "crl fetched successfully but data coded in unknown "
"format");
}
return crl;
}
/**
* Complete a distributionPoint URI with ca information
*/
static char* complete_uri(char *distPoint, const char *ldaphost)
{
char *symbol = strchr(distPoint, ':');
if (symbol)
{
int type_len = symbol - distPoint;
if (type_len >= 4 && strncasecmp(distPoint, "ldap", 4) == 0)
{
char *ptr = symbol + 1;
int len = strlen(distPoint) - (type_len + 1);
if (len > 2 && *ptr++ == '/' && *ptr++ == '/')
{
len -= 2;
symbol = strchr(ptr, '/');
if (symbol && symbol - ptr == 0 && ldaphost)
{
char uri[BUF_LEN];
/* insert the ldaphost into the uri */
snprintf(uri, BUF_LEN, "%.*s%s%.*s",
(int)strlen(distPoint) - len, distPoint, ldaphost,
len, symbol);
return strdup(uri);
}
}
}
}
/* default action: copy distributionPoint without change */
return strdup(distPoint);
}
/**
* Try to fetch the crls defined by the fetch requests
*/
static void fetch_crls(bool cache_crls)
{
fetch_req_t *req;
fetch_req_t **reqp;
lock_crl_fetch_list("fetch_crls");
req = crl_fetch_reqs;
reqp = &crl_fetch_reqs;
while (req != NULL)
{
enumerator_t *enumerator;
char *point;
bool valid_crl = FALSE;
const char *ldaphost;
ca_info_t *ca;
lock_ca_info_list("fetch_crls");
ca = get_ca_info(req->issuer, req->authKeyID);
ldaphost = (ca == NULL)? NULL : ca->ldaphost;
enumerator = req->distributionPoints->create_enumerator(req->distributionPoints);
while (enumerator->enumerate(enumerator, &point))
{
x509crl_t *crl;
char *uri;
uri = complete_uri(point, ldaphost);
crl = fetch_crl(uri);
free(uri);
if (crl)
{
if (insert_crl(crl, point, cache_crls))
{
DBG(DBG_CONTROL,
DBG_log("we have a valid crl")
)
valid_crl = TRUE;
break;
}
}
}
enumerator->destroy(enumerator);
unlock_ca_info_list("fetch_crls");
if (valid_crl)
{
/* delete fetch request */
fetch_req_t *req_free = req;
req = req->next;
*reqp = req;
free_fetch_request(req_free);
}
else
{
/* try again next time */
req->trials++;
reqp = &req->next;
req = req->next;
}
}
unlock_crl_fetch_list("fetch_crls");
}
static void fetch_ocsp_status(ocsp_location_t* location)
{
chunk_t request = build_ocsp_request(location);
chunk_t response = chunk_empty;
DBG1(DBG_LIB, " requesting ocsp status from '%s' ...", location->uri);
if (lib->fetcher->fetch(lib->fetcher, location->uri, &response,
FETCH_REQUEST_DATA, request,
FETCH_REQUEST_TYPE, "application/ocsp-request",
FETCH_END) == SUCCESS)
{
parse_ocsp(location, response);
}
else
{
DBG1(DBG_LIB, "ocsp request to %s failed", location->uri);
}
free(request.ptr);
chunk_free(&location->nonce);
/* increment the trial counter of the unresolved fetch requests */
{
ocsp_certinfo_t *certinfo = location->certinfo;
while (certinfo != NULL)
{
certinfo->trials++;
certinfo = certinfo->next;
}
}
}
/**
* Try to fetch the necessary ocsp information
*/
static void fetch_ocsp(void)
{
ocsp_location_t *location;
lock_ocsp_fetch_list("fetch_ocsp");
location = ocsp_fetch_reqs;
/* fetch the ocps status for all locations */
while (location != NULL)
{
if (location->certinfo != NULL)
{
fetch_ocsp_status(location);
}
location = location->next;
}
unlock_ocsp_fetch_list("fetch_ocsp");
}
static void* fetch_thread(void *arg)
{
struct timespec wait_interval;
/* the fetching thread is only cancellable while waiting for new events */
thread_cancelability(FALSE);
DBG(DBG_CONTROL,
DBG_log("fetch thread started")
)
pthread_mutex_lock(&fetch_wake_mutex);
while(1)
{
int status;
wait_interval.tv_nsec = 0;
wait_interval.tv_sec = time(NULL) + crl_check_interval;
DBG(DBG_CONTROL,
DBG_log("next regular crl check in %ld seconds", crl_check_interval)
)
thread_cancelability(TRUE);
status = pthread_cond_timedwait(&fetch_wake_cond, &fetch_wake_mutex
, &wait_interval);
thread_cancelability(FALSE);
if (status == ETIMEDOUT)
{
DBG(DBG_CONTROL,
DBG_log(" ");
DBG_log("*time to check crls and the ocsp cache")
)
check_ocsp();
check_crls();
}
else
{
DBG(DBG_CONTROL,
DBG_log("fetch thread was woken up")
)
}
fetch_ocsp();
fetch_crls(cache_crls);
}
return NULL;
}
#endif /* THREADS*/
/**
* Initializes curl and starts the fetching thread
*/
void fetch_initialize(void)
{
if (crl_check_interval > 0)
{
#ifdef THREADS
thread = thread_create((thread_main_t)fetch_thread, NULL);
if (thread == NULL)
{
plog("fetching thread could not be started");
}
#else /* !THREADS */
plog("warning: not compiled with pthread support");
#endif /* !THREADS */
}
}
/**
* Terminates the fetching thread
*/
void fetch_finalize(void)
{
if (crl_check_interval > 0)
{
#ifdef THREADS
if (thread)
{
thread->cancel(thread);
thread->join(thread);
}
#endif
}
}
void free_crl_fetch(void)
{
lock_crl_fetch_list("free_crl_fetch");
while (crl_fetch_reqs != NULL)
{
fetch_req_t *req = crl_fetch_reqs;
crl_fetch_reqs = req->next;
free_fetch_request(req);
}
unlock_crl_fetch_list("free_crl_fetch");
}
/**
* Free the chained list of ocsp requests
*/
void free_ocsp_fetch(void)
{
lock_ocsp_fetch_list("free_ocsp_fetch");
free_ocsp_locations(&ocsp_fetch_reqs);
unlock_ocsp_fetch_list("free_ocsp_fetch");
}
/**
* Add an additional distribution point
*/
void add_distribution_point(linked_list_t *points, char *new_point)
{
char *point;
bool add = TRUE;
enumerator_t *enumerator;
if (new_point == NULL || *new_point == '\0')
{
return;
}
enumerator = points->create_enumerator(points);
while (enumerator->enumerate(enumerator, &point))
{
if (streq(point, new_point))
{
add = FALSE;
break;
}
}
enumerator->destroy(enumerator);
if (add)
{
points->insert_last(points, strdup(new_point));
}
}
/**
* Add additional distribution points
*/
void add_distribution_points(linked_list_t *points, linked_list_t *new_points)
{
char *new_point;
enumerator_t *enumerator;
enumerator = new_points->create_enumerator(new_points);
while (enumerator->enumerate(enumerator, &new_point))
{
bool add = TRUE;
char *point;
enumerator_t *enumerator;
enumerator = points->create_enumerator(points);
while (enumerator->enumerate(enumerator, &point))
{
if (streq(point, new_point))
{
add = FALSE;
break;
}
}
enumerator->destroy(enumerator);
if (add)
{
points->insert_last(points, strdup(new_point));
}
}
enumerator->destroy(enumerator);
}
fetch_req_t* build_crl_fetch_request(identification_t *issuer,
chunk_t authKeyID,
linked_list_t *distributionPoints)
{
char *point;
enumerator_t *enumerator;
fetch_req_t *req = malloc_thing(fetch_req_t);
memset(req, 0, sizeof(fetch_req_t));
req->distributionPoints = linked_list_create();
/* clone fields */
req->issuer = issuer->clone(issuer);
req->authKeyID = chunk_clone(authKeyID);
/* copy distribution points */
enumerator = distributionPoints->create_enumerator(distributionPoints);
while (enumerator->enumerate(enumerator, &point))
{
req->distributionPoints->insert_last(req->distributionPoints,
strdup(point));
}
enumerator->destroy(enumerator);
return req;
}
/**
* Add a crl fetch request to the chained list
*/
void add_crl_fetch_request(fetch_req_t *req)
{
fetch_req_t *r;
lock_crl_fetch_list("add_crl_fetch_request");
r = crl_fetch_reqs;
while (r != NULL)
{
if (req->authKeyID.ptr ? same_keyid(req->authKeyID, r->authKeyID) :
req->issuer->equals(req->issuer, r->issuer))
{
/* there is already a fetch request */
DBG(DBG_CONTROL,
DBG_log("crl fetch request already exists")
)
/* there might be new distribution points */
add_distribution_points(r->distributionPoints,
req->distributionPoints);
unlock_crl_fetch_list("add_crl_fetch_request");
free_fetch_request(req);
return;
}
r = r->next;
}
/* insert new fetch request at the head of the queue */
req->next = crl_fetch_reqs;
crl_fetch_reqs = req;
DBG(DBG_CONTROL,
DBG_log("crl fetch request added")
)
unlock_crl_fetch_list("add_crl_fetch_request");
}
/**
* Add an ocsp fetch request to the chained list
*/
void add_ocsp_fetch_request(ocsp_location_t *location, chunk_t serialNumber)
{
ocsp_certinfo_t certinfo;
certinfo.serialNumber = serialNumber;
lock_ocsp_fetch_list("add_ocsp_fetch_request");
add_certinfo(location, &certinfo, &ocsp_fetch_reqs, TRUE);
unlock_ocsp_fetch_list("add_ocsp_fetch_request");
}
/**
* List all distribution points
*/
void list_distribution_points(linked_list_t *distributionPoints)
{
char *point;
bool first_point = TRUE;
enumerator_t *enumerator;
enumerator = distributionPoints->create_enumerator(distributionPoints);
while (enumerator->enumerate(enumerator, &point))
{
whack_log(RC_COMMENT, " %s '%s'",
(first_point)? "distPts: " : " ", point);
first_point = FALSE;
}
enumerator->destroy(enumerator);
}
/**
* List all fetch requests in the chained list
*/
void list_crl_fetch_requests(bool utc)
{
fetch_req_t *req;
lock_crl_fetch_list("list_crl_fetch_requests");
req = crl_fetch_reqs;
if (req != NULL)
{
whack_log(RC_COMMENT, " ");
whack_log(RC_COMMENT, "List of CRL Fetch Requests:");
}
while (req != NULL)
{
whack_log(RC_COMMENT, " ");
whack_log(RC_COMMENT, " trials: %d", req->trials);
whack_log(RC_COMMENT, " issuer: \"%Y\"", req->issuer);
if (req->authKeyID.ptr)
{
whack_log(RC_COMMENT, " authkey: %#B", &req->authKeyID);
}
list_distribution_points(req->distributionPoints);
req = req->next;
}
unlock_crl_fetch_list("list_crl_fetch_requests");
}
void list_ocsp_fetch_requests(bool utc)
{
lock_ocsp_fetch_list("list_ocsp_fetch_requests");
list_ocsp_locations(ocsp_fetch_reqs, TRUE, utc, FALSE);
unlock_ocsp_fetch_list("list_ocsp_fetch_requests");
}

View File

@ -1,82 +0,0 @@
/* Dynamic fetching of X.509 CRLs
* Copyright (C) 2002 Stephane Laroche <stephane.laroche@colubris.com>
* Copyright (C) 2002-2004 Andreas Steffen, Zuercher Hochschule Winterthur
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <utils/linked_list.h>
#include <utils/identification.h>
#include "x509.h"
#define FETCH_CMD_TIMEOUT 10 /* seconds */
struct ocsp_location; /* forward declaration of ocsp_location defined in ocsp.h */
typedef enum {
FETCH_GET = 1,
FETCH_POST = 2
} fetch_request_t;
typedef struct fetch_req fetch_req_t;
struct fetch_req {
fetch_req_t *next;
int trials;
identification_t *issuer;
chunk_t authKeyID;
linked_list_t *distributionPoints;
};
#ifdef THREADS
extern void lock_crl_list(const char *who);
extern void unlock_crl_list(const char *who);
extern void lock_ocsp_cache(const char *who);
extern void unlock_ocsp_cache(const char *who);
extern void lock_ca_info_list(const char *who);
extern void unlock_ca_info_list(const char *who);
extern void lock_authcert_list(const char *who);
extern void unlock_authcert_list(const char *who);
extern void lock_certs_and_keys(const char *who);
extern void unlock_certs_and_keys(const char *who);
extern void wake_fetch_thread(const char *who);
#else
#define lock_crl_list(who) /* do nothing */
#define unlock_crl_list(who) /* do nothing */
#define lock_ocsp_cache(who) /* do nothing */
#define unlock_ocsp_cache(who) /* do nothing */
#define lock_ca_info_list(who) /* do nothing */
#define unlock_ca_info_list(who) /* do nothing */
#define lock_authcert_list(who) /* do nothing */
#define unlock_authcert_list(who) /* do nothing */
#define lock_certs_and_keys(who) /* do nothing */
#define unlock_certs_and_keys(who) /* do nothing */
#define wake_fetch_thread(who) /* do nothing */
#endif
extern void fetch_initialize(void);
extern void fetch_finalize(void);
extern void free_crl_fetch(void);
extern void free_ocsp_fetch(void);
extern void add_distribution_point(linked_list_t *points, char* new_point);
extern void add_distribution_points(linked_list_t *points,
linked_list_t *new_points);
extern fetch_req_t* build_crl_fetch_request(identification_t *issuer,
chunk_t authKeyID,
linked_list_t *distributionPoints);
extern void add_crl_fetch_request(fetch_req_t *req);
extern void add_ocsp_fetch_request(struct ocsp_location *location,
chunk_t serialNumber);
extern void list_distribution_points(linked_list_t *distributionPoints);
extern void list_crl_fetch_requests(bool utc);
extern void list_ocsp_fetch_requests(bool utc);
extern size_t write_buffer(void *ptr, size_t size, size_t nmemb, void *data);

View File

@ -1,450 +0,0 @@
/* Implement policy groups-style control files (aka "foodgroups")
* Copyright (C) 2002 D. Hugh Redelmeier.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include <string.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <sys/queue.h>
#include <freeswan.h>
#include "constants.h"
#include "defs.h"
#include "connections.h"
#include "foodgroups.h"
#include "kernel.h"
#include "lex.h"
#include "log.h"
#include "whack.h"
/* Food group config files are found in directory fg_path */
#ifndef POLICYGROUPSDIR
#define POLICYGROUPSDIR IPSEC_CONFDIR "/ipsec.d/policies"
#endif
const char *policygroups_dir = POLICYGROUPSDIR;
static char *fg_path = NULL;
static size_t fg_path_space = 0;
/* Groups is a list of connections that are policy groups.
* The list is updated as group connections are added and deleted.
*/
struct fg_groups {
struct fg_groups *next;
connection_t *connection;
};
static struct fg_groups *groups = NULL;
/* Targets is a list of pairs: subnet and its policy group.
* This list is bulk-updated on whack --listen and
* incrementally updated when group connections are deleted.
*
* It is ordered by source subnet, and if those are equal, then target subnet.
* A subnet is compared by comparing the network, and if those are equal,
* comparing the mask.
*/
struct fg_targets {
struct fg_targets *next;
struct fg_groups *group;
ip_subnet subnet;
char *name; /* name of instance of group conn */
};
static struct fg_targets *targets = NULL;
struct fg_targets *new_targets;
/* ipcmp compares the two ip_address values a and b.
* It returns -1, 0, or +1 if a is, respectively,
* less than, equal to, or greater than b.
*/
static int ipcmp(ip_address *a, ip_address *b)
{
if (addrtypeof(a) != addrtypeof(b))
{
return addrtypeof(a) < addrtypeof(b)? -1 : 1;
}
else if (sameaddr(a, b))
{
return 0;
}
else
{
const struct sockaddr *sa = sockaddrof(a)
, *sb = sockaddrof(b);
passert(addrtypeof(a) == AF_INET); /* not yet implemented IPv6 version :-( */
return (ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr)
< ntohl(((const struct sockaddr_in *)sb)->sin_addr.s_addr))
? -1 : 1;
}
}
/* subnetcmp compares the two ip_subnet values a and b.
* It returns -1, 0, or +1 if a is, respectively,
* less than, equal to, or greater than b.
*/
static int subnetcmp(const ip_subnet *a, const ip_subnet *b)
{
ip_address neta, maska, netb, maskb;
int r;
networkof(a, &neta);
maskof(a, &maska);
networkof(b, &netb);
maskof(b, &maskb);
r = ipcmp(&neta, &netb);
if (r == 0)
r = ipcmp(&maska, &maskb);
return r;
}
static void read_foodgroup(struct fg_groups *g)
{
const char *fgn = g->connection->name;
const ip_subnet *lsn = &g->connection->spd.this.client;
size_t plen = strlen(policygroups_dir) + 1 + strlen(fgn) + 1;
struct file_lex_position flp_space;
if (plen > fg_path_space)
{
free(fg_path);
fg_path_space = plen + 10;
fg_path = malloc(fg_path_space);
}
snprintf(fg_path, fg_path_space, "%s/%s", policygroups_dir, fgn);
if (!lexopen(&flp_space, fg_path, TRUE))
{
DBG(DBG_CONTROL, DBG_log("no group file \"%s\"", fg_path));
}
else
{
plog("loading group \"%s\"", fg_path);
for (;;)
{
switch (flp->bdry)
{
case B_none:
{
/* !!! this test is not sufficient for distinguishing address families.
* We need a notation to specify that a FQDN is to be resolved to IPv6.
*/
const struct af_info *afi = strchr(tok, ':') == NULL
? &af_inet4_info: &af_inet6_info;
ip_subnet sn;
err_t ugh;
if (strchr(tok, '/') == NULL)
{
/* no /, so treat as /32 or V6 equivalent */
ip_address t;
ugh = ttoaddr(tok, 0, afi->af, &t);
if (ugh == NULL)
ugh = addrtosubnet(&t, &sn);
}
else
{
ugh = ttosubnet(tok, 0, afi->af, &sn);
}
if (ugh != NULL)
{
loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s \"%s\""
, flp->filename, flp->lino, ugh, tok);
}
else if (afi->af != AF_INET)
{
loglog(RC_LOG_SERIOUS
, "\"%s\" line %d: unsupported Address Family \"%s\""
, flp->filename, flp->lino, tok);
}
else
{
/* Find where new entry ought to go in new_targets. */
struct fg_targets **pp;
int r;
for (pp = &new_targets; ; pp = &(*pp)->next)
{
if (*pp == NULL)
{
r = -1; /* end of list is infinite */
break;
}
r = subnetcmp(lsn, &(*pp)->group->connection->spd.this.client);
if (r == 0)
r = subnetcmp(&sn, &(*pp)->subnet);
if (r <= 0)
break;
}
if (r == 0)
{
char source[SUBNETTOT_BUF];
subnettot(lsn, 0, source, sizeof(source));
loglog(RC_LOG_SERIOUS
, "\"%s\" line %d: subnet \"%s\", source %s, already \"%s\""
, flp->filename
, flp->lino
, tok
, source
, (*pp)->group->connection->name);
}
else
{
struct fg_targets *f = malloc_thing(struct fg_targets);
f->next = *pp;
f->group = g;
f->subnet = sn;
f->name = NULL;
*pp = f;
}
}
}
(void)shift(); /* next */
continue;
case B_record:
flp->bdry = B_none; /* eat the Record Boundary */
(void)shift(); /* get real first token */
continue;
case B_file:
break; /* done */
}
break; /* if we reach here, out of loop */
}
lexclose();
}
}
static void free_targets(void)
{
while (targets != NULL)
{
struct fg_targets *t = targets;
targets = t->next;
free(t->name);
free(t);
}
}
void load_groups(void)
{
passert(new_targets == NULL);
/* for each group, add config file targets into new_targets */
{
struct fg_groups *g;
for (g = groups; g != NULL; g = g->next)
if (oriented(*g->connection))
read_foodgroup(g);
}
/* dump new_targets */
DBG(DBG_CONTROL,
{
struct fg_targets *t;
for (t = new_targets; t != NULL; t = t->next)
{
char asource[SUBNETTOT_BUF];
char atarget[SUBNETTOT_BUF];
subnettot(&t->group->connection->spd.this.client
, 0, asource, sizeof(asource));
subnettot(&t->subnet, 0, atarget, sizeof(atarget));
DBG_log("%s->%s %s"
, asource, atarget
, t->group->connection->name);
}
});
/* determine and deal with differences between targets and new_targets.
* structured like a merge.
*/
{
struct fg_targets *op = targets
, *np = new_targets;
while (op != NULL && np != NULL)
{
int r = subnetcmp(&op->group->connection->spd.this.client
, &np->group->connection->spd.this.client);
if (r == 0)
r = subnetcmp(&op->subnet, &np->subnet);
if (r == 0 && op->group == np->group)
{
/* unchanged -- steal name & skip over */
np->name = op->name;
op->name = NULL;
op = op->next;
np = np->next;
}
else
{
/* note: following cases overlap! */
if (r <= 0)
{
remove_group_instance(op->group->connection, op->name);
op = op->next;
}
if (r >= 0)
{
np->name = add_group_instance(np->group->connection, &np->subnet);
np = np->next;
}
}
}
for (; op != NULL; op = op->next)
remove_group_instance(op->group->connection, op->name);
for (; np != NULL; np = np->next)
np->name = add_group_instance(np->group->connection, &np->subnet);
/* update: new_targets replaces targets */
free_targets();
targets = new_targets;
new_targets = NULL;
}
}
void add_group(connection_t *c)
{
struct fg_groups *g = malloc_thing(struct fg_groups);
g->next = groups;
groups = g;
g->connection = c;
}
static struct fg_groups *find_group(const connection_t *c)
{
struct fg_groups *g;
for (g = groups; g != NULL && g->connection != c; g = g->next)
;
return g;
}
void route_group(connection_t *c)
{
/* it makes no sense to route a connection that is ISAKMP-only */
if (!NEVER_NEGOTIATE(c->policy) && !HAS_IPSEC_POLICY(c->policy))
{
loglog(RC_ROUTE, "cannot route an ISAKMP-only group connection");
}
else
{
struct fg_groups *g = find_group(c);
struct fg_targets *t;
passert(g != NULL);
g->connection->policy |= POLICY_GROUTED;
for (t = targets; t != NULL; t = t->next)
{
if (t->group == g)
{
connection_t *ci = con_by_name(t->name, FALSE);
if (ci != NULL)
{
set_cur_connection(ci);
if (!trap_connection(ci))
whack_log(RC_ROUTE, "could not route");
set_cur_connection(c);
}
}
}
}
}
void unroute_group(connection_t *c)
{
struct fg_groups *g = find_group(c);
struct fg_targets *t;
passert(g != NULL);
g->connection->policy &= ~POLICY_GROUTED;
for (t = targets; t != NULL; t = t->next)
{
if (t->group == g)
{
connection_t *ci = con_by_name(t->name, FALSE);
if (ci != NULL)
{
set_cur_connection(ci);
unroute_connection(ci);
set_cur_connection(c);
}
}
}
}
void delete_group(const connection_t *c)
{
struct fg_groups *g;
/* find and remove from groups */
{
struct fg_groups **pp;
for (pp = &groups; (g = *pp)->connection != c; pp = &(*pp)->next)
;
*pp = g->next;
}
/* find and remove from targets */
{
struct fg_targets **pp;
for (pp = &targets; *pp != NULL; )
{
struct fg_targets *t = *pp;
if (t->group == g)
{
*pp = t->next;
remove_group_instance(t->group->connection, t->name);
free(t);
/* pp is ready for next iteration */
}
else
{
pp = &t->next;
}
}
}
free(g);
}

View File

@ -1,22 +0,0 @@
/* Implement policygroups-style control files (aka "foodgroups")
* Copyright (C) 2002 D. Hugh Redelmeier.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
struct connection; /* forward declaration */
extern void add_group(struct connection *c);
extern void route_group(struct connection *c);
extern void unroute_group(struct connection *c);
extern void delete_group(const struct connection *c);
extern const char *policygroups_dir;
extern void load_groups(void);

Some files were not shown because too many files have changed in this diff Show More