summaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
authorHans-Joerg Hoexer <hshoexer@cvs.openbsd.org>2005-08-22 17:26:47 +0000
committerHans-Joerg Hoexer <hshoexer@cvs.openbsd.org>2005-08-22 17:26:47 +0000
commit52d0815f533373817d503611005204c0608d5379 (patch)
tree071c31bcf1062707250b909f23159ae41caf7457 /sbin
parent9e4e60c7b87a0ea47e7c7222e5d9c35a51047a05 (diff)
Teach ipsecctl to control isakmpd.
ok deraadt
Diffstat (limited to 'sbin')
-rw-r--r--sbin/ipsecctl/Makefile4
-rw-r--r--sbin/ipsecctl/ike.c378
-rw-r--r--sbin/ipsecctl/ipsecctl.c31
-rw-r--r--sbin/ipsecctl/ipsecctl.h24
-rw-r--r--sbin/ipsecctl/parse.y148
-rw-r--r--sbin/ipsecctl/pfkey.c10
-rw-r--r--sbin/ipsecctl/pfkey.h6
7 files changed, 568 insertions, 33 deletions
diff --git a/sbin/ipsecctl/Makefile b/sbin/ipsecctl/Makefile
index 170f6246dec..f6310de15e2 100644
--- a/sbin/ipsecctl/Makefile
+++ b/sbin/ipsecctl/Makefile
@@ -1,9 +1,9 @@
-# $OpenBSD: Makefile,v 1.3 2005/05/27 05:19:55 hshoexer Exp $
+# $OpenBSD: Makefile,v 1.4 2005/08/22 17:26:46 hshoexer Exp $
PROG= ipsecctl
MAN= ipsecctl.8 ipsec.conf.5
-SRCS= ipsecctl.c pfkey.c pfkdump.c parse.y
+SRCS= ike.c ipsecctl.c pfkey.c pfkdump.c parse.y
CFLAGS+= -Wall -I${.CURDIR}
CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
diff --git a/sbin/ipsecctl/ike.c b/sbin/ipsecctl/ike.c
new file mode 100644
index 00000000000..72100ecba9a
--- /dev/null
+++ b/sbin/ipsecctl/ike.c
@@ -0,0 +1,378 @@
+/* $OpenBSD: ike.c,v 1.1 2005/08/22 17:26:46 hshoexer Exp $ */
+/*
+ * Copyright (c) 2005 Hans-Joerg Hoexer <hshoexer@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ipsecctl.h"
+
+static void ike_section_peer(struct ipsec_addr *, FILE *);
+static void ike_section_ids(struct ipsec_addr *, struct ipsec_auth *,
+ FILE *);
+static void ike_section_ipsec(struct ipsec_addr *, struct ipsec_addr *,
+ struct ipsec_addr *, FILE *);
+static int ike_section_qm(struct ipsec_addr *, struct ipsec_addr *,
+ u_int8_t, struct ipsec_transforms *, FILE *);
+static int ike_section_mm(struct ipsec_addr *, struct ipsec_transforms *,
+ FILE *);
+static void ike_section_qmids(struct ipsec_addr *, struct ipsec_addr *,
+ FILE *);
+static int ike_connect(u_int8_t, struct ipsec_addr *, struct ipsec_addr *,
+ FILE *);
+static int ike_gen_config(struct ipsec_rule *, FILE *);
+static int ike_delete_config(struct ipsec_rule *, FILE *);
+
+int ike_print_config(struct ipsec_rule *, int);
+int ike_ipsec_establish(int, struct ipsec_rule *);
+
+#define SET "C set "
+#define ADD "C add "
+#define DELETE "C rms "
+
+static void
+ike_section_peer(struct ipsec_addr *peer, FILE *fd)
+{
+ fprintf(fd, SET "[peer-%s]:Phase=1 force\n", peer->name);
+ fprintf(fd, SET "[peer-%s]:Address=%s force\n", peer->name, peer->name);
+}
+
+static void
+ike_section_ids(struct ipsec_addr *peer, struct ipsec_auth *auth, FILE *fd)
+{
+ if (auth == NULL)
+ return;
+
+ if (auth->srcid) {
+ fprintf(fd, SET "[peer-%s]:ID=%s-ID force\n", peer->name,
+ "local");
+ fprintf(fd, SET "[%s-ID]:ID-type=FQDN force\n", "local");
+ fprintf(fd, SET "[%s-ID]:Name=%s force\n", "local",
+ auth->srcid);
+ }
+ if (auth->dstid) {
+ fprintf(fd, SET "[peer-%s]:Remote-ID=%s-ID force\n",
+ peer->name, peer->name);
+ fprintf(fd, SET "[%s-ID]:ID-type=FQDN force\n", peer->name);
+ fprintf(fd, SET "[%s-ID]:Name=%s force\n", peer->name,
+ auth->dstid);
+ }
+}
+
+static void
+ike_section_ipsec(struct ipsec_addr *src, struct ipsec_addr *dst, struct
+ ipsec_addr *peer, FILE *fd)
+{
+ fprintf(fd, SET "[IPsec-%s-%s]:Phase=2 force\n", src->name, dst->name);
+ fprintf(fd, SET "[IPsec-%s-%s]:ISAKMP-peer=peer-%s force\n", src->name,
+ dst->name, peer->name);
+ fprintf(fd, SET "[IPsec-%s-%s]:Configuration=qm-%s-%s force\n",
+ src->name, dst->name, src->name, dst->name);
+ fprintf(fd, SET "[IPsec-%s-%s]:Local-ID=lid-%s force\n", src->name,
+ dst->name, src->name);
+ fprintf(fd, SET "[IPsec-%s-%s]:Remote-ID=rid-%s force\n", src->name,
+ dst->name, dst->name);
+}
+
+static int
+ike_section_qm(struct ipsec_addr *src, struct ipsec_addr *dst, u_int8_t proto,
+ struct ipsec_transforms *qmxfs, FILE *fd)
+{
+ fprintf(fd, SET "[qm-%s-%s]:EXCHANGE_TYPE=QUICK_MODE force\n",
+ src->name, dst->name);
+ fprintf(fd, SET "[qm-%s-%s]:Suites=QM-", src->name, dst->name);
+
+ switch (proto) {
+ case IPSEC_ESP:
+ fprintf(fd, "ESP");
+ break;
+ default:
+ warnx("illegal protocol %d", proto);
+ return (-1);
+ };
+ fprintf(fd, "-");
+
+ if (qmxfs->encxf) {
+ switch (qmxfs->encxf->id) {
+ case ENCXF_3DES_CBC:
+ fprintf(fd, "3DES");
+ break;
+ case ENCXF_DES_CBC:
+ fprintf(fd, "DES");
+ break;
+ case ENCXF_AES:
+ fprintf(fd, "AES");
+ break;
+ case ENCXF_BLOWFISH:
+ fprintf(fd, "BLF");
+ break;
+ case ENCXF_CAST128:
+ fprintf(fd, "CAST");
+ break;
+ default:
+ warnx("illegal transform %s", qmxfs->encxf->name);
+ return (-1);
+ };
+ } else
+ fprintf(fd, "AES");
+ fprintf(fd, "-");
+
+ if (qmxfs->authxf) {
+ switch (qmxfs->authxf->id) {
+ case AUTHXF_HMAC_MD5:
+ case AUTHXF_MD5:
+ fprintf(fd, "MD5");
+ break;
+ case AUTHXF_HMAC_SHA1:
+ case AUTHXF_SHA1:
+ fprintf(fd, "SHA");
+ break;
+ case AUTHXF_HMAC_RIPEMD160:
+ fprintf(fd, "RIPEMD");
+ break;
+ case AUTHXF_HMAC_SHA2_256:
+ fprintf(fd, "SHA2-256");
+ break;
+ case AUTHXF_HMAC_SHA2_384:
+ fprintf(fd, "SHA2-384");
+ break;
+ case AUTHXF_HMAC_SHA2_512:
+ fprintf(fd, "SHA2-512");
+ break;
+ default:
+ warnx("illegal transform %s", qmxfs->authxf->name);
+ return (-1);
+ };
+ } else
+ fprintf(fd, "SHA2-256");
+ fprintf(fd, "-PFS-SUITE force\n");
+
+ return (0);
+}
+
+static int
+ike_section_mm(struct ipsec_addr *peer, struct ipsec_transforms *mmxfs,
+ FILE *fd)
+{
+ if (!(mmxfs->authxf || mmxfs->encxf))
+ return (0);
+
+ fprintf(fd, SET "[peer-%s]:Configuration=mm-%s force\n", peer->name,
+ peer->name);
+ fprintf(fd, SET "[mm-%s]:EXCHANGE_TYPE=ID_PROT force\n", peer->name);
+ fprintf(fd, ADD "[mm-%s]:Transforms=", peer->name);
+
+ if (mmxfs->encxf) {
+ switch (mmxfs->encxf->id) {
+ case ENCXF_3DES_CBC:
+ fprintf(fd, "3DES");
+ break;
+ case ENCXF_DES_CBC:
+ fprintf(fd, "DES");
+ break;
+ case ENCXF_AES:
+ fprintf(fd, "AES");
+ break;
+ case ENCXF_BLOWFISH:
+ fprintf(fd, "BLF");
+ break;
+ case ENCXF_CAST128:
+ fprintf(fd, "CAST");
+ break;
+ default:
+ warnx("illegal transform %s", mmxfs->encxf->name);
+ return (-1);
+ };
+ } else
+ fprintf(fd, "AES");
+ fprintf(fd, "-");
+
+ if (mmxfs->authxf) {
+ switch (mmxfs->authxf->id) {
+ case AUTHXF_HMAC_MD5:
+ case AUTHXF_MD5:
+ fprintf(fd, "MD5");
+ break;
+ case AUTHXF_HMAC_SHA1:
+ case AUTHXF_SHA1:
+ fprintf(fd, "SHA");
+ break;
+ default:
+ warnx("illegal transform %s", mmxfs->authxf->name);
+ return (-1);
+ };
+ } else
+ fprintf(fd, "SHA");
+
+ fprintf(fd, "-RSA_SIG\n");
+
+ return (0);
+}
+
+static void
+ike_section_qmids(struct ipsec_addr *src, struct ipsec_addr *dst, FILE *fd)
+{
+ char *mask, *network, *p;
+
+ if (src->netaddress) {
+ mask = inet_ntoa(src->v4mask.mask);
+ if ((network = strdup(src->name)) == NULL)
+ err(1, "strdup");
+ if ((p = strrchr(network, '/')) != NULL)
+ *p = '\0';
+
+ fprintf(fd, SET "[lid-%s]:ID-type=IPV4_ADDR_SUBNET force\n",
+ src->name);
+ fprintf(fd, SET "[lid-%s]:Network=%s force\n", src->name,
+ network);
+ fprintf(fd, SET "[lid-%s]:Netmask=%s force\n", src->name, mask);
+
+ free(network);
+ } else {
+ fprintf(fd, SET "[lid-%s]:ID-type=IPV4_ADDR force\n",
+ src->name);
+ fprintf(fd, SET "[lid-%s]:Address=%s force\n", src->name,
+ src->name);
+ }
+ if (dst->netaddress) {
+ mask = inet_ntoa(dst->v4mask.mask);
+ if ((network = strdup(dst->name)) == NULL)
+ err(1, "strdup");
+ if ((p = strrchr(network, '/')) != NULL)
+ *p = '\0';
+
+ fprintf(fd, SET "[rid-%s]:ID-type=IPV4_ADDR_SUBNET force\n",
+ dst->name);
+ fprintf(fd, SET "[rid-%s]:Network=%s force\n", dst->name,
+ network);
+ fprintf(fd, SET "[rid-%s]:Netmask=%s force\n", dst->name, mask);
+
+ free(network);
+ } else {
+ fprintf(fd, SET "[rid-%s]:ID-type=IPV4_ADDR force\n",
+ dst->name);
+ fprintf(fd, SET "[rid-%s]:Address=%s force\n", dst->name,
+ dst->name);
+ }
+}
+
+static int
+ike_connect(u_int8_t mode, struct ipsec_addr *src, struct ipsec_addr *dst,
+ FILE *fd)
+{
+ switch (mode) {
+ case IKE_ACTIVE:
+ fprintf(fd, "t IPsec-%s-%s\n", src->name, dst->name);
+ fprintf(fd, "c IPsec-%s-%s\n", src->name, dst->name);
+ break;
+ case IKE_PASSIVE:
+ fprintf(fd, ADD "[Phase 2]:Passive-Connections=IPsec-%s-%s\n",
+ src->name, dst->name);
+ break;
+ default:
+ return (-1);
+ }
+ return (0);
+}
+
+static int
+ike_gen_config(struct ipsec_rule *r, FILE *fd)
+{
+ ike_section_peer(r->peer, fd);
+ if (ike_section_mm(r->peer, r->mmxfs, fd) == -1)
+ return (-1);
+ ike_section_ids(r->peer, r->auth, fd);
+ ike_section_ipsec(r->src, r->dst, r->peer, fd);
+ if (ike_section_qm(r->src, r->dst, r->proto, r->qmxfs, fd) == -1)
+ return (-1);
+ ike_section_qmids(r->src, r->dst, fd);
+
+ if (ike_connect(r->ikemode, r->src, r->dst, fd) == -1)
+ return (-1);
+
+ return (0);
+}
+
+static int
+ike_delete_config(struct ipsec_rule *r, FILE *fd)
+{
+ switch (r->ikemode) {
+ case IKE_ACTIVE:
+ fprintf(fd, "t IPsec-%s-%s\n", r->src->name, r->dst->name);
+ break;
+ case IKE_PASSIVE:
+ fprintf(fd, DELETE "[Phase 2]\n");
+ fprintf(fd, "t IPsec-%s-%s\n", r->src->name, r->dst->name);
+ break;
+ default:
+ return (-1);
+ }
+
+ fprintf(fd, DELETE "[peer-%s]\n", r->peer->name);
+ if (r->auth) {
+ if (r->auth->srcid)
+ fprintf(fd, DELETE "[%s-ID]\n", r->auth->srcid);
+ if (r->auth->dstid)
+ fprintf(fd, DELETE "[%s-ID]\n", r->auth->dstid);
+ }
+ fprintf(fd, DELETE "[IPsec-%s-%s]\n", r->src->name, r->dst->name);
+ fprintf(fd, DELETE "[qm-%s-%s]\n", r->src->name, r->dst->name);
+ fprintf(fd, DELETE "[mm-%s]\n", r->peer->name);
+ fprintf(fd, DELETE "[lid-%s]\n", r->src->name);
+ fprintf(fd, DELETE "[rid-%s]\n", r->dst->name);
+
+ return (0);
+}
+
+int
+ike_print_config(struct ipsec_rule *r, int opts)
+{
+ return (ike_gen_config(r, stdout));
+}
+
+int
+ike_ipsec_establish(int action, struct ipsec_rule *r)
+{
+ FILE *fd;
+ int ret = 0;
+
+ if ((fd = fopen("/var/run/isakmpd.fifo", "w")) == NULL)
+ errx(1, "fopen");
+
+ switch (action) {
+ case ACTION_ADD:
+ ret = ike_gen_config(r, fd);
+ break;
+ case ACTION_DELETE:
+ ret = ike_delete_config(r, fd);
+ break;
+ default:
+ ret = -1;
+ }
+
+ fclose(fd);
+ return (ret);
+}
diff --git a/sbin/ipsecctl/ipsecctl.c b/sbin/ipsecctl/ipsecctl.c
index 14852b333a1..b4fe59975cb 100644
--- a/sbin/ipsecctl/ipsecctl.c
+++ b/sbin/ipsecctl/ipsecctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipsecctl.c,v 1.25 2005/08/09 12:37:45 hshoexer Exp $ */
+/* $OpenBSD: ipsecctl.c,v 1.26 2005/08/22 17:26:46 hshoexer Exp $ */
/*
* Copyright (c) 2004, 2005 Hans-Joerg Hoexer <hshoexer@openbsd.org>
*
@@ -97,9 +97,9 @@ ipsecctl_rules(char *filename, int opts)
error = 1;
} else {
if (opts & IPSECCTL_OPT_DELETE)
- action = PFK_ACTION_DELETE;
+ action = ACTION_DELETE;
else
- action = PFK_ACTION_ADD;
+ action = ACTION_ADD;
if ((opts & IPSECCTL_OPT_NOACTION) == 0)
if (ipsecctl_commit(action, &ipsec))
@@ -141,22 +141,31 @@ ipsecctl_commit(int action, struct ipsecctl *ipsec)
while ((rp = TAILQ_FIRST(&ipsec->rule_queue))) {
TAILQ_REMOVE(&ipsec->rule_queue, rp, entries);
- if (pfkey_ipsec_establish(action, rp) == -1)
- warnx("failed to add rule %d", rp->nr);
+ if (rp->type & RULE_IKE) {
+ if (ike_ipsec_establish(action, rp) == -1)
+ warnx("failed to add rule %d", rp->nr);
+ } else {
+ if (pfkey_ipsec_establish(action, rp) == -1)
+ warnx("failed to add rule %d", rp->nr);
+ }
/* src and dst are always used. */
+ free(rp->src->name);
free(rp->src);
+ free(rp->dst->name);
free(rp->dst);
- if (rp->peer)
+ if (rp->peer) {
+ free(rp->peer->name);
free(rp->peer);
+ }
if (rp->auth) {
if (rp->auth->srcid)
free(rp->auth->srcid);
if (rp->auth->dstid)
free(rp->auth->dstid);
- }
free(rp->auth);
+ }
if (rp->xfs)
free(rp->xfs);
if (rp->authkey) {
@@ -241,6 +250,7 @@ ipsecctl_print_flow(struct ipsec_rule *r, int opts)
}
printf("\n\ttype %s", flowtype[r->flowtype]);
}
+ printf("\n");
}
void
@@ -275,6 +285,7 @@ ipsecctl_print_sa(struct ipsec_rule *r, int opts)
printf("enckey 0x");
ipsecctl_print_key(r->enckey);
}
+ printf("\n");
}
void
@@ -287,7 +298,8 @@ ipsecctl_print_rule(struct ipsec_rule *r, int opts)
ipsecctl_print_flow(r, opts);
if (r->type & RULE_SA)
ipsecctl_print_sa(r, opts);
- printf("\n");
+ if (r->type & RULE_IKE)
+ ike_print_config(r, opts);
}
int
@@ -382,8 +394,11 @@ ipsecctl_show_flows(int opts)
ipsecctl_print_rule(rp, ipsec.opts);
+ free(rp->src->name);
free(rp->src);
+ free(rp->dst->name);
free(rp->dst);
+ free(rp->peer->name);
free(rp->peer);
if (rp->auth) {
if (rp->auth->srcid)
diff --git a/sbin/ipsecctl/ipsecctl.h b/sbin/ipsecctl/ipsecctl.h
index 14c086db724..1d005f1e9b4 100644
--- a/sbin/ipsecctl/ipsecctl.h
+++ b/sbin/ipsecctl/ipsecctl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipsecctl.h,v 1.16 2005/08/09 12:37:45 hshoexer Exp $ */
+/* $OpenBSD: ipsecctl.h,v 1.17 2005/08/22 17:26:46 hshoexer Exp $ */
/*
* Copyright (c) 2004, 2005 Hans-Joerg Hoexer <hshoexer@openbsd.org>
*
@@ -28,8 +28,13 @@
#define IPSECCTL_OPT_FLUSH 0x0100
#define IPSECCTL_OPT_DELETE 0x0200
+enum {
+ ACTION_ADD, ACTION_DELETE
+};
+
#define RULE_FLOW 0x01
#define RULE_SA 0x02
+#define RULE_IKE 0x04
enum {
DIRECTION_UNKNOWN, IPSEC_IN, IPSEC_OUT, IPSEC_INOUT
@@ -56,15 +61,19 @@ enum {
ENCXF_UNKNOWN,ENCXF_NONE, ENCXF_3DES_CBC, ENCXF_DES_CBC, ENCXF_AES,
ENCXF_AESCTR, ENCXF_BLOWFISH, ENCXF_CAST128, ENCXF_NULL, ENCXF_SKIPJACK
};
+enum {
+ IKE_ACTIVE, IKE_PASSIVE
+};
struct ipsec_addr {
- struct in_addr v4;
+ struct in_addr v4;
union {
struct in_addr mask;
u_int32_t mask32;
- } v4mask;
- int netaddress;
- sa_family_t af;
+ } v4mask;
+ int netaddress;
+ sa_family_t af;
+ char *name;
};
struct ipsec_auth {
@@ -103,12 +112,15 @@ struct ipsec_rule {
struct ipsec_addr *peer;
struct ipsec_auth *auth;
struct ipsec_transforms *xfs;
+ struct ipsec_transforms *mmxfs;
+ struct ipsec_transforms *qmxfs;
struct ipsec_key *authkey;
struct ipsec_key *enckey;
u_int8_t proto;
u_int8_t direction;
u_int8_t flowtype;
+ u_int8_t ikemode;
u_int32_t spi;
u_int32_t nr;
@@ -126,5 +138,7 @@ struct ipsecctl {
int parse_rules(FILE *, struct ipsecctl *);
int ipsecctl_add_rule(struct ipsecctl * ipsec, struct ipsec_rule *);
void ipsecctl_get_rules(struct ipsecctl *);
+int ike_print_config(struct ipsec_rule *, int);
+int ike_ipsec_establish(int, struct ipsec_rule *);
#endif /* _IPSECCTL_H_ */
diff --git a/sbin/ipsecctl/parse.y b/sbin/ipsecctl/parse.y
index b0b5c149eab..8d34bab0d4c 100644
--- a/sbin/ipsecctl/parse.y
+++ b/sbin/ipsecctl/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.23 2005/08/19 08:47:56 hshoexer Exp $ */
+/* $OpenBSD: parse.y,v 1.24 2005/08/22 17:26:46 hshoexer Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -122,13 +122,17 @@ struct ipsec_rule *create_flow(u_int8_t, struct ipsec_addr *, struct
ipsec_addr *, struct ipsec_addr *, u_int8_t,
char *, char *, u_int16_t);
struct ipsec_rule *reverse_rule(struct ipsec_rule *);
+struct ipsec_rule *create_ike(struct ipsec_addr *, struct ipsec_addr *,
+ struct ipsec_addr *, struct ipsec_transforms *,
+ struct ipsec_transforms *, u_int8_t, u_int8_t,
+ char *, char *);
typedef struct {
union {
u_int32_t number;
+ u_int8_t ikemode;
u_int8_t dir;
char *string;
- int log;
u_int8_t protocol;
struct {
struct ipsec_addr *src;
@@ -159,6 +163,8 @@ typedef struct {
struct ipsec_key *keyin;
} keys;
struct ipsec_transforms *transforms;
+ struct ipsec_transforms *mmxfs;
+ struct ipsec_transforms *qmxfs;
} v;
int lineno;
} YYSTYPE;
@@ -166,7 +172,8 @@ typedef struct {
%}
%token FLOW FROM ESP AH IN PEER ON OUT TO SRCID DSTID RSA PSK TCPMD5 SPI
-%token AUTHKEY ENCKEY FILENAME AUTHXF ENCXF ERROR
+%token AUTHKEY ENCKEY FILENAME AUTHXF ENCXF ERROR IKE MAIN QUICK PASSIVE
+%token ACTIVE
%token <v.string> STRING
%type <v.dir> dir
%type <v.protocol> protocol
@@ -182,10 +189,14 @@ typedef struct {
%type <v.enckeys> enckeyspec
%type <v.keys> keyspec
%type <v.transforms> transforms
+%type <v.mmxfs> mmxfs
+%type <v.qmxfs> qmxfs
+%type <v.ikemode> ikemode
%%
grammar : /* empty */
| grammar '\n'
+ | grammar ikerule '\n'
| grammar flowrule '\n'
| grammar sarule '\n'
| grammar tcpmd5rule '\n'
@@ -283,6 +294,19 @@ flowrule : FLOW protocol dir hosts peer ids authtype {
}
;
+ikerule : IKE ikemode protocol hosts peer mmxfs qmxfs ids {
+ struct ipsec_rule *r;
+
+ r = create_ike($4.src, $4.dst, $5, $6, $7, $3, $2,
+ $8.srcid, $8.dstid);
+ if (r == NULL)
+ YYERROR;
+ r->nr = ipsec->rule_nr++;
+
+ if (ipsecctl_add_rule(ipsec, r))
+ errx(1, "ikerule: ipsecctl_add_rule");
+ };
+
protocol : /* empty */ { $$ = IPSEC_ESP; }
| ESP { $$ = IPSEC_ESP; }
| AH { $$ = IPSEC_AH; }
@@ -388,6 +412,7 @@ spispec : SPI STRING {
transforms : /* empty */ {
struct ipsec_transforms *xfs;
+ /* We create just an empty transform */
if ((xfs = calloc(1, sizeof(struct ipsec_transforms)))
== NULL)
err(1, "calloc");
@@ -421,6 +446,30 @@ transforms : /* empty */ {
}
;
+mmxfs : /* empty */ {
+ struct ipsec_transforms *xfs;
+
+ /* We create just an empty transform */
+ if ((xfs = calloc(1, sizeof(struct ipsec_transforms)))
+ == NULL)
+ err(1, "calloc");
+ $$ = xfs;
+ }
+ | MAIN transforms { $$ = $2; }
+ ;
+
+qmxfs : /* empty */ {
+ struct ipsec_transforms *xfs;
+
+ /* We create just an empty transform */
+ if ((xfs = calloc(1, sizeof(struct ipsec_transforms)))
+ == NULL)
+ err(1, "calloc");
+ $$ = xfs;
+ }
+ | QUICK transforms { $$ = $2; }
+ ;
+
authkeyspec : /* empty */ {
$$.keyout = NULL;
$$.keyin = NULL;
@@ -471,6 +520,10 @@ keyspec : STRING {
free($2);
}
;
+ikemode : /* empty */ { $$ = IKE_ACTIVE; }
+ | PASSIVE { $$ = IKE_PASSIVE; }
+ | ACTIVE { $$ = IKE_ACTIVE; }
+ ;
%%
struct keywords {
@@ -504,6 +557,7 @@ lookup(char *s)
{
/* this has to be sorted always */
static const struct keywords keywords[] = {
+ { "active", ACTIVE},
{ "ah", AH},
{ "auth", AUTHXF},
{ "authkey", AUTHKEY},
@@ -514,10 +568,14 @@ lookup(char *s)
{ "file", FILENAME},
{ "flow", FLOW},
{ "from", FROM},
+ { "ike", IKE},
{ "in", IN},
+ { "main", MAIN},
{ "out", OUT},
+ { "passive", PASSIVE},
{ "peer", PEER},
{ "psk", PSK},
+ { "quick", QUICK},
{ "rsa", RSA},
{ "spi", SPI},
{ "srcid", SRCID},
@@ -927,17 +985,22 @@ host(const char *s)
ipa = calloc(1, sizeof(struct ipsec_addr));
if (ipa == NULL)
err(1, "calloc");
+
+ if ((ipa->name = strdup(s)) == NULL)
+ err(1, "strdup");
if (strrchr(s, '/') != NULL) {
bits = inet_net_pton(AF_INET, s, &ipa->v4, sizeof(ipa->v4));
if (bits == -1 || bits > 32) {
+ free(ipa->name);
free(ipa);
return(NULL);
}
} else {
if (inet_pton(AF_INET, s, &ipa->v4) != 1) {
+ free(ipa->name);
free(ipa);
- return NULL;
+ return (NULL);
}
}
@@ -954,7 +1017,7 @@ host(const char *s)
ipa->af = AF_INET;
- return ipa;
+ return (ipa);
}
struct ipsec_addr *
@@ -965,8 +1028,12 @@ copyhost(const struct ipsec_addr *src)
dst = calloc(1, sizeof(struct ipsec_addr));
if (dst == NULL)
err(1, "calloc");
-
+
memcpy(dst, src, sizeof(struct ipsec_addr));
+
+ if ((dst->name = strdup(src->name)) == NULL)
+ err(1, "strdup");
+
return dst;
}
@@ -992,10 +1059,16 @@ transforms(const char *authname, const char *encname)
if (xfs == NULL)
err(1, "calloc");
- if (authname)
+ if (authname) {
xfs->authxf = parse_xf(authname, authxfs);
- if (encname)
+ if (xfs->authxf == NULL)
+ yyerror("%s not a valid transform", authname);
+ }
+ if (encname) {
xfs->encxf = parse_xf(encname, encxfs);
+ if (xfs->encxf == NULL)
+ yyerror("%s not a valid transform", encname);
+ }
return (xfs);
}
@@ -1242,3 +1315,62 @@ reverse_rule(struct ipsec_rule *rule)
return reverse;
}
+
+struct ipsec_rule *
+create_ike(struct ipsec_addr *src, struct ipsec_addr *dst, struct ipsec_addr *
+ peer, struct ipsec_transforms *mmxfs, struct ipsec_transforms *qmxfs,
+ u_int8_t proto, u_int8_t mode, char *srcid, char *dstid)
+{
+ struct ipsec_rule *r;
+
+ r = calloc(1, sizeof(struct ipsec_rule));
+ if (r == NULL)
+ err(1, "calloc");
+
+ r->type = RULE_IKE;
+
+ r->src = src;
+ r->dst = dst;
+
+ if (peer == NULL) {
+ /* Set peer to remote host. Must be a host address. */
+ if (r->direction == IPSEC_IN) {
+ if (r->src->netaddress) {
+ yyerror("no peer specified");
+ goto errout;
+ }
+ r->peer = copyhost(r->src);
+ } else {
+ if (r->dst->netaddress) {
+ yyerror("no peer specified");
+ goto errout;
+ }
+ r->peer = copyhost(r->dst);
+ }
+ } else
+ r->peer = peer;
+
+ r->proto = proto;
+ r->ikemode = mode;
+ r->mmxfs = mmxfs;
+ r->qmxfs = qmxfs;
+ r->auth = calloc(1, sizeof(struct ipsec_auth));
+ if (r->auth == NULL)
+ err(1, "calloc");
+ r->auth->srcid = srcid;
+ r->auth->dstid = dstid;
+ r->auth->idtype = ID_FQDN; /* XXX For now only FQDN. */
+
+ return (r);
+
+errout:
+ free(r);
+ if (srcid)
+ free(srcid);
+ if (dstid)
+ free(dstid);
+ free(src);
+ free(dst);
+
+ return (NULL);
+}
diff --git a/sbin/ipsecctl/pfkey.c b/sbin/ipsecctl/pfkey.c
index a96d6daa575..ff2814d5978 100644
--- a/sbin/ipsecctl/pfkey.c
+++ b/sbin/ipsecctl/pfkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkey.c,v 1.22 2005/08/09 12:37:45 hshoexer Exp $ */
+/* $OpenBSD: pfkey.c,v 1.23 2005/08/22 17:26:46 hshoexer Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
* Copyright (c) 2003, 2004 Markus Friedl <markus@openbsd.org>
@@ -831,11 +831,11 @@ pfkey_ipsec_establish(int action, struct ipsec_rule *r)
}
switch (action) {
- case PFK_ACTION_ADD:
+ case ACTION_ADD:
ret = pfkey_flow(fd, satype, SADB_X_ADDFLOW, direction,
r->src, r->dst, r->peer, r->auth, r->flowtype);
break;
- case PFK_ACTION_DELETE:
+ case ACTION_DELETE:
/* No peer for flow deletion. */
ret = pfkey_flow(fd, satype, SADB_X_DELFLOW, direction,
r->src, r->dst, NULL, NULL, r->flowtype);
@@ -858,11 +858,11 @@ pfkey_ipsec_establish(int action, struct ipsec_rule *r)
return -1;
}
switch (action) {
- case PFK_ACTION_ADD:
+ case ACTION_ADD:
ret = pfkey_sa(fd, satype, SADB_ADD, r->spi,
r->src, r->dst, r->xfs, r->authkey, r->enckey);
break;
- case PFK_ACTION_DELETE:
+ case ACTION_DELETE:
ret = pfkey_sa(fd, satype, SADB_DELETE, r->spi,
r->src, r->dst, r->xfs, NULL, NULL);
break;
diff --git a/sbin/ipsecctl/pfkey.h b/sbin/ipsecctl/pfkey.h
index b2bbceba503..8ff8bd16ad8 100644
--- a/sbin/ipsecctl/pfkey.h
+++ b/sbin/ipsecctl/pfkey.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkey.h,v 1.3 2005/06/30 18:27:14 hshoexer Exp $ */
+/* $OpenBSD: pfkey.h,v 1.4 2005/08/22 17:26:46 hshoexer Exp $ */
/*
* Copyright (c) 2004, 2005 Hans-Joerg Hoexer <hshoexer@openbsd.org>
*
@@ -20,10 +20,6 @@
#define PFKEYV2_CHUNK sizeof(u_int64_t)
-enum {
- PFK_ACTION_ADD, PFK_ACTION_DELETE
-};
-
int pfkey_parse(struct sadb_msg *, struct ipsec_rule *);
void pfkey_print_sa(struct sadb_msg *, int);
int pfkey_ipsec_establish(int, struct ipsec_rule *);