diff options
author | Hans-Joerg Hoexer <hshoexer@cvs.openbsd.org> | 2005-08-22 17:26:47 +0000 |
---|---|---|
committer | Hans-Joerg Hoexer <hshoexer@cvs.openbsd.org> | 2005-08-22 17:26:47 +0000 |
commit | 52d0815f533373817d503611005204c0608d5379 (patch) | |
tree | 071c31bcf1062707250b909f23159ae41caf7457 /sbin | |
parent | 9e4e60c7b87a0ea47e7c7222e5d9c35a51047a05 (diff) |
Teach ipsecctl to control isakmpd.
ok deraadt
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/ipsecctl/Makefile | 4 | ||||
-rw-r--r-- | sbin/ipsecctl/ike.c | 378 | ||||
-rw-r--r-- | sbin/ipsecctl/ipsecctl.c | 31 | ||||
-rw-r--r-- | sbin/ipsecctl/ipsecctl.h | 24 | ||||
-rw-r--r-- | sbin/ipsecctl/parse.y | 148 | ||||
-rw-r--r-- | sbin/ipsecctl/pfkey.c | 10 | ||||
-rw-r--r-- | sbin/ipsecctl/pfkey.h | 6 |
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 *); |