diff options
author | Hans-Joerg Hoexer <hshoexer@cvs.openbsd.org> | 2005-08-08 13:29:01 +0000 |
---|---|---|
committer | Hans-Joerg Hoexer <hshoexer@cvs.openbsd.org> | 2005-08-08 13:29:01 +0000 |
commit | 1ae33a9b91fcb7c602c32fabfab8bf4334565c1b (patch) | |
tree | 6f7a9feafea9ad893ef0193c446e43fa1a0b1297 /sbin | |
parent | aa265bd00546d9ebfb6a04dd18e957052d87896f (diff) |
add crypto transforms and static keying rules
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/ipsecctl/ipsecctl.c | 21 | ||||
-rw-r--r-- | sbin/ipsecctl/ipsecctl.h | 21 | ||||
-rw-r--r-- | sbin/ipsecctl/parse.y | 192 |
3 files changed, 215 insertions, 19 deletions
diff --git a/sbin/ipsecctl/ipsecctl.c b/sbin/ipsecctl/ipsecctl.c index 465e2b85c18..1eba368d4e7 100644 --- a/sbin/ipsecctl/ipsecctl.c +++ b/sbin/ipsecctl/ipsecctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ipsecctl.c,v 1.23 2005/08/08 09:15:09 hshoexer Exp $ */ +/* $OpenBSD: ipsecctl.c,v 1.24 2005/08/08 13:29:00 hshoexer Exp $ */ /* * Copyright (c) 2004, 2005 Hans-Joerg Hoexer <hshoexer@openbsd.org> * @@ -246,12 +246,27 @@ ipsecctl_print_sa(struct ipsec_rule *r, int opts) printf(" to "); ipsecctl_print_addr(r->dst); printf(" spi 0x%08x", r->spi); + + if (r->proto != IPSEC_TCPMD5) { + if (r->authxf) + printf(" auth %s", r->authxf->name); + if (r->encxf) + printf(" enc %s", r->encxf->name); + } if (r->authkey) { - printf(" authkey 0x"); + if (r->proto == IPSEC_TCPMD5) + printf(" "); + else + printf("\n\t"); + printf("authkey 0x"); ipsecctl_print_key(r->authkey); } if (r->enckey) { - printf(" enckey 0x"); + if (r->proto == IPSEC_TCPMD5) + printf(" "); + else + printf("\n\t"); + printf("enckey 0x"); ipsecctl_print_key(r->enckey); } } diff --git a/sbin/ipsecctl/ipsecctl.h b/sbin/ipsecctl/ipsecctl.h index e9a6eca54d1..0e85060f9ef 100644 --- a/sbin/ipsecctl/ipsecctl.h +++ b/sbin/ipsecctl/ipsecctl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ipsecctl.h,v 1.14 2005/08/08 09:15:09 hshoexer Exp $ */ +/* $OpenBSD: ipsecctl.h,v 1.15 2005/08/08 13:29:00 hshoexer Exp $ */ /* * Copyright (c) 2004, 2005 Hans-Joerg Hoexer <hshoexer@openbsd.org> * @@ -48,10 +48,13 @@ enum { TYPE_BYPASS, TYPE_DONTACQ }; enum { - ENC_NONE + AUTHXF_UNKNOWN, AUTHXF_NONE, AUTHXF_HMAC_MD5, AUTHXF_HMAC_RIPEMD160, + AUTHXF_HMAC_SHA1, AUTHXF_HMAC_SHA2_256, AUTHXF_HMAC_SHA2_384, + AUTHXF_HMAC_SHA2_512, AUTHXF_MD5, AUTHXF_SHA1 }; enum { - AUTH_NONE + ENCXF_UNKNOWN,ENCXF_NONE, ENCXF_3DES_CBC, ENCXF_DES_CBC, ENCXF_AES, + ENCXF_AESCTR, ENCXF_BLOWFISH, ENCXF_CAST128, ENCXF_NULL, ENCXF_SKIPJACK }; struct ipsec_addr { @@ -76,6 +79,16 @@ struct ipsec_key { u_int8_t *data; }; +struct ipsec_xf { + char *name; + u_int16_t id; + size_t keymin; + size_t keymax; +}; + +extern const struct ipsec_xf authxfs[]; +extern const struct ipsec_xf encxfs[]; + /* Complete state of one rule. */ struct ipsec_rule { u_int8_t type; @@ -84,6 +97,8 @@ struct ipsec_rule { struct ipsec_addr *dst; struct ipsec_addr *peer; struct ipsec_auth *auth; + const struct ipsec_xf *authxf; + const struct ipsec_xf *encxf; struct ipsec_key *authkey; struct ipsec_key *enckey; diff --git a/sbin/ipsecctl/parse.y b/sbin/ipsecctl/parse.y index dbc98420294..3c5ea5ab94c 100644 --- a/sbin/ipsecctl/parse.y +++ b/sbin/ipsecctl/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.19 2005/08/08 09:15:09 hshoexer Exp $ */ +/* $OpenBSD: parse.y,v 1.20 2005/08/08 13:29:00 hshoexer Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -50,6 +50,34 @@ static int lineno = 1; static int errors = 0; static int debug = 0; +const struct ipsec_xf authxfs[] = { + {"unknown", AUTHXF_UNKNOWN, 0, 0}, + {"none", AUTHXF_NONE, 0, 0}, + {"hmac-md5", AUTHXF_HMAC_MD5, 16, 0}, + {"hmac-ripemd160", AUTHXF_HMAC_RIPEMD160, 20, 0}, + {"hmac-sha1", AUTHXF_HMAC_SHA1, 20, 0}, + {"hmac-sha2-256", AUTHXF_HMAC_SHA2_256, 32, 0}, + {"hmac-sha2-384", AUTHXF_HMAC_SHA2_384, 48, 0}, + {"hmac-sha2-512", AUTHXF_HMAC_SHA2_512, 64, 0}, + {"md5", AUTHXF_MD5, 16, 0}, + {"sha1", AUTHXF_SHA1, 20, 0}, + {NULL, 0, 0, 0}, +}; + +const struct ipsec_xf encxfs[] = { + {"unknown", ENCXF_UNKNOWN, 0, 0}, + {"none", ENCXF_NONE, 0, 0}, + {"3des-cbc", ENCXF_3DES_CBC, 8, 8}, + {"des-cbc", ENCXF_DES_CBC, 8, 8}, + {"aes", ENCXF_AES, 16, 32}, + {"aesctr", ENCXF_AESCTR, 16+4, 32+4}, + {"blowfish", ENCXF_BLOWFISH, 5, 56}, + {"cast128", ENCXF_CAST128, 5, 16}, + {"null", ENCXF_NULL, 0, 0}, + {"skipjack", ENCXF_SKIPJACK, 10, 10}, + {NULL, 0, 0, 0}, +}; + int yyerror(const char *, ...); int yyparse(void); int kw_cmp(const void *, const void *); @@ -78,9 +106,14 @@ struct ipsec_key *parsekey(unsigned char *, size_t); struct ipsec_key *parsekeyfile(char *); struct ipsec_addr *host(const char *); struct ipsec_addr *copyhost(const struct ipsec_addr *); +const struct ipsec_xf *parse_xf(const char *, const struct ipsec_xf *); +int validate_sa(u_int32_t, u_int8_t, + const struct ipsec_xf *, const struct ipsec_xf *, + struct ipsec_key *, struct ipsec_key *); struct ipsec_rule *create_sa(u_int8_t, struct ipsec_addr *, - struct ipsec_addr *, u_int32_t, u_int16_t, - u_int16_t, struct ipsec_key *, struct ipsec_key *); + struct ipsec_addr *, u_int32_t, + const struct ipsec_xf *, const struct ipsec_xf *, + struct ipsec_key *, struct ipsec_key *); struct ipsec_rule *reverse_sa(struct ipsec_rule *, u_int32_t, struct ipsec_key *, struct ipsec_key *); struct ipsec_rule *create_flow(u_int8_t, struct ipsec_addr *, struct @@ -123,6 +156,10 @@ typedef struct { struct ipsec_key *keyout; struct ipsec_key *keyin; } keys; + struct { + const struct ipsec_xf *authxf; + const struct ipsec_xf *encxf; + } transforms; } v; int lineno; } YYSTYPE; @@ -130,7 +167,7 @@ typedef struct { %} %token FLOW FROM ESP AH IN PEER ON OUT TO SRCID DSTID RSA PSK TCPMD5 SPI -%token AUTHKEY ENCKEY FILENAME ERROR +%token AUTHKEY ENCKEY FILENAME AUTHXF ENCXF ERROR %token <v.string> STRING %type <v.dir> dir %type <v.protocol> protocol @@ -145,11 +182,13 @@ typedef struct { %type <v.authkeys> authkeyspec %type <v.enckeys> enckeyspec %type <v.keys> keyspec +%type <v.transforms> transforms %% grammar : /* empty */ | grammar '\n' | grammar flowrule '\n' + | grammar sarule '\n' | grammar tcpmd5rule '\n' | grammar error '\n' { errors++; } ; @@ -175,7 +214,7 @@ tcpmd5rule : TCPMD5 hosts spispec authkeyspec { struct ipsec_rule *r; r = create_sa(IPSEC_TCPMD5, $2.src, $2.dst, $3.spiout, - AUTH_NONE, ENC_NONE, $4.keyout, NULL); + NULL, NULL, $4.keyout, NULL); if (r == NULL) YYERROR; r->nr = ipsec->rule_nr++; @@ -196,6 +235,32 @@ tcpmd5rule : TCPMD5 hosts spispec authkeyspec { } ; +sarule : protocol hosts spispec transforms authkeyspec enckeyspec { + struct ipsec_rule *r; + + r = create_sa($1, $2.src, $2.dst, $3.spiout, + $4.authxf, $4.encxf, $5.keyout, $6.keyout); + if (r == NULL) + YYERROR; + r->nr = ipsec->rule_nr++; + + if (ipsecctl_add_rule(ipsec, r)) + errx(1, "sarule: ipsecctl_add_rule"); + + /* Create and add reverse SA rule. */ + if ($3.spiin != 0 || $5.keyin || $6.keyin) { + r = reverse_sa(r, $3.spiin, $5.keyin, + $6.keyin); + if (r == NULL) + YYERROR; + r->nr = ipsec->rule_nr++; + + if (ipsecctl_add_rule(ipsec, r)) + errx(1, "sarule: ipsecctl_add_rule"); + } + } + ; + flowrule : FLOW protocol dir hosts peer ids authtype { struct ipsec_rule *r; @@ -321,6 +386,44 @@ spispec : SPI STRING { } ; +transforms : /* empty */ { + $$.authxf = &authxfs[AUTHXF_HMAC_SHA2_256]; + $$.encxf = &encxfs[ENCXF_AESCTR]; + } + | AUTHXF STRING ENCXF STRING { + $$.authxf = parse_xf($2, authxfs); + free($2); + if ($$.authxf == NULL) { + yyerror("could not parse authentication xf"); + YYERROR; + } + $$.encxf = parse_xf($4, encxfs); + free($4); + if ($$.encxf == NULL) { + yyerror("could not parse encryption xf"); + YYERROR; + } + } + | AUTHXF STRING { + $$.encxf = &encxfs[ENCXF_AESCTR]; + $$.authxf = parse_xf($2, authxfs); + free($2); + if ($$.authxf == NULL) { + yyerror("could not parse authentication xf"); + YYERROR; + } + } + | ENCXF STRING { + $$.authxf = &authxfs[AUTHXF_HMAC_SHA2_256]; + $$.encxf = parse_xf($2, encxfs); + free($2); + if ($$.encxf == NULL) { + yyerror("could not parse encryption xf"); + YYERROR; + } + } + ; + authkeyspec : /* empty */ { $$.keyout = NULL; $$.keyin = NULL; @@ -405,8 +508,10 @@ lookup(char *s) /* this has to be sorted always */ static const struct keywords keywords[] = { { "ah", AH}, + { "auth", AUTHXF}, { "authkey", AUTHKEY}, { "dstid", DSTID}, + { "enc", ENCXF}, { "enckey", ENCKEY}, { "esp", ESP}, { "file", FILENAME}, @@ -746,8 +851,10 @@ atospi(char *s, u_int32_t *spivalp) if (atoul(s, &ulval) == -1) return (-1); - if (ulval >= SPI_RESERVED_MIN && ulval <= SPI_RESERVED_MAX) + if (ulval >= SPI_RESERVED_MIN && ulval <= SPI_RESERVED_MAX) { + yyerror("illegal SPI value"); return (-1); + } *spivalp = ulval; return (0); } @@ -866,16 +973,72 @@ copyhost(const struct ipsec_addr *src) return dst; } +const struct ipsec_xf * +parse_xf(const char *name, const struct ipsec_xf xfs[]) +{ + int i; + + for (i = 0; xfs[i].name != NULL; i++) { + if (strncmp(name, xfs[i].name, strlen(name))) + continue; + return &xfs[i]; + } + return (NULL); +} + +int +validate_sa(u_int32_t spi, u_int8_t protocol, const struct ipsec_xf *authxf, + const struct ipsec_xf *encxf, struct ipsec_key *authkey, + struct ipsec_key *enckey) +{ + /* Sanity checks */ + if (spi == 0) { + yyerror("no SPI specified"); + return (0); + } + if (protocol == IPSEC_TCPMD5 && authkey == NULL) { + yyerror("authentication key needed for tcpmd5"); + return (0); + } + if (authxf) { + if (!authkey) { + yyerror("no authentication key specified"); + return (0); + } + if (authkey->len != authxf->keymin) { + yyerror("wrong authentication key length, needs to be " + "%d bits", authxf->keymin * 8); + return (0); + } + } + if (encxf) { + if (!enckey) { + yyerror("no encryption key specified"); + return (0); + } + if (enckey->len < encxf->keymin) { + yyerror("encryption key too short, minimum %d bits", + encxf->keymin * 8); + return (0); + } + if (encxf->keymax < enckey->len) { + yyerror("encryption key too long, maximum %d bits", + encxf->keymax * 8); + return (0); + } + } + + return 1; +} + struct ipsec_rule * create_sa(u_int8_t protocol, struct ipsec_addr *src, struct ipsec_addr *dst, - u_int32_t spi, u_int16_t authxf, u_int16_t encxf, + u_int32_t spi, const struct ipsec_xf *authxf, const struct ipsec_xf *encxf, struct ipsec_key *authkey, struct ipsec_key *enckey) { struct ipsec_rule *r; - if (spi == 0) - return (NULL); - if (protocol == IPSEC_TCPMD5 && authkey == NULL) + if (validate_sa(spi, protocol, authxf, encxf, authkey, enckey) == 0) return (NULL); r = calloc(1, sizeof(struct ipsec_rule)); @@ -887,6 +1050,8 @@ create_sa(u_int8_t protocol, struct ipsec_addr *src, struct ipsec_addr *dst, r->src = src; r->dst = dst; r->spi = spi; + r->authxf = authxf; + r->encxf = encxf; r->authkey = authkey; r->enckey = enckey; @@ -899,9 +1064,8 @@ reverse_sa(struct ipsec_rule *rule, u_int32_t spi, struct ipsec_key *authkey, { struct ipsec_rule *reverse; - if (spi == 0) - return (NULL); - if (rule->proto == IPSEC_TCPMD5 && authkey == NULL) + if (validate_sa(spi, rule->proto, rule->authxf, rule->encxf, authkey, + enckey) == 0) return (NULL); reverse = calloc(1, sizeof(struct ipsec_rule)); @@ -913,6 +1077,8 @@ reverse_sa(struct ipsec_rule *rule, u_int32_t spi, struct ipsec_key *authkey, reverse->src = copyhost(rule->dst); reverse->dst = copyhost(rule->src); reverse->spi = spi; + reverse->authxf = rule->authxf; + reverse->encxf = rule->encxf; reverse->authkey = authkey; reverse->enckey = enckey; |