Module Name: src Committed By: vanhu Date: Mon Mar 14 15:50:37 UTC 2011
Modified Files: src/crypto/dist/ipsec-tools/src/racoon: cfparse.y isakmp_xauth.c isakmp_xauth.h remoteconf.c remoteconf.h rsalist.c rsalist.h Log Message: avoid some memory leaks / free memory access when reloading conf and have inherited config. patch from Roman Hoog Antink <r...@open.ch> To generate a diff of this commit: cvs rdiff -u -r1.41 -r1.42 src/crypto/dist/ipsec-tools/src/racoon/cfparse.y cvs rdiff -u -r1.21 -r1.22 \ src/crypto/dist/ipsec-tools/src/racoon/isakmp_xauth.c cvs rdiff -u -r1.6 -r1.7 \ src/crypto/dist/ipsec-tools/src/racoon/isakmp_xauth.h cvs rdiff -u -r1.25 -r1.26 \ src/crypto/dist/ipsec-tools/src/racoon/remoteconf.c cvs rdiff -u -r1.15 -r1.16 \ src/crypto/dist/ipsec-tools/src/racoon/remoteconf.h cvs rdiff -u -r1.5 -r1.6 src/crypto/dist/ipsec-tools/src/racoon/rsalist.c \ src/crypto/dist/ipsec-tools/src/racoon/rsalist.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/crypto/dist/ipsec-tools/src/racoon/cfparse.y diff -u src/crypto/dist/ipsec-tools/src/racoon/cfparse.y:1.41 src/crypto/dist/ipsec-tools/src/racoon/cfparse.y:1.42 --- src/crypto/dist/ipsec-tools/src/racoon/cfparse.y:1.41 Wed Mar 2 14:58:27 2011 +++ src/crypto/dist/ipsec-tools/src/racoon/cfparse.y Mon Mar 14 15:50:36 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: cfparse.y,v 1.41 2011/03/02 14:58:27 vanhu Exp $ */ +/* $NetBSD: cfparse.y,v 1.42 2011/03/14 15:50:36 vanhu Exp $ */ /* Id: cfparse.y,v 1.66 2006/08/22 18:17:17 manubsd Exp */ @@ -145,6 +145,7 @@ static struct secprotospec *newspspec __P((void)); static void insspspec __P((struct remoteconf *, struct secprotospec *)); +void dupspspec_list __P((struct remoteconf *dst, struct remoteconf *src)); void flushspspec __P((struct remoteconf *)); static void adminsock_conf __P((vchar_t *, vchar_t *, vchar_t *, int)); @@ -1629,7 +1630,7 @@ return -1; } - new = duprmconf(from); + new = duprmconf_shallow(from); if (new == NULL) { yyerror("failed to duplicate remoteconf from \"%s\".", $4->v); @@ -1674,13 +1675,14 @@ return -1; } - new = duprmconf(from); + new = duprmconf_shallow(from); if (new == NULL) { yyerror("failed to duplicate remoteconf from %s.", saddr2str($4)); return -1; } + racoon_free($4); new->remote = $2; cur_rmconf = new; } @@ -1727,11 +1729,19 @@ return -1; } } - + + if (duprmconf_finish(cur_rmconf)) + return -1; + +#if 0 + /* this pointer copy will never happen, because duprmconf_shallow + * already copied all pointers. + */ if (cur_rmconf->spspec == NULL && cur_rmconf->inherited_from != NULL) { cur_rmconf->spspec = cur_rmconf->inherited_from->spspec; } +#endif if (set_isakmp_proposal(cur_rmconf) != 0) return -1; @@ -2415,6 +2425,62 @@ rmconf->spspec = spspec; } +static struct secprotospec * +dupspspec(spspec) + struct secprotospec *spspec; +{ + struct secprotospec *new; + + new = newspspec(); + if (new == NULL) { + plog(LLV_ERROR, LOCATION, NULL, + "dupspspec: malloc failed\n"); + return NULL; + } + memcpy(new, spspec, sizeof(*new)); + + if (spspec->gssid) { + new->gssid = racoon_strdup(spspec->gssid); + STRDUP_FATAL(new->gssid); + } + if (spspec->remote) { + new->remote = racoon_malloc(sizeof(*new->remote)); + if (new->remote == NULL) { + plog(LLV_ERROR, LOCATION, NULL, + "dupspspec: malloc failed (remote)\n"); + return NULL; + } + memcpy(new->remote, spspec->remote, sizeof(*new->remote)); + } + + return new; +} + +/* + * copy the whole list + */ +void +dupspspec_list(dst, src) + struct remoteconf *dst, *src; +{ + struct secprotospec *p, *new, *last; + + for(p = src->spspec, last = NULL; p; p = p->next, last = new) { + new = dupspspec(p); + if (new == NULL) + exit(1); + + new->prev = last; + new->next = NULL; /* not necessary but clean */ + + if (last) + last->next = new; + else /* first element */ + dst->spspec = new; + + } +} + /* * delete the whole list */ @@ -2430,8 +2496,13 @@ if (p->next != NULL) p->next->prev = NULL; /* not necessary but clean */ - racoon_free(p); + if (p->gssid) + racoon_free(p->gssid); + if (p->remote) + racoon_free(p->remote); + racoon_free(p); } + rmconf->spspec = NULL; } /* set final acceptable proposal */ Index: src/crypto/dist/ipsec-tools/src/racoon/isakmp_xauth.c diff -u src/crypto/dist/ipsec-tools/src/racoon/isakmp_xauth.c:1.21 src/crypto/dist/ipsec-tools/src/racoon/isakmp_xauth.c:1.22 --- src/crypto/dist/ipsec-tools/src/racoon/isakmp_xauth.c:1.21 Mon Sep 27 11:57:59 2010 +++ src/crypto/dist/ipsec-tools/src/racoon/isakmp_xauth.c Mon Mar 14 15:50:36 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: isakmp_xauth.c,v 1.21 2010/09/27 11:57:59 vanhu Exp $ */ +/* $NetBSD: isakmp_xauth.c,v 1.22 2011/03/14 15:50:36 vanhu Exp $ */ /* Id: isakmp_xauth.c,v 1.38 2006/08/22 18:17:17 manubsd Exp */ @@ -1764,3 +1764,42 @@ return; } + +struct xauth_rmconf * +xauth_rmconf_dup(xauth_rmconf) + struct xauth_rmconf *xauth_rmconf; +{ + struct xauth_rmconf *new; + + if (xauth_rmconf != NULL) { + new = racoon_malloc(sizeof(*new)); + if (new == NULL) { + plog(LLV_ERROR, LOCATION, NULL, + "xauth_rmconf_dup: malloc failed\n"); + return NULL; + } + + memcpy(new, xauth_rmconf, sizeof(*new)); + + if (xauth_rmconf->login != NULL) { + new->login = vdup(xauth_rmconf->login); + if (new->login == NULL) { + plog(LLV_ERROR, LOCATION, NULL, + "xauth_rmconf_dup: malloc failed (login)\n"); + return NULL; + } + } + if (xauth_rmconf->pass != NULL) { + new->pass = vdup(xauth_rmconf->pass); + if (new->pass == NULL) { + plog(LLV_ERROR, LOCATION, NULL, + "xauth_rmconf_dup: malloc failed (password)\n"); + return NULL; + } + } + + return new; + } + + return NULL; +} Index: src/crypto/dist/ipsec-tools/src/racoon/isakmp_xauth.h diff -u src/crypto/dist/ipsec-tools/src/racoon/isakmp_xauth.h:1.6 src/crypto/dist/ipsec-tools/src/racoon/isakmp_xauth.h:1.7 --- src/crypto/dist/ipsec-tools/src/racoon/isakmp_xauth.h:1.6 Fri Sep 19 11:01:08 2008 +++ src/crypto/dist/ipsec-tools/src/racoon/isakmp_xauth.h Mon Mar 14 15:50:36 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: isakmp_xauth.h,v 1.6 2008/09/19 11:01:08 tteras Exp $ */ +/* $NetBSD: isakmp_xauth.h,v 1.7 2011/03/14 15:50:36 vanhu Exp $ */ /* $KAME$ */ @@ -114,6 +114,7 @@ int xauth_reply(struct ph1handle *, int, int, int); int xauth_rmconf_used(struct xauth_rmconf **); void xauth_rmconf_delete(struct xauth_rmconf **); +struct xauth_rmconf * xauth_rmconf_dup(struct xauth_rmconf *); #ifdef HAVE_LIBPAM int xauth_login_pam(int, struct sockaddr *, char *, char *); Index: src/crypto/dist/ipsec-tools/src/racoon/remoteconf.c diff -u src/crypto/dist/ipsec-tools/src/racoon/remoteconf.c:1.25 src/crypto/dist/ipsec-tools/src/racoon/remoteconf.c:1.26 --- src/crypto/dist/ipsec-tools/src/racoon/remoteconf.c:1.25 Wed Mar 2 15:04:01 2011 +++ src/crypto/dist/ipsec-tools/src/racoon/remoteconf.c Mon Mar 14 15:50:36 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: remoteconf.c,v 1.25 2011/03/02 15:04:01 vanhu Exp $ */ +/* $NetBSD: remoteconf.c,v 1.26 2011/03/14 15:50:36 vanhu Exp $ */ /* Id: remoteconf.c,v 1.38 2006/05/06 15:52:44 manubsd Exp */ @@ -570,8 +570,25 @@ return NULL; } +void * +duprsa(entry, arg) + void *entry; + void *arg; +{ + struct rsa_key *new; + + new = rsa_key_dup((struct rsa_key *)entry); + if (new == NULL) + return (void *) -1; + genlist_append(arg, new); + + /* keep genlist_foreach going */ + return NULL; +} + +/* Creates shallow copy of a remote config. Used for "inherit" keyword. */ struct remoteconf * -duprmconf (rmconf) +duprmconf_shallow (rmconf) struct remoteconf *rmconf; { struct remoteconf *new; @@ -585,31 +602,113 @@ new->name = NULL; new->inherited_from = rmconf; - /* duplicate dynamic structures */ - if (new->etypes) + new->proposal = NULL; /* will be filled by set_isakmp_proposal() */ + + return new; +} + +/* Copies pointer structures of an inherited remote config. + * Used by "inherit" mechanism in a two step copy method, necessary to + * prevent both double free() and memory leak during config reload. + */ +int +duprmconf_finish (new) + struct remoteconf *new; +{ + struct remoteconf *rmconf; + int i; + + if (new->inherited_from == NULL) + return 0; /* nothing todo, no inheritance */ + + rmconf = new->inherited_from; + + /* duplicate dynamic structures unless value overridden */ + if (new->etypes != NULL && new->etypes == rmconf->etypes) new->etypes = dupetypes(new->etypes); - new->idvl_p = genlist_init(); - genlist_foreach(rmconf->idvl_p, dupidvl, new->idvl_p); + if (new->idvl_p == rmconf->idvl_p) { + new->idvl_p = genlist_init(); + genlist_foreach(rmconf->idvl_p, dupidvl, new->idvl_p); + } + + if (new->rsa_private == rmconf->rsa_private) { + new->rsa_private = genlist_init(); + genlist_foreach(rmconf->rsa_private, duprsa, new->rsa_private); + } + if (new->rsa_public == rmconf->rsa_public) { + new->rsa_public = genlist_init(); + genlist_foreach(rmconf->rsa_public, duprsa, new->rsa_public); + } + if (new->remote != NULL && new->remote == rmconf->remote) { + new->remote = racoon_malloc(sizeof(*new->remote)); + if (new->remote == NULL) { + plog(LLV_ERROR, LOCATION, NULL, + "duprmconf_finish: malloc failed (remote)\n"); + exit(1); + } + memcpy(new->remote, rmconf->remote, sizeof(*new->remote)); + } + if (new->spspec != NULL && new->spspec == rmconf->spspec) { + dupspspec_list(new, rmconf); + } + + /* proposal has been deep copied already from spspec's, see + * cfparse.y:set_isakmp_proposal, which in turn calls + * cfparse.y:expand_isakmpspec where the copying happens. + */ + +#ifdef ENABLE_HYBRID + if (new->xauth != NULL && new->xauth == rmconf->xauth) { + new->xauth = xauth_rmconf_dup(new->xauth); + if (new->xauth == NULL) + exit(1); + } +#endif - /* duplicate strings */ - if (new->mycertfile != NULL) { + /* duplicate strings unless value overridden */ + if (new->mycertfile != NULL && new->mycertfile == rmconf->mycertfile) { new->mycertfile = racoon_strdup(new->mycertfile); STRDUP_FATAL(new->mycertfile); } - if (new->myprivfile != NULL) { + if (new->myprivfile != NULL && new->myprivfile == rmconf->myprivfile) { new->myprivfile = racoon_strdup(new->myprivfile); STRDUP_FATAL(new->myprivfile); } - if (new->peerscertfile != NULL) { + if (new->peerscertfile != NULL && new->peerscertfile == rmconf->peerscertfile) { new->peerscertfile = racoon_strdup(new->peerscertfile); STRDUP_FATAL(new->peerscertfile); } - if (new->cacertfile != NULL) { - new->cacertfile = racoon_strdup(new->cacertfile); + if (new->cacertfile != NULL && new->cacertfile == rmconf->cacertfile) { + new->cacertfile = racoon_strdup(new->cacertfile); STRDUP_FATAL(new->cacertfile); } + if (new->idv != NULL && new->idv == rmconf->idv) { + new->idv = vdup(new->idv); + STRDUP_FATAL(new->idv); + } + if (new->key != NULL && new->key == rmconf->key) { + new->key = vdup(new->key); + STRDUP_FATAL(new->key); + } + if (new->mycert != NULL && new->mycert == rmconf->mycert) { + new->mycert = vdup(new->mycert); + STRDUP_FATAL(new->mycert); + } + if (new->peerscert != NULL && new->peerscert == rmconf->peerscert) { + new->peerscert = vdup(new->peerscert); + STRDUP_FATAL(new->peerscert); + } + if (new->cacert != NULL && new->cacert == rmconf->cacert) { + new->cacert = vdup(new->cacert); + STRDUP_FATAL(new->cacert); + } + for (i = 0; i <= SCRIPT_MAX; i++) + if (new->script[i] != NULL && new->script[i] == rmconf->script[i]) { + new->script[i] = vdup(new->script[i]); + STRDUP_FATAL(new->script[i]); + } - return new; + return 0; } static void @@ -623,6 +722,8 @@ delrmconf(rmconf) struct remoteconf *rmconf; { + int i; + #ifdef ENABLE_HYBRID if (rmconf->xauth) xauth_rmconf_delete(&rmconf->xauth); @@ -631,12 +732,17 @@ deletypes(rmconf->etypes); rmconf->etypes=NULL; } + if (rmconf->idv) + vfree(rmconf->idv); + if (rmconf->key) + vfree(rmconf->key); if (rmconf->idvl_p) genlist_free(rmconf->idvl_p, idspec_free); if (rmconf->dhgrp) oakley_dhgrp_free(rmconf->dhgrp); if (rmconf->proposal) delisakmpsa(rmconf->proposal); + flushspspec(rmconf); if (rmconf->mycert) vfree(rmconf->mycert); if (rmconf->mycertfile) @@ -659,7 +765,10 @@ racoon_free(rmconf->name); if (rmconf->remote) racoon_free(rmconf->remote); - flushspspec(rmconf); + for (i = 0; i <= SCRIPT_MAX; i++) + if (rmconf->script[i]) + vfree(rmconf->script[i]); + racoon_free(rmconf); } Index: src/crypto/dist/ipsec-tools/src/racoon/remoteconf.h diff -u src/crypto/dist/ipsec-tools/src/racoon/remoteconf.h:1.15 src/crypto/dist/ipsec-tools/src/racoon/remoteconf.h:1.16 --- src/crypto/dist/ipsec-tools/src/racoon/remoteconf.h:1.15 Wed Mar 2 14:58:27 2011 +++ src/crypto/dist/ipsec-tools/src/racoon/remoteconf.h Mon Mar 14 15:50:36 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: remoteconf.h,v 1.15 2011/03/02 14:58:27 vanhu Exp $ */ +/* $NetBSD: remoteconf.h,v 1.16 2011/03/14 15:50:36 vanhu Exp $ */ /* Id: remoteconf.h,v 1.26 2006/05/06 15:52:44 manubsd Exp */ @@ -201,13 +201,15 @@ extern struct remoteconf *getrmconf_by_name __P((const char *name)); extern struct remoteconf *newrmconf __P((void)); -extern struct remoteconf *duprmconf __P((struct remoteconf *)); +extern struct remoteconf *duprmconf_shallow __P((struct remoteconf *)); +extern int duprmconf_finish __P((struct remoteconf *)); extern void delrmconf __P((struct remoteconf *)); extern void deletypes __P((struct etypes *)); extern struct etypes * dupetypes __P((struct etypes *)); extern void insrmconf __P((struct remoteconf *)); extern void remrmconf __P((struct remoteconf *)); extern void flushrmconf __P((void)); +extern void dupspspec_list __P((struct remoteconf *, struct remoteconf *)); extern void flushspspec __P((struct remoteconf *)); extern void initrmconf __P((void)); extern void rmconf_start_reload __P((void)); Index: src/crypto/dist/ipsec-tools/src/racoon/rsalist.c diff -u src/crypto/dist/ipsec-tools/src/racoon/rsalist.c:1.5 src/crypto/dist/ipsec-tools/src/racoon/rsalist.c:1.6 --- src/crypto/dist/ipsec-tools/src/racoon/rsalist.c:1.5 Wed Mar 2 15:04:01 2011 +++ src/crypto/dist/ipsec-tools/src/racoon/rsalist.c Mon Mar 14 15:50:36 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: rsalist.c,v 1.5 2011/03/02 15:04:01 vanhu Exp $ */ +/* $NetBSD: rsalist.c,v 1.6 2011/03/14 15:50:36 vanhu Exp $ */ /* Id: rsalist.c,v 1.3 2004/11/08 12:04:23 ludvigm Exp */ @@ -88,6 +88,48 @@ return 0; } +struct rsa_key * +rsa_key_dup(struct rsa_key *key) +{ + struct rsa_key *new; + + new = calloc(sizeof(struct rsa_key), 1); + if (new == NULL) + return NULL; + + if (key->rsa) { + new->rsa = key->rsa->d != NULL ? RSAPrivateKey_dup(key->rsa) : RSAPublicKey_dup(key->rsa); + if (new->rsa == NULL) + goto dup_error; + } + + if (key->src) { + new->src = malloc(sizeof(*new->src)); + if (new->src == NULL) + goto dup_error; + memcpy(new->src, key->src, sizeof(*new->src)); + } + if (key->dst) { + new->dst = malloc(sizeof(*new->dst)); + if (new->dst == NULL) + goto dup_error; + memcpy(new->dst, key->dst, sizeof(*new->dst)); + } + + return new; + +dup_error: + if (new->rsa != NULL) + RSA_free(new->rsa); + if (new->dst != NULL) + free(new->dst); + if (new->src != NULL) + free(new->src); + + free(new); + return NULL; +} + void rsa_key_free(void *data) { Index: src/crypto/dist/ipsec-tools/src/racoon/rsalist.h diff -u src/crypto/dist/ipsec-tools/src/racoon/rsalist.h:1.5 src/crypto/dist/ipsec-tools/src/racoon/rsalist.h:1.6 --- src/crypto/dist/ipsec-tools/src/racoon/rsalist.h:1.5 Wed Mar 2 15:04:01 2011 +++ src/crypto/dist/ipsec-tools/src/racoon/rsalist.h Mon Mar 14 15:50:36 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: rsalist.h,v 1.5 2011/03/02 15:04:01 vanhu Exp $ */ +/* $NetBSD: rsalist.h,v 1.6 2011/03/14 15:50:36 vanhu Exp $ */ /* Id: rsalist.h,v 1.2 2004/07/12 20:43:51 ludvigm Exp */ /* @@ -53,6 +53,7 @@ }; int rsa_key_insert(struct genlist *list, struct netaddr *src, struct netaddr *dst, RSA *rsa); +struct rsa_key *rsa_key_dup(struct rsa_key *key); void rsa_key_free(void *data); void rsa_key_dump(struct genlist *list);