diff options
author | Hans-Joerg Hoexer <hshoexer@cvs.openbsd.org> | 2005-08-09 12:37:46 +0000 |
---|---|---|
committer | Hans-Joerg Hoexer <hshoexer@cvs.openbsd.org> | 2005-08-09 12:37:46 +0000 |
commit | 1e540711bb6cafcb339cac85392e23b8288b67eb (patch) | |
tree | 8a17ce0783e6e6645b76dad221485558adb4b6ad /sbin/ipsecctl | |
parent | b15edfb230e8fc9ccae7c9f1890170dc936cdfd3 (diff) |
Rewrite handling of transforms. Now both ah and esp can be specified and
validated correctly. Unbreaks ah.
Diffstat (limited to 'sbin/ipsecctl')
-rw-r--r-- | sbin/ipsecctl/ipsecctl.c | 16 | ||||
-rw-r--r-- | sbin/ipsecctl/ipsecctl.h | 10 | ||||
-rw-r--r-- | sbin/ipsecctl/parse.y | 158 | ||||
-rw-r--r-- | sbin/ipsecctl/pfkey.c | 31 |
4 files changed, 137 insertions, 78 deletions
diff --git a/sbin/ipsecctl/ipsecctl.c b/sbin/ipsecctl/ipsecctl.c index 1eba368d4e7..14852b333a1 100644 --- a/sbin/ipsecctl/ipsecctl.c +++ b/sbin/ipsecctl/ipsecctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ipsecctl.c,v 1.24 2005/08/08 13:29:00 hshoexer Exp $ */ +/* $OpenBSD: ipsecctl.c,v 1.25 2005/08/09 12:37:45 hshoexer Exp $ */ /* * Copyright (c) 2004, 2005 Hans-Joerg Hoexer <hshoexer@openbsd.org> * @@ -157,10 +157,16 @@ ipsecctl_commit(int action, struct ipsecctl *ipsec) free(rp->auth->dstid); } free(rp->auth); + if (rp->xfs) + free(rp->xfs); if (rp->authkey) { free(rp->authkey->data); free(rp->authkey); } + if (rp->enckey) { + free(rp->enckey->data); + free(rp->enckey); + } free(rp); } @@ -248,10 +254,10 @@ ipsecctl_print_sa(struct ipsec_rule *r, int opts) 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->xfs && r->xfs->authxf) + printf(" auth %s", r->xfs->authxf->name); + if (r->xfs && r->xfs->encxf) + printf(" enc %s", r->xfs->encxf->name); } if (r->authkey) { if (r->proto == IPSEC_TCPMD5) diff --git a/sbin/ipsecctl/ipsecctl.h b/sbin/ipsecctl/ipsecctl.h index 0e85060f9ef..14c086db724 100644 --- a/sbin/ipsecctl/ipsecctl.h +++ b/sbin/ipsecctl/ipsecctl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ipsecctl.h,v 1.15 2005/08/08 13:29:00 hshoexer Exp $ */ +/* $OpenBSD: ipsecctl.h,v 1.16 2005/08/09 12:37:45 hshoexer Exp $ */ /* * Copyright (c) 2004, 2005 Hans-Joerg Hoexer <hshoexer@openbsd.org> * @@ -86,6 +86,11 @@ struct ipsec_xf { size_t keymax; }; +struct ipsec_transforms { + const struct ipsec_xf *authxf; + const struct ipsec_xf *encxf; +}; + extern const struct ipsec_xf authxfs[]; extern const struct ipsec_xf encxfs[]; @@ -97,8 +102,7 @@ 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_transforms *xfs; struct ipsec_key *authkey; struct ipsec_key *enckey; diff --git a/sbin/ipsecctl/parse.y b/sbin/ipsecctl/parse.y index 5560ac3d059..78694d44e75 100644 --- a/sbin/ipsecctl/parse.y +++ b/sbin/ipsecctl/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.21 2005/08/09 12:35:25 hshoexer Exp $ */ +/* $OpenBSD: parse.y,v 1.22 2005/08/09 12:37:45 hshoexer Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -107,13 +107,15 @@ 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 *); +struct ipsec_transforms *transforms(const char *, const char *); +struct ipsec_transforms *copytransforms(const struct ipsec_transforms *); 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_transforms *, struct ipsec_key *, + struct ipsec_key *); struct ipsec_rule *create_sa(u_int8_t, struct ipsec_addr *, struct ipsec_addr *, u_int32_t, - const struct ipsec_xf *, const struct ipsec_xf *, - struct ipsec_key *, struct ipsec_key *); + struct ipsec_transforms *, 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 @@ -156,10 +158,7 @@ typedef struct { struct ipsec_key *keyout; struct ipsec_key *keyin; } keys; - struct { - const struct ipsec_xf *authxf; - const struct ipsec_xf *encxf; - } transforms; + struct ipsec_transforms *transforms; } v; int lineno; } YYSTYPE; @@ -214,7 +213,7 @@ tcpmd5rule : TCPMD5 hosts spispec authkeyspec { struct ipsec_rule *r; r = create_sa(IPSEC_TCPMD5, $2.src, $2.dst, $3.spiout, - NULL, NULL, $4.keyout, NULL); + NULL, $4.keyout, NULL); if (r == NULL) YYERROR; r->nr = ipsec->rule_nr++; @@ -238,8 +237,8 @@ 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); + r = create_sa($1, $2.src, $2.dst, $3.spiout, $4, + $5.keyout, $6.keyout); if (r == NULL) YYERROR; r->nr = ipsec->rule_nr++; @@ -387,40 +386,38 @@ spispec : SPI STRING { ; transforms : /* empty */ { - $$.authxf = &authxfs[AUTHXF_HMAC_SHA2_256]; - $$.encxf = &encxfs[ENCXF_AESCTR]; + struct ipsec_transforms *xfs; + + if ((xfs = calloc(1, sizeof(struct ipsec_transforms))) + == NULL) + err(1, "calloc"); + $$ = xfs; } | AUTHXF STRING ENCXF STRING { - $$.authxf = parse_xf($2, authxfs); - free($2); - if ($$.authxf == NULL) { - yyerror("could not parse authentication xf"); + if (($$ = transforms($2, $4)) == NULL) { + free($2); + free($4); + yyerror("could not parse transforms"); YYERROR; } - $$.encxf = parse_xf($4, encxfs); + free($2); 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"); + if (($$ = transforms($2, NULL)) == NULL) { + free($2); + yyerror("could not parse transforms"); YYERROR; } + free($2); } | ENCXF STRING { - $$.authxf = &authxfs[AUTHXF_HMAC_SHA2_256]; - $$.encxf = parse_xf($2, encxfs); - free($2); - if ($$.encxf == NULL) { - yyerror("could not parse encryption xf"); + if (($$ = transforms(NULL, $2)) == NULL) { + free($2); + yyerror("could not parse transforms"); YYERROR; } + free($2); } ; @@ -986,46 +983,102 @@ parse_xf(const char *name, const struct ipsec_xf xfs[]) return (NULL); } +struct ipsec_transforms * +transforms(const char *authname, const char *encname) +{ + struct ipsec_transforms *xfs; + + xfs = calloc(1, sizeof(struct ipsec_transforms)); + if (xfs == NULL) + err(1, "calloc"); + + if (authname) + xfs->authxf = parse_xf(authname, authxfs); + if (encname) + xfs->encxf = parse_xf(encname, encxfs); + + return (xfs); +} + +struct ipsec_transforms * +copytransforms(const struct ipsec_transforms *xfs) +{ + struct ipsec_transforms *newxfs; + + if (xfs == NULL) + return (NULL); + + newxfs = calloc(1, sizeof(struct ipsec_transforms)); + if (newxfs == NULL) + err(1, "calloc"); + + memcpy(newxfs, xfs, sizeof(struct ipsec_transforms)); + return (newxfs); +} + 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) +validate_sa(u_int32_t spi, u_int8_t protocol, struct ipsec_transforms *xfs, + struct ipsec_key *authkey, struct ipsec_key *enckey) { /* Sanity checks */ if (spi == 0) { yyerror("no SPI specified"); return (0); } + if (protocol == IPSEC_AH) { + if (!xfs) { + yyerror("no transforms specified"); + return (0); + } + if (!xfs->authxf) + xfs->authxf = &authxfs[AUTHXF_HMAC_SHA2_256]; + if (xfs->encxf) { + yyerror("ah does not provide encryption"); + return (0); + } + } + if (protocol == IPSEC_ESP) { + if (!xfs) { + yyerror("no transforms specified"); + return (0); + } + if (!xfs->authxf) + xfs->authxf = &authxfs[AUTHXF_HMAC_SHA2_256]; + if (!xfs->encxf) + xfs->encxf = &encxfs[ENCXF_AESCTR]; + } if (protocol == IPSEC_TCPMD5 && authkey == NULL) { yyerror("authentication key needed for tcpmd5"); return (0); } - if (authxf) { + if (xfs && xfs->authxf) { if (!authkey) { yyerror("no authentication key specified"); return (0); } - if (authkey->len != authxf->keymin) { + if (authkey->len != xfs->authxf->keymin) { yyerror("wrong authentication key length, needs to be " - "%d bits", authxf->keymin * 8); + "%d bits", xfs->authxf->keymin * 8); return (0); } } - if (encxf) { - if (!enckey) { + if (xfs && xfs->encxf) { + if (!enckey && xfs->encxf != &encxfs[ENCXF_NULL]) { yyerror("no encryption key specified"); return (0); } - if (enckey->len < encxf->keymin) { + if (enckey) { + if (enckey->len < xfs->encxf->keymin) { yyerror("encryption key too short, minimum %d bits", - encxf->keymin * 8); + xfs->encxf->keymin * 8); return (0); } - if (encxf->keymax < enckey->len) { + if (xfs->encxf->keymax < enckey->len) { yyerror("encryption key too long, maximum %d bits", - encxf->keymax * 8); + xfs->encxf->keymax * 8); return (0); } + } } return 1; @@ -1033,12 +1086,12 @@ validate_sa(u_int32_t spi, u_int8_t protocol, const struct ipsec_xf *authxf, struct ipsec_rule * create_sa(u_int8_t protocol, struct ipsec_addr *src, struct ipsec_addr *dst, - u_int32_t spi, const struct ipsec_xf *authxf, const struct ipsec_xf *encxf, - struct ipsec_key *authkey, struct ipsec_key *enckey) + u_int32_t spi, struct ipsec_transforms *xfs, struct ipsec_key *authkey, + struct ipsec_key *enckey) { struct ipsec_rule *r; - if (validate_sa(spi, protocol, authxf, encxf, authkey, enckey) == 0) + if (validate_sa(spi, protocol, xfs, authkey, enckey) == 0) return (NULL); r = calloc(1, sizeof(struct ipsec_rule)); @@ -1050,8 +1103,7 @@ 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->xfs = xfs; r->authkey = authkey; r->enckey = enckey; @@ -1064,8 +1116,7 @@ reverse_sa(struct ipsec_rule *rule, u_int32_t spi, struct ipsec_key *authkey, { struct ipsec_rule *reverse; - if (validate_sa(spi, rule->proto, rule->authxf, rule->encxf, authkey, - enckey) == 0) + if (validate_sa(spi, rule->proto, rule->xfs, authkey, enckey) == 0) return (NULL); reverse = calloc(1, sizeof(struct ipsec_rule)); @@ -1077,8 +1128,7 @@ 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->xfs = copytransforms(rule->xfs); reverse->authkey = authkey; reverse->enckey = enckey; diff --git a/sbin/ipsecctl/pfkey.c b/sbin/ipsecctl/pfkey.c index 0768c566bbb..a96d6daa575 100644 --- a/sbin/ipsecctl/pfkey.c +++ b/sbin/ipsecctl/pfkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfkey.c,v 1.21 2005/08/08 14:19:16 hshoexer Exp $ */ +/* $OpenBSD: pfkey.c,v 1.22 2005/08/09 12:37:45 hshoexer Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> * Copyright (c) 2003, 2004 Markus Friedl <markus@openbsd.org> @@ -45,8 +45,8 @@ static int pfkey_flow(int, u_int8_t, u_int8_t, u_int8_t, struct ipsec_addr *, struct ipsec_addr *, struct ipsec_addr *, struct ipsec_auth *, u_int8_t); static int pfkey_sa(int, u_int8_t, u_int8_t, u_int32_t, - struct ipsec_addr *, struct ipsec_addr *, const struct - ipsec_xf *, const struct ipsec_xf *, struct ipsec_key *, + struct ipsec_addr *, struct ipsec_addr *, + struct ipsec_transforms *, struct ipsec_key *, struct ipsec_key *); static int pfkey_reply(int); int pfkey_parse(struct sadb_msg *, struct ipsec_rule *); @@ -303,10 +303,9 @@ out: } static int -pfkey_sa(int sd, u_int8_t satype, u_int8_t action, u_int32_t spi, - struct ipsec_addr *src, struct ipsec_addr *dst, const struct ipsec_xf - *authxf, const struct ipsec_xf *encxf, struct ipsec_key *authkey, - struct ipsec_key *enckey) +pfkey_sa(int sd, u_int8_t satype, u_int8_t action, u_int32_t spi, struct + ipsec_addr *src, struct ipsec_addr *dst, struct ipsec_transforms *xfs, + struct ipsec_key *authkey, struct ipsec_key *enckey) { struct sadb_msg smsg; struct sadb_sa sa; @@ -357,8 +356,8 @@ pfkey_sa(int sd, u_int8_t satype, u_int8_t action, u_int32_t spi, sa.sadb_sa_spi = htonl(spi); sa.sadb_sa_state = SADB_SASTATE_MATURE; - if (authxf) { - switch (authxf->id) { + if (xfs && xfs->authxf) { + switch (xfs->authxf->id) { case AUTHXF_NONE: break; case AUTHXF_HMAC_MD5: @@ -387,11 +386,11 @@ pfkey_sa(int sd, u_int8_t satype, u_int8_t action, u_int32_t spi, break; default: warnx("unsupported authentication algorithm %d", - authxf->id); + xfs->authxf->id); } } - if (encxf) { - switch (encxf->id) { + if (xfs && xfs->encxf) { + switch (xfs->encxf->id) { case ENCXF_NONE: break; case ENCXF_3DES_CBC: @@ -419,7 +418,8 @@ pfkey_sa(int sd, u_int8_t satype, u_int8_t action, u_int32_t spi, sa.sadb_sa_encrypt = SADB_X_EALG_SKIPJACK; break; default: - warnx("unsupported encryption algorithm %d", encxf->id); + warnx("unsupported encryption algorithm %d", + xfs->encxf->id); } } @@ -860,12 +860,11 @@ pfkey_ipsec_establish(int action, struct ipsec_rule *r) switch (action) { case PFK_ACTION_ADD: ret = pfkey_sa(fd, satype, SADB_ADD, r->spi, - r->src, r->dst, r->encxf, r->authxf, - r->authkey, r->enckey); + r->src, r->dst, r->xfs, r->authkey, r->enckey); break; case PFK_ACTION_DELETE: ret = pfkey_sa(fd, satype, SADB_DELETE, r->spi, - r->src, r->dst, r->encxf, r->authxf, NULL, NULL); + r->src, r->dst, r->xfs, NULL, NULL); break; default: return -1; |