diff --git a/kame/kame/racoon/doc/question b/kame/kame/racoon/doc/question index d7a463a1f2..2de3f7e0ef 100644 --- a/kame/kame/racoon/doc/question +++ b/kame/kame/racoon/doc/question @@ -1,4 +1,4 @@ -$Id: question,v 1.2 2000/01/09 23:38:24 sakane Exp $ +$Id: question,v 1.3 2000/01/10 00:39:40 sakane Exp $ HOW DO I DO ? o ID payload handling in phase 2 besides IPSECDOI_ID_IP*. @@ -34,3 +34,4 @@ o base mode Nr ? o What's proto_id in notify message of responder 2nd message with commit bit processing when multiple different SA applyed ? +o Is it forbidden to clear commit bit during phase2 negotiation ? diff --git a/kame/kame/racoon/handler.c b/kame/kame/racoon/handler.c index ae79f37fe2..697168ab0f 100644 --- a/kame/kame/racoon/handler.c +++ b/kame/kame/racoon/handler.c @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -/* YIPS @(#)$Id: handler.c,v 1.8 2000/01/09 01:31:23 itojun Exp $ */ +/* YIPS @(#)$Id: handler.c,v 1.9 2000/01/10 00:39:35 sakane Exp $ */ #include #include @@ -379,7 +379,6 @@ void initph2(iph2) struct ph2handle *iph2; { - /* iph2->inuse = 0; don't init ! */ if (iph2->ivm) oakley_delivm(iph2->ivm); if (iph2->sce) diff --git a/kame/kame/racoon/handler.h b/kame/kame/racoon/handler.h index a1d4e48970..4384967242 100644 --- a/kame/kame/racoon/handler.h +++ b/kame/kame/racoon/handler.h @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -/* YIPS @(#)$Id: handler.h,v 1.4 2000/01/09 23:11:04 sakane Exp $ */ +/* YIPS @(#)$Id: handler.h,v 1.5 2000/01/10 00:39:35 sakane Exp $ */ /* Phase 1 handler */ /* @@ -173,9 +173,10 @@ struct ph1handle { * 4 getspi done getspi done * 5 1st msg sent 1st msg sent * 6 1st valid msg received 2nd valid msg received - * 7 SAs added SAs added - * 8 SAs established SAs established - * 9 SAs expired SAs expired + * 7 (commit bit) (commit bit) + * 8 SAs added SAs added + * 9 SAs established SAs established + * 10 SAs expired SAs expired */ #define PHASE2ST_SPAWN 0 #define PHASE2ST_START 1 @@ -184,10 +185,11 @@ struct ph1handle { #define PHASE2ST_GETSPIDONE 4 #define PHASE2ST_MSG1SENT 5 #define PHASE2ST_STATUS6 6 -#define PHASE2ST_ADDSA 7 -#define PHASE2ST_ESTABLISHED 8 -#define PHASE2ST_EXPIRED 9 -#define PHASE2ST_MAX 10 +#define PHASE2ST_COMMIT 7 +#define PHASE2ST_ADDSA 8 +#define PHASE2ST_ESTABLISHED 9 +#define PHASE2ST_EXPIRED 10 +#define PHASE2ST_MAX 11 struct ph2handle { struct policyindex *spidx; /* pointer to policy */ diff --git a/kame/kame/racoon/isakmp.c b/kame/kame/racoon/isakmp.c index 2a280d52ff..a71029d1b1 100644 --- a/kame/kame/racoon/isakmp.c +++ b/kame/kame/racoon/isakmp.c @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -/* YIPS @(#)$Id: isakmp.c,v 1.16 2000/01/09 23:11:06 sakane Exp $ */ +/* YIPS @(#)$Id: isakmp.c,v 1.17 2000/01/10 00:39:36 sakane Exp $ */ #include #include @@ -112,9 +112,9 @@ static int (*ph2exchange[][2][PHASE2ST_MAX]) __P((struct ph2handle *, vchar_t *)) = { { /* Quick mode for IKE*/ { NULL, NULL, quick_i1prep, NULL, quick_i1send, - quick_i2recv, quick_i2send, NULL, NULL, NULL, }, + quick_i2recv, quick_i2send, quick_i3recv, NULL, NULL, }, { NULL, quick_r1recv, quick_r1prep, NULL, quick_r2send, - quick_r3recv, quick_r3prep, NULL, NULL, NULL, } + quick_r3recv, quick_r3send, quick_r3prep, NULL, NULL, } }, }; @@ -448,6 +448,16 @@ isakmp_main(msg, remote, local) /*NOTREACHED*/ } + /* commit bit. */ + /* XXX + * we keep to set commit bit during negotiation. + * When SA is configured, bit will be reset. + * XXX + * don't initiate commit bit. should be fixed in the future. + */ + if (ISSET(isakmp->flags, ISAKMP_FLAG_C)) + iph2->ph1->flags |= ISAKMP_FLAG_C; + /* receive */ YIPSDEBUG(DEBUG_USEFUL, plog(logp, LOCATION, NULL, "===\n")); if ((ph2exchange[etypesw(isakmp->etype)] diff --git a/kame/kame/racoon/isakmp_quick.c b/kame/kame/racoon/isakmp_quick.c index 57ab710c5a..7604717f20 100644 --- a/kame/kame/racoon/isakmp_quick.c +++ b/kame/kame/racoon/isakmp_quick.c @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -/* YIPS @(#)$Id: isakmp_quick.c,v 1.2 2000/01/09 22:59:37 sakane Exp $ */ +/* YIPS @(#)$Id: isakmp_quick.c,v 1.3 2000/01/10 00:39:36 sakane Exp $ */ #include #include @@ -601,6 +601,13 @@ quick_i2send(iph2, msg0) goto end; } + /* if there is commit bit don't set up SA now. */ + if (ISSET(iph2->ph1->flags, ISAKMP_FLAG_C)) { + iph2->status = PHASE2ST_COMMIT; + error = 0; + goto end; + } + /* Do UPDATE for initiator */ if (pk_sendupdate(iph2) < 0) { plog(logp, LOCATION, NULL, "pfkey update failed.\n"); @@ -632,6 +639,152 @@ quick_i2send(iph2, msg0) return error; } +/* + * receive from responder + * HDR#*, HASH(4), notify + */ +int +quick_i3recv(iph2, msg0) + struct ph2handle *iph2; + vchar_t *msg0; +{ + vchar_t *msg = NULL; + vchar_t *pbuf = NULL; /* for payload parsing */ + struct isakmp_parse_t *pa; + struct isakmp_pl_hash *hash = NULL; + vchar_t *notify = NULL; + int error = -1; + + YIPSDEBUG(DEBUG_STAMP, plog(logp, LOCATION, NULL, "begin.\n")); + + /* validity check */ + if (iph2->status != PHASE2ST_COMMIT) { + plog(logp, LOCATION, NULL, + "status mismatched %d.\n", iph2->status); + goto end; + } + + /* decrypt packet */ + if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) { + plog(logp, LOCATION, iph2->ph1->remote, + "Packet wasn't encrypted.\n"); + goto end; + } + msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive); + if (msg == NULL) + goto end; + + /* validate the type of next payload */ + /* + * ISAKMP_ETYPE_QUICK, RESPONDER, PHASE2ST_COMMIT + * ISAKMP_NPTYPE_HASH, (ISAKMP_NPTYPE_N), ISAKMP_NPTYPE_NONE + */ + pbuf = isakmp_parse(msg); + if (pbuf == NULL) + goto end; + + for (pa = (struct isakmp_parse_t *)pbuf->v; + pa->type != ISAKMP_NPTYPE_NONE; + pa++) { + + switch (pa->type) { + case ISAKMP_NPTYPE_HASH: + hash = (struct isakmp_pl_hash *)pa->ptr; + break; + case ISAKMP_NPTYPE_N: + isakmp_check_notify(pa->ptr, iph2->ph1); + notify = vmalloc(pa->len); + if (notify == NULL) { + plog(logp, LOCATION, NULL, + "vmalloc (%s)\n", strerror(errno)); + goto end; + } + memcpy(notify->v, pa->ptr, notify->l); + break; + default: + /* don't send information, see ident_r1recv() */ + error = 0; + plog(logp, LOCATION, iph2->ph1->remote, + "ignore the packet, " + "received unexpecting payload type %d.\n", + pa->type); + goto end; + } + } + + /* payload existency check */ + if (hash == NULL) { + plog(logp, LOCATION, iph2->ph1->remote, + "few isakmp message received.\n"); + goto end; + } + + /* validate HASH(4) */ + { + char *r_hash; + vchar_t *my_hash = NULL; + vchar_t *tmp = NULL; + int result; + + r_hash = (char *)hash + sizeof(*hash); + + YIPSDEBUG(DEBUG_KEY, plog(logp, LOCATION, NULL, "HASH(4) validate:")); + YIPSDEBUG(DEBUG_DKEY, + hexdump(r_hash, ntohs(hash->h.len) - sizeof(*hash))); + + my_hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, notify); + vfree(tmp); + if (my_hash == NULL) + goto end; + + result = memcmp(my_hash->v, r_hash, my_hash->l); + vfree(my_hash); + + if (result) { + plog(logp, LOCATION, iph2->ph1->remote, "HASH(4) mismatch.\n"); + isakmp_info_send_n2(iph2, ISAKMP_NTYPE_INVALID_HASH_INFORMATION, NULL, iph2->ph1->flags); + goto end; + } + } + + iph2->status = PHASE2ST_ADDSA; + iph2->ph1->flags ^= ISAKMP_FLAG_C; /* reset bit */ + + /* don't anything if local test mode. */ + if (f_local) { + error = 0; + goto end; + } + + /* Do UPDATE for initiator */ + if (pk_sendupdate(iph2) < 0) { + plog(logp, LOCATION, NULL, "pfkey update failed.\n"); + goto end; + } + YIPSDEBUG(DEBUG_STAMP, + plog(logp, LOCATION, NULL, "pfkey update sent.\n")); + + /* Do ADD for responder */ + if (pk_sendadd(iph2) < 0) { + plog(logp, LOCATION, NULL, "pfkey add failed.\n"); + goto end; + } + YIPSDEBUG(DEBUG_STAMP, + plog(logp, LOCATION, NULL, "pfkey add sent.\n")); + + plog(logp, LOCATION, iph2->ph1->remote, + "get SA values for IPsec, %s.\n", + isakmp_pindex(&iph2->ph1->index, iph2->msgid)); + + error = 0; + +end: + if (msg != NULL) + vfree(msg); + + return error; +} + /* * receive from initiator * HDR*, HASH(1), SA, Ni [, KE ] [, IDi2, IDr2 ] @@ -1271,6 +1424,13 @@ quick_r3recv(iph2, msg0) } } + /* if there is commit bit don't set up SA now. */ + if (ISSET(iph2->ph1->flags, ISAKMP_FLAG_C)) { + iph2->status = PHASE2ST_COMMIT; + error = 0; + goto end; + } + iph2->status = PHASE2ST_STATUS6; error = 0; @@ -1284,6 +1444,108 @@ quick_r3recv(iph2, msg0) return error; } +/* + * send to initiator + * HDR#*, HASH(4), notify + */ +int +quick_r3send(iph2, msg0) + struct ph2handle *iph2; + vchar_t *msg0; +{ + vchar_t *buf = NULL; + vchar_t *myhash = NULL; + struct isakmp_pl_n *n; + vchar_t *notify = NULL; + char *p; + int tlen; + int error = -1; + + YIPSDEBUG(DEBUG_STAMP, plog(logp, LOCATION, NULL, "begin.\n")); + + /* validity check */ + if (iph2->status != PHASE2ST_COMMIT) { + plog(logp, LOCATION, NULL, + "status mismatched %d.\n", iph2->status); + goto end; + } + + /* generate HASH(4) */ + /* XXX What can I do in the case of multiple different SA */ + YIPSDEBUG(DEBUG_KEY, plog(logp, LOCATION, NULL, "HASH(4) generate\n")); + + tlen = sizeof(struct isakmp_pl_n) + sizeof(iph2->keys->spi); + notify = vmalloc(tlen); + if (notify == NULL) { + plog(logp, LOCATION, NULL, + "vmalloc (%s)\n", strerror(errno)); + goto end; + } + n = (struct isakmp_pl_n *)notify->v; + n->h.np = ISAKMP_NPTYPE_NONE; + n->h.len = htons(tlen); + n->doi = IPSEC_DOI; + n->proto_id = iph2->keys->proto_id; + n->spi_size = sizeof(iph2->keys->spi); + n->type = htons(ISAKMP_NTYPE_CONNECTED); + memcpy(n + 1, &iph2->keys->spi, sizeof(iph2->keys->spi)); + + myhash = oakley_compute_hash1(iph2->ph1, iph2->msgid, notify); + if (myhash == NULL) + goto end; + + /* create buffer for isakmp payload */ + tlen = sizeof(struct isakmp) + + sizeof(struct isakmp_gen) + myhash->l + + notify->l; + buf = vmalloc(tlen); + if (buf == NULL) { + plog(logp, LOCATION, NULL, + "vmalloc (%s)\n", strerror(errno)); + goto end; + } + + /* create isakmp header */ + p = set_isakmp_header2(buf, iph2, ISAKMP_NPTYPE_HASH); + if (p == NULL) + goto end; + + /* add HASH(4) payload */ + p = set_isakmp_payload(p, myhash, ISAKMP_NPTYPE_N); + + /* add notify payload */ + memcpy(p, notify->v, notify->l); + +#ifdef HAVE_PRINT_ISAKMP_C + isakmp_printpacket(buf, iph2->ph1->local, iph2->ph1->remote, 1); +#endif + + /* encoding */ + iph2->sendbuf = oakley_do_encrypt(iph2->ph1, buf, iph2->ivm->ive, iph2->ivm->iv); + if (iph2->sendbuf == NULL) + goto end; + + /* send HDR*;HASH(3) */ + if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0) + goto end; + + /* XXX: How resend ? */ + + iph2->status = PHASE2ST_COMMIT; + + error = 0; + +end: + if (buf != NULL) + vfree(buf); + if (myhash != NULL) + vfree(myhash); + if (notify != NULL) + vfree(notify); + + return error; +} + /* * set SA to kernel. */ @@ -1309,6 +1571,7 @@ quick_r3prep(iph2, msg0) goto end; iph2->status = PHASE2ST_ADDSA; + iph2->ph1->flags ^= ISAKMP_FLAG_C; /* reset bit */ /* don't anything if local test mode. */ if (f_local) { diff --git a/kame/kame/racoon/isakmp_quick.h b/kame/kame/racoon/isakmp_quick.h index 915bc215e7..1bede32062 100644 --- a/kame/kame/racoon/isakmp_quick.h +++ b/kame/kame/racoon/isakmp_quick.h @@ -26,15 +26,17 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -/* YIPS @(#)$Id: isakmp_quick.h,v 1.1 2000/01/09 01:31:27 itojun Exp $ */ +/* YIPS @(#)$Id: isakmp_quick.h,v 1.2 2000/01/10 00:39:37 sakane Exp $ */ extern int quick_i1prep __P((struct ph2handle *, vchar_t *msg)); extern int quick_i1send __P((struct ph2handle *, vchar_t *msg)); extern int quick_i2recv __P((struct ph2handle *, vchar_t *msg)); extern int quick_i2send __P((struct ph2handle *, vchar_t *msg)); +extern int quick_i3recv __P((struct ph2handle *, vchar_t *msg)); extern int quick_r1recv __P((struct ph2handle *, vchar_t *msg)); extern int quick_r1prep __P((struct ph2handle *, vchar_t *msg)); extern int quick_r2send __P((struct ph2handle *, vchar_t *msg)); extern int quick_r3recv __P((struct ph2handle *, vchar_t *msg)); +extern int quick_r3send __P((struct ph2handle *, vchar_t *msg)); extern int quick_r3prep __P((struct ph2handle *, vchar_t *msg));