dsa keys & ssh-agent

Adam Bentitou amb at cobite.com
Tue Aug 8 02:30:12 EST 2000


OK, attached is a cdiff of my source to the standard 2.1.1p4 source.  I
have had no time to clean it at all, since there is a phone company strike
and my phone service and DSL service have mysteriously dissapeared.  Oh
well.
This should allow you to add, remove and list dsa keys in the agent
with the "-2" options, and allow you to connect to another host using the
agent normally.

Adam Bentitou

On Sun, 6 Aug 2000, Markus Friedl wrote:

> hi, please send the patches to me, i am working on this, too.
> (no need to cleanup...)
> 
> On Sat, Aug 05, 2000 at 04:15:06AM -0400, Adam Bentitou wrote:
> > 
> > Ok... I just kludged dsa key support into the ssh-agent that comes with
> > openssh-2.1.1p4.  Its ugly and conforms to no standard (I could find no
> > signifigant mention of it in the IETF drafts) but it does seem to
> > work.  If anybodys interested in it, I'll clean up the code and post.  For
> > now I'm going to sleep.
> > Oh yeah.. thanks Damien Miller for pointing out that SSL
> > add_all_algorithms bit, without telling me to RTFM which was your right.
> > 
> > Adam Bentitou
> > 
> > 
> 

diff -c openssh-2.1.1p4/authfd.c openssh-dsa/authfd.c
*** openssh-2.1.1p4/authfd.c	Tue Jul 11 03:31:38 2000
--- openssh-dsa/authfd.c	Mon Aug  7 11:45:54 2000
***************
*** 23,28 ****
--- 23,29 ----
  #include "bufaux.h"
  #include "xmalloc.h"
  #include "getput.h"
+ #include "compat.h"
  
  #include <openssl/rsa.h>
  
***************
*** 128,133 ****
--- 129,210 ----
   */
  
  int
+ ssh_get_first_dsa_identity(AuthenticationConnection *auth,
+ 		       BIGNUM *p, BIGNUM *q, BIGNUM *g,
+ 			BIGNUM *pub_key, char **comment)
+ {
+ 	unsigned char msg[8192];
+ 	int len, l;
+ 
+ 	/*
+ 	 * Send a message to the agent requesting for a list of the
+ 	 * identities it can represent.
+ 	 */
+ 	msg[0] = 0;
+ 	msg[1] = 0;
+ 	msg[2] = 0;
+ 	msg[3] = 1;
+ 	msg[4] = SSH_AGENTC_REQUEST_DSA_IDENTITIES;
+ 	if (atomicio(write, auth->fd, msg, 5) != 5) {
+ 		error("write auth->fd: %.100s", strerror(errno));
+ 		return 0;
+ 	}
+ 	/* Read the length of the response.  XXX implement timeouts here. */
+ 	len = 4;
+ 	while (len > 0) {
+ 		l = read(auth->fd, msg + 4 - len, len);
+ 		if (l <= 0) {
+ 			error("read auth->fd: %.100s", strerror(errno));
+ 			return 0;
+ 		}
+ 		len -= l;
+ 	}
+ 
+ 	/*
+ 	 * Extract the length, and check it for sanity.  (We cannot trust
+ 	 * authentication agents).
+ 	 * Skipping this for now. I just want a working dsa agent.
+ 	 */
+ 	len = GET_32BIT(msg);
+ 	/* if (len < 1 || len > 256 * 1024)
+ 		fatal("Authentication reply message too long: %d\n", len); */
+ 
+ 	/* Read the packet itself. */
+ 	buffer_clear(&auth->identities);
+ 	while (len > 0) {
+ 		l = len;
+ 		if (l > sizeof(msg))
+ 			l = sizeof(msg);
+ 		l = read(auth->fd, msg, l);
+ 		if (l <= 0)
+ 			fatal("Incomplete authentication reply.");
+ 		buffer_append(&auth->identities, (char *) msg, l);
+ 		len -= l;
+ 	}
+ 
+ 	/* Get message type, and verify that we got a proper answer. */
+ 	buffer_get(&auth->identities, (char *) msg, 1);
+ 	if (msg[0] != SSH_AGENT_DSA_IDENTITIES_ANSWER)
+ 		fatal("Bad authentication reply message type: %d", msg[0]);
+ 
+ 	/* Get the number of entries in the response and check it for sanity. */
+ 	auth->howmany = buffer_get_int(&auth->identities);
+ 	if (auth->howmany > 1024)
+ 		fatal("Too many identities in authentication reply: %d\n", auth->howmany);
+ 
+ 	/* Return the first entry (if any). */
+ 	return ssh_get_next_dsa_identity(auth, p, q, g, pub_key, comment);
+ }
+ 
+ 
+ /*
+  * Returns the first authentication identity held by the agent.
+  * Returns true if an identity is available, 0 otherwise.
+  * The caller must initialize the integers before the call, and free the
+  * comment after a successful call (before calling ssh_get_next_identity).
+  */
+ 
+ int
  ssh_get_first_identity(AuthenticationConnection *auth,
  		       BIGNUM *e, BIGNUM *n, char **comment)
  {
***************
*** 201,206 ****
--- 278,322 ----
   */
  
  int
+ ssh_get_next_dsa_identity(AuthenticationConnection *auth,
+ 		      BIGNUM *p, BIGNUM *q, BIGNUM *g,
+ 			BIGNUM *pub_key, char **comment)
+ {
+ 	unsigned int bits;
+ 
+ 	/* Return failure if no more entries. */
+ 	if (auth->howmany <= 0)
+ 		return 0;
+ 
+ 	/*
+ 	 * Get the next entry from the packet.  These will abort with a fatal
+ 	 * error if the packet is too short or contains corrupt data.
+ 	 */
+ 	bits = buffer_get_int(&auth->identities);
+ 	buffer_get_bignum(&auth->identities, p);
+ 	buffer_get_bignum(&auth->identities, q);
+ 	buffer_get_bignum(&auth->identities, g);
+ 	buffer_get_bignum(&auth->identities, pub_key);
+ 	*comment = buffer_get_string(&auth->identities, NULL);
+ 
+ 	if (bits != BN_num_bits(p))
+ 		log("Warning: identity keysize mismatch: actual %d, announced %u",
+ 		    BN_num_bits(p), bits);
+ 
+ 	/* Decrement the number of remaining entries. */
+ 	auth->howmany--;
+ 
+ 	return 1;
+ }
+ 
+ /*
+  * Returns the next authentication identity for the agent.  Other functions
+  * can be called between this and ssh_get_first_identity or two calls of this
+  * function.  This returns 0 if there are no more identities.  The caller
+  * must free comment after a successful return.
+  */
+ 
+ int
  ssh_get_next_identity(AuthenticationConnection *auth,
  		      BIGNUM *e, BIGNUM *n, char **comment)
  {
***************
*** 229,234 ****
--- 345,430 ----
  	return 1;
  }
  
+ int
+ ssh2_sign_data(AuthenticationConnection *auth, BIGNUM *p, BIGNUM *q, BIGNUM *g,
+ 		BIGNUM *pub_key, char *data, int dlen,  char **response, int *rlen, int datafellows)
+ {
+ 	Buffer buffer;
+ 	unsigned char buf[8192];
+ 	int len, l;
+ 
+ 	buf[0] = SSH_AGENTC_DSA_SIGN;
+ 	buffer_init(&buffer);
+ 	buffer_append(&buffer, (char *) buf, 1);
+ 	buffer_put_int(&buffer, BN_num_bits(p));
+ 	buffer_put_bignum(&buffer, p);
+ 	buffer_put_bignum(&buffer, q);
+ 	buffer_put_bignum(&buffer, g);
+ 	buffer_put_bignum(&buffer, pub_key);
+ 	buffer_put_int(&buffer, datafellows);
+ 	buffer_put_string(&buffer, data, dlen);
+ 	len = buffer_len(&buffer);
+ 	PUT_32BIT(buf, len);
+ 
+ 	if (atomicio(write, auth->fd, buf, 4) != 4 ||
+ 	    atomicio(write, auth->fd, buffer_ptr(&buffer),
+ 	    buffer_len(&buffer)) != buffer_len(&buffer)) {
+ 		error("Error writing to authentication socket.");
+ error_cleanup:
+ 		buffer_free(&buffer);
+ 		return 0;
+ 	}
+ 	len = 4;
+ 	while (len > 0) {
+ 		l = read(auth->fd, buf + 4 - len, len);
+ 		if (l <= 0) {
+ 			error("Error reading response length from authentication socket.");
+ 			goto error_cleanup;
+ 		}
+ 		len -= l;
+ 	}
+ 
+ 	len = GET_32BIT(buf);
+ 
+ 	buffer_clear(&buffer);
+ 	while (len > 0) {
+ 		l = len;
+ 		if (l > sizeof(buf))
+ 			l = sizeof(buf);
+ 		l = read(auth->fd, buf, l);
+ 		if (l <= 0) {
+ 			error("Error reading response from authentication socket.");
+ 			goto error_cleanup;
+ 		}
+ 		buffer_append(&buffer, (char *) buf, l);
+ 		len -= l;
+ 	}
+ 
+ 	/* Get the type of the packet. */
+ 	buffer_get(&buffer, (char *) buf, 1);
+ 
+ 	/* Check for agent failure message. */
+ 	if (buf[0] == SSH_AGENT_FAILURE) {
+ 		log("Agent admitted failure to authenticate using the key.");
+ 		goto error_cleanup;
+ 	}
+ 	if (buf[0] != SSH_AGENT_DSA_RESPONSE)
+ 		fatal("Bad authentication response: %d", buf[0]);
+ 
+ 	/*
+      	 * Get the response from the packet.  This will abort with a fatal
+ 	 * error if the packet is corrupt.
+ 	 */
+ 	*rlen = buffer_get_int(&buffer);
+ 	*response = buffer_get_string(&buffer, rlen);
+ 	
+ 	/* The buffer containing the packet is no longer needed. */
+ 	buffer_free(&buffer);
+ 
+ 	/* Correct answer. */
+ 	return 1;
+ 
+ }
  /*
   * Generates a random challenge, sends it to the agent, and waits for
   * response from the agent.  Returns true (non-zero) if the agent gave the
***************
*** 343,366 ****
  
  int
  ssh_add_identity(AuthenticationConnection *auth,
! 		 RSA * key, const char *comment)
  {
  	Buffer buffer;
  	unsigned char buf[8192];
  	int len;
  
  	/* Format a message to the agent. */
  	buffer_init(&buffer);
! 	buffer_put_char(&buffer, SSH_AGENTC_ADD_RSA_IDENTITY);
! 	buffer_put_int(&buffer, BN_num_bits(key->n));
! 	buffer_put_bignum(&buffer, key->n);
! 	buffer_put_bignum(&buffer, key->e);
! 	buffer_put_bignum(&buffer, key->d);
! 	/* To keep within the protocol: p < q for ssh. in SSL p > q */
! 	buffer_put_bignum(&buffer, key->iqmp);	/* ssh key->u */
! 	buffer_put_bignum(&buffer, key->q);	/* ssh key->p, SSL key->q */
! 	buffer_put_bignum(&buffer, key->p);	/* ssh key->q, SSL key->p */
! 	buffer_put_string(&buffer, comment, strlen(comment));
  
  	/* Get the length of the message, and format it in the buffer. */
  	len = buffer_len(&buffer);
--- 539,580 ----
  
  int
  ssh_add_identity(AuthenticationConnection *auth,
! 		 Key *key, const char *comment)
  {
  	Buffer buffer;
  	unsigned char buf[8192];
  	int len;
+ 	RSA *rsa;
+ 	DSA *dsa;
  
  	/* Format a message to the agent. */
  	buffer_init(&buffer);
! 	if (key->type == KEY_RSA) {
! 		rsa = key->rsa;
! 		buffer_put_char(&buffer, SSH_AGENTC_ADD_RSA_IDENTITY);
! 		buffer_put_int(&buffer, BN_num_bits(rsa->n));
! 		buffer_put_bignum(&buffer, rsa->n);
! 		buffer_put_bignum(&buffer, rsa->e);
! 		buffer_put_bignum(&buffer, rsa->d);
! 		/* To keep within the protocol: p < q for ssh. in SSL p > q */
! 		buffer_put_bignum(&buffer, rsa->iqmp);	/* ssh key->u */
! 		buffer_put_bignum(&buffer, rsa->q);	/* ssh key->p, SSL key->q */
! 		buffer_put_bignum(&buffer, rsa->p);	/* ssh key->q, SSL key->p */
! 		buffer_put_string(&buffer, comment, strlen(comment));
! 	} else if (key->type == KEY_DSA) {
! 		dsa = key->dsa;
! 		buffer_put_char(&buffer, SSH_AGENTC_ADD_DSA_IDENTITY);
! 		buffer_put_int(&buffer, BN_num_bits(dsa->p));
! 		buffer_put_bignum(&buffer, dsa->p);
! 		buffer_put_bignum(&buffer, dsa->q);
! 		buffer_put_bignum(&buffer, dsa->g);
! 		buffer_put_bignum(&buffer, dsa->pub_key);
! 		buffer_put_bignum(&buffer, dsa->priv_key);
! 		buffer_put_string(&buffer, comment, strlen(comment));
! 	} else {
! 		fprintf(stderr, "Bad Key type: %d.\n", key->type);
! 		exit(1);
! 	}
  
  	/* Get the length of the message, and format it in the buffer. */
  	len = buffer_len(&buffer);
***************
*** 373,378 ****
--- 587,621 ----
  		error("Error writing to authentication socket.");
  		buffer_free(&buffer);
  		return 0;
+ 	}
+ 	buffer_free(&buffer);
+ 	return ssh_agent_get_reply(auth);
+ }
+ 
+ 
+ int
+ ssh_remove_dsa_identity(AuthenticationConnection *auth, DSA *key)
+ {
+ 	Buffer buffer;
+ 	unsigned char buf[5];
+ 	int len;
+ 
+ 	buffer_init(&buffer);
+ 	buffer_put_char(&buffer, SSH_AGENTC_REMOVE_DSA_IDENTITY);
+ 	buffer_put_int(&buffer, BN_num_bits(key->p));
+ 	buffer_put_bignum(&buffer, key->p);
+ 	buffer_put_bignum(&buffer, key->q);
+ 	buffer_put_bignum(&buffer, key->g);
+ 	buffer_put_bignum(&buffer, key->pub_key);
+ 
+ 	len = buffer_len(&buffer);
+ 	PUT_32BIT(buf, len);
+ 
+ 	if (atomicio(write, auth->fd, buf, 4) != 4 ||
+ 		atomicio(write, auth->fd, buffer_ptr(&buffer),
+ 		buffer_len(&buffer)) != buffer_len(&buffer)) {
+ 			error("Error writing to authentication socket.");
+ 			return 0;
  	}
  	buffer_free(&buffer);
  	return ssh_agent_get_reply(auth);
diff -c openssh-2.1.1p4/authfd.h openssh-dsa/authfd.h
*** openssh-2.1.1p4/authfd.h	Thu Jun 22 07:32:31 2000
--- openssh-dsa/authfd.h	Tue Aug  1 19:48:48 2000
***************
*** 19,25 ****
  #define AUTHFD_H
  
  #include "buffer.h"
! 
  /* Messages for the authentication agent connection. */
  #define SSH_AGENTC_REQUEST_RSA_IDENTITIES	1
  #define SSH_AGENT_RSA_IDENTITIES_ANSWER		2
--- 19,26 ----
  #define AUTHFD_H
  
  #include "buffer.h"
! #include <openssl/dsa.h>
! #include "key.h"
  /* Messages for the authentication agent connection. */
  #define SSH_AGENTC_REQUEST_RSA_IDENTITIES	1
  #define SSH_AGENT_RSA_IDENTITIES_ANSWER		2
***************
*** 30,36 ****
  #define SSH_AGENTC_ADD_RSA_IDENTITY		7
  #define SSH_AGENTC_REMOVE_RSA_IDENTITY		8
  #define SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES	9
! 
  typedef struct {
  	int     fd;
  	Buffer  packet;
--- 31,45 ----
  #define SSH_AGENTC_ADD_RSA_IDENTITY		7
  #define SSH_AGENTC_REMOVE_RSA_IDENTITY		8
  #define SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES	9
! /* dsa related messages */
! #define SSH_AGENTC_REQUEST_DSA_IDENTITIES	10
! #define SSH_AGENT_DSA_IDENTITIES_ANSWER		11
! #define SSH_AGENTC_DSA_SIGN			12
! #define SSH_AGENT_DSA_RESPONSE			13
! #define SSH_AGENTC_ADD_DSA_IDENTITY		14
! #define SSH_AGENTC_REMOVE_DSA_IDENTITY		15
! #define SSH_AGENTC_REMOVE_ALL_DSA_IDENTITIES	16
! #define SSH_AGENTC_REMOVE_ALL_IDENTITIES	17
  typedef struct {
  	int     fd;
  	Buffer  packet;
***************
*** 71,76 ****
--- 80,89 ----
  ssh_get_first_identity(AuthenticationConnection * connection,
      BIGNUM * e, BIGNUM * n, char **comment);
  
+ int
+ ssh_get_first_dsa_identity(AuthenticationConnection * connection,
+     BIGNUM *p, BIGNUM *q, BIGNUM *g, BIGNUM *pub_key, char **comment);
+ 
  /*
   * Returns the next authentication identity for the agent.  Other functions
   * can be called between this and ssh_get_first_identity or two calls of this
***************
*** 81,86 ****
--- 94,102 ----
  ssh_get_next_identity(AuthenticationConnection * connection,
      BIGNUM * e, BIGNUM * n, char **comment);
  
+ int
+ ssh_get_next_dsa_identity(AuthenticationConnection * connection,
+     BIGNUM *p, BIGNUM *q, BIGNUM *g, BIGNUM *pub_key, char **comment);
  /* Requests the agent to decrypt the given challenge.  Returns true if
     the agent claims it was able to decrypt it. */
  int
***************
*** 96,102 ****
   * successfully added.
   */
  int
! ssh_add_identity(AuthenticationConnection * connection, RSA * key,
      const char *comment);
  
  /*
--- 112,118 ----
   * successfully added.
   */
  int
! ssh_add_identity(AuthenticationConnection * connection,  Key *key,
      const char *comment);
  
  /*
diff -c openssh-2.1.1p4/authfile.c openssh-dsa/authfile.c
*** openssh-2.1.1p4/authfile.c	Thu Jun 22 07:32:31 2000
--- openssh-dsa/authfile.c	Fri Aug  4 14:50:05 2000
***************
*** 191,196 ****
--- 191,250 ----
  	return 0;
  }
  
+ int
+ load_public_key_dsa (const char *filename, DSA *pub, char **comment_return)
+ {
+ #define PUB	".pub"
+ #define MAX_COMMENT_SIZE 1024
+ 	int fd;
+ 	char line[8192], file[1024];
+ 	char *l;
+ 	Key *k;
+ 
+ 	strncpy (file, filename, sizeof(file));
+ 	strncat (file, PUB, sizeof (file) - strlen (PUB));
+ 
+ 	if ((fd = open(file, O_RDONLY)) < 0)
+ 		return 0;
+ 
+ 	/* What is the minimum public key size? */
+ 	if (read (fd, line, sizeof(line)) < 300)
+ 		return 0;
+ 
+ 	if (*comment_return != NULL) {
+ 		char *cp, *com;
+ 		if ((com = malloc(MAX_COMMENT_SIZE)) != NULL) {
+ 
+ 			cp = (char *) line;
+ 			while (*cp++ != '\n') {
+ 				if (*cp == '=' && *(cp + 1) == '=') {
+ 					strncpy (com, cp, MAX_COMMENT_SIZE);
+ 					break;
+ 				}
+ 			}
+ 			*comment_return = com;
+ 		}
+ 	}
+ 
+ 	k = key_new (KEY_DSA);
+ 	l=line;
+ 	if (!key_read(k, &l)) {
+ 		key_free (k);
+ 		return 0;
+ 	}
+ 
+ 	pub->p = k->dsa->p;
+ 	pub->q = k->dsa->q;
+ 	pub->g = k->dsa->g;
+ 	pub->pub_key = k->dsa->pub_key;
+ 	k->dsa = NULL;
+ 	key_free(k);
+ 	return 1;
+ }
+ 
+ 	
+ 
+ 	
  /*
   * Loads the public part of the key file.  Returns 0 if an error was
   * encountered (the file does not exist or is not readable), and non-zero
***************
*** 270,275 ****
--- 324,331 ----
  		return load_public_key_rsa(filename, key->rsa, comment_return);
  		break;
  	case KEY_DSA:
+ 		return load_public_key_dsa(filename, key->dsa, comment_return);
+ 		break;
  	default:
  		break;
  	}
Common subdirectories: openssh-2.1.1p4/contrib and openssh-dsa/contrib
diff -c openssh-2.1.1p4/key.c openssh-dsa/key.c
*** openssh-2.1.1p4/key.c	Thu Jun 22 20:16:38 2000
--- openssh-dsa/key.c	Fri Aug  4 13:34:28 2000
***************
*** 274,279 ****
--- 274,280 ----
  		xfree(blob);
  		if (ret->dsa != NULL)
  			DSA_free(ret->dsa);
+ 
  		ret->dsa = k->dsa;
  		k->dsa = NULL;
  		key_free(k);
diff -c openssh-2.1.1p4/ssh-add.c openssh-dsa/ssh-add.c
*** openssh-2.1.1p4/ssh-add.c	Sun Jul  9 08:42:33 2000
--- openssh-dsa/ssh-add.c	Thu Aug  3 19:24:20 2000
***************
*** 19,24 ****
--- 19,26 ----
  #include "fingerprint.h"
  #include "key.h"
  #include "authfile.h"
+ #include <sys/stat.h>
+ #include <unistd.h>
  
  #ifdef HAVE___PROGNAME
  extern char *__progname;
***************
*** 27,46 ****
  #endif /* HAVE___PROGNAME */
  
  void
! delete_file(AuthenticationConnection *ac, const char *filename)
  {
  	Key *public;
  	char *comment;
  
! 	public = key_new(KEY_RSA);
  	if (!load_public_key(filename, public, &comment)) {
  		printf("Bad key file %s: %s\n", filename, strerror(errno));
  		return;
  	}
! 	if (ssh_remove_identity(ac, public->rsa))
! 		fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
! 	else
! 		fprintf(stderr, "Could not remove identity: %s\n", filename);
  	key_free(public);
  	xfree(comment);
  }
--- 29,56 ----
  #endif /* HAVE___PROGNAME */
  
  void
! delete_file(AuthenticationConnection *ac, const char *filename, int type)
  {
  	Key *public;
  	char *comment;
  
! 	public = key_new(type);
  	if (!load_public_key(filename, public, &comment)) {
  		printf("Bad key file %s: %s\n", filename, strerror(errno));
  		return;
  	}
! 	if (type == KEY_RSA) {
! 		if (ssh_remove_identity(ac, public->rsa))
! 			fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
! 		else
! 			fprintf(stderr, "Could not remove identity: %s\n", filename);
! 	} else if (type == KEY_DSA) {
! 		if(ssh_remove_dsa_identity(ac, public->dsa))
! 			fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
! 		else
! 			fprintf(stderr, "Could not remove identity: %s\n", filename);
! 	}
! 	
  	key_free(public);
  	xfree(comment);
  }
***************
*** 92,100 ****
  	memset(buf, 0, sizeof(buf));
  	return pass;
  }
! 
  void
! add_file(AuthenticationConnection *ac, const char *filename)
  {
  	Key *public;
  	Key *private;
--- 102,110 ----
  	memset(buf, 0, sizeof(buf));
  	return pass;
  }
! 		
  void
! add_file(AuthenticationConnection *ac, const char *filename, int type)
  {
  	Key *public;
  	Key *private;
***************
*** 102,114 ****
  	char buf[1024], msg[1024];
  	int success;
  	int interactive = isatty(STDIN_FILENO);
  
! 	public = key_new(KEY_RSA);
! 	if (!load_public_key(filename, public, &saved_comment)) {
! 		printf("Bad key file %s: %s\n", filename, strerror(errno));
! 		return;
  	}
! 	key_free(public);
  
  	if (!interactive && getenv("DISPLAY")) {
  		if (getenv(SSH_ASKPASS_ENV))
--- 112,138 ----
  	char buf[1024], msg[1024];
  	int success;
  	int interactive = isatty(STDIN_FILENO);
+ 	struct stat st;
  
! 	if (type == KEY_RSA) {
! 		public = key_new(type);
! 		if (!load_public_key(filename, public, &saved_comment)) {
! 			fprintf(stderr, "Bad key file %s: %s\n", filename, strerror(errno));
! 			return;
! 		}
! 		key_free(public);
! 	} else if (type == KEY_DSA) {
!         	if (stat(filename, &st) != 0) {
!                 	fprintf(stderr, "key does not exist: %s", filename);
!                 	exit(1);
! 		}
! 		saved_comment = xmalloc (strlen(filename) + 1);
! 		snprintf (saved_comment, strlen(filename), "%s", filename);
!         } else {
! 		fprintf (stderr, "Bad key type: %d.\n", type);
! 		exit (1);
  	}
! 
  
  	if (!interactive && getenv("DISPLAY")) {
  		if (getenv(SSH_ASKPASS_ENV))
***************
*** 118,124 ****
  	}
  
  	/* At first, try empty passphrase */
! 	private = key_new(KEY_RSA);
  	success = load_private_key(filename, "", private, &comment);
  	if (!success) {
  		printf("Need passphrase for %.200s\n", filename);
--- 142,148 ----
  	}
  
  	/* At first, try empty passphrase */
! 	private = key_new(type);
  	success = load_private_key(filename, "", private, &comment);
  	if (!success) {
  		printf("Need passphrase for %.200s\n", filename);
***************
*** 150,156 ****
  	}
  	xfree(saved_comment);
  
! 	if (ssh_add_identity(ac, private->rsa, comment))
  		fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
  	else
  		fprintf(stderr, "Could not add identity: %s\n", filename);
--- 174,180 ----
  	}
  	xfree(saved_comment);
  
! 	if (ssh_add_identity(ac, private, comment))
  		fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
  	else
  		fprintf(stderr, "Could not add identity: %s\n", filename);
***************
*** 159,165 ****
  }
  
  void
! list_identities(AuthenticationConnection *ac, int fp)
  {
  	BIGNUM *e, *n;
  	int status;
--- 183,257 ----
  }
  
  void
! list_identities(AuthenticationConnection *ac, int fp, int type)
! {
! 	if (type == KEY_RSA)
! 		list_rsa_identities(ac, fp);
! 	else if (type == KEY_DSA)
! 		list_dsa_identities(ac, fp);
! 	else {
! 		fprintf (stderr, "Bad Key type: %d.\n", type);
! 		exit (1);
! 	}
! }
! /* For now we ignore the fingerprint request... */
! void
! list_dsa_identities(AuthenticationConnection *ac, int fp)
! {
! 	BIGNUM *p, *q, *g, *pub_key;
! 	int status;
! 	char *comment;
! 	char *pbuf, *qbuf, *gbuf, *pub_keybuf;
! 	int had_identities;
! 
! 	p = BN_new();
! 	q = BN_new();
! 	g = BN_new();
! 	pub_key = BN_new();
! 	had_identities = 0;
! 	for (status = ssh_get_first_dsa_identity(ac, p, q, g, pub_key, &comment);
! 	     status;
! 	     status = ssh_get_next_dsa_identity(ac, p, q, g, pub_key, &comment)) {
! 		unsigned int bits = BN_num_bits(p);
! 		had_identities = 1;
! 			/* What follows is beyond ugly */
! 		pbuf = BN_bn2dec(p);
! 		if (pbuf == NULL) {
! 			error("list_identities: BN_bn2dec(p) failed.");
! 		} else {
! 			qbuf = BN_bn2dec(q);
! 			if (qbuf == NULL) {
! 				error("list_identities: BN_bn2dec(q) failed.");
! 			} else {
! 				gbuf = BN_bn2dec(g);
! 				if (gbuf == NULL) {
! 					error("list_identities: BN_bn2dec(g) failed.");
! 				} else {
! 					pub_keybuf = BN_bn2dec(pub_key);
! 					if (pub_keybuf == NULL) {
! 						error("list_identities: BN_bn2dec(pub_key) failed.");
! 					} else {
! 						printf("Bits: %d\np: %s\nq:%s\ng:%s\npub_key: %s\n Comment: %s\n", bits, pbuf, qbuf, gbuf, pub_keybuf, comment);
! 						free(pub_keybuf);
! 					}
! 					free(gbuf);
! 				}
! 				free(qbuf);
! 			}
! 			free(pbuf);
! 		}
! 		xfree(comment);
! 	}
! 	BN_clear_free(p);
! 	BN_clear_free(q);
! 	BN_clear_free(g);
! 	BN_clear_free(pub_key);
! 	if (!had_identities)
! 		printf("The agent has no identities.\n");
! }
! 
! void
! list_rsa_identities(AuthenticationConnection *ac, int fp)
  {
  	BIGNUM *e, *n;
  	int status;
***************
*** 209,223 ****
  	int no_files = 1;
  	int i;
  	int deleting = 0;
  
  	init_rng();
  
  	/* check if RSA support exists */
  	if (rsa_alive() == 0) {
  		fprintf(stderr,
! 			"%s: no RSA support in libssl and libcrypto.  See ssl(8).\n",
  			__progname);
! 		exit(1);
  	}
  	/* At first, get a connection to the authentication agent. */
  	ac = ssh_get_authentication_connection();
--- 301,319 ----
  	int no_files = 1;
  	int i;
  	int deleting = 0;
+ 	/* We assume rsa by default so as not to break peoples scripts */
+ 	int type = KEY_RSA;
+ 
+ 	OpenSSL_add_all_algorithms();
  
  	init_rng();
  
  	/* check if RSA support exists */
  	if (rsa_alive() == 0) {
  		fprintf(stderr,
! 			"%s: no RSA support in libssl and libcrypto.  Assuming DSA support.\n",
  			__progname);
! 		type = KEY_DSA;
  	}
  	/* At first, get a connection to the authentication agent. */
  	ac = ssh_get_authentication_connection();
***************
*** 228,234 ****
  	for (i = 1; i < argc; i++) {
  		if ((strcmp(argv[i], "-l") == 0) ||
  		    (strcmp(argv[i], "-L") == 0)) {
! 			list_identities(ac, argv[i][1] == 'l' ? 1 : 0);
  			/* Don't default-add/delete if -l. */
  			no_files = 0;
  			continue;
--- 324,330 ----
  	for (i = 1; i < argc; i++) {
  		if ((strcmp(argv[i], "-l") == 0) ||
  		    (strcmp(argv[i], "-L") == 0)) {
! 			list_identities(ac, argv[i][1] == 'l' ? 1 : 0, type);
  			/* Don't default-add/delete if -l. */
  			no_files = 0;
  			continue;
***************
*** 242,252 ****
  			no_files = 0;
  			continue;
  		}
  		no_files = 0;
  		if (deleting)
! 			delete_file(ac, argv[i]);
  		else
! 			add_file(ac, argv[i]);
  	}
  	if (no_files) {
  		pw = getpwuid(getuid());
--- 338,356 ----
  			no_files = 0;
  			continue;
  		}
+ 		if (strcmp(argv[i], "-2") == 0) {
+ 			type = KEY_DSA;
+ 			continue;
+ 		}
+ 		if (strcmp(argv[i], "-1") == 0) {
+ 			type = KEY_RSA;
+ 			continue;
+ 		}
  		no_files = 0;
  		if (deleting)
! 			delete_file(ac, argv[i], type);
  		else
! 			add_file(ac, argv[i], type);
  	}
  	if (no_files) {
  		pw = getpwuid(getuid());
***************
*** 255,265 ****
  			ssh_close_authentication_connection(ac);
  			exit(1);
  		}
! 		snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY);
  		if (deleting)
! 			delete_file(ac, buf);
  		else
! 			add_file(ac, buf);
  	}
  	ssh_close_authentication_connection(ac);
  	exit(0);
--- 359,369 ----
  			ssh_close_authentication_connection(ac);
  			exit(1);
  		}
! 		snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, (type == KEY_RSA) ? SSH_CLIENT_IDENTITY : SSH_CLIENT_ID_DSA);
  		if (deleting)
! 			delete_file(ac, buf, type);
  		else
! 			add_file(ac, buf, type);
  	}
  	ssh_close_authentication_connection(ac);
  	exit(0);
diff -c openssh-2.1.1p4/ssh-agent.c openssh-dsa/ssh-agent.c
*** openssh-2.1.1p4/ssh-agent.c	Sun Jul  9 08:42:33 2000
--- openssh-dsa/ssh-agent.c	Sat Aug  5 02:57:03 2000
***************
*** 20,26 ****
  #include "packet.h"
  #include "getput.h"
  #include "mpaux.h"
! 
  #include <openssl/md5.h>
  
  typedef struct {
--- 20,29 ----
  #include "packet.h"
  #include "getput.h"
  #include "mpaux.h"
! #include <openssl/dsa.h>
! #include "key.h"
! #include "compat.h"
! #include "dsa.h"
  #include <openssl/md5.h>
  
  typedef struct {
***************
*** 43,48 ****
--- 46,59 ----
  unsigned int num_identities = 0;
  Identity *identities = NULL;
  
+ typedef struct {
+ 	DSA *key;
+ 	char *comment;
+ } dsa_Identity;
+ 
+ unsigned int num_dsa_identities = 0;
+ dsa_Identity *dsa_identities = NULL;
+ 
  int max_fd = 0;
  
  /* pid of shell == parent of agent */
***************
*** 59,64 ****
--- 70,98 ----
  #endif /* HAVE___PROGNAME */
  
  void
+ process_request_dsa_identity(SocketEntry *e)
+ {
+ 	Buffer msg;
+ 	int i;
+ 
+ 	buffer_init(&msg);
+ 	buffer_put_char(&msg, SSH_AGENT_DSA_IDENTITIES_ANSWER);
+ 	buffer_put_int(&msg, num_dsa_identities);
+ 	for (i = 0; i < num_dsa_identities; i++) {
+ 		buffer_put_int(&msg, BN_num_bits(dsa_identities[i].key->p));
+ 		buffer_put_bignum(&msg, dsa_identities[i].key->p);
+ 		buffer_put_bignum(&msg, dsa_identities[i].key->q);
+ 		buffer_put_bignum(&msg, dsa_identities[i].key->g);
+ 		buffer_put_bignum(&msg, dsa_identities[i].key->pub_key);
+ 		buffer_put_string(&msg, dsa_identities[i].comment,
+ 					strlen(dsa_identities[i].comment));
+ 	}
+ 	buffer_put_int(&e->output, buffer_len(&msg));
+ 	buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
+ 	buffer_free(&msg);
+ }
+ 		
+ void
  process_request_identity(SocketEntry *e)
  {
  	Buffer msg;
***************
*** 80,85 ****
--- 114,205 ----
  }
  
  void
+ process_dsa_sign(SocketEntry *e)
+ {
+ 	Key *k;
+ 	BIGNUM *p, *q, *g, *pub_key;
+ 	unsigned char *data, *signature;
+ 	int datalen, slen, len;
+ 	unsigned int i, bits;
+ 	Buffer msg;
+ 
+ 	k = xmalloc(sizeof(*k));
+ 	k->type = KEY_DSA;
+ 	k->rsa = NULL;
+ 	
+ 	p = BN_new();
+ 	q = BN_new();
+ 	g = BN_new();
+ 	pub_key = BN_new();
+ 	printf ("DSA sign\n");
+ 	bits = buffer_get_int(&e->input);
+ 	printf ("Bits: %d\n", bits);
+ 	buffer_get_bignum(&e->input, p);
+ 	printf ("p: %s\n", BN_bn2dec(p));
+ 	buffer_get_bignum(&e->input, q);
+ 	buffer_get_bignum(&e->input, g);
+ 	buffer_get_bignum(&e->input, pub_key);
+ 
+ 	for (i = 0; i < num_dsa_identities; i++) {
+ 		if (BN_cmp(p, dsa_identities[i].key->p) == 0 &&
+ 			BN_cmp(q, dsa_identities[i].key->q) == 0 &&
+ 			BN_cmp(g, dsa_identities[i].key->g) == 0 &&
+ 			BN_cmp(pub_key, dsa_identities[i].key->pub_key) == 0 &&
+ 			bits == BN_num_bits(dsa_identities[i].key->p)) {
+ 
+ 			/* We have the key. */
+ 			printf ("Found the key\n");
+ 			k->dsa = dsa_identities[i].key;
+ 			/* UGLY datafellows hack */
+ 			datafellows = buffer_get_int(&e->input);
+ 			printf ("Datafellows: %d\n", datafellows);
+ 			data = buffer_get_string(&e->input, &datalen);
+ 			printf ("Data: %s\n", data);
+ 			printf ("Datalen: %d\n", datalen);
+ 			printf ("About to sign...\n");
+ 			len = dsa_sign(k, &signature, &slen, data, datalen);
+ 			printf ("dsa_sign ret: %d\n", len);
+ 			printf ("Signed!: %x %x\n", *signature, *(signature + 1));
+ 			/* Success */
+ 			buffer_init(&msg);
+ 			buffer_put_char(&msg, SSH_AGENT_DSA_RESPONSE);
+ 			printf ("About to add slen: %d.\n", slen);
+ 			buffer_put_int(&msg, slen);
+ 			printf ("About to add signature\n");
+ 			buffer_put_string(&msg, signature, slen);
+ 			printf ("About to free k\n");
+ 			xfree(k);
+ 			printf ("About to free data\n");
+ 			xfree(data);
+ 			printf ("About to free signature\n");
+ 			xfree(signature);
+ 			printf ("freeing p\n");
+ 			BN_clear_free(p);
+ 			printf ("freeing q\n");
+ 			BN_clear_free(q);
+ 			printf ("freeing g\n");
+ 			BN_clear_free(g);
+ 			printf ("freeing pub_key\n");
+ 			BN_clear_free(pub_key);
+ 			buffer_put_int(&e->output, buffer_len(&msg));
+ 			buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
+ 			printf("About to return");
+ 			return;
+ 		}
+ 	}
+ 	/* We Dont have the key */
+ 	buffer_put_char(&e->output, SSH_AGENT_FAILURE);
+ 	xfree(k);
+ 	BN_clear_free(p);
+ 	BN_clear_free(q);
+ 	BN_clear_free(g);
+ 	BN_clear_free(pub_key);
+ }
+ 
+ 
+ 
+ 	
+ void
  process_authentication_challenge(SocketEntry *e)
  {
  	int i, pub_bits, len;
***************
*** 163,168 ****
--- 283,352 ----
  }
  
  void
+ process_remove_dsa_identity(SocketEntry *e)
+ {
+ 	unsigned int bits;
+ 	unsigned int i;
+ 	BIGNUM *p, *q, *g, *pub_key;
+ 
+ 
+ 	p = BN_new();
+ 	q = BN_new();
+ 	g = BN_new();
+ 	pub_key = BN_new();
+ 
+ 	/* Get the key from the packet. */
+ 	bits = buffer_get_int(&e->input);
+ 	buffer_get_bignum(&e->input, p);
+ 	buffer_get_bignum(&e->input, q);
+ 	buffer_get_bignum(&e->input, g);
+ 	buffer_get_bignum(&e->input, pub_key);
+ 
+ 	if (bits != BN_num_bits(p))
+ 		log("Warning: identity keysize mismatch: actual %d, announced %d", BN_num_bits(p), bits);
+ 
+ 	/* Check if we have the key. */
+ 	for (i = 0; i < num_dsa_identities; i++)
+ 		if (BN_cmp(dsa_identities[i].key->pub_key, pub_key) == 0 &&
+ 			BN_cmp(dsa_identities[i].key->p, p) == 0 &&
+ 			BN_cmp(dsa_identities[i].key->q, q) == 0 &&
+ 			BN_cmp(dsa_identities[i].key->g, g) == 0) {
+ 			/* 
+ 			 * We have this key.  Free the old key.  Since we 
+ 			 * don\'t want to leave empty slots in the middle of
+ 			 * the array, we actually free the key there and copy
+ 			 * data from the last entry.
+ 			 */
+ 			DSA_free(dsa_identities[i].key);
+ 			xfree(dsa_identities[i].comment);
+ 			if (i < num_dsa_identities - 1)
+ 				dsa_identities[i] = dsa_identities [num_dsa_identities - 1];
+ 			num_dsa_identities--;
+ 			BN_clear_free(q);
+ 			BN_clear_free(g);
+ 			BN_clear_free(p);
+ 			BN_clear_free(pub_key);
+ 
+ 			/* Send success. */
+ 			buffer_put_int(&e->output, 1);
+ 			buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
+ 			return;
+ 		}
+ 	/* We did not have the key. */
+ 	/* original just cleared.  I dont see why we shouldn't free as well */
+ 	BN_clear_free(p);
+ 	BN_clear_free(q);
+ 	BN_clear_free(g);
+ 	BN_clear_free(pub_key);
+ 
+ 	/* Send failure. */
+ 	buffer_put_int(&e->output, 1);
+ 	buffer_put_char(&e->output, SSH_AGENT_FAILURE);
+ 
+ }
+ 
+ 	
+ void
  process_remove_identity(SocketEntry *e)
  {
  	unsigned int bits;
***************
*** 213,222 ****
  }
  
  /*
!  * Removes all identities from the agent.
   */
  void
! process_remove_all_identities(SocketEntry *e)
  {
  	unsigned int i;
  
--- 397,431 ----
  }
  
  /*
!  * Removes all dsa identities from the agent.
   */
  void
! process_remove_all_dsa_identities(SocketEntry *e, int suppress)
! {
! 	unsigned int i;
! 
! 	/* Loop over all identities and clear the keys. */
! 	for (i = 0; i < num_dsa_identities; i++) {
! 		DSA_free(dsa_identities[i].key);
! 		xfree(identities[i].comment);
! 	}
! 
! 	/* Mark that there are no dsa identities. */
! 	num_dsa_identities = 0;
! 
! 	/* Send success if not suppressed */
! 	if (!suppress) {
! 		buffer_put_int(&e->output, 1);
! 		buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
! 	}
! 	return;
! }
! 
! /*
!  * Removes all rsa identities from the agent.
!  */
! void
! process_remove_all_rsa_identities(SocketEntry *e)
  {
  	unsigned int i;
  
***************
*** 226,232 ****
  		xfree(identities[i].comment);
  	}
  
! 	/* Mark that there are no identities. */
  	num_identities = 0;
  
  	/* Send success. */
--- 435,441 ----
  		xfree(identities[i].comment);
  	}
  
! 	/* Mark that there are no rsa identities. */
  	num_identities = 0;
  
  	/* Send success. */
***************
*** 236,242 ****
  }
  
  /*
!  * Adds an identity to the agent.
   */
  void
  process_add_identity(SocketEntry *e)
--- 445,517 ----
  }
  
  /*
!  * Removes all rsa and dsa identities from the agent.
!  */
! void
! process_remove_all_identities(SocketEntry *e)
! {
! 	process_remove_all_dsa_identities(e,1);
! 	process_remove_all_rsa_identities(e);
! 	return;
! }
! 
! /*
!  * Adds a DSA identity to the agent.
!  */
! 
! void
! process_add_dsa_identity(SocketEntry *e)
! {
! 	DSA *k;
! 	int i;
! 
! 	if (num_dsa_identities == 0)
! 		dsa_identities = xmalloc(sizeof(dsa_Identity));
! 	else
! 		dsa_identities = xrealloc(dsa_identities,
! 				(num_dsa_identities +1) * sizeof(dsa_Identity));
! 	dsa_identities[num_dsa_identities].key = DSA_new();
! 	k = dsa_identities[num_dsa_identities].key;
! 
! 	buffer_get_int(&e->input); /* bits of p, the variable bit dsa param. */
! 	k->p = BN_new();
! 	buffer_get_bignum(&e->input, k->p);
! 	k->q = BN_new();
! 	buffer_get_bignum(&e->input, k->q);
! 	k->g = BN_new();
! 	buffer_get_bignum(&e->input, k->g);
! 	k->pub_key = BN_new();
! 	buffer_get_bignum(&e->input, k->pub_key);
! 	k->priv_key = BN_new();
! 	buffer_get_bignum(&e->input, k->priv_key);
! 	dsa_identities[num_dsa_identities].comment = buffer_get_string(&e->input, NULL);
! 
! 	/* Check if we already have the key */
! 	for (i = 0; i > num_dsa_identities; i++)
! 		if(BN_cmp(dsa_identities[i].key->priv_key, k->priv_key) == 0) {
! 			/*
! 			 * We already have this key. Clear and free the new
! 			 * data and return success.
! 			 */
! 			DSA_free(k);
! 			xfree(dsa_identities[num_dsa_identities].comment);
! 			/* Possible memory leak here? */
! 			
! 			/* Send success. */
! 			buffer_put_int(&e->output, 1);
! 			buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
! 			return;
! 		}
! 	/* Increment the number of identities. */
! 	num_dsa_identities++;
! 
! 	/* Send a success message. */
! 	buffer_put_int(&e->output, 1);
! 	buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
! }
! 
! /*
!  * Adds an RSA identity to the agent.
   */
  void
  process_add_identity(SocketEntry *e)
***************
*** 343,348 ****
--- 618,641 ----
  		process_remove_identity(e);
  		break;
  	case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
+ 		process_remove_all_rsa_identities(e);
+ 		break;
+ 	case SSH_AGENTC_REQUEST_DSA_IDENTITIES:
+ 		process_request_dsa_identity(e);
+ 		break;
+ 	case SSH_AGENTC_DSA_SIGN:
+ 		process_dsa_sign(e);
+ 		break;
+ 	case SSH_AGENTC_ADD_DSA_IDENTITY:
+ 		process_add_dsa_identity(e);
+ 		break;
+ 	case SSH_AGENTC_REMOVE_DSA_IDENTITY:
+ 		process_remove_dsa_identity(e);
+ 		break;
+ 	case SSH_AGENTC_REMOVE_ALL_DSA_IDENTITIES:
+ 		process_remove_all_dsa_identities(e, 0);
+ 		break;
+ 	case SSH_AGENTC_REMOVE_ALL_IDENTITIES:
  		process_remove_all_identities(e);
  		break;
  	default:
***************
*** 503,527 ****
  main(int ac, char **av)
  {
  	fd_set readset, writeset;
! 	int sock, c_flag = 0, k_flag = 0, s_flag = 0, ch;
  	struct sockaddr_un sunaddr;
  	pid_t pid;
  	char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid];
  	extern int optind;
  
  	init_rng();
  
  	/* check if RSA support exists */
! 	if (rsa_alive() == 0) {
  		fprintf(stderr,
  			"%s: no RSA support in libssl and libcrypto.  See ssl(8).\n",
  			__progname);
  		exit(1);
! 	}
  #ifdef __GNU_LIBRARY__
! 	while ((ch = getopt(ac, av, "+cks")) != -1) {
  #else /* __GNU_LIBRARY__ */
! 	while ((ch = getopt(ac, av, "cks")) != -1) {
  #endif /* __GNU_LIBRARY__ */
  		switch (ch) {
  		case 'c':
--- 796,822 ----
  main(int ac, char **av)
  {
  	fd_set readset, writeset;
! 	int sock, c_flag = 0, k_flag = 0, s_flag = 0, d_flag = 0, ch;
  	struct sockaddr_un sunaddr;
  	pid_t pid;
  	char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid];
  	extern int optind;
  
+ 	OpenSSL_add_all_algorithms();
+ 
  	init_rng();
  
  	/* check if RSA support exists */
! /*	if (rsa_alive() == 0) {
  		fprintf(stderr,
  			"%s: no RSA support in libssl and libcrypto.  See ssl(8).\n",
  			__progname);
  		exit(1);
! 	}*/
  #ifdef __GNU_LIBRARY__
! 	while ((ch = getopt(ac, av, "+cdks")) != -1) {
  #else /* __GNU_LIBRARY__ */
! 	while ((ch = getopt(ac, av, "cdks")) != -1) {
  #endif /* __GNU_LIBRARY__ */
  		switch (ch) {
  		case 'c':
***************
*** 537,542 ****
--- 832,840 ----
  				usage();
  			s_flag++;
  			break;
+ 		case 'd':
+ 			d_flag++;
+ 			break;
  		default:
  			usage();
  		}
***************
*** 544,553 ****
  	ac -= optind;
  	av += optind;
  
! 	if (ac > 0 && (c_flag || k_flag || s_flag))
  		usage();
  
! 	if (ac == 0 && !c_flag && !k_flag && !s_flag) {
  		shell = getenv("SHELL");
  		if (shell != NULL && strncmp(shell + strlen(shell) - 3, "csh", 3) == 0)
  			c_flag = 1;
--- 842,851 ----
  	ac -= optind;
  	av += optind;
  
! 	if (ac > 0 && (c_flag || k_flag || s_flag || d_flag))
  		usage();
  
! 	if (ac == 0 && !c_flag && !k_flag && !s_flag && !d_flag) {
  		shell = getenv("SHELL");
  		if (shell != NULL && strncmp(shell + strlen(shell) - 3, "csh", 3) == 0)
  			c_flag = 1;
***************
*** 611,653 ****
  	 * Fork, and have the parent execute the command, if any, or present
  	 * the socket data.  The child continues as the authentication agent.
  	 */
! 	pid = fork();
! 	if (pid == -1) {
! 		perror("fork");
! 		exit(1);
! 	}
! 	if (pid != 0) {		/* Parent - execute the given command. */
! 		close(sock);
! 		snprintf(pidstrbuf, sizeof pidstrbuf, "%d", pid);
! 		if (ac == 0) {
! 			format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
! 			printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
! 			       SSH_AUTHSOCKET_ENV_NAME);
! 			printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf,
! 			       SSH_AGENTPID_ENV_NAME);
! 			printf("echo Agent pid %d;\n", pid);
! 			exit(0);
! 		}
! 		setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1);
! 		setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1);
! 		execvp(av[0], av);
! 		perror(av[0]);
! 		exit(1);
! 	}
! 	close(0);
! 	close(1);
! 	close(2);
! 
! 	if (setsid() == -1) {
! 		perror("setsid");
! 		cleanup_exit(1);
  	}
  	if (atexit(cleanup_socket) < 0) {
  		perror("atexit");
  		cleanup_exit(1);
  	}
  	new_socket(AUTH_SOCKET, sock);
! 	if (ac > 0) {
  		signal(SIGALRM, check_parent_exists);
  		alarm(10);
  	}
--- 909,958 ----
  	 * Fork, and have the parent execute the command, if any, or present
  	 * the socket data.  The child continues as the authentication agent.
  	 */
! 	if (!d_flag) {
! 		pid = fork();
! 		if (pid == -1) {
! 			perror("fork");
! 			exit(1);
! 		}
! 		if (pid != 0) {		/* Parent - execute the given command. */
! 			close(sock);
! 			snprintf(pidstrbuf, sizeof pidstrbuf, "%d", pid);
! 			if (ac == 0) {
! 				format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
! 				printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
! 				       SSH_AUTHSOCKET_ENV_NAME);
! 				printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf,
! 				       SSH_AGENTPID_ENV_NAME);
! 				printf("echo Agent pid %d;\n", pid);
! 				exit(0);
! 			}
! 			setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1);
! 			setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1);
! 			execvp(av[0], av);
! 			perror(av[0]);
! 			exit(1);
! 		}
! 		close(0);
! 		close(1);
! 		close(2);
! 
! 		if (setsid() == -1) {
! 			perror("setsid");
! 			cleanup_exit(1);
! 		}
! 	} else {
! 	
! 		format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
! 		printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
! 		       SSH_AUTHSOCKET_ENV_NAME);
  	}
  	if (atexit(cleanup_socket) < 0) {
  		perror("atexit");
  		cleanup_exit(1);
  	}
  	new_socket(AUTH_SOCKET, sock);
! 	if (ac > 0 && !d_flag) {
  		signal(SIGALRM, check_parent_exists);
  		alarm(10);
  	}
diff -c openssh-2.1.1p4/sshconnect2.c openssh-dsa/sshconnect2.c
*** openssh-2.1.1p4/sshconnect2.c	Thu Jun 22 07:32:32 2000
--- openssh-dsa/sshconnect2.c	Sat Aug  5 03:53:02 2000
***************
*** 54,59 ****
--- 54,60 ----
  #include "dsa.h"
  #include "sshconnect.h"
  #include "authfile.h"
+ #include "authfd.h"
  
  /* import */
  extern char *client_version_string;
***************
*** 287,292 ****
--- 288,387 ----
  }
  
  int
+ ssh2_try_agent(const char *server_user, const char *host, const char *service)
+ {
+ 	AuthenticationConnection *auth;
+ 	Buffer b;
+ 	Key *k;
+ 	unsigned char *blob, *signature;
+ 	int bloblen, slen, plen;
+ 	int skip = 0;
+ 	int status;
+ 	BIGNUM *p, *q, *g, *pub_key;
+ 	char *comment;
+ 
+ 	auth = ssh_get_authentication_connection();
+ 	if(!auth)
+ 		return 0;
+ 
+ 	p = BN_new();
+ 	q = BN_new();
+ 	g = BN_new();
+ 	pub_key = BN_new();
+ 	
+ 
+ 	for (status = ssh_get_first_dsa_identity(auth, p, q, g, pub_key, &comment); status; status = ssh_get_next_dsa_identity(auth, p, q, g, pub_key, &comment)) {
+ 		xfree (comment);
+ 		k = key_new(KEY_DSA);
+ 		k->dsa->p = p;
+ 		k->dsa->q = q;
+ 		k->dsa->g = g;
+ 		k->dsa->pub_key = pub_key;
+ 		dsa_make_key_blob(k, &blob, &bloblen);
+ 
+ 		/* data to be signed */
+ 		buffer_init(&b);
+ 		if (datafellows & SSH_COMPAT_SESSIONID_ENCODING) {
+ 			buffer_put_string(&b, session_id2, session_id2_len);
+ 			skip = buffer_len(&b);
+ 		} else {
+ 			buffer_append(&b, session_id2, session_id2_len);
+ 			skip = session_id2_len; 
+ 		}
+ 		buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
+ 		buffer_put_cstring(&b, server_user);
+ 		buffer_put_cstring(&b,
+ 		    datafellows & SSH_BUG_PUBKEYAUTH ?
+ 		    "ssh-userauth" :
+ 		    service);
+ 		buffer_put_cstring(&b, "publickey");
+ 		buffer_put_char(&b, 1);
+ 		buffer_put_cstring(&b, KEX_DSS); 
+ 		buffer_put_string(&b, blob, bloblen);
+ 
+ 		/* generate signature */
+ 		ssh2_sign_data(auth, p, q, g, pub_key, buffer_ptr(&b), buffer_len(&b), &signature, &slen, datafellows);
+ 		key_free(k);
+ #ifdef DEBUG_DSS
+ 		buffer_dump(&b);
+ #endif
+ 		if (datafellows & SSH_BUG_PUBKEYAUTH) {
+ 			buffer_clear(&b);
+ 			buffer_append(&b, session_id2, session_id2_len);
+ 			buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
+ 			buffer_put_cstring(&b, server_user);
+ 			buffer_put_cstring(&b, service);
+ 			buffer_put_cstring(&b, "publickey");
+ 			buffer_put_char(&b, 1);
+ 			buffer_put_cstring(&b, KEX_DSS); 
+ 			buffer_put_string(&b, blob, bloblen);
+ 		}
+ 		xfree(blob);
+ 		/* append signature */
+ 		buffer_put_string(&b, signature, slen);
+ 
+ 		/* skip session id and packet type */
+ 		if (buffer_len(&b) < skip + 1)
+ 			fatal("ssh2_try_pubkey: internal error");
+ 		buffer_consume(&b, skip + 1);
+ 
+ 		/* put remaining data from buffer into packet */
+ 		packet_start(SSH2_MSG_USERAUTH_REQUEST);
+ 		packet_put_raw(buffer_ptr(&b), buffer_len(&b));
+ 		buffer_free(&b);
+ 
+ 		/* send */
+ 		packet_send();
+ 		packet_write_wait();
+ 
+ 		if (SSH2_MSG_USERAUTH_SUCCESS == packet_read(&plen))
+ 			return 1;
+ 
+ 	}
+ 	return 0;
+ }
+ 
+ int
  ssh2_try_pubkey(char *filename,
      const char *server_user, const char *host, const char *service)
  {
***************
*** 437,442 ****
--- 532,539 ----
  			debug("partial success");
  		if (options.dsa_authentication &&
  		    strstr(auths, "publickey") != NULL) {
+ 			if (ssh2_try_agent(server_user, host, service))
+ 				break;
  			while (i < options.num_identity_files2) {
  				sent = ssh2_try_pubkey(
  				    options.identity_files2[i++],






More information about the openssh-unix-dev mailing list