Subject: Changes (fixes!) to racoon GSS API authentication
To: NetBSD-network <tech-net@netbsd.org>
From: Jason Thorpe <thorpej@shagadelic.org>
List: tech-net
Date: 11/05/2004 15:30:14
--Apple-Mail-36--1016353762
Content-Type: multipart/mixed; boundary=Apple-Mail-35--1016353780


--Apple-Mail-35--1016353780
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	charset=US-ASCII;
	format=flowed

Hi folks...

I've been exchanging mail with a Microsoft developer recently about 
racoon's GSS-API auth code, and how it doesn't interoperate with 
Windows IKE.

There were really a few problems:

- If the GSS ID was specified in racoon.conf, the NUL at the end of the 
C-string would erroneously be put onto the wire.

- While the GSS-API-for-IKE draft specifies "Unicode" (for Windows 
compatibility), this was unfortunately a little too vague.  Currently, 
racoon sends this string out simply in what amounts to ISO-Latin-1.  
While ISO-Latin-1 is a subset of UTF-8 (and thus is technically 
compliant with the draft), it turns out that Windows assumes the GSS ID 
to be encoded as UTF-16LE... apparently, it pulls the attribute out of 
the ISAKMP packet, appends a UTF-16LE NUL, and passes it directly into 
an SSPI method that requires a UTF-16LE string.  I added a 
configuration knob that allows the old ISO-Latin-1 encoding to be used, 
if you can't upgrade all of your racoon installations and don't need to 
interoperate with Windows IKE.

- racoon would only send the GSS ID attribute if the GSS ID was 
specified in racoon.conf.  This needs to always be done for Windows 
compatibility.

- The default GSS ID selection was ... poor.  It should be 
host/hostname (i.e. match a host/... principal in the system's keytab). 
  Even though Active Directory computer accounts are of the form 
"machine$@REALM", I'm told that the Windows KDC accepts the 
host/machine form of the name, as well.

The following patch addresses the above problems.  I'm still waiting to 
hear back if it fixes Windows IKE interoperability (he's currently 
stuck on a crash inside the Mac OS X Kerberos libraries, but everything 
up to that happening is looking fine).

I have successfully used racoon to set up IPsec-SAs between two NetBSD 
systems using GSS-API to set up the ISAKMP-SA, using both the old 
ISO-Latin-1 and new UTF-16LE GSS ID encodings (obviously configured the 
same on both sides).

Here is detailed information about the changes.  As I don't have any 
Windows Active Directory set up here, I can't really test this against 
a Windows IKE myself.  If someone else here could (Jonathan??), I'd 
really like to hear how it turns out.  Obviously, I want to get this 
stuff pushed upstream to KAME, as well (and what about the ipsec-tools 
racoon?)

Once these are in, there is some cleanup that can be done related to 
GSS ID handling.  But I'd rather do that as a separate step.

         -- Jason R. Thorpe <thorpej@shagadelic.org>

--Apple-Mail-35--1016353780
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	x-unix-mode=0700;
	name="racoon-changelog.txt"
Content-Disposition: attachment;
	filename=racoon-changelog.txt

	* auth_gssapi.h (GSSAPI_DEF_NAME): Change from "ike" to "host".
	(gssapi_get_default_id): Rename to gssapi_get_id.
	(gssapi_get_default_gss_id): New prototype.
	* cfparse.y (GSSAPI_ID): Rename to GSS_ID.
	(GSS_ID_ENC, GSS_ID_ENCTYPE): New tokens.
	(gssenc_statement): New statement.
	(isakmpproposal_spec): Use GSS_ID token.
	(expand_isakmpspec): Fill in gssid in the new proposal only
	if authmethod is OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB.  If the
	GSS ID is not provided, call gssapi_get_default_gss_id() to
	place the default ID in the proposal.
	* cftoken.l (S_GSSENC): New start condition.
	(<S_RMTP>gss_id): New, return the GSS_ID token.
	(<S_RMTP>gssapi_id): Return the GSS_ID token.
	(<S_INI>gss_id_enc, <S_GSSENC>latin1, <S_GSSENC>utf-16le)
	(<S_GSSENC>{semi}): New, tokenize the "gss_id_enc enctype;"
	statement.
	* gssapi.c: Include <unistd.h>.
	(gssapi_get_default_gss_id): New function.
	(gssapi_init): Disable a broken debugging message.  Make
	printf formats consistent in their handling of non-NUL-terminated
	strings.
	(gssapi_get_default_id): Rename to...
	(gssapi_get_id): ...this.  If the proposal has a gssid, vdup()
	that and return it.  Disable a broken debugging message.  Make
	printf formats consistent in their handling of non-NUL-terminated
	strings.
	* ipsec_doi.c: Include <iconv.h>.
	(get_ph1approval): Make printf formats consistent in their handling
	of non-NUL-terminated strings.  Call gssapi_get_id() instead of
	gssapi_get_default_id(), and remove some complexity that has been
	pushed into that function.
	(t2isakmpsa): When parsing the OAKLEY_ATTR_GSS_ID attribute,
	check convert the attribute from UTF-16LE to ISO-Latin-1, unless
	we are configured to assume the attribute is already ISO-Latin-1
	encoded.
	(setph1attr): When setting the OAKLEY_ATTR_GSS_ID attribute,
	convert the attribute from ISO-Latin-1 to UTF-16LE, unless we
	are configured to encode the attribute in ISO-Latin-1.
	* localconf.c (setdefault): Set the default GSS ID encoding type
	to UTF-16LE.
	* localconf.h (LC_GSSENC_UTF16LE, LC_GSSENC_LATIN1)
	(LC_GSSENC_MAX): New constants.
	(struct localconf): Add gss_id_enc member.
	* racoon.conf.5: Document changes to GSS ID encoding and default
	GSS ID computation.  Document "gss_id_enc enctype;" statement.
	* samples/racoon.conf.sample-gssapi: Update and add comments to
	provide more information.

--Apple-Mail-35--1016353780
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	x-unix-mode=0700;
	name="racoon-gssapi-patch.txt"
Content-Disposition: attachment;
	filename=racoon-gssapi-patch.txt

Index: auth_gssapi.h
===================================================================
RCS file: /cvsroot/src/crypto/dist/kame/racoon/auth_gssapi.h,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 auth_gssapi.h
--- auth_gssapi.h	12 Apr 2004 03:26:57 -0000	1.1.1.1
+++ auth_gssapi.h	5 Nov 2004 22:27:32 -0000
@@ -42,7 +42,7 @@
 #include <gssapi/gssapi.h>
 #endif
 
-#define GSSAPI_DEF_NAME         "ike"
+#define GSSAPI_DEF_NAME         "host"
 
 struct ph1handle;
 struct isakmpsa;
@@ -89,4 +89,5 @@ int gssapi_id_sent __P((struct ph1handle
 void gssapi_set_id_rcvd __P((struct ph1handle *));
 int gssapi_id_rcvd __P((struct ph1handle *));
 void gssapi_free_state __P((struct ph1handle *));
-vchar_t *gssapi_get_default_id __P((struct ph1handle *));
+vchar_t *gssapi_get_id __P((struct ph1handle *));
+vchar_t *gssapi_get_default_gss_id __P((void));
Index: cfparse.y
===================================================================
RCS file: /cvsroot/src/crypto/dist/kame/racoon/cfparse.y,v
retrieving revision 1.20
diff -u -p -r1.20 cfparse.y
--- cfparse.y	12 Apr 2004 03:34:05 -0000	1.20
+++ cfparse.y	5 Nov 2004 22:27:32 -0000
@@ -192,7 +192,7 @@ static int fix_lifebyte __P((u_long));
 %token GENERATE_POLICY SUPPORT_PROXY
 %token PROPOSAL
 %token EXEC_PATH EXEC_COMMAND EXEC_SUCCESS EXEC_FAILURE
-%token GSSAPI_ID
+%token GSS_ID GSS_ID_ENC GSS_ID_ENCTYPE
 %token COMPLEX_BUNDLE
 
 %token PREFIX PORT PORTANY UL_PROTO ANY
@@ -205,7 +205,7 @@ static int fix_lifebyte __P((u_long));
 %token EOS BOC EOC COMMA
 
 %type <num> NUMBER BOOLEAN SWITCH keylength
-%type <num> PATHTYPE IDENTIFIERTYPE LOGLEV 
+%type <num> PATHTYPE IDENTIFIERTYPE LOGLEV GSS_ID_ENCTYPE
 %type <num> ALGORITHM_CLASS dh_group_num
 %type <num> ALGORITHMTYPE STRENGTHTYPE
 %type <num> PREFIX prefix PORT port ike_port
@@ -227,6 +227,7 @@ statements
 statement
 	:	path_statement
 	|	include_statement
+	|	gssenc_statement
 	|	identifier_statement
 	|	logging_statement
 	|	padding_statement
@@ -276,6 +277,18 @@ include_statement
 		}
 	;
 
+	/* gss_id_enc */
+gssenc_statement
+	:	GSS_ID_ENC GSS_ID_ENCTYPE EOS
+		{
+			if ($2 >= LC_GSSENC_MAX) {
+				yyerror("invalid GSS ID encoding %d", $2);
+				return -1;
+			}
+			lcconf->gss_id_enc = $2;
+		}
+	;
+
 	/* self infomation */
 identifier_statement
 	:	IDENTIFIER identifier_stmt
@@ -1011,7 +1024,7 @@ isakmpproposal_spec
 			prhead->spspec->algclass[algclass_isakmp_dh] = $2;
 		}
 		EOS
-	|	GSSAPI_ID QUOTEDSTRING
+	|	GSS_ID QUOTEDSTRING
 		{
 			if (prhead->spspec->vendorid != VENDORID_GSSAPI) {
 				yyerror("wrong Vendor ID for gssapi_id");
@@ -1364,12 +1377,20 @@ expand_isakmpspec(prop_no, trns_no, type
 	new->dh_group = types[algclass_isakmp_dh];
 	new->vendorid = vendorid;
 #ifdef HAVE_GSSAPI
-	if (gssid != NULL) {
-		new->gssid = vmalloc(strlen(gssid) + 1);
-		memcpy(new->gssid->v, gssid, new->gssid->l);
-		racoon_free(gssid);
-	} else
-		new->gssid = NULL;
+	if (new->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) {
+		if (gssid != NULL) {
+			new->gssid = vmalloc(strlen(gssid));
+			memcpy(new->gssid->v, gssid, new->gssid->l);
+			racoon_free(gssid);
+		} else {
+			/*
+			 * Allocate the default ID so that it gets put
+			 * into a GSS ID attribute during the Phase 1
+			 * exchange.
+			 */
+			new->gssid = gssapi_get_default_gss_id();
+		}
+	}
 #endif
 	insisakmpsa(new, rmconf);
 
Index: cftoken.l
===================================================================
RCS file: /cvsroot/src/crypto/dist/kame/racoon/cftoken.l,v
retrieving revision 1.14
diff -u -p -r1.14 cftoken.l
--- cftoken.l	12 Apr 2004 03:34:06 -0000	1.14
+++ cftoken.l	5 Nov 2004 22:27:33 -0000
@@ -137,6 +137,7 @@ hexstring	0x{hexdigit}+
 %s S_SAINF S_SAINFS
 %s S_RMT S_RMTS S_RMTP
 %s S_SA
+%s S_GSSENC
 
 %%
 %{
@@ -282,7 +283,16 @@ hexstring	0x{hexdigit}+
 <S_RMTP>authentication_method { YYD; yylval.num = algclass_isakmp_ameth; return(ALGORITHM_CLASS); }
 <S_RMTP>hash_algorithm	{ YYD; yylval.num = algclass_isakmp_hash; return(ALGORITHM_CLASS); }
 <S_RMTP>dh_group	{ YYD; return(DH_GROUP); }
-<S_RMTP>gssapi_id	{ YYD; return(GSSAPI_ID); }
+<S_RMTP>gss_id		{ YYD; return(GSS_ID); }
+<S_RMTP>gssapi_id	{ YYD; return(GSS_ID); } /* for back compatibility */
+
+	/* GSS ID encoding type (global) */
+<S_INI>gss_id_enc	{ BEGIN S_GSSENC; YYDB; return(GSS_ID_ENC); }
+<S_GSSENC>latin1	{ YYD; yylval.num = LC_GSSENC_LATIN1;
+				return(GSS_ID_ENCTYPE); }
+<S_GSSENC>utf-16le	{ YYD; yylval.num = LC_GSSENC_UTF16LE;
+				return(GSS_ID_ENCTYPE); }
+<S_GSSENC>{semi}	{ BEGIN S_INI; YYDB; return(EOS); }
 
 	/* parameter */
 on		{ YYD; yylval.num = TRUE; return(SWITCH); }
Index: gssapi.c
===================================================================
RCS file: /cvsroot/src/crypto/dist/kame/racoon/gssapi.c,v
retrieving revision 1.3
diff -u -p -r1.3 gssapi.c
--- gssapi.c	12 Apr 2004 03:34:07 -0000	1.3
+++ gssapi.c	5 Nov 2004 22:27:33 -0000
@@ -44,6 +44,7 @@ __RCSID("$NetBSD: gssapi.c,v 1.3 2004/04
 #include <sys/queue.h>
 #include <sys/socket.h>
 #include <netdb.h>
+#include <unistd.h>
 
 #include <stdlib.h>
 #include <string.h>
@@ -132,6 +133,25 @@ gssapi_gss2vmbuf(gss_buffer_t gsstoken, 
 	return 0;
 }
 
+vchar_t *
+gssapi_get_default_gss_id(void)
+{
+	char name[NI_MAXHOST];
+	vchar_t *gssid;
+
+	if (gethostname(name, sizeof(name)) != 0) {
+		plog(LLV_ERROR, LOCATION, NULL, "gethostname failed: %s\n",
+		    strerror(errno));
+		return (NULL);
+	}
+	name[sizeof(name) - 1] = '\0';
+
+	gssid = racoon_malloc(sizeof(*gssid));
+	gssid->l = asprintf(&gssid->v, "%s/%s", GSSAPI_DEF_NAME, name);
+
+	return (gssid);
+}
+
 static int
 gssapi_get_default_name(struct ph1handle *iph1, int remote, gss_name_t *service)
 {
@@ -220,8 +240,15 @@ gssapi_init(struct ph1handle *iph1)
 		return -1;
 	}
 
-	plog(LLV_DEBUG, LOCATION, NULL, "will try to acquire '%*s' creds\n",
+#if 0
+	/*
+	 * XXXJRT Did this debug message ever work?  This is a GSS name
+	 * blob at this point.
+	 */
+	plog(LLV_DEBUG, LOCATION, NULL, "will try to acquire '%.*s' creds\n",
 	    cred->length, cred->value);
+#endif
+
 	maj_stat = gss_release_buffer(&min_stat, cred);
 	if (GSS_ERROR(maj_stat))
 		gssapi_error(min_stat, LOCATION, "release cred buffer\n");
@@ -263,15 +290,16 @@ gssapi_get_itoken(struct ph1handle *iph1
 	dummy = &empty;
 
 	if (iph1->approval != NULL && iph1->approval->gssid != NULL) {
-		plog(LLV_DEBUG, LOCATION, NULL, "using provided service '%s'\n",
-		    iph1->approval->gssid->v);
+		plog(LLV_DEBUG, LOCATION, NULL,
+		    "using provided service '%.*s'\n",
+		    iph1->approval->gssid->l, iph1->approval->gssid->v);
 		name_token.length = iph1->approval->gssid->l;
 		name_token.value = iph1->approval->gssid->v;
 		maj_stat = gss_import_name(&min_stat, &name_token,
 		    GSS_C_NO_OID, &partner);
 		if (GSS_ERROR(maj_stat)) {
-			gssapi_error(min_stat, LOCATION, "import of %s\n",
-			    name_token.value);
+			gssapi_error(min_stat, LOCATION, "import of '%.*s'\n",
+			    name_token.length, name_token.value);
 			return -1;
 		}
 	} else
@@ -653,7 +681,7 @@ gssapi_free_state(struct ph1handle *iph1
 }
 
 vchar_t *
-gssapi_get_default_id(struct ph1handle *iph1)
+gssapi_get_id(struct ph1handle *iph1)
 {
 	gss_buffer_desc id_buffer;
 	gss_buffer_t id = &id_buffer;
@@ -661,6 +689,9 @@ gssapi_get_default_id(struct ph1handle *
 	OM_uint32 min_stat, maj_stat;
 	vchar_t *vmbuf;
 
+	if (iph1->rmconf->proposal->gssid != NULL)
+		return (vdup(iph1->rmconf->proposal->gssid));
+
 	if (gssapi_get_default_name(iph1, 0, &defname) < 0)
 		return NULL;
 
@@ -691,8 +722,14 @@ gssapi_get_default_id(struct ph1handle *
 	if (GSS_ERROR(maj_stat))
 		gssapi_error(min_stat, LOCATION, "release canonical name\n");
 
-	plog(LLV_DEBUG, LOCATION, NULL, "will try to acquire '%*s' creds\n",
+#if 0
+	/*
+	 * XXXJRT Did this debug message ever work?  This is a GSS name
+	 * blob at this point.
+	 */
+	plog(LLV_DEBUG, LOCATION, NULL, "will try to acquire '%.*s'\n",
 	    id->length, id->value);
+#endif
 
 	if (gssapi_gss2vmbuf(id, &vmbuf) < 0) {
 		plog(LLV_ERROR, LOCATION, NULL, "gss2vmbuf failed\n");
Index: ipsec_doi.c
===================================================================
RCS file: /cvsroot/src/crypto/dist/kame/racoon/ipsec_doi.c,v
retrieving revision 1.15
diff -u -p -r1.15 ipsec_doi.c
--- ipsec_doi.c	12 Apr 2004 03:34:07 -0000	1.15
+++ ipsec_doi.c	5 Nov 2004 22:27:37 -0000
@@ -85,6 +85,7 @@ __RCSID("$NetBSD: ipsec_doi.c,v 1.15 200
 #include "gcmalloc.h"
 
 #ifdef HAVE_GSSAPI
+#include <iconv.h>
 #include "auth_gssapi.h"
 #endif
 
@@ -269,8 +270,8 @@ found:
 saok:
 #ifdef HAVE_GSSAPI
 	if (sa->gssid != NULL)
-		plog(LLV_DEBUG, LOCATION, NULL, "gss id in new sa '%s'\n",
-		    sa->gssid->v);
+		plog(LLV_DEBUG, LOCATION, NULL, "gss id in new sa '%.*s'\n",
+		    sa->gssid->l, sa->gssid->v);
 	if (iph1-> side == INITIATOR) {
 		if (iph1->rmconf->proposal->gssid != NULL)
 			iph1->gi_i = vdup(iph1->rmconf->proposal->gssid);
@@ -280,21 +281,17 @@ saok:
 	} else {
 		if (tsa.gssid != NULL) {
 			iph1->gi_r = vdup(tsa.gssid);
-			if (iph1->rmconf->proposal->gssid != NULL)
-				iph1->gi_i =
-				    vdup(iph1->rmconf->proposal->gssid);
-			else
-				iph1->gi_i = gssapi_get_default_id(iph1);
+			iph1->gi_i = gssapi_get_id(iph1);
 			if (sa->gssid == NULL && iph1->gi_i != NULL)
 				sa->gssid = vdup(iph1->gi_i);
 		}
 		iph1->approval = sa;
 	}
 	if (iph1->gi_i != NULL)
-		plog(LLV_DEBUG, LOCATION, NULL, "GIi is %*s\n",
+		plog(LLV_DEBUG, LOCATION, NULL, "GIi is '%.*s'\n",
 		    iph1->gi_i->l, iph1->gi_i->v);
 	if (iph1->gi_r != NULL)
-		plog(LLV_DEBUG, LOCATION, NULL, "GIr is %*s\n",
+		plog(LLV_DEBUG, LOCATION, NULL, "GIr is '%.*s'\n",
 		    iph1->gi_r->l, iph1->gi_r->v);
 #else
 	iph1->approval = sa;
@@ -662,16 +659,81 @@ t2isakmpsa(trns, sa)
 #ifdef HAVE_GSSAPI
 		case OAKLEY_ATTR_GSS_ID:
 		{
+			iconv_t cd;
+			size_t srcleft, dstleft, rv;
+			const char *src;
+			char *dst;
 			int len = ntohs(d->lorv);
 
-			sa->gssid = vmalloc(len);
-			memcpy(sa->gssid->v, d + 1, len);
+			/*
+			 * Older versions of racoon just placed the
+			 * ISO-Latin-1 string on the wire directly.
+			 * Check to see if we are configured to be
+			 * compatible with this behavior.
+			 */
+			if (lcconf->gss_id_enc == LC_GSSENC_LATIN1) {
+				sa->gssid = vmalloc(len);
+				memcpy(sa->gssid->v, d + 1, len);
+				plog(LLV_DEBUG, LOCATION, NULL,
+				  "received old-style gss id '%.*s' (len %d)\n",
+				  sa->gssid->l, sa->gssid->v, sa->gssid->l);
+				break;
+			}
+
+			/*
+			 * For Windows 2000 compatbility, we expect
+			 * the GSS ID attribute on the wire to be
+			 * encoded in UTF-16LE.  Internally, we work
+			 * in ISO-Latin-1.  Therefore, we should need
+			 * 1/2 the specified length, which should
+			 * always be a multiple of 2 octets.
+			 */
+			cd = iconv_open("latin1", "utf-16le");
+			if (cd == (iconv_t) -1) {
+				plog(LLV_ERROR, LOCATION, NULL,
+				    "unable to initialize utf-16le -> latin1 "
+				    "conversion descriptor: %s\n",
+				    strerror(errno));
+				break;
+			}
+
+			sa->gssid = vmalloc(len / 2);
+
+			src = (const char *)(d + 1);
+			srcleft = len;
+
+			dst = sa->gssid->v;
+			dstleft = len / 2;
+
+			rv = iconv(cd, &src, &srcleft, &dst, &dstleft);
+			if (rv != 0) {
+				if (rv == -1) {
+					plog(LLV_ERROR, LOCATION, NULL,
+					   "unable to convert GSS ID from "
+					   "utf-16le -> latin1: %s\n",
+					   strerror(errno));
+				} else {
+					plog(LLV_ERROR, LOCATION, NULL,
+					    "%zd character%s in GSS ID cannot "
+					    "be represented in latin1\n",
+					    rv, rv == 1 ? "" : "s");
+				}
+				(void) iconv_close(cd);
+				vfree(sa->gssid);
+				sa->gssid = NULL;
+				break;
+			}
+			(void) iconv_close(cd);
+
+			/* XXX dstleft should always be 0; assert it? */
+			sa->gssid->l = (len / 2) - dstleft;
+
 			plog(LLV_DEBUG, LOCATION, NULL,
-			    "received gss id '%s' (len %d)\n", sa->gssid->v,
-			    sa->gssid->l);
+			    "received gss id '%.*s' (len %d)\n", sa->gssid->l,
+			    sa->gssid->v, sa->gssid->l);
 			break;
 		}
-#endif
+#endif /* HAVE_GSSAPI */
 
 		default:
 			break;
@@ -2583,16 +2645,77 @@ setph1attr(sa, buf)
 	if (sa->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
 	    sa->gssid != NULL) {
 		attrlen += sizeof(struct isakmp_data);
-		attrlen += sa->gssid->l;
+		/*
+		 * Older versions of racoon just placed the ISO-Latin-1
+		 * string on the wire directly.  Check to see if we are
+		 * configured to be compatible with this behavior.  Otherwise,
+		 * we encode the GSS ID as UTF-16LE for Windows 2000
+		 * comatibility, which requires twice the number of octets.
+		 */
+		if (lcconf->gss_id_enc == LC_GSSENC_LATIN1)
+			attrlen += sa->gssid->l;
+		else
+			attrlen += sa->gssid->l * 2;
 		if (buf) {
 			plog(LLV_DEBUG, LOCATION, NULL, "gss id attr: len %d, "
-			    "val '%s'\n", sa->gssid->l, sa->gssid->v);
-			p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
-				(caddr_t)sa->gssid->v, 
-				sa->gssid->l);
+			    "val '%.*s'\n", sa->gssid->l, sa->gssid->l,
+			    sa->gssid->v);
+			if (lcconf->gss_id_enc == LC_GSSENC_LATIN1) {
+				p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
+					(caddr_t)sa->gssid->v, 
+					sa->gssid->l);
+			} else {
+				size_t dstleft = sa->gssid->l * 2;
+				size_t srcleft = sa->gssid->l;
+				const char *src = (const char *)sa->gssid->v;
+				char *odst, *dst = racoon_malloc(dstleft);
+				iconv_t cd;
+				size_t rv;
+
+				cd = iconv_open("utf-16le", "latin1");
+				if (cd == (iconv_t) -1) {
+					plog(LLV_ERROR, LOCATION, NULL,
+					    "unable to initialize "
+					    "latin1 -> utf-16le "
+					    "converstion descriptor: %s\n",
+					    strerror(errno));
+					attrlen -= sa->gssid->l * 2;
+					goto gssid_done;
+				}
+				odst = dst;
+				rv = iconv(cd, &src, &srcleft,
+				    &dst, &dstleft);
+				if (rv != 0) {
+					if (rv == -1) {
+						plog(LLV_ERROR, LOCATION, NULL,
+						    "unable to convert GSS ID "
+						    "from latin1 -> utf-16le: "
+						    "%s\n", strerror(errno));
+					} else {
+						/* should never happen */
+						plog(LLV_ERROR, LOCATION, NULL,
+						    "%zd character%s in GSS ID "
+						    "cannot be represented "
+						    "in utf-16le\n",
+						    rv, rv == 1 ? "" : "s");
+					}
+					(void) iconv_close(cd);
+					attrlen -= sa->gssid->l * 2;
+					goto gssid_done;
+				}
+				(void) iconv_close(cd);
+
+				/* XXX Check srcleft and dstleft? */
+
+				p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
+					odst, sa->gssid->l * 2);
+
+				racoon_free(odst);
+			}
 		}
 	}
-#endif
+ gssid_done:
+#endif /* HAVE_GSSAPI */
 
 	return attrlen;
 }
Index: localconf.c
===================================================================
RCS file: /cvsroot/src/crypto/dist/kame/racoon/localconf.c,v
retrieving revision 1.3
diff -u -p -r1.3 localconf.c
--- localconf.c	30 Oct 2004 15:15:38 -0000	1.3
+++ localconf.c	5 Nov 2004 22:27:37 -0000
@@ -116,6 +116,7 @@ setdefault()
 	lcconf->wait_ph2complete = LC_DEFAULT_WAIT_PH2COMPLETE;
 	lcconf->strict_address = FALSE;
 	lcconf->complex_bundle = TRUE; /*XXX FALSE;*/
+	lcconf->gss_id_enc = LC_GSSENC_UTF16LE;	/* Windows compatibility */
 }
 
 /*
Index: localconf.h
===================================================================
RCS file: /cvsroot/src/crypto/dist/kame/racoon/localconf.h,v
retrieving revision 1.1.1.6
diff -u -p -r1.1.1.6 localconf.h
--- localconf.h	26 Apr 2002 02:18:04 -0000	1.1.1.6
+++ localconf.h	5 Nov 2004 22:27:37 -0000
@@ -54,6 +54,10 @@
 
 #define LC_IDENTTYPE_MAX	5	/* XXX */
 
+#define	LC_GSSENC_UTF16LE	0	/* GSS ID in UTF-16LE */
+#define	LC_GSSENC_LATIN1	1	/* GSS ID in ISO-Latin-1 */
+#define	LC_GSSENC_MAX		2
+
 struct localconf {
 	char *racoon_conf;		/* configuration filename */
 
@@ -98,6 +102,8 @@ struct localconf {
 		 * usually uses this format.  If the option, 'complex_bundle'
 		 * is enable, racoon uses old format.
 		 */
+
+	int gss_id_enc;			/* GSS ID encoding to use */
 };
 
 extern struct localconf *lcconf;
Index: racoon.conf.5
===================================================================
RCS file: /cvsroot/src/crypto/dist/kame/racoon/racoon.conf.5,v
retrieving revision 1.21
diff -u -p -r1.21 racoon.conf.5
--- racoon.conf.5	12 Apr 2004 03:34:07 -0000	1.21
+++ racoon.conf.5	5 Nov 2004 22:27:38 -0000
@@ -28,7 +28,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd April 12, 2004
+.Dd November 4, 2004
 .Dt RACOON.CONF 5
 .Os
 .\"
@@ -211,6 +211,36 @@ This statement will be ignored if you do
 .El
 .El
 .\"
+.Ss Miscellaneous Global Parameters
+.Bl -tag -width Ds -compact
+.It Ic gss_id_enc Ar enctype ;
+Older versions of
+.Xr racoon 8
+used ISO-Latin-1 as the encoding of the GSS-API identifier attribute.
+For interoperability with Microsoft Windows' GSS-API authentication
+scheme, the default encoding has been changed to UTF-16LE.
+The
+.Ic gss_id_enc
+parameter allows
+.Xr racoon 8
+to be configured to use the old encoding for compatibility with existing
+.Xr racoon 8
+installations.
+The following are valid values for
+.Ar enctype :
+.Pp
+.Bl -tag -width Ds -compact
+.It Ic utf-16le
+Use UTF-16LE to encode the GSS-API identifier attribute.
+This is the default encoding.
+This encoding is compatible with Microsoft Windows.
+.It Ic latin1
+Use ISO-Latin-1 to encode the GSS-API identifier attribute.
+This is the encoding used by older versions of
+.Xr racoon 8 .
+.El
+.El
+.\"
 .Ss Remote Nodes Specifications
 .Bl -tag -width Ds -compact
 .It Xo
@@ -478,13 +508,15 @@ Refer to the description of
 directive immediately defined in
 .Ic remote
 directive.
-.It Ic gssapi_id Ar string ;
+.It Ic gss_id Ar string ;
 define the GSS-API endpoint name, to be included as an attribute in the SA,
 if the
 .Ic gssapi_krb
 authentication method is used. If this is not defined, the default value of
-.Ql ike/hostname
-is used, where hostname is the FQDN of the interface being used.
+.Ql host/hostname
+is used, where hostname is the value returned by the
+.Xr hostname 1
+command.
 .El
 .El
 .El
Index: samples/racoon.conf.sample-gssapi
===================================================================
RCS file: /cvsroot/src/crypto/dist/kame/racoon/samples/racoon.conf.sample-gssapi,v
retrieving revision 1.4
diff -u -p -r1.4 racoon.conf.sample-gssapi
--- samples/racoon.conf.sample-gssapi	31 Aug 2001 10:36:09 -0000	1.4
+++ samples/racoon.conf.sample-gssapi	5 Nov 2004 22:27:38 -0000
@@ -8,32 +8,36 @@
 #	strict_address;
 #}
 
+# Uncomment the following for GSS-API to work with older versions of
+# racoon that (incorrectly) used ISO-Latin-1 encoding for the GSS-API
+# identifier attribute.
+#gss_id_enc latin1;
+
 remote anonymous {
 	exchange_mode main;
-	#exchange_mode aggressive;
-
-	# specify the identifier type
-	my_identifier fqdn "foo.kame.net";
 
-	lifetime time 1 min;
+	lifetime time 24 hour;
 
 	proposal {
-		encryption_algorithm blowfish;
+		encryption_algorithm 3des;
 		hash_algorithm sha1;
-		#authentication_method pre_shared_key;
 		authentication_method gssapi_krb;
-		gssapi_id "ike/myidentification";
+		# The default GSS-API ID is "host/hostname", where
+		# hostname is the output of the hostname(1) command.
+		# You probably want this to match your system's host
+		# principal.  ktutil(8)'s "list" command will list the
+		# principals in your system's keytab.  If you need to,
+		# you can change the GSS-API ID here.
+		#gss_id "host/some.host.name";
 
 		dh_group 1;
 	}
 }
 
 sainfo anonymous {
-	my_identifier fqdn "foo.kame.net";
-
-	lifetime time 30 min;
+	lifetime time 2 hour;
 
-	encryption_algorithm blowfish 448;
-	authentication_algorithm hmac_sha1;
+	encryption_algorithm rijndael, 3des;
+	authentication_algorithm hmac_sha1, hmac_md5;
 	compression_algorithm deflate;
 }

--Apple-Mail-35--1016353780--

--Apple-Mail-36--1016353762
content-type: application/pgp-signature; x-mac-type=70674453;
	name=PGP.sig
content-description: This is a digitally signed message part
content-disposition: inline; filename=PGP.sig
content-transfer-encoding: 7bit

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.3 (Darwin)

iD8DBQFBjA0GOpVKkaBm8XkRAh+bAJ472fTmuKKUfK4J214Op901Ol+fCwCcCrua
8LwpinvJYAh6ARc6Q8qiu4M=
=/eOa
-----END PGP SIGNATURE-----

--Apple-Mail-36--1016353762--