diff options
author | Hans-Joerg Hoexer <hshoexer@cvs.openbsd.org> | 2005-07-09 21:12:08 +0000 |
---|---|---|
committer | Hans-Joerg Hoexer <hshoexer@cvs.openbsd.org> | 2005-07-09 21:12:08 +0000 |
commit | 91eec04b6ec0820169a78aeb07fb7f03776c329d (patch) | |
tree | 8e03af04e3a7ffa2e04dd987443bb406448e54a5 /sbin | |
parent | f8981ea38815218f1299718d5ad49f3c612233cd (diff) |
add support tcpmd5
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/ipsecctl/ipsecctl.c | 75 | ||||
-rw-r--r-- | sbin/ipsecctl/parse.y | 115 |
2 files changed, 169 insertions, 21 deletions
diff --git a/sbin/ipsecctl/ipsecctl.c b/sbin/ipsecctl/ipsecctl.c index c5466c216c4..6323807274c 100644 --- a/sbin/ipsecctl/ipsecctl.c +++ b/sbin/ipsecctl/ipsecctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ipsecctl.c,v 1.16 2005/07/07 22:00:36 hshoexer Exp $ */ +/* $OpenBSD: ipsecctl.c,v 1.17 2005/07/09 21:12:07 hshoexer Exp $ */ /* * Copyright (c) 2004, 2005 Hans-Joerg Hoexer <hshoexer@openbsd.org> * @@ -43,6 +43,9 @@ FILE *ipsecctl_fopen(const char *, const char *); int ipsecctl_commit(int, struct ipsecctl *); int ipsecctl_add_rule(struct ipsecctl *, struct ipsec_rule *); void ipsecctl_print_addr(struct ipsec_addr *); +void ipsecctl_print_key(struct ipsec_key *); +void ipsecctl_print_flow(struct ipsec_rule *, int); +void ipsecctl_print_sa(struct ipsec_rule *, int); void ipsecctl_print_rule(struct ipsec_rule *, int); int ipsecctl_flush(int); void ipsecctl_get_rules(struct ipsecctl *); @@ -61,6 +64,13 @@ static const char *showopt_list[] = { "flow", "sa", "all", NULL }; +static const char *ruletype[] = {"?", "flow", "tcpmd5"}; +static const char *direction[] = {"?", "in", "out"}; +static const char *flowtype[] = {"?", "use", "acquire", "require", "deny", + "bypass", "dontacq"}; +static const char *proto[] = {"?", "esp", "ah"}; +static const char *auth[] = {"?", "psk", "rsa"}; + int ipsecctl_rules(char *filename, int opts) { @@ -135,13 +145,20 @@ ipsecctl_commit(int action, struct ipsecctl *ipsec) if (pfkey_ipsec_establish(action, rp) == -1) warnx("failed to add rule %d", rp->nr); + /* src and dst are always used. */ free(rp->src); free(rp->dst); - free(rp->peer); + + if (rp->peer) + free(rp->peer); if (rp->auth.srcid) free(rp->auth.srcid); if (rp->auth.dstid) free(rp->auth.dstid); + if (rp->key) { + free(rp->key->data); + free(rp->key); + } free(rp); } @@ -185,20 +202,19 @@ ipsecctl_print_addr(struct ipsec_addr *ipa) } void -ipsecctl_print_rule(struct ipsec_rule *r, int opts) +ipsecctl_print_key(struct ipsec_key *key) { - static const char *rule[] = {"?", "flow", "tcpmd5"}; - static const char *direction[] = {"?", "in", "out"}; - static const char *type[] = {"?", "use", "acquire", "require", "deny", - "bypass", "dontacq"}; - static const char *proto[] = {"?", "esp", "ah"}; - static const char *auth[] = {"?", "psk", "rsa"}; + int i; - if (opts & IPSECCTL_OPT_VERBOSE2) - printf("@%d ", r->nr); + for (i = 0; i < (int)key->len; i++) + printf("%02x", key->data[i]); +} + +void +ipsecctl_print_flow(struct ipsec_rule *r, int opts) +{ + printf(" %s %s", proto[r->proto], direction[r->direction]); - printf("%s %s %s", rule[r->type], proto[r->proto], - direction[r->direction]); printf(" from "); ipsecctl_print_addr(r->src); printf(" to "); @@ -213,8 +229,39 @@ ipsecctl_print_rule(struct ipsec_rule *r, int opts) printf("\n\tdstid %s", r->auth.dstid); if (r->auth.type > 0) printf("\n\t%s", auth[r->auth.type]); - printf("\n\ttype %s", type[r->flowtype]); + printf("\n\ttype %s", flowtype[r->flowtype]); + } +} + +void +ipsecctl_print_sa(struct ipsec_rule *r, int opts) +{ + printf(" from "); + ipsecctl_print_addr(r->src); + printf(" to "); + ipsecctl_print_addr(r->dst); + printf(" spi 0x%08x", r->spi); + printf(" key 0x"); + ipsecctl_print_key(r->key); +} + +void +ipsecctl_print_rule(struct ipsec_rule *r, int opts) +{ + if (opts & IPSECCTL_OPT_VERBOSE2) + printf("@%d ", r->nr); + + printf("%s", ruletype[r->type]); + + switch (r->type) { + case RULE_FLOW: + ipsecctl_print_flow(r, opts); + break; + case RULE_SA: + ipsecctl_print_sa(r, opts); + break; } + printf("\n"); } diff --git a/sbin/ipsecctl/parse.y b/sbin/ipsecctl/parse.y index a4fc1b1b7fc..3425c4b95c2 100644 --- a/sbin/ipsecctl/parse.y +++ b/sbin/ipsecctl/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.6 2005/07/07 22:00:36 hshoexer Exp $ */ +/* $OpenBSD: parse.y,v 1.7 2005/07/09 21:12:07 hshoexer Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -25,6 +25,7 @@ #include <sys/queue.h> #include <sys/socket.h> #include <netinet/in.h> +#include <netinet/ip_ipsp.h> #include <arpa/inet.h> #include <ctype.h> @@ -66,9 +67,12 @@ int symset(const char *, const char *, int); int cmdline_symset(char *); char *symget(const char *); int atoul(char *, u_long *); +u_int8_t x2i(unsigned char *); struct ipsec_addr *host(const char *); struct ipsec_addr *copyhost(const struct ipsec_addr *); -struct ipsec_rule *create_rule(u_int8_t, struct ipsec_addr *, struct +struct ipsec_rule *create_sa(struct ipsec_addr *, struct ipsec_addr *, + u_int32_t, struct ipsec_key *); +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 *); @@ -92,13 +96,15 @@ typedef struct { } ids; char *id; u_int16_t authtype; + u_int32_t spi; + struct ipsec_key *key; } v; int lineno; } YYSTYPE; %} -%token FLOW FROM ESP AH IN PEER ON OUT TO SRCID DSTID RSA PSK +%token FLOW FROM ESP AH IN PEER ON OUT TO SRCID DSTID RSA PSK TCPMD5 SPI KEY %token ERROR %token <v.string> STRING %type <v.dir> dir @@ -110,11 +116,14 @@ typedef struct { %type <v.ids> ids %type <v.id> id %type <v.authtype> authtype +%type <v.spi> spi +%type <v.key> key %% grammar : /* empty */ | grammar '\n' | grammar flowrule '\n' + | grammar tcpmd5rule '\n' | grammar error '\n' { errors++; } ; @@ -125,18 +134,36 @@ number : STRING { yyerror("%s is not a number", $1); free($1); YYERROR; - } else - $$ = ulval; + } + if (ulval > UINT_MAX) { + yyerror("0x%lx out of range", ulval); + free($1); + YYERROR; + } + $$ = (u_int32_t)ulval; free($1); } flowrule : FLOW ipsecrule { } ; +tcpmd5rule : TCPMD5 hosts spi key { + struct ipsec_rule *r; + + r = create_sa($2.src, $2.dst, $3, $4); + if (r == NULL) + YYERROR; + r->nr = ipsec->rule_nr++; + + if (ipsecctl_add_rule(ipsec, r)) + errx(1, "tcpmd5rule: ipsecctl_add_rule"); + } + ; + ipsecrule : protocol dir hosts peer ids authtype { struct ipsec_rule *r; - r = create_rule($2, $3.src, $3.dst, $4, $1, $5.srcid, + r = create_flow($2, $3.src, $3.dst, $4, $1, $5.srcid, $5.dstid, $6); if (r == NULL) YYERROR; @@ -231,6 +258,41 @@ authtype : /* empty */ { $$ = 0; } | RSA { $$ = AUTH_RSA; } | PSK { $$ = AUTH_PSK; } ; + +spi : SPI number { + if ($2 >= SPI_RESERVED_MIN && $2 <= SPI_RESERVED_MAX) { + yyerror("invalid spi 0x%lx", $2); + YYERROR; + } + $$ = $2; + } + ; + +key : KEY STRING { + struct ipsec_key *key; + int i; + char *hexkey; + + hexkey = $2; + if (!strncmp(hexkey, "0x", 2)) + hexkey += 2; + + key = calloc(1, sizeof(struct ipsec_key)); + if (key == NULL) + err(1, "calloc:"); + + key->len = strlen(hexkey) / 2; + key->data = calloc(key->len, sizeof(u_int8_t)); + if (key->data == NULL) + err(1, "calloc:"); + + for (i = 0; i < (int)key->len; i++) + key->data[i] = x2i(hexkey + 2 * i); + + $$ = key; + free($2); + } + ; %% struct keywords { @@ -270,11 +332,14 @@ lookup(char *s) { "flow", FLOW}, { "from", FROM}, { "in", IN}, + { "key", KEY}, { "out", OUT}, { "peer", PEER}, { "psk", PSK}, { "rsa", RSA}, + { "spi", SPI}, { "srcid", SRCID}, + { "tcpmd5", TCPMD5}, { "to", TO}, }; const struct keywords *p; @@ -594,6 +659,22 @@ atoul(char *s, u_long *ulvalp) return (0); } +u_int8_t +x2i(unsigned char *s) +{ + char ss[3]; + + ss[0] = s[0]; + ss[1] = s[1]; + ss[2] = 0; + + if (!isxdigit(s[0]) || !isxdigit(s[1])) { + yyerror("keys need to be specified in hex digits"); + return -1; + } + return ((u_int8_t)strtoul(ss, NULL, 16)); +} + struct ipsec_addr * host(const char *s) { @@ -649,7 +730,27 @@ copyhost(const struct ipsec_addr *src) } struct ipsec_rule * -create_rule(u_int8_t dir, struct ipsec_addr *src, struct ipsec_addr *dst, +create_sa(struct ipsec_addr *src, struct ipsec_addr *dst, u_int32_t spi, + struct ipsec_key *key) +{ + struct ipsec_rule *r; + + r = calloc(1, sizeof(struct ipsec_rule)); + if (r == NULL) + err(1, "calloc"); + + r->type = RULE_SA; + + r->src = src; + r->dst = dst; + r->spi = spi; + r->key = key; + + return r; +} + +struct ipsec_rule * +create_flow(u_int8_t dir, struct ipsec_addr *src, struct ipsec_addr *dst, struct ipsec_addr *peer, u_int8_t proto, char *srcid, char *dstid, u_int16_t authtype) { |