diff -u ../../freeswan-1.4/pluto/Makefile ./Makefile
--- ../../freeswan-1.4/pluto/Makefile	Mon May 22 06:37:44 2000
+++ ./Makefile	Mon Jun 19 19:05:19 2000
@@ -80,7 +80,7 @@
 
 # libefence is a free memory allocation debugger
 # Solaris 2 needs -lsocket -lnsl
-LIBSPLUTO = -lresolv # -lefence
+LIBSPLUTO = -lresolv -lefence
 
 LDFLAGS =
 
diff -u ../../freeswan-1.4/pluto/connections.c ./connections.c
--- ../../freeswan-1.4/pluto/connections.c	Mon May 22 06:37:44 2000
+++ ./connections.c	Mon Jun 19 19:03:01 2000
@@ -491,6 +491,9 @@
 	c->sa_rekey_fuzz = wm->sa_rekey_fuzz;
 	c->sa_keying_tries = wm->sa_keying_tries;
 
+	c->this.id.key_id.len = 0;
+	c->that.id.key_id.len = 0;
+	
 	extract_end(&c->this, &wm->left, "left", whack_fd);
 	extract_end(&c->that, &wm->right, "right", whack_fd);
 
diff -u ../../freeswan-1.4/pluto/defs.h ./defs.h
--- ../../freeswan-1.4/pluto/defs.h	Mon May 22 06:37:45 2000
+++ ./defs.h	Mon Jun 19 19:03:01 2000
@@ -121,3 +121,11 @@
 
 /* pad_up(n, m) is the amount to add to n to make it a multiple of m */
 #define pad_up(n, m) (((m) - 1) - (((n) + (m) - 1) % (m)))
+
+
+typedef struct pc{
+	char *cert;
+	int cert_len;
+	} pc;
+	
+struct pc pgpcert;
\ No newline at end of file
diff -u ../../freeswan-1.4/pluto/demux.c ./demux.c
--- ../../freeswan-1.4/pluto/demux.c	Mon May 22 06:37:45 2000
+++ ./demux.c	Mon Jun 19 19:03:01 2000
@@ -229,7 +229,7 @@
      *	    --> HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r
      */
     { STATE_MAIN_R1, SMF_PSK_AUTH | SMF_DS_AUTH
-    , P(KE) | P(NONCE), P(VID), PT(KE)
+    , P(KE) | P(NONCE), P(VID) | P(CR), PT(KE)
     , EVENT_RETRANSMIT, main_inI2_outR2 },
 
     { STATE_MAIN_R1, SMF_PKE_AUTH
@@ -251,11 +251,11 @@
      *	    --> HDR*, HASH_I
      */
     { STATE_MAIN_I2, SMF_PSK_AUTH | SMF_DS_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED
-    , P(KE) | P(NONCE), P(VID), PT(ID)
+    , P(KE) | P(NONCE), P(VID) | P(CR), PT(ID)
     , EVENT_RETRANSMIT, main_inR2_outI3 },
 
     { STATE_MAIN_I2, SMF_PKE_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED
-    , P(KE) | P(ID) | P(NONCE), P(VID), PT(HASH)
+    , P(KE) | P(ID) | P(NONCE), P(VID) | P(CR), PT(HASH)
     , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ },
 
     { STATE_MAIN_I2, SMF_ALL_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED
@@ -274,7 +274,7 @@
     , EVENT_SA_REPLACE, main_inI3_outR3 },
 
     { STATE_MAIN_R2, SMF_DS_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
-    , P(ID) | P(SIG), P(VID) | P(CERT), PT(ID)
+    , P(ID) | P(SIG), P(VID) | P(CERT) | P(CR), PT(ID)
     , EVENT_SA_REPLACE, main_inI3_outR3 },
 
     { STATE_MAIN_R2, SMF_PKE_AUTH | SMF_RPKE_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
@@ -292,7 +292,7 @@
     , EVENT_SA_REPLACE, main_inR3 },
 
     { STATE_MAIN_I3, SMF_DS_AUTH | SMF_INITIATOR | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
-    , P(ID) | P(SIG), P(VID) | P(CERT), PT(NONE)
+    , P(ID) | P(SIG), P(VID) | P(CERT) | P(CR), PT(NONE)
     , EVENT_SA_REPLACE, main_inR3 },
 
     { STATE_MAIN_I3, SMF_PKE_AUTH | SMF_RPKE_AUTH | SMF_INITIATOR | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED
diff -u ../../freeswan-1.4/pluto/id.c ./id.c
--- ../../freeswan-1.4/pluto/id.c	Mon May 22 06:37:46 2000
+++ ./id.c	Tue Jun 20 13:41:05 2000
@@ -38,7 +38,11 @@
 atoid(char *src, struct id *id)
 {
     const char *ugh = NULL;
-
+	char	*nptr, *kptr;
+	char	s[4];
+	
+	u_int i;
+	
     memset(id, 0, sizeof(*id));
     id->name.ptr = NULL;
     id->next = NULL;
@@ -52,18 +56,37 @@
     {
 	if (*src == '@')
 	{
-	    id->kind = ID_FQDN;
-	    id->name.ptr = src+1;	/* discard @ */
-	}
-	else
-	{
-	    /* We leave in @, as per DOI 4.6.2.4
-	     * (but DNS wants . instead).
-	     */
-	    id->kind = ID_USER_FQDN;
-	    id->name.ptr = src;
-	}
-	id->name.len = strlen(id->name.ptr);
+	
+	
+		if (*(src+1) == '#')
+		{
+	    		id->kind = ID_KEY_ID;
+	    		id->name.ptr = src+2;
+	    		id->key_id.ptr = alloc_bytes(strlen(id->name.ptr)/2, "keyid-ptr");
+	    		id->key_id.len = strlen(id->name.ptr)/2;
+	    		nptr = id->name.ptr;
+	    		kptr = id->key_id.ptr;
+	    
+	    		for (i=0; i< strlen(id->name.ptr)/2; i++, kptr++)
+	    		{
+	    			snprintf(s, 3, "%s", nptr);
+	    			*kptr = strtol(s, NULL, 16);
+	    			nptr+=2;
+	    		}
+	    		DBG_dump("Key-ID: ", id->key_id.ptr, id->key_id.len);
+		}
+    		else
+    		{
+			id->kind = ID_FQDN;
+			id->name.ptr = src+1;	/* discard @ */
+    		}
+    	}
+    	else
+    	{
+		id->kind = ID_USER_FQDN;
+		id->name.ptr = src;
+    	}
+    	id->name.len = strlen(id->name.ptr);
     }
     return ugh;
 }
@@ -81,6 +104,8 @@
 	return snprintf(dst, dstlen, "@%.*s", (int)id->name.len, id->name.ptr);
     case ID_USER_FQDN:
 	return snprintf(dst, dstlen, "%.*s", (int)id->name.len, id->name.ptr);
+    case ID_KEY_ID:
+    	return snprintf(dst, dstlen, "%.*s", (int)id->name.len, id->name.ptr); 
     default:
 	return snprintf(dst, dstlen, "unknown id kind %d", id->kind);
     }
@@ -103,19 +128,22 @@
 void
 clone_id_content(struct id *id)
 {
-    switch (id->kind)
-    {
-    case ID_FQDN:
-    case ID_USER_FQDN:
-	id->name.ptr = clone_bytes(id->name.ptr, id->name.len, "keep id name");
-	break;
-    case ID_NONE:
-    case ID_IPV4_ADDR:
-	break;
-    default:
-	passert(FALSE);
-    }
+switch (id->kind)
+     {
+     case ID_KEY_ID:
+        id->key_id.ptr = clone_bytes(id->key_id.ptr, id->key_id.len,"keep keyid");
+     case ID_FQDN:
+     case ID_USER_FQDN:
+        id->name.ptr = clone_bytes(id->name.ptr, id->name.len, "keep id name");
+        break;
+     case ID_NONE:
+     case ID_IPV4_ADDR:
+        break;
+     default:
+        passert(FALSE);
+     }
 }
+                                                                                           
 
 /* free a heap struct id */
 void
@@ -134,6 +162,10 @@
     case ID_USER_FQDN:
 	pfree(id->name.ptr);
 	break;
+    case ID_KEY_ID:
+    	pfree(id->name.ptr); 
+    	pfree(id->key_id.ptr);
+    	break;
     case ID_NONE:
     case ID_IPV4_ADDR:
 	break;
@@ -158,6 +190,7 @@
 
     case ID_FQDN:
     case ID_USER_FQDN:
+    case ID_KEY_ID:
 	/* assumption: case should be ignored */
 	return a->name.len == b->name.len
 	    && strncasecmp(a->name.ptr, b->name.ptr, a->name.len) == 0;
@@ -187,6 +220,9 @@
 	tl->ptr = (void *)&end->id.ip_addr;
 	tl->len = sizeof(end->id.ip_addr);
 	break;
+    case ID_KEY_ID:
+    	*tl = end->id.key_id;
+    	break;
     default:
 	passert(FALSE);
     }
diff -u ../../freeswan-1.4/pluto/id.h ./id.h
--- ../../freeswan-1.4/pluto/id.h	Mon May 22 06:37:46 2000
+++ ./id.h	Mon Jun 19 19:03:01 2000
@@ -18,6 +18,7 @@
     int kind;	/* ID_* value */
     struct in_addr ip_addr;	/* (network order) ID_IPV4_ADDR */
     chunk_t name;	/* ID_FQDN, ID_USER_FQDN (with @) */
+    chunk_t key_id;	/* ID_KEY_ID */
     struct id *next;
 };
 
diff -u ../../freeswan-1.4/pluto/ipsec_doi.c ./ipsec_doi.c
--- ../../freeswan-1.4/pluto/ipsec_doi.c	Mon May 22 06:37:47 2000
+++ ./ipsec_doi.c	Mon Jun 19 19:03:01 2000
@@ -53,6 +53,14 @@
 #define RETURN_STF_FAILURE(f) \
     { int r = (f); if (r != NOTHING_WRONG) return STF_FAIL + r; }
 
+stf_status send_delete(struct state *p2st, ipsec_spi_t *spi, bool ESP);
+static bool encrypt_message(pb_stream *pbs, struct state *st);
+
+/* needed for PGPnet Vendor ID */
+char pgp_vid[] = { 0x4f, 0x70, 0x65, 0x6e,
+		 0x50, 0x47, 0x50, 0x31,
+		 0x30, 0x31, 0x37, 0x31};
+
 /* if we haven't already done so, compute a local DH secret (st->st_sec) and
  * the corresponding public value (g).  This is emitted as a KE payload.
  */
@@ -258,6 +266,118 @@
 //}
 #endif /* not currently used */
 
+stf_status
+send_delete(struct state *p2st, ipsec_spi_t *spi, bool ESP)
+{
+     pb_stream reply_pbs;
+     pb_stream r_hdr_pbs;
+     msgid_t	msgid;
+     u_char 	old_new_iv[MAX_DIGEST_LEN];
+     u_char 	old_iv[MAX_DIGEST_LEN];         
+     u_char buffer[8192];
+     struct state *p1st;
+     
+     u_char spilen = sizeof(ipsec_spi_t);
+     u_char
+ 	*r_hashval,	/* where in reply to jam hash value */
+ 	*r_hash_start;	/* start of what is to be hashed */
+     
+     memset(buffer, '\0', sizeof(buffer));
+     init_pbs(&reply_pbs, buffer, sizeof(buffer), "delete msg");
+ 
+     /* find the related P1-State to the calling P2-state */
+     p1st = find_state(p2st->st_icookie, p2st->st_rcookie, 
+     			p2st->st_connection->that.host_addr, 0);
+     if (p1st == NULL) 
+     {
+ 	DBG_log("no phase 1 state where one should be");
+	return STF_INTERNAL_ERROR;
+     }
+ 
+     msgid = generate_msgid(p1st->st_connection->that.host_addr);
+
+     /* HDR* */
+     {
+ 	struct isakmp_hdr hdr;
+ 
+ 	hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;
+ 	hdr.isa_np = ISAKMP_NEXT_HASH;
+ 	hdr.isa_xchg = ISAKMP_XCHG_INFO;
+ 	hdr.isa_msgid = msgid;
+ 	hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION;
+ 	memcpy(hdr.isa_icookie, p1st->st_icookie, COOKIE_SIZE);
+ 	memcpy(hdr.isa_rcookie, p1st->st_rcookie, COOKIE_SIZE);
+ 	if (!out_struct(&hdr, &isakmp_hdr_desc, &reply_pbs, &r_hdr_pbs))
+ 	    return STF_INTERNAL_ERROR;
+     }
+ 
+     /* HASH -- space to be filled later */
+     {
+ 	pb_stream hash_pbs;
+ 
+ 	if (!out_generic(ISAKMP_NEXT_D, &isakmp_hash_desc, &r_hdr_pbs, &hash_pbs))
+     	    return STF_INTERNAL_ERROR;
+ 	r_hashval = hash_pbs.cur;	/* remember where to plant value */
+ 	if (!out_zero(p1st->st_oakley.hasher->hash_digest_len, &hash_pbs, "HASH(1)"))
+ 	    return STF_INTERNAL_ERROR;
+ 	close_output_pbs(&hash_pbs);
+ 	r_hash_start = r_hdr_pbs.cur;	/* hash from after HASH(1) */
+     }
+ 
+     /* DELETE PAYLOAD */
+     {
+ 	pb_stream del_pbs;
+ 	struct isakmp_delete isad;
+ 	
+        isad.isad_doi = ISAKMP_DOI_IPSEC;
+ 	isad.isad_np = ISAKMP_NEXT_NONE;
+ 	isad.isad_spisize = spilen;
+        if (ESP) isad.isad_protoid = PROTO_IPSEC_ESP;
+        else isad.isad_protoid = PROTO_IPSEC_AH;
+ 	isad.isad_nospi = 0x0001;
+         if (!out_struct(&isad, &isakmp_delete_desc, &r_hdr_pbs, &del_pbs))
+ 	    return STF_INTERNAL_ERROR;
+ 	if (!out_raw(spi, spilen, &del_pbs, "delete payload"))
+ 	    return STF_INTERNAL_ERROR;;
+         close_output_pbs(&del_pbs);
+     }
+     
+     {
+         struct hmac_ctx ctx;
+ 	hmac_init_chunk(&ctx, p1st->st_oakley.hasher, p1st->st_skeyid_a);
+         hmac_update(&ctx, (u_char *) &msgid, sizeof(msgid_t));
+         hmac_update(&ctx, r_hash_start, r_hdr_pbs.cur-r_hash_start);
+ 	hmac_final(r_hashval, &ctx);
+ 
+         DBG(DBG_CRYPT,
+     	    DBG_log("HASH(1) computed:");
+ 	    DBG_dump("", r_hashval, ctx.hmac_digest_len));
+     }
+ 
+     /* save old IV (this prevents from copying a whole new state object 
+      * for NOTIFICATION / DELETE messages we don't need to maintain a state
+      * because there are no retransmissions...
+      */
+      
+     memcpy(old_new_iv, p1st->st_new_iv, p1st->st_new_iv_len);
+     memcpy(old_iv, p1st->st_iv, p1st->st_iv_len);
+     init_phase2_iv(p1st, &msgid);
+ 
+     if(!encrypt_message(&r_hdr_pbs, p1st)) passert(FALSE);
+     
+     clonetochunk(p1st->st_tpacket, reply_pbs.start, pbs_offset(&reply_pbs)
+ 	, "reply packet for main_outI1");
+ 
+     send_packet(p1st, "delete notify");
+     
+     /* get back old IV for this state */
+     memcpy(p1st->st_new_iv, old_new_iv, p1st->st_new_iv_len);
+     memcpy(p1st->st_iv, old_iv, p1st->st_iv_len);    
+     
+     return STF_IGNORE; 
+}
+	
+
 /* The whole message must be a multiple of 4 octets.
  * I'm not sure where this is spelled out, but look at
  * rfc2408 3.6 Transform Payload.
@@ -290,6 +410,7 @@
 
     struct state *st;
 
+    int np;
     /* set up new state */
     cur_state = st = new_state();
     st->st_connection = c;
@@ -358,9 +479,17 @@
 		return STF_INTERNAL_ERROR;
 	    }
 	}
+	
+	if (c->this.id.kind == ID_KEY_ID)
+		np = ISAKMP_NEXT_VID;
+	else
+		np = ISAKMP_NEXT_NONE;
+		
+
+
 	if (!out_sa(&rbody
 	, &oakley_sadb[auth_policy >> POLICY_ISAKMP_SHIFT]
-	, st, TRUE, ISAKMP_NEXT_NONE))
+	, st, TRUE, np))
 	{
 	    cur_state = NULL;
 	    return STF_INTERNAL_ERROR;
@@ -371,6 +500,11 @@
 	clonetochunk(st->st_p1isa, sa_start, rbody.cur - sa_start
 	    , "sa in main_outI1");
     }
+    if (c->this.id.kind == ID_KEY_ID)
+    {
+    	if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_vendor_id_desc, &rbody, pgp_vid, sizeof(pgp_vid), "V_ID"))
+    		return STF_INTERNAL_ERROR;
+    }
 
     close_message(&rbody);
     close_output_pbs(&reply);
@@ -707,14 +841,19 @@
 		, hashus? "my" : "his"
 		, enum_show(&ident_names, id_hd.isaiid_idtype)
 		, id_hd.isaiid_protoid, htons(id_hd.isaiid_port)));
-
+	DBG_dump("ID to be hashed:"
+		, (u_char *)&id_hd + sizeof(struct isakmp_generic)
+		, sizeof(id_hd) - sizeof(struct isakmp_generic));
+		
 	/* NOTE: hash does NOT include the generic payload part of
 	 * Identity Payload
 	 */
 	hash_update(ctx
 	    , (u_char *)&id_hd + sizeof(struct isakmp_generic)
 	    , sizeof(id_hd) - sizeof(struct isakmp_generic));
-
+	
+	DBG_dump("ID to be hashed:", id_b.ptr, id_b.len);
+	
 	hash_update_chunk(ctx, id_b);
     }
 #   undef hash_update_chunk
@@ -1296,10 +1435,15 @@
     pb_stream *const id_pbs = &id_pld->pbs;
     struct isakmp_id *const id = &id_pld->payload.id;
     struct id peer;
+    u_char key_id[256];
+    u_int i, len;
+    
+    peer.key_id.len = 0;
 
     /* XXX Check for valid ID types? */
     peer.kind = id->isaid_idtype;
 
+
     switch (peer.kind)
     {
     case ID_IPV4_ADDR:
@@ -1360,7 +1504,45 @@
 
 	setchunk(peer.name, id_pbs->cur, pbs_left(id_pbs));
 	break;
+    	
+    case ID_KEY_ID:
+	if (!(id->isaid_doi_specific_a == 0 && id->isaid_doi_specific_b == 0))
+	{
+	    log("protocol/port in Phase 1 ID Payload must be 0/0"
+		" but are %d/%d"
+		, id->isaid_doi_specific_a, id->isaid_doi_specific_b);
+	    return FALSE;
+	}
+	
+	len = pbs_left(id_pbs);
+	
+	/* we need double size for ASCII representation of key id */
+	if (2*len > 256)
+	{
+		log("too large key id");
+		return FALSE;
+	}
+		
+	DBG_dump("Key ID:", id_pbs->cur, pbs_left(id_pbs));
 
+	/* hold the binary representation of KEY_ID */
+	/* possible memory hole? */
+
+	peer.key_id.ptr = alloc_bytes(len, "key_id");
+	peer.key_id.len = len;
+	memcpy(peer.key_id.ptr, id_pbs->cur, len);
+	
+	for (i=0; i<len; i++, id_pbs->cur++)
+		sprintf(&key_id[i*2], "%02x", *(id_pbs->cur));
+	
+	/* possible memory hole? */
+	
+	peer.name.ptr = alloc_bytes(2*len, "name");
+	peer.name.len = 2*len;
+	memcpy(peer.name.ptr, key_id, peer.name.len);
+	
+	break;	
+	    	
     default:
 	/* XXX Could send notification back */
 	log("Unacceptable identity type (%s) in Phase 1 ID Payload"
@@ -1413,6 +1595,11 @@
 	    SET_CUR_CONNECTION(r);
 	    rw_connection_discard(c);
 	}
+	if (peer.key_id.len)
+	{
+		r->that.id.key_id.ptr = clone_bytes( peer.key_id.ptr, peer.key_id.len, "KEY_ID");
+		r->that.id.key_id.len = peer.key_id.len;
+	}
     }
 
     return TRUE;
@@ -1793,7 +1980,10 @@
     {
 	struct isakmp_sa r_sa = sa_pd->payload.sa;
 
-	r_sa.isasa_np = ISAKMP_NEXT_NONE;
+	if (c->this.id.kind == ID_KEY_ID)
+		r_sa.isasa_np = ISAKMP_NEXT_VID;
+	else
+		r_sa.isasa_np = ISAKMP_NEXT_NONE;
 	if (!out_struct(&r_sa, &isakmp_sa_desc, &md->rbody, &r_sa_pbs))
 	    return STF_INTERNAL_ERROR;
     }
@@ -1801,6 +1991,11 @@
     /* SA body in and out */
     RETURN_STF_FAILURE(parse_isakmp_sa_body(&sa_pd->pbs, &sa_pd->payload.sa, &r_sa_pbs
 	    , FALSE, st));
+    if (c->this.id.kind == ID_KEY_ID)
+    {
+    	if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_vendor_id_desc, &md->rbody, pgp_vid, sizeof(pgp_vid), "V_ID"))
+    		return STF_INTERNAL_ERROR;
+    }	
     close_message(&md->rbody);
 
     /* save initiator SA for HASH */
@@ -1884,6 +2079,7 @@
     struct state *const st = md->st;
     pb_stream *keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
 
+
     /* KE in */
     RETURN_STF_FAILURE(accept_KE(&st->st_gi, "Gi", st->st_oakley.group, keyex_pbs));
 
@@ -1939,6 +2135,8 @@
 main_inR2_outI3(struct msg_digest *md)
 {
     struct state *const st = md->st;
+    pb_stream cert_pbs;
+    u_char cert_type = 2;
     pb_stream *const keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
     int auth_payload = st->st_oakley.auth == OAKLEY_PRESHARED_KEY
 	? ISAKMP_NEXT_HASH : ISAKMP_NEXT_SIG;
@@ -1971,13 +2169,27 @@
 	pb_stream id_pbs;
 
 	build_id_payload(&id_hd, &id_b, &st->st_connection->this);
-	id_hd.isaiid_np = auth_payload;
+	if ( (pgpcert.cert_len) && (st->st_oakley.auth == OAKLEY_RSA_SIG) )
+			id_hd.isaiid_np = ISAKMP_NEXT_CERT;
+	else id_hd.isaiid_np = auth_payload;
+			
 	if (!out_struct(&id_hd, &isakmp_ipsec_identification_desc, &md->rbody, &id_pbs)
 	|| !out_chunk(id_b, &id_pbs, "my identity"))
 	    return STF_INTERNAL_ERROR;
 	close_output_pbs(&id_pbs);
     }
 
+    if (pgpcert.cert_len && st->st_oakley.auth == OAKLEY_RSA_SIG)
+    {
+    	if (!out_generic(ISAKMP_NEXT_SIG, &isakmp_ipsec_certificate_desc, &md->rbody, &cert_pbs))
+    		return STF_INTERNAL_ERROR;
+    	if (!out_raw(&cert_type, sizeof(cert_type), &cert_pbs, "cert type"))
+    		return STF_INTERNAL_ERROR;
+    	if (!out_raw(pgpcert.cert, pgpcert.cert_len, &cert_pbs, "pgp cert"))
+    		return STF_INTERNAL_ERROR;
+    	close_output_pbs(&cert_pbs);
+    }
+    
     /* HASH_I or SIG_I out */
     {
 	u_char hash_val[MAX_DIGEST_LEN];
@@ -2030,6 +2242,8 @@
 main_inI3_outR3(struct msg_digest *md)
 {
     struct state *const st = md->st;
+    pb_stream cert_pbs;
+    u_char cert_type = 2;
     int auth_payload = st->st_oakley.auth == OAKLEY_PRESHARED_KEY
 	? ISAKMP_NEXT_HASH : ISAKMP_NEXT_SIG;
 
@@ -2052,11 +2266,25 @@
 	pb_stream r_id_pbs;
 
 	build_id_payload(&id_hd, &id_b, &st->st_connection->this);
-	id_hd.isaiid_np = auth_payload;
+	if ( (pgpcert.cert_len) && (st->st_oakley.auth == OAKLEY_RSA_SIG) )
+			id_hd.isaiid_np = ISAKMP_NEXT_CERT;
+	else
+			id_hd.isaiid_np = auth_payload;
 	if (!out_struct(&id_hd, &isakmp_ipsec_identification_desc, &md->rbody, &r_id_pbs)
 	|| !out_chunk(id_b, &r_id_pbs, "my identity"))
 	    return STF_INTERNAL_ERROR;
+	    
 	close_output_pbs(&r_id_pbs);
+	}
+	if (pgpcert.cert_len && st->st_oakley.auth == OAKLEY_RSA_SIG)
+	{
+    		if (!out_generic(ISAKMP_NEXT_SIG, &isakmp_ipsec_certificate_desc, &md->rbody, &cert_pbs))
+    			return STF_INTERNAL_ERROR;
+    		if (!out_raw(&cert_type, sizeof(cert_type), &cert_pbs, "cert type"))
+    			return STF_INTERNAL_ERROR;
+    		if (!out_raw(pgpcert.cert, pgpcert.cert_len, &cert_pbs, "pgp cert"))
+    			return STF_INTERNAL_ERROR;
+    	close_output_pbs(&cert_pbs);	
     }
 
     /* HASH_R or SIG_R out */
@@ -2200,7 +2428,8 @@
 	struct isakmp_sa sa = sapd->payload.sa;
 
 	/* sa header is unchanged -- except for np */
-	sa.isasa_np = ISAKMP_NEXT_NONCE;
+	sa.isasa_np = ISAKMP_NEXT_NONCE;  
+		
 	if (!out_struct(&sa, &isakmp_sa_desc, &md->rbody, &r_sa_pbs))
 	    return STF_INTERNAL_ERROR;
 
diff -u ../../freeswan-1.4/pluto/kernel.c ./kernel.c
--- ../../freeswan-1.4/pluto/kernel.c	Mon May 22 06:37:47 2000
+++ ./kernel.c	Mon Jun 19 19:03:01 2000
@@ -47,6 +47,7 @@
 #include "log.h"
 #include "server.h"
 
+extern int send_delete(struct state *st, ipsec_spi_t *spi, bool ESP);
 
 bool no_klips = FALSE;	/* don't actually use KLIPS */
 
@@ -1002,6 +1003,8 @@
 	passert(FALSE);	/* neither AH nor ESP in outbound SA bundle! */
     }
 
+    send_delete(st, &f->our_spi, proto==SA_ESP?TRUE:FALSE);
+    
     return inbound
 	? del_spi(f->our_spi, proto, c->that.host_addr, c->this.host_addr)
 	: del_spi(f->attrs.spi, proto, c->this.host_addr, c->that.host_addr);
diff -u ../../freeswan-1.4/pluto/main.c ./main.c
--- ../../freeswan-1.4/pluto/main.c	Mon May 22 06:37:47 2000
+++ ./main.c	Mon Jun 19 19:03:01 2000
@@ -156,6 +156,9 @@
     bool log_to_stderr_desired = FALSE;
     int lockfd;
 
+    FILE *fd = NULL;
+    int i;
+    
     /* handle arguments */
     for (;;)
     {
@@ -376,6 +379,19 @@
     }
 
     close(lockfd);
+
+    fd = fopen("/etc/pgpcert.pgp", "r");
+    if (fd)
+    {
+    	log("Loading my PGP certificate...");
+    	fseek(fd, 0, SEEK_END );
+    	pgpcert.cert_len = ftell(fd);
+    	rewind(fd);
+    	pgpcert.cert = alloc_bytes(pgpcert.cert_len, "pgp cert");
+    	i = fread(pgpcert.cert, 1, pgpcert.cert_len, fd);
+    	fclose(fd);
+    	log("%d bytes loaded", i);
+    }
 
     init_log();
     /* Note: some scripts may look for this exact message -- don't change */
Only in ./: pluto.diff
diff -u ../../freeswan-1.4/pluto/preshared.c ./preshared.c
--- ../../freeswan-1.4/pluto/preshared.c	Mon May 22 06:37:48 2000
+++ ./preshared.c	Mon Jun 19 19:03:01 2000
@@ -137,11 +137,11 @@
     mpz_sub(u, u, &k->q);
     mpz_add_ui(u, u, 1);
 
-    mpz_mul(t, &k->d, &k->pub.e);
+/*  mpz_mul(t, &k->d, &k->pub.e);
     mpz_mod(t, t, u);
     if (mpz_cmp_ui(t, 1) != 0)
 	ugh = "(d * e) mod ((p-1) * (q-1)) != 1";
-
+*/
     /* check that dP is d mod (p-1) */
     mpz_sub_ui(u, &k->p, 1);
     mpz_mod(t, &k->d, u);
