-/* $OpenBSD: ssh-agent.c,v 1.33 2000/08/19 21:34:43 markus Exp $ */
+/* $OpenBSD: ssh-agent.c,v 1.41 2000/11/30 18:33:05 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
- * Created: Wed Mar 29 03:46:59 1995 ylo
* The authentication agent program.
*
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose. Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ *
* SSH2 implementation,
* Copyright (c) 2000 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
-RCSID("$OpenBSD: ssh-agent.c,v 1.33 2000/08/19 21:34:43 markus Exp $");
+RCSID("$OpenBSD: ssh-agent.c,v 1.41 2000/11/30 18:33:05 markus Exp $");
#include "ssh.h"
#include "rsa.h"
#include <openssl/rsa.h>
#include "key.h"
#include "authfd.h"
-#include "dsa.h"
#include "kex.h"
+#include "compat.h"
typedef struct {
int fd;
#ifdef HAVE___PROGNAME
extern char *__progname;
-#else /* HAVE___PROGNAME */
-static const char *__progname = "ssh-agent";
-#endif /* HAVE___PROGNAME */
+#else
+char *__progname;
+#endif
void
idtab_init(void)
buffer_put_int(&msg, tab->nentries);
for (i = 0; i < tab->nentries; i++) {
Identity *id = &tab->identities[i];
- if (id->key->type == KEY_RSA) {
+ if (id->key->type == KEY_RSA1) {
buffer_put_int(&msg, BN_num_bits(id->key->rsa->n));
buffer_put_bignum(&msg, id->key->rsa->e);
buffer_put_bignum(&msg, id->key->rsa->n);
} else {
unsigned char *blob;
unsigned int blen;
- dsa_make_key_blob(id->key, &blob, &blen);
+ key_to_blob(id->key, &blob, &blen);
buffer_put_string(&msg, blob, blen);
xfree(blob);
}
unsigned int response_type;
buffer_init(&msg);
- key = key_new(KEY_RSA);
+ key = key_new(KEY_RSA1);
challenge = BN_new();
buffer_get_int(&e->input); /* ignored */
Key *key, *private;
unsigned char *blob, *data, *signature = NULL;
unsigned int blen, dlen, slen = 0;
+ int flags;
Buffer msg;
int ok = -1;
blob = buffer_get_string(&e->input, &blen);
data = buffer_get_string(&e->input, &dlen);
- key = dsa_key_from_blob(blob, blen);
+ flags = buffer_get_int(&e->input);
+ if (flags & SSH_AGENT_OLD_SIGNATURE)
+ datafellows = SSH_BUG_SIGBLOB;
+
+ key = key_from_blob(blob, blen);
if (key != NULL) {
private = lookup_private_key(key, NULL, 2);
if (private != NULL)
- ok = dsa_sign(private, &signature, &slen, data, dlen);
+ ok = key_sign(private, &signature, &slen, data, dlen);
}
key_free(key);
buffer_init(&msg);
switch(version){
case 1:
- key = key_new(KEY_RSA);
+ key = key_new(KEY_RSA1);
bits = buffer_get_int(&e->input);
buffer_get_bignum(&e->input, key->rsa->e);
buffer_get_bignum(&e->input, key->rsa->n);
break;
case 2:
blob = buffer_get_string(&e->input, &blen);
- key = dsa_key_from_blob(blob, blen);
+ key = key_from_blob(blob, blen);
xfree(blob);
break;
}
/*
* 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.
+ * the array, we actually free the key there and move
+ * all the entries between the empty slot and the end
+ * of the array.
*/
Idtab *tab = idtab_lookup(version);
key_free(tab->identities[idx].key);
xfree(tab->identities[idx].comment);
- if (idx != tab->nentries)
- tab->identities[idx] = tab->identities[tab->nentries];
+ if (tab->nentries < 1)
+ fatal("process_remove_identity: "
+ "internal error: tab->nentries %d",
+ tab->nentries);
+ if (idx != tab->nentries - 1) {
+ int i;
+ for (i = idx; i < tab->nentries - 1; i++)
+ tab->identities[i] = tab->identities[i+1];
+ }
+ tab->identities[tab->nentries - 1].key = NULL;
+ tab->identities[tab->nentries - 1].comment = NULL;
tab->nentries--;
success = 1;
}
}
void
-process_add_identity(SocketEntry *e, int version)
+generate_additional_parameters(RSA *rsa)
{
- Key *k = NULL;
- RSA *rsa;
BIGNUM *aux;
BN_CTX *ctx;
- char *type;
+ /* Generate additional parameters */
+ aux = BN_new();
+ ctx = BN_CTX_new();
+
+ BN_sub(aux, rsa->q, BN_value_one());
+ BN_mod(rsa->dmq1, rsa->d, aux, ctx);
+
+ BN_sub(aux, rsa->p, BN_value_one());
+ BN_mod(rsa->dmp1, rsa->d, aux, ctx);
+
+ BN_clear_free(aux);
+ BN_CTX_free(ctx);
+}
+
+void
+process_add_identity(SocketEntry *e, int version)
+{
+ Key *k = NULL;
+ char *type_name;
char *comment;
- int success = 0;
+ int type, success = 0;
Idtab *tab = idtab_lookup(version);
switch (version) {
case 1:
- k = key_new(KEY_RSA);
- rsa = k->rsa;
-
- /* allocate mem for private key */
- /* XXX rsa->n and rsa->e are already allocated */
- rsa->d = BN_new();
- rsa->iqmp = BN_new();
- rsa->q = BN_new();
- rsa->p = BN_new();
- rsa->dmq1 = BN_new();
- rsa->dmp1 = BN_new();
-
- buffer_get_int(&e->input); /* ignored */
-
- buffer_get_bignum(&e->input, rsa->n);
- buffer_get_bignum(&e->input, rsa->e);
- buffer_get_bignum(&e->input, rsa->d);
- buffer_get_bignum(&e->input, rsa->iqmp);
+ k = key_new_private(KEY_RSA1);
+ buffer_get_int(&e->input); /* ignored */
+ buffer_get_bignum(&e->input, k->rsa->n);
+ buffer_get_bignum(&e->input, k->rsa->e);
+ buffer_get_bignum(&e->input, k->rsa->d);
+ buffer_get_bignum(&e->input, k->rsa->iqmp);
/* SSH and SSL have p and q swapped */
- buffer_get_bignum(&e->input, rsa->q); /* p */
- buffer_get_bignum(&e->input, rsa->p); /* q */
+ buffer_get_bignum(&e->input, k->rsa->q); /* p */
+ buffer_get_bignum(&e->input, k->rsa->p); /* q */
/* Generate additional parameters */
- aux = BN_new();
- ctx = BN_CTX_new();
-
- BN_sub(aux, rsa->q, BN_value_one());
- BN_mod(rsa->dmq1, rsa->d, aux, ctx);
-
- BN_sub(aux, rsa->p, BN_value_one());
- BN_mod(rsa->dmp1, rsa->d, aux, ctx);
-
- BN_clear_free(aux);
- BN_CTX_free(ctx);
-
+ generate_additional_parameters(k->rsa);
break;
case 2:
- type = buffer_get_string(&e->input, NULL);
- if (strcmp(type, KEX_DSS)) {
+ type_name = buffer_get_string(&e->input, NULL);
+ type = key_type_from_name(type_name);
+ xfree(type_name);
+ switch(type) {
+ case KEY_DSA:
+ k = key_new_private(type);
+ buffer_get_bignum2(&e->input, k->dsa->p);
+ buffer_get_bignum2(&e->input, k->dsa->q);
+ buffer_get_bignum2(&e->input, k->dsa->g);
+ buffer_get_bignum2(&e->input, k->dsa->pub_key);
+ buffer_get_bignum2(&e->input, k->dsa->priv_key);
+ break;
+ case KEY_RSA:
+ k = key_new_private(type);
+ buffer_get_bignum2(&e->input, k->rsa->n);
+ buffer_get_bignum2(&e->input, k->rsa->e);
+ buffer_get_bignum2(&e->input, k->rsa->d);
+ buffer_get_bignum2(&e->input, k->rsa->iqmp);
+ buffer_get_bignum2(&e->input, k->rsa->p);
+ buffer_get_bignum2(&e->input, k->rsa->q);
+
+ /* Generate additional parameters */
+ generate_additional_parameters(k->rsa);
+ break;
+ default:
buffer_clear(&e->input);
- xfree(type);
goto send;
}
- xfree(type);
-
- k = key_new(KEY_DSA);
-
- /* allocate mem for private key */
- k->dsa->priv_key = BN_new();
-
- buffer_get_bignum2(&e->input, k->dsa->p);
- buffer_get_bignum2(&e->input, k->dsa->q);
- buffer_get_bignum2(&e->input, k->dsa->g);
- buffer_get_bignum2(&e->input, k->dsa->pub_key);
- buffer_get_bignum2(&e->input, k->dsa->priv_key);
-
break;
}
-
comment = buffer_get_string(&e->input, NULL);
if (k == NULL) {
xfree(comment);
void
cleanup_socket(void)
{
- remove(socket_name);
+ unlink(socket_name);
rmdir(socket_dir);
}
fd_set readset, writeset;
int sock, c_flag = 0, k_flag = 0, s_flag = 0, ch;
struct sockaddr_un sunaddr;
+ struct rlimit rlim;
pid_t pid;
char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid];
extern int optind;
+ __progname = get_progname(av[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);
- }
#ifdef __GNU_LIBRARY__
while ((ch = getopt(ac, av, "+cks")) != -1) {
#else /* __GNU_LIBRARY__ */
printf("echo Agent pid %d;\n", pid);
exit(0);
}
- setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1);
- setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1);
+ if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 ||
+ setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1) == -1) {
+ perror("setenv");
+ exit(1);
+ }
execvp(av[0], av);
perror(av[0]);
exit(1);
close(1);
close(2);
+ /* deny core dumps, since memory contains unencrypted private keys */
+ rlim.rlim_cur = rlim.rlim_max = 0;
+ if (setrlimit(RLIMIT_CORE, &rlim) < 0) {
+ perror("setrlimit rlimit_core failed");
+ cleanup_exit(1);
+ }
if (setsid() == -1) {
perror("setsid");
cleanup_exit(1);