]> andersk Git - gssapi-openssh.git/commitdiff
Initial revision
authorjbasney <jbasney>
Tue, 16 Sep 2003 15:52:13 +0000 (15:52 +0000)
committerjbasney <jbasney>
Tue, 16 Sep 2003 15:52:13 +0000 (15:52 +0000)
21 files changed:
openssh/README.dns [new file with mode: 0644]
openssh/cipher-3des1.c [new file with mode: 0644]
openssh/cipher-aes.c [new file with mode: 0644]
openssh/cipher-bf1.c [new file with mode: 0644]
openssh/cipher-ctr.c [new file with mode: 0644]
openssh/contrib/findssl.sh [new file with mode: 0644]
openssh/dns.c [new file with mode: 0644]
openssh/dns.h [new file with mode: 0644]
openssh/mdoc2man.awk [new file with mode: 0644]
openssh/moduli.c [new file with mode: 0644]
openssh/moduli.h [new file with mode: 0644]
openssh/openbsd-compat/fake-rfc2553.c [new file with mode: 0644]
openssh/openbsd-compat/fake-rfc2553.h [new file with mode: 0644]
openssh/openbsd-compat/getrrsetbyname.c [new file with mode: 0644]
openssh/openbsd-compat/getrrsetbyname.h [new file with mode: 0644]
openssh/openbsd-compat/xcrypt.c [new file with mode: 0644]
openssh/regress/README.regress [new file with mode: 0644]
openssh/regress/dynamic-forward.sh [new file with mode: 0644]
openssh/regress/reconfigure.sh [new file with mode: 0644]
openssh/regress/rekey.sh [new file with mode: 0644]
openssh/regress/sftp-badcmds.sh [new file with mode: 0644]

diff --git a/openssh/README.dns b/openssh/README.dns
new file mode 100644 (file)
index 0000000..e24092e
--- /dev/null
@@ -0,0 +1,52 @@
+How to verify host keys using OpenSSH and DNS
+---------------------------------------------
+
+OpenSSH contains experimental support for verifying host keys using DNS
+as described in draft-ietf-secsh-dns-xx.txt. The document contains
+very brief instructions on how to test this feature. Configuring DNS
+and DNSSEC is out of the scope of this document.
+
+
+(1) Enable DNS fingerprint support in OpenSSH
+
+       configure --with-dns
+
+(2) Generate and publish the DNS RR
+
+To create a DNS resource record (RR) containing a fingerprint of the
+public host key, use the following command:
+
+       ssh-keygen -r hostname -f keyfile -g
+
+where "hostname" is your fully qualified hostname and "keyfile" is the
+file containing the public host key file. If you have multiple keys,
+you should generate one RR for each key.
+
+In the example above, ssh-keygen will print the fingerprint in a
+generic DNS RR format parsable by most modern name server
+implementations. If your nameserver has support for the SSHFP RR, as
+defined by the draft, you can omit the -g flag and ssh-keygen will
+print a standard RR.
+
+To publish the fingerprint using the DNS you must add the generated RR
+to your DNS zone file and sign your zone.
+
+
+(3) Enable the ssh client to verify host keys using DNS
+
+To enable the ssh client to verify host keys using DNS, you have to
+add the following option to the ssh configuration file
+($HOME/.ssh/config or /etc/ssh/ssh_config):
+
+    VerifyHostKeyDNS yes
+
+Upon connection the client will try to look up the fingerprint RR
+using DNS. If the fingerprint received from the DNS server matches
+the remote host key, the user will be notified.
+
+
+       Jakob Schlyter
+       Wesley Griffin
+
+
+$OpenBSD: README.dns,v 1.1 2003/05/14 18:16:20 jakob Exp $
diff --git a/openssh/cipher-3des1.c b/openssh/cipher-3des1.c
new file mode 100644 (file)
index 0000000..f9a3523
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2003 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: cipher-3des1.c,v 1.1 2003/05/15 03:08:29 markus Exp $");
+
+#include <openssl/evp.h>
+#include "xmalloc.h"
+#include "log.h"
+
+/*
+ * This is used by SSH1:
+ *
+ * What kind of triple DES are these 2 routines?
+ *
+ * Why is there a redundant initialization vector?
+ *
+ * If only iv3 was used, then, this would till effect have been
+ * outer-cbc. However, there is also a private iv1 == iv2 which
+ * perhaps makes differential analysis easier. On the other hand, the
+ * private iv1 probably makes the CRC-32 attack ineffective. This is a
+ * result of that there is no longer any known iv1 to use when
+ * choosing the X block.
+ */
+struct ssh1_3des_ctx
+{
+       EVP_CIPHER_CTX  k1, k2, k3;
+};
+
+const EVP_CIPHER * evp_ssh1_3des(void);
+void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
+
+static int
+ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
+    int enc)
+{
+       struct ssh1_3des_ctx *c;
+       u_char *k1, *k2, *k3;
+
+       if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
+               c = xmalloc(sizeof(*c));
+               EVP_CIPHER_CTX_set_app_data(ctx, c);
+       }
+       if (key == NULL)
+               return (1);
+       if (enc == -1)
+               enc = ctx->encrypt;
+       k1 = k2 = k3 = (u_char *) key;
+       k2 += 8;
+       if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
+               if (enc)
+                       k3 += 16;
+               else
+                       k1 += 16;
+       }
+       EVP_CIPHER_CTX_init(&c->k1);
+       EVP_CIPHER_CTX_init(&c->k2);
+       EVP_CIPHER_CTX_init(&c->k3);
+#ifdef SSH_OLD_EVP
+       EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc);
+       EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc);
+       EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc);
+#else
+       if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
+           EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
+           EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
+               memset(c, 0, sizeof(*c));
+               xfree(c);
+               EVP_CIPHER_CTX_set_app_data(ctx, NULL);
+               return (0);
+       }
+#endif
+       return (1);
+}
+
+static int
+ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
+{
+       struct ssh1_3des_ctx *c;
+
+       if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
+               error("ssh1_3des_cbc: no context");
+               return (0);
+       }
+#ifdef SSH_OLD_EVP
+       EVP_Cipher(&c->k1, dest, (u_char *)src, len);
+       EVP_Cipher(&c->k2, dest, dest, len);
+       EVP_Cipher(&c->k3, dest, dest, len);
+#else
+       if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
+           EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
+           EVP_Cipher(&c->k3, dest, dest, len) == 0)
+               return (0);
+#endif
+       return (1);
+}
+
+static int
+ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
+{
+       struct ssh1_3des_ctx *c;
+
+       if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
+               memset(c, 0, sizeof(*c));
+               xfree(c);
+               EVP_CIPHER_CTX_set_app_data(ctx, NULL);
+       }
+       return (1);
+}
+
+void
+ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len)
+{
+       struct ssh1_3des_ctx *c;
+
+       if (len != 24)
+               fatal("%s: bad 3des iv length: %d", __func__, len);
+       if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
+               fatal("%s: no 3des context", __func__);
+       if (doset) {
+               debug3("%s: Installed 3DES IV", __func__);
+               memcpy(c->k1.iv, iv, 8);
+               memcpy(c->k2.iv, iv + 8, 8);
+               memcpy(c->k3.iv, iv + 16, 8);
+       } else {
+               debug3("%s: Copying 3DES IV", __func__);
+               memcpy(iv, c->k1.iv, 8);
+               memcpy(iv + 8, c->k2.iv, 8);
+               memcpy(iv + 16, c->k3.iv, 8);
+       }
+}
+
+const EVP_CIPHER *
+evp_ssh1_3des(void)
+{
+       static EVP_CIPHER ssh1_3des;
+
+       memset(&ssh1_3des, 0, sizeof(EVP_CIPHER));
+       ssh1_3des.nid = NID_undef;
+       ssh1_3des.block_size = 8;
+       ssh1_3des.iv_len = 0;
+       ssh1_3des.key_len = 16;
+       ssh1_3des.init = ssh1_3des_init;
+       ssh1_3des.cleanup = ssh1_3des_cleanup;
+       ssh1_3des.do_cipher = ssh1_3des_cbc;
+#ifndef SSH_OLD_EVP
+       ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
+#endif
+       return (&ssh1_3des);
+}
diff --git a/openssh/cipher-aes.c b/openssh/cipher-aes.c
new file mode 100644 (file)
index 0000000..c41def6
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2003 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"
+#if OPENSSL_VERSION_NUMBER < 0x00907000L
+RCSID("$OpenBSD: cipher-aes.c,v 1.1 2003/05/15 03:08:29 markus Exp $");
+
+#include <openssl/evp.h>
+#include "rijndael.h"
+#include "xmalloc.h"
+#include "log.h"
+
+#define RIJNDAEL_BLOCKSIZE 16
+struct ssh_rijndael_ctx
+{
+       rijndael_ctx    r_ctx;
+       u_char          r_iv[RIJNDAEL_BLOCKSIZE];
+};
+
+const EVP_CIPHER * evp_rijndael(void);
+void ssh_rijndael_iv(EVP_CIPHER_CTX *, int, u_char *, u_int);
+
+static int
+ssh_rijndael_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
+    int enc)
+{
+       struct ssh_rijndael_ctx *c;
+
+       if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
+               c = xmalloc(sizeof(*c));
+               EVP_CIPHER_CTX_set_app_data(ctx, c);
+       }
+       if (key != NULL) {
+               if (enc == -1)
+                       enc = ctx->encrypt;
+               rijndael_set_key(&c->r_ctx, (u_char *)key,
+                   8*EVP_CIPHER_CTX_key_length(ctx), enc);
+       }
+       if (iv != NULL)
+               memcpy(c->r_iv, iv, RIJNDAEL_BLOCKSIZE);
+       return (1);
+}
+
+static int
+ssh_rijndael_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
+    u_int len)
+{
+       struct ssh_rijndael_ctx *c;
+       u_char buf[RIJNDAEL_BLOCKSIZE];
+       u_char *cprev, *cnow, *plain, *ivp;
+       int i, j, blocks = len / RIJNDAEL_BLOCKSIZE;
+
+       if (len == 0)
+               return (1);
+       if (len % RIJNDAEL_BLOCKSIZE)
+               fatal("ssh_rijndael_cbc: bad len %d", len);
+       if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
+               error("ssh_rijndael_cbc: no context");
+               return (0);
+       }
+       if (ctx->encrypt) {
+               cnow  = dest;
+               plain = (u_char *)src;
+               cprev = c->r_iv;
+               for (i = 0; i < blocks; i++, plain+=RIJNDAEL_BLOCKSIZE,
+                   cnow+=RIJNDAEL_BLOCKSIZE) {
+                       for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
+                               buf[j] = plain[j] ^ cprev[j];
+                       rijndael_encrypt(&c->r_ctx, buf, cnow);
+                       cprev = cnow;
+               }
+               memcpy(c->r_iv, cprev, RIJNDAEL_BLOCKSIZE);
+       } else {
+               cnow  = (u_char *) (src+len-RIJNDAEL_BLOCKSIZE);
+               plain = dest+len-RIJNDAEL_BLOCKSIZE;
+
+               memcpy(buf, cnow, RIJNDAEL_BLOCKSIZE);
+               for (i = blocks; i > 0; i--, cnow-=RIJNDAEL_BLOCKSIZE,
+                   plain-=RIJNDAEL_BLOCKSIZE) {
+                       rijndael_decrypt(&c->r_ctx, cnow, plain);
+                       ivp = (i == 1) ? c->r_iv : cnow-RIJNDAEL_BLOCKSIZE;
+                       for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
+                               plain[j] ^= ivp[j];
+               }
+               memcpy(c->r_iv, buf, RIJNDAEL_BLOCKSIZE);
+       }
+       return (1);
+}
+
+static int
+ssh_rijndael_cleanup(EVP_CIPHER_CTX *ctx)
+{
+       struct ssh_rijndael_ctx *c;
+
+       if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
+               memset(c, 0, sizeof(*c));
+               xfree(c);
+               EVP_CIPHER_CTX_set_app_data(ctx, NULL);
+       }
+       return (1);
+}
+
+void
+ssh_rijndael_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, u_int len)
+{
+       struct ssh_rijndael_ctx *c;
+
+       if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
+               fatal("ssh_rijndael_iv: no context");
+       if (doset)
+               memcpy(c->r_iv, iv, len);
+       else
+               memcpy(iv, c->r_iv, len);
+}
+
+const EVP_CIPHER *
+evp_rijndael(void)
+{
+       static EVP_CIPHER rijndal_cbc;
+
+       memset(&rijndal_cbc, 0, sizeof(EVP_CIPHER));
+       rijndal_cbc.nid = NID_undef;
+       rijndal_cbc.block_size = RIJNDAEL_BLOCKSIZE;
+       rijndal_cbc.iv_len = RIJNDAEL_BLOCKSIZE;
+       rijndal_cbc.key_len = 16;
+       rijndal_cbc.init = ssh_rijndael_init;
+       rijndal_cbc.cleanup = ssh_rijndael_cleanup;
+       rijndal_cbc.do_cipher = ssh_rijndael_cbc;
+#ifndef SSH_OLD_EVP
+       rijndal_cbc.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
+           EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV;
+#endif
+       return (&rijndal_cbc);
+}
+#endif /* OPENSSL_VERSION_NUMBER */
diff --git a/openssh/cipher-bf1.c b/openssh/cipher-bf1.c
new file mode 100644 (file)
index 0000000..64578ba
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2003 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: cipher-bf1.c,v 1.1 2003/05/15 03:08:29 markus Exp $");
+
+#include <openssl/evp.h>
+#include "xmalloc.h"
+#include "log.h"
+/*
+ * SSH1 uses a variation on Blowfish, all bytes must be swapped before
+ * and after encryption/decryption. Thus the swap_bytes stuff (yuk).
+ */
+
+const EVP_CIPHER * evp_ssh1_bf(void);
+
+static void
+swap_bytes(const u_char *src, u_char *dst, int n)
+{
+       u_char c[4];
+
+       /* Process 4 bytes every lap. */
+       for (n = n / 4; n > 0; n--) {
+               c[3] = *src++;
+               c[2] = *src++;
+               c[1] = *src++;
+               c[0] = *src++;
+
+               *dst++ = c[0];
+               *dst++ = c[1];
+               *dst++ = c[2];
+               *dst++ = c[3];
+       }
+}
+
+#ifdef SSH_OLD_EVP
+static void bf_ssh1_init (EVP_CIPHER_CTX * ctx, const unsigned char *key,
+                         const unsigned char *iv, int enc)
+{
+       if (iv != NULL)
+               memcpy (&(ctx->oiv[0]), iv, 8);
+       memcpy (&(ctx->iv[0]), &(ctx->oiv[0]), 8);
+       if (key != NULL)
+               BF_set_key (&(ctx->c.bf_ks), EVP_CIPHER_CTX_key_length (ctx),
+                           key);
+}
+#endif
+
+static int (*orig_bf)(EVP_CIPHER_CTX *, u_char *, const u_char *, u_int) = NULL;
+
+static int
+bf_ssh1_cipher(EVP_CIPHER_CTX *ctx, u_char *out, const u_char *in, u_int len)
+{
+       int ret;
+
+       swap_bytes(in, out, len);
+       ret = (*orig_bf)(ctx, out, out, len);
+       swap_bytes(out, out, len);
+       return (ret);
+}
+
+const EVP_CIPHER *
+evp_ssh1_bf(void)
+{
+       static EVP_CIPHER ssh1_bf;
+
+       memcpy(&ssh1_bf, EVP_bf_cbc(), sizeof(EVP_CIPHER));
+       orig_bf = ssh1_bf.do_cipher;
+       ssh1_bf.nid = NID_undef;
+#ifdef SSH_OLD_EVP
+       ssh1_bf.init = bf_ssh1_init;
+#endif
+       ssh1_bf.do_cipher = bf_ssh1_cipher;
+       ssh1_bf.key_len = 32;
+       return (&ssh1_bf);
+}
diff --git a/openssh/cipher-ctr.c b/openssh/cipher-ctr.c
new file mode 100644 (file)
index 0000000..a2bab5c
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2003 Markus Friedl <markus@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "includes.h"
+RCSID("$OpenBSD: cipher-ctr.c,v 1.2 2003/06/17 18:14:23 markus Exp $");
+
+#include <openssl/evp.h>
+
+#include "log.h"
+#include "xmalloc.h"
+
+#if OPENSSL_VERSION_NUMBER < 0x00907000L
+#include "rijndael.h"
+#define AES_KEY rijndael_ctx
+#define AES_BLOCK_SIZE 16
+#define AES_encrypt(a, b, c) rijndael_encrypt(c, a, b)
+#define AES_set_encrypt_key(a, b, c) rijndael_set_key(c, (char *)a, b, 1)
+#else
+#include <openssl/aes.h>
+#endif
+
+const EVP_CIPHER *evp_aes_128_ctr(void);
+void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, u_int);
+
+struct ssh_aes_ctr_ctx
+{
+       AES_KEY         aes_ctx;
+       u_char          aes_counter[AES_BLOCK_SIZE];
+};
+
+/*
+ * increment counter 'ctr',
+ * the counter is of size 'len' bytes and stored in network-byte-order.
+ * (LSB at ctr[len-1], MSB at ctr[0])
+ */
+static void
+ssh_ctr_inc(u_char *ctr, u_int len)
+{
+       int i;
+
+       for (i = len - 1; i >= 0; i--)
+               if (++ctr[i])   /* continue on overflow */
+                       return;
+}
+
+static int
+ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
+    u_int len)
+{
+       struct ssh_aes_ctr_ctx *c;
+       u_int n = 0;
+       u_char buf[AES_BLOCK_SIZE];
+
+       if (len == 0)
+               return (1);
+       if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL)
+               return (0);
+
+       while ((len--) > 0) {
+               if (n == 0) {
+                       AES_encrypt(c->aes_counter, buf, &c->aes_ctx);
+                       ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE);
+               }
+               *(dest++) = *(src++) ^ buf[n];
+               n = (n + 1) % AES_BLOCK_SIZE;
+       }
+       return (1);
+}
+
+static int
+ssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
+    int enc)
+{
+       struct ssh_aes_ctr_ctx *c;
+
+       if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
+               c = xmalloc(sizeof(*c));
+               EVP_CIPHER_CTX_set_app_data(ctx, c);
+       }
+       if (key != NULL)
+                AES_set_encrypt_key(key, ctx->key_len * 8, &c->aes_ctx);
+       if (iv != NULL)
+               memcpy(c->aes_counter, iv, AES_BLOCK_SIZE);
+       return (1);
+}
+
+static int
+ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx)
+{
+       struct ssh_aes_ctr_ctx *c;
+
+       if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
+               memset(c, 0, sizeof(*c));
+               xfree(c);
+               EVP_CIPHER_CTX_set_app_data(ctx, NULL);
+       }
+       return (1);
+}
+
+void
+ssh_aes_ctr_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, u_int len)
+{
+       struct ssh_aes_ctr_ctx *c;
+
+       if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
+               fatal("ssh_aes_ctr_iv: no context");
+       if (doset)
+               memcpy(c->aes_counter, iv, len);
+       else
+               memcpy(iv, c->aes_counter, len);
+}
+
+const EVP_CIPHER *
+evp_aes_128_ctr(void)
+{
+       static EVP_CIPHER aes_ctr;
+
+       memset(&aes_ctr, 0, sizeof(EVP_CIPHER));
+       aes_ctr.nid = NID_undef;
+       aes_ctr.block_size = AES_BLOCK_SIZE;
+       aes_ctr.iv_len = AES_BLOCK_SIZE;
+       aes_ctr.key_len = 16;
+       aes_ctr.init = ssh_aes_ctr_init;
+       aes_ctr.cleanup = ssh_aes_ctr_cleanup;
+       aes_ctr.do_cipher = ssh_aes_ctr;
+       aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
+           EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV;
+       return (&aes_ctr);
+}
diff --git a/openssh/contrib/findssl.sh b/openssh/contrib/findssl.sh
new file mode 100644 (file)
index 0000000..271870f
--- /dev/null
@@ -0,0 +1,159 @@
+#!/bin/sh
+#
+# findssl.sh
+#      Search for all instances of OpenSSL headers and libraries
+#      and print their versions.
+#      Intended to help diagnose OpenSSH's "OpenSSL headers do not
+#      match your library" errors.
+#
+#      Written by Darren Tucker (dtucker at zip dot com dot au)
+#      This file is placed in the public domain.
+#
+# $Id$
+#      2002-07-27: Initial release.
+#      2002-08-04: Added public domain notice.
+#      2003-06-24: Incorporated readme, set library paths. First cvs version.
+#
+# "OpenSSL headers do not match your library" are usually caused by 
+# OpenSSH's configure picking up an older version of OpenSSL headers
+# or libraries.  You can use the following # procedure to help identify
+# the cause.
+# 
+# The  output  of  configure  will  tell you the versions of the OpenSSL
+# headers and libraries that were picked up, for example:
+# 
+# checking OpenSSL header version... 90604f (OpenSSL 0.9.6d 9 May 2002)
+# checking OpenSSL library version... 90602f (OpenSSL 0.9.6b [engine] 9 Jul 2001)
+# checking whether OpenSSL's headers match the library... no
+# configure: error: Your OpenSSL headers do not match your library
+# 
+# Now run findssl.sh. This should identify the headers and libraries
+# present  and  their  versions.  You  should  be  able  to identify the
+# libraries  and headers used and adjust your CFLAGS or remove incorrect
+# versions.  The  output will show OpenSSL's internal version identifier
+# and should look something like:
+
+# $ ./findssl.sh
+# Searching for OpenSSL header files.
+# 0x0090604fL /usr/include/openssl/opensslv.h
+# 0x0090604fL /usr/local/ssl/include/openssl/opensslv.h
+# 
+# Searching for OpenSSL shared library files.
+# 0x0090602fL /lib/libcrypto.so.0.9.6b
+# 0x0090602fL /lib/libcrypto.so.2
+# 0x0090581fL /usr/lib/libcrypto.so.0
+# 0x0090602fL /usr/lib/libcrypto.so
+# 0x0090581fL /usr/lib/libcrypto.so.0.9.5a
+# 0x0090600fL /usr/lib/libcrypto.so.0.9.6
+# 0x0090600fL /usr/lib/libcrypto.so.1
+# 
+# Searching for OpenSSL static library files.
+# 0x0090602fL /usr/lib/libcrypto.a
+# 0x0090604fL /usr/local/ssl/lib/libcrypto.a
+# 
+# In  this  example, I gave configure no extra flags, so it's picking up
+# the  OpenSSL header from /usr/include/openssl (90604f) and the library
+# from /usr/lib/ (90602f).
+
+#
+# Adjust these to suit your compiler.
+# You may also need to set the *LIB*PATH environment variables if
+# DEFAULT_LIBPATH is not correct for your system.
+#
+CC=gcc
+STATIC=-static
+
+#
+# Set up conftest C source
+#
+rm -f findssl.log
+cat >conftest.c <<EOD
+#include <stdio.h>
+int main(){printf("0x%08xL\n", SSLeay());}
+EOD
+
+#
+# Set default library paths if not already set
+#
+DEFAULT_LIBPATH=/usr/lib:/usr/local/lib
+LIBPATH=${LIBPATH:=$DEFAULT_LIBPATH}
+LD_LIBRARY_PATH=${LD_LIBRARY_PATH:=$DEFAULT_LIBPATH}
+LIBRARY_PATH=${LIBRARY_PATH:=$DEFAULT_LIBPATH}
+export LIBPATH LD_LIBRARY_PATH LIBRARY_PATH
+
+#
+# Search for OpenSSL headers and print versions
+#
+echo Searching for OpenSSL header files.
+if [ -x "`which locate`" ]
+then
+       headers=`locate opensslv.h`
+else
+       headers=`find / -name opensslv.h -print 2>/dev/null`
+fi
+
+for header in $headers
+do
+       ver=`awk '/OPENSSL_VERSION_NUMBER/{printf \$3}' $header`
+       echo "$ver $header"
+done
+echo
+
+#
+# Search for shared libraries.
+# Relies on shared libraries looking like "libcrypto.s*"
+#
+echo Searching for OpenSSL shared library files.
+if [ -x "`which locate`" ]
+then
+       libraries=`locate libcrypto.s`
+else
+       libraries=`find / -name 'libcrypto.s*' -print 2>/dev/null`
+fi
+
+for lib in $libraries
+do
+       (echo "Trying libcrypto $lib" >>findssl.log
+       dir=`dirname $lib`
+       LIBPATH="$dir:$LIBPATH"
+       LD_LIBRARY_PATH="$dir:$LIBPATH"
+       LIBRARY_PATH="$dir:$LIBPATH"
+       export LIBPATH LD_LIBRARY_PATH LIBRARY_PATH
+       ${CC} -o conftest conftest.c $lib 2>>findssl.log
+       if [ -x ./conftest ]
+       then
+               ver=`./conftest 2>/dev/null`
+               rm -f ./conftest
+               echo "$ver $lib"
+       fi)
+done
+echo
+
+#
+# Search for static OpenSSL libraries and print versions
+#
+echo Searching for OpenSSL static library files.
+if [ -x "`which locate`" ]
+then
+       libraries=`locate libcrypto.a`
+else
+       libraries=`find / -name libcrypto.a -print 2>/dev/null`
+fi
+
+for lib in $libraries
+do
+       libdir=`dirname $lib`
+       echo "Trying libcrypto $lib" >>findssl.log
+       ${CC} ${STATIC} -o conftest conftest.c -L${libdir} -lcrypto 2>>findssl.log
+       if [ -x ./conftest ]
+       then
+               ver=`./conftest 2>/dev/null`
+               rm -f ./conftest
+               echo "$ver $lib"
+       fi
+done
+
+#
+# Clean up
+#
+rm -f conftest.c
diff --git a/openssh/dns.c b/openssh/dns.c
new file mode 100644 (file)
index 0000000..90ab560
--- /dev/null
@@ -0,0 +1,290 @@
+/*     $OpenBSD: dns.c,v 1.6 2003/06/11 10:18:47 jakob Exp $   */
+
+/*
+ * Copyright (c) 2003 Wesley Griffin. All rights reserved.
+ * Copyright (c) 2003 Jakob Schlyter. 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"
+
+#ifdef DNS
+#include <openssl/bn.h>
+#ifdef LWRES
+#include <lwres/netdb.h>
+#include <dns/result.h>
+#else /* LWRES */
+#include <netdb.h>
+#endif /* LWRES */
+
+#include "xmalloc.h"
+#include "key.h"
+#include "dns.h"
+#include "log.h"
+#include "uuencode.h"
+
+extern char *__progname;
+RCSID("$OpenBSD: dns.c,v 1.6 2003/06/11 10:18:47 jakob Exp $");
+
+#ifndef LWRES
+static const char *errset_text[] = {
+       "success",              /* 0 ERRSET_SUCCESS */
+       "out of memory",        /* 1 ERRSET_NOMEMORY */
+       "general failure",      /* 2 ERRSET_FAIL */
+       "invalid parameter",    /* 3 ERRSET_INVAL */
+       "name does not exist",  /* 4 ERRSET_NONAME */
+       "data does not exist",  /* 5 ERRSET_NODATA */
+};
+
+static const char *
+dns_result_totext(unsigned int error)
+{
+       switch (error) {
+       case ERRSET_SUCCESS:
+               return errset_text[ERRSET_SUCCESS];
+       case ERRSET_NOMEMORY:
+               return errset_text[ERRSET_NOMEMORY];
+       case ERRSET_FAIL:
+               return errset_text[ERRSET_FAIL];
+       case ERRSET_INVAL:
+               return errset_text[ERRSET_INVAL];
+       case ERRSET_NONAME:
+               return errset_text[ERRSET_NONAME];
+       case ERRSET_NODATA:
+               return errset_text[ERRSET_NODATA];
+       default:
+               return "unknown error";
+       }
+}
+#endif /* LWRES */
+
+
+/*
+ * Read SSHFP parameters from key buffer.
+ */
+static int
+dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type,
+    u_char **digest, u_int *digest_len, Key *key)
+{
+       int success = 0;
+
+       switch (key->type) {
+       case KEY_RSA:
+               *algorithm = SSHFP_KEY_RSA;
+               break;
+       case KEY_DSA:
+               *algorithm = SSHFP_KEY_DSA;
+               break;
+       default:
+               *algorithm = SSHFP_KEY_RESERVED;
+       }
+
+       if (*algorithm) {
+               *digest_type = SSHFP_HASH_SHA1;
+               *digest = key_fingerprint_raw(key, SSH_FP_SHA1, digest_len);
+               success = 1;
+       } else {
+               *digest_type = SSHFP_HASH_RESERVED;
+               *digest = NULL;
+               *digest_len = 0;
+               success = 0;
+       }
+
+       return success;
+}
+
+/*
+ * Read SSHFP parameters from rdata buffer.
+ */
+static int
+dns_read_rdata(u_int8_t *algorithm, u_int8_t *digest_type,
+    u_char **digest, u_int *digest_len, u_char *rdata, int rdata_len)
+{
+       int success = 0;
+
+       *algorithm = SSHFP_KEY_RESERVED;
+       *digest_type = SSHFP_HASH_RESERVED;
+
+       if (rdata_len >= 2) {
+               *algorithm = rdata[0];
+               *digest_type = rdata[1];
+               *digest_len = rdata_len - 2;
+
+               if (*digest_len > 0) {
+                       *digest = (u_char *) xmalloc(*digest_len);
+                       memcpy(*digest, rdata + 2, *digest_len);
+               } else {
+                       *digest = NULL;
+               }
+
+               success = 1;
+       }
+
+       return success;
+}
+
+
+/*
+ * Verify the given hostname, address and host key using DNS.
+ * Returns 0 if key verifies or -1 if key does NOT verify
+ */
+int
+verify_host_key_dns(const char *hostname, struct sockaddr *address,
+    Key *hostkey)
+{
+       int counter;
+       int result;
+       struct rrsetinfo *fingerprints = NULL;
+       int failures = 0;
+
+       u_int8_t hostkey_algorithm;
+       u_int8_t hostkey_digest_type;
+       u_char *hostkey_digest;
+       u_int hostkey_digest_len;
+
+       u_int8_t dnskey_algorithm;
+       u_int8_t dnskey_digest_type;
+       u_char *dnskey_digest;
+       u_int dnskey_digest_len;
+
+
+       debug3("verify_hostkey_dns");
+       if (hostkey == NULL)
+               fatal("No key to look up!");
+
+       result = getrrsetbyname(hostname, DNS_RDATACLASS_IN,
+           DNS_RDATATYPE_SSHFP, 0, &fingerprints);
+       if (result) {
+               verbose("DNS lookup error: %s", dns_result_totext(result));
+               return DNS_VERIFY_ERROR;
+       }
+
+#ifdef DNSSEC
+       /* Only accept validated answers */
+       if (!fingerprints->rri_flags & RRSET_VALIDATED) {
+               error("Ignored unvalidated fingerprint from DNS.");
+               freerrset(fingerprints);
+               return DNS_VERIFY_ERROR;
+       }
+#endif
+
+       debug("found %d fingerprints in DNS", fingerprints->rri_nrdatas);
+
+       /* Initialize host key parameters */
+       if (!dns_read_key(&hostkey_algorithm, &hostkey_digest_type,
+           &hostkey_digest, &hostkey_digest_len, hostkey)) {
+               error("Error calculating host key fingerprint.");
+               freerrset(fingerprints);
+               return DNS_VERIFY_ERROR;
+       }
+
+       for (counter = 0 ; counter < fingerprints->rri_nrdatas ; counter++)  {
+               /*
+                * Extract the key from the answer. Ignore any badly
+                * formatted fingerprints.
+                */
+               if (!dns_read_rdata(&dnskey_algorithm, &dnskey_digest_type,
+                   &dnskey_digest, &dnskey_digest_len,
+                   fingerprints->rri_rdatas[counter].rdi_data,
+                   fingerprints->rri_rdatas[counter].rdi_length)) {
+                       verbose("Error parsing fingerprint from DNS.");
+                       continue;
+               }
+
+               /* Check if the current key is the same as the given key */
+               if (hostkey_algorithm == dnskey_algorithm &&
+                   hostkey_digest_type == dnskey_digest_type) {
+
+                       if (hostkey_digest_len == dnskey_digest_len &&
+                           memcmp(hostkey_digest, dnskey_digest,
+                           hostkey_digest_len) == 0) {
+
+                               /* Matching algoritm and digest. */
+                               freerrset(fingerprints);
+                               debug("matching host key fingerprint found in DNS");
+                               return DNS_VERIFY_OK;
+                       } else {
+                               /* Correct algorithm but bad digest */
+                               debug("verify_hostkey_dns: failed");
+                               failures++;
+                       }
+               }
+       }
+
+       freerrset(fingerprints);
+
+       if (failures) {
+               error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+               error("@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @");
+               error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+               error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
+               error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
+               error("It is also possible that the %s host key has just been changed.",
+                   key_type(hostkey));
+               error("Please contact your system administrator.");
+               return DNS_VERIFY_FAILED;
+       }
+
+       debug("fingerprints found in DNS, but none of them matched");
+
+       return DNS_VERIFY_ERROR;
+}
+
+
+/*
+ * Export the fingerprint of a key as a DNS resource record
+ */
+int
+export_dns_rr(const char *hostname, Key *key, FILE *f, int generic)
+{
+       u_int8_t rdata_pubkey_algorithm = 0;
+       u_int8_t rdata_digest_type = SSHFP_HASH_SHA1;
+       u_char *rdata_digest;
+       u_int rdata_digest_len;
+
+       int i;
+       int success = 0;
+
+       if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type,
+                        &rdata_digest, &rdata_digest_len, key)) {
+
+               if (generic)
+                       fprintf(f, "%s IN TYPE%d \\# %d %02x %02x ", hostname,
+                           DNS_RDATATYPE_SSHFP, 2 + rdata_digest_len,
+                           rdata_pubkey_algorithm, rdata_digest_type);
+               else
+                       fprintf(f, "%s IN SSHFP %d %d ", hostname,
+                           rdata_pubkey_algorithm, rdata_digest_type);
+
+               for (i = 0; i < rdata_digest_len; i++)
+                       fprintf(f, "%02x", rdata_digest[i]);
+               fprintf(f, "\n");
+               success = 1;
+       } else {
+               error("dns_export_rr: unsupported algorithm");
+       }
+
+       return success;
+}
+
+#endif /* DNS */
diff --git a/openssh/dns.h b/openssh/dns.h
new file mode 100644 (file)
index 0000000..ba0ea9f
--- /dev/null
@@ -0,0 +1,57 @@
+/*     $OpenBSD: dns.h,v 1.3 2003/05/14 22:56:51 jakob Exp $   */
+
+/*
+ * Copyright (c) 2003 Wesley Griffin. All rights reserved.
+ * Copyright (c) 2003 Jakob Schlyter. 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"
+
+#ifdef DNS
+#ifndef DNS_H
+#define DNS_H
+
+enum sshfp_types {
+       SSHFP_KEY_RESERVED,
+       SSHFP_KEY_RSA,
+       SSHFP_KEY_DSA
+};
+
+enum sshfp_hashes {
+       SSHFP_HASH_RESERVED,
+       SSHFP_HASH_SHA1
+};
+
+#define DNS_RDATACLASS_IN      1
+#define DNS_RDATATYPE_SSHFP    44
+
+#define DNS_VERIFY_FAILED      -1
+#define DNS_VERIFY_OK          0
+#define DNS_VERIFY_ERROR       1
+
+int    verify_host_key_dns(const char *, struct sockaddr *, Key *);
+int    export_dns_rr(const char *, Key *, FILE *, int);
+
+#endif /* DNS_H */
+#endif /* DNS */
diff --git a/openssh/mdoc2man.awk b/openssh/mdoc2man.awk
new file mode 100644 (file)
index 0000000..856e2d7
--- /dev/null
@@ -0,0 +1,340 @@
+#!/usr/bin/awk
+#
+# Version history:
+#  v3, I put the program under a proper license
+#      Dan Nelson <dnelson@allantgroup.com> added .An, .Aq and fixed a typo
+#  v2, fixed to work on GNU awk --posix and MacOS X
+#  v1, first attempt, didn't work on MacOS X
+#
+# Copyright (c) 2003 Peter Stuge <stuge-mdoc2man@cdy.org>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+
+BEGIN {
+  optlist=0
+  oldoptlist=0
+  nospace=0
+  synopsis=0
+  reference=0
+  block=0
+  ext=0
+  extopt=0
+  literal=0
+  prenl=0
+  line=""
+}
+
+function wtail() {
+  retval=""
+  while(w<nwords) {
+    if(length(retval))
+      retval=retval OFS
+    retval=retval words[++w]
+  }
+  return retval
+}
+
+function add(str) {
+  for(;prenl;prenl--)
+    line=line "\n"
+  line=line str
+}
+
+! /^\./ {
+  for(;prenl;prenl--)
+    print ""
+  print
+  if(literal)
+    print ".br"
+  next
+}
+
+/^\.\\"/ { next }
+
+{
+  option=0
+  parens=0
+  angles=0
+  sub("^\\.","")
+  nwords=split($0,words)
+  for(w=1;w<=nwords;w++) {
+    skip=0
+    if(match(words[w],"^Li|Pf$")) {
+      skip=1
+    } else if(match(words[w],"^Xo$")) {
+      skip=1
+      ext=1
+      if(length(line)&&!(match(line," $")||prenl))
+        add(OFS)
+    } else if(match(words[w],"^Xc$")) {
+      skip=1
+      ext=0
+      if(!extopt)
+        prenl++
+      w=nwords
+    } else if(match(words[w],"^Bd$")) {
+      skip=1
+      if(match(words[w+1],"-literal")) {
+        literal=1
+        prenl++
+        w=nwords
+      }
+    } else if(match(words[w],"^Ed$")) {
+      skip=1
+      literal=0
+    } else if(match(words[w],"^Ns$")) {
+      skip=1
+      if(!nospace)
+        nospace=1
+      sub(" $","",line)
+    } else if(match(words[w],"^No$")) {
+      skip=1
+      sub(" $","",line)
+      add(words[++w])
+    } else if(match(words[w],"^Dq$")) {
+      skip=1
+      add("``")
+      add(words[++w])
+      while(w<nwords&&!match(words[w+1],"^[\\.,]"))
+        add(OFS words[++w])
+      add("''")
+      if(!nospace&&match(words[w+1],"^[\\.,]"))
+        nospace=1
+    } else if(match(words[w],"^Sq|Ql$")) {
+      skip=1
+      add("`" words[++w] "'")
+      if(!nospace&&match(words[w+1],"^[\\.,]"))
+        nospace=1
+    } else if(match(words[w],"^Oo$")) {
+      skip=1
+      extopt=1
+      if(!nospace)
+        nospace=1
+      add("[")
+    } else if(match(words[w],"^Oc$")) {
+      skip=1
+      extopt=0
+      add("]")
+    }
+    if(!skip) {
+      if(!nospace&&length(line)&&!(match(line," $")||prenl))
+        add(OFS)
+      if(nospace==1)
+        nospace=0
+    }
+    if(match(words[w],"^Dd$")) {
+      date=wtail()
+      next
+    } else if(match(words[w],"^Dt$")) {
+      id=wtail()
+      next
+    } else if(match(words[w],"^Os$")) {
+      add(".TH " id " \"" date "\" \"" wtail() "\"")
+    } else if(match(words[w],"^Sh$")) {
+      add(".SH")
+      synopsis=match(words[w+1],"SYNOPSIS")
+    } else if(match(words[w],"^Xr$")) {
+      add("\\fB" words[++w] "\\fP(" words[++w] ")" words[++w])
+    } else if(match(words[w],"^Rs$")) {
+      split("",refauthors)
+      nrefauthors=0
+      reftitle=""
+      refissue=""
+      refdate=""
+      refopt=""
+      reference=1
+      next
+    } else if(match(words[w],"^Re$")) {
+      prenl++
+      for(i=nrefauthors-1;i>0;i--) {
+        add(refauthors[i])
+        if(i>1)
+          add(", ")
+      }
+      if(nrefauthors>1)
+        add(" and ")
+      add(refauthors[0] ", \\fI" reftitle "\\fP")
+      if(length(refissue))
+        add(", " refissue)
+      if(length(refdate))
+        add(", " refdate)
+      if(length(refopt))
+        add(", " refopt)
+      add(".")
+      reference=0
+    } else if(reference) {
+      if(match(words[w],"^%A$")) { refauthors[nrefauthors++]=wtail() }
+      if(match(words[w],"^%T$")) {
+        reftitle=wtail()
+        sub("^\"","",reftitle)
+        sub("\"$","",reftitle)
+      }
+      if(match(words[w],"^%N$")) { refissue=wtail() }
+      if(match(words[w],"^%D$")) { refdate=wtail() }
+      if(match(words[w],"^%O$")) { refopt=wtail() }
+    } else if(match(words[w],"^Nm$")) {
+      if(synopsis) {
+        add(".br")
+        prenl++
+      }
+      n=words[++w]
+      if(!length(name))
+        name=n
+      if(!length(n))
+        n=name
+      add("\\fB" n "\\fP")
+      if(!nospace&&match(words[w+1],"^[\\.,]"))
+        nospace=1
+    } else if(match(words[w],"^Nd$")) {
+      add("\\- " wtail())
+    } else if(match(words[w],"^Fl$")) {
+      add("\\fB\\-" words[++w] "\\fP")
+      if(!nospace&&match(words[w+1],"^[\\.,]"))
+        nospace=1
+    } else if(match(words[w],"^Ar$")) {
+      add("\\fI")
+      if(w==nwords)
+        add("file ...\\fP")
+      else {
+        add(words[++w] "\\fP")
+        while(match(words[w+1],"^\\|$"))
+          add(OFS words[++w] " \\fI" words[++w] "\\fP")
+      }
+      if(!nospace&&match(words[w+1],"^[\\.,]"))
+        nospace=1
+    } else if(match(words[w],"^Cm$")) {
+      add("\\fB" words[++w] "\\fP")
+      while(w<nwords&&match(words[w+1],"^[\\.,:;)]"))
+        add(words[++w])
+    } else if(match(words[w],"^Op$")) {
+      option=1
+      if(!nospace)
+        nospace=1
+      add("[")
+    } else if(match(words[w],"^Pp$")) {
+      prenl++
+    } else if(match(words[w],"^An$")) {
+      prenl++
+    } else if(match(words[w],"^Ss$")) {
+      add(".SS")
+    } else if(match(words[w],"^Pa$")&&!option) {
+      add("\\fI")
+      w++
+      if(match(words[w],"^\\."))
+        add("\\&")
+      add(words[w] "\\fP")
+      while(w<nwords&&match(words[w+1],"^[\\.,:;)]"))
+        add(words[++w])
+    } else if(match(words[w],"^Dv$")) {
+      add(".BR")
+    } else if(match(words[w],"^Em|Ev$")) {
+      add(".IR")
+    } else if(match(words[w],"^Pq$")) {
+      add("(")
+      nospace=1
+      parens=1
+    } else if(match(words[w],"^Aq$")) {
+      add("<")
+      nospace=1
+      angles=1
+    } else if(match(words[w],"^S[xy]$")) {
+      add(".B " wtail())
+    } else if(match(words[w],"^Ic$")) {
+      plain=1
+      add("\\fB")
+      while(w<nwords) {
+        w++
+        if(match(words[w],"^Op$")) {
+          w++
+          add("[")
+          words[nwords]=words[nwords] "]"
+        }
+        if(match(words[w],"^Ar$")) {
+          add("\\fI" words[++w] "\\fP")
+        } else if(match(words[w],"^[\\.,]")) {
+          sub(" $","",line)
+          if(plain) {
+            add("\\fP")
+            plain=0
+          }
+          add(words[w])
+        } else {
+          if(!plain) {
+            add("\\fB")
+            plain=1
+          }
+          add(words[w])
+        }
+        if(!nospace)
+          add(OFS)
+      }
+      sub(" $","",line)
+      if(plain)
+        add("\\fP")
+    } else if(match(words[w],"^Bl$")) {
+      oldoptlist=optlist
+      if(match(words[w+1],"-bullet"))
+        optlist=1
+      else if(match(words[w+1],"-enum")) {
+        optlist=2
+        enum=0
+      } else if(match(words[w+1],"-tag"))
+        optlist=3
+      else if(match(words[w+1],"-item"))
+        optlist=4
+      else if(match(words[w+1],"-bullet"))
+        optlist=1
+      w=nwords
+    } else if(match(words[w],"^El$")) {
+      optlist=oldoptlist
+    } else if(match(words[w],"^It$")&&optlist) {
+      if(optlist==1)
+        add(".IP \\(bu")
+      else if(optlist==2)
+        add(".IP " ++enum ".")
+      else if(optlist==3) {
+        add(".TP")
+        prenl++
+        if(match(words[w+1],"^Pa|Ev$")) {
+          add(".B")
+          w++
+        }
+      } else if(optlist==4)
+        add(".IP")
+    } else if(match(words[w],"^Sm$")) {
+      if(match(words[w+1],"off"))
+        nospace=2
+      else if(match(words[w+1],"on"))
+        nospace=0
+      w++
+    } else if(!skip) {
+      add(words[w])
+    }
+  }
+  if(match(line,"^\\.[^a-zA-Z]"))
+    sub("^\\.","",line)
+  if(parens)
+    add(")")
+  if(angles)
+    add(">")
+  if(option)
+    add("]")
+  if(ext&&!extopt&&!match(line," $"))
+    add(OFS)
+  if(!ext&&!extopt&&length(line)) {
+    print line
+    prenl=0
+    line=""
+  }
+}
diff --git a/openssh/moduli.c b/openssh/moduli.c
new file mode 100644 (file)
index 0000000..eb2c0fd
--- /dev/null
@@ -0,0 +1,617 @@
+/* $OpenBSD: moduli.c,v 1.1 2003/07/28 09:49:56 djm Exp $ */
+/*
+ * Copyright 1994 Phil Karn <karn@qualcomm.com>
+ * Copyright 1996-1998, 2003 William Allen Simpson <wsimpson@greendragon.com>
+ * Copyright 2000 Niels Provos <provos@citi.umich.edu>
+ * 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.
+ */
+
+/*
+ * Two-step process to generate safe primes for DHGEX
+ *
+ *  Sieve candidates for "safe" primes,
+ *  suitable for use as Diffie-Hellman moduli;
+ *  that is, where q = (p-1)/2 is also prime.
+ *
+ * First step: generate candidate primes (memory intensive)
+ * Second step: test primes' safety (processor intensive)
+ */
+
+#include "includes.h"
+#include "moduli.h"
+#include "xmalloc.h"
+#include "log.h"
+
+#include <openssl/bn.h>
+
+
+/*
+ * Debugging defines 
+ */
+
+/* define DEBUG_LARGE 1 */
+/* define DEBUG_SMALL 1 */
+/* define DEBUG_TEST  1 */
+
+/*
+ * File output defines
+ */
+
+/* need line long enough for largest moduli plus headers */
+#define QLINESIZE               (100+8192)
+
+/* Type: decimal.
+ * Specifies the internal structure of the prime modulus.
+ */
+#define QTYPE_UNKNOWN           (0)
+#define QTYPE_UNSTRUCTURED      (1)
+#define QTYPE_SAFE              (2)
+#define QTYPE_SCHNOOR           (3)
+#define QTYPE_SOPHIE_GERMAINE   (4)
+#define QTYPE_STRONG            (5)
+
+/* Tests: decimal (bit field).
+ * Specifies the methods used in checking for primality.
+ * Usually, more than one test is used.
+ */
+#define QTEST_UNTESTED          (0x00)
+#define QTEST_COMPOSITE         (0x01)
+#define QTEST_SIEVE             (0x02)
+#define QTEST_MILLER_RABIN      (0x04)
+#define QTEST_JACOBI            (0x08)
+#define QTEST_ELLIPTIC          (0x10)
+
+/* Size: decimal.
+ * Specifies the number of the most significant bit (0 to M).
+ ** WARNING: internally, usually 1 to N.
+ */
+#define QSIZE_MINIMUM           (511)
+
+/*
+ * Prime sieving defines
+ */
+
+/* Constant: assuming 8 bit bytes and 32 bit words */
+#define SHIFT_BIT       (3)
+#define SHIFT_BYTE      (2)
+#define SHIFT_WORD      (SHIFT_BIT+SHIFT_BYTE)
+#define SHIFT_MEGABYTE  (20)
+#define SHIFT_MEGAWORD  (SHIFT_MEGABYTE-SHIFT_BYTE)
+
+/*
+ * Constant: when used with 32-bit integers, the largest sieve prime
+ * has to be less than 2**32.
+ */
+#define SMALL_MAXIMUM   (0xffffffffUL)
+
+/* Constant: can sieve all primes less than 2**32, as 65537**2 > 2**32-1. */
+#define TINY_NUMBER     (1UL<<16)
+
+/* Ensure enough bit space for testing 2*q. */
+#define TEST_MAXIMUM    (1UL<<16)
+#define TEST_MINIMUM    (QSIZE_MINIMUM + 1)
+/* real TEST_MINIMUM    (1UL << (SHIFT_WORD - TEST_POWER)) */
+#define TEST_POWER      (3)    /* 2**n, n < SHIFT_WORD */
+
+/* bit operations on 32-bit words */
+#define BIT_CLEAR(a,n)  ((a)[(n)>>SHIFT_WORD] &= ~(1L << ((n) & 31)))
+#define BIT_SET(a,n)    ((a)[(n)>>SHIFT_WORD] |= (1L << ((n) & 31)))
+#define BIT_TEST(a,n)   ((a)[(n)>>SHIFT_WORD] & (1L << ((n) & 31)))
+
+/*
+ * Prime testing defines
+ */
+
+/*
+ * Sieving data (XXX - move to struct)
+ */
+
+/* sieve 2**16 */
+static u_int32_t *TinySieve, tinybits;
+
+/* sieve 2**30 in 2**16 parts */
+static u_int32_t *SmallSieve, smallbits, smallbase;
+
+/* sieve relative to the initial value */
+static u_int32_t *LargeSieve, largewords, largetries, largenumbers;
+static u_int32_t largebits, largememory;       /* megabytes */
+static BIGNUM *largebase;
+
+
+/*
+ * print moduli out in consistent form,
+ */
+static int
+qfileout(FILE * ofile, u_int32_t otype, u_int32_t otests, u_int32_t otries,
+    u_int32_t osize, u_int32_t ogenerator, BIGNUM * omodulus)
+{
+       struct tm *gtm;
+       time_t time_now;
+       int res;
+
+       time(&time_now);
+       gtm = gmtime(&time_now);
+       
+       res = fprintf(ofile, "%04d%02d%02d%02d%02d%02d %u %u %u %u %x ",
+           gtm->tm_year + 1900, gtm->tm_mon + 1, gtm->tm_mday,
+           gtm->tm_hour, gtm->tm_min, gtm->tm_sec,
+           otype, otests, otries, osize, ogenerator);
+
+       if (res < 0)
+               return (-1);
+
+       if (BN_print_fp(ofile, omodulus) < 1)
+               return (-1);
+
+       res = fprintf(ofile, "\n");
+       fflush(ofile);
+
+       return (res > 0 ? 0 : -1);
+}
+
+
+/*
+ ** Sieve p's and q's with small factors
+ */
+static void
+sieve_large(u_int32_t s)
+{
+       u_int32_t r, u;
+
+       debug2("sieve_large %u", s);
+       largetries++;
+       /* r = largebase mod s */
+       r = BN_mod_word(largebase, s);
+       if (r == 0)
+               u = 0; /* s divides into largebase exactly */
+       else
+               u = s - r; /* largebase+u is first entry divisible by s */
+
+       if (u < largebits * 2) {
+               /*
+                * The sieve omits p's and q's divisible by 2, so ensure that
+                * largebase+u is odd. Then, step through the sieve in
+                * increments of 2*s
+                */
+               if (u & 0x1)
+                       u += s; /* Make largebase+u odd, and u even */
+
+               /* Mark all multiples of 2*s */
+               for (u /= 2; u < largebits; u += s)
+                       BIT_SET(LargeSieve, u);
+       }
+
+       /* r = p mod s */
+       r = (2 * r + 1) % s;
+       if (r == 0)
+               u = 0; /* s divides p exactly */
+       else
+               u = s - r; /* p+u is first entry divisible by s */
+
+       if (u < largebits * 4) {
+               /*
+                * The sieve omits p's divisible by 4, so ensure that
+                * largebase+u is not. Then, step through the sieve in
+                * increments of 4*s
+                */
+               while (u & 0x3) {
+                       if (SMALL_MAXIMUM - u < s)
+                               return;
+                       u += s;
+               }
+
+               /* Mark all multiples of 4*s */
+               for (u /= 4; u < largebits; u += s)
+                       BIT_SET(LargeSieve, u);
+       }
+}
+
+/*
+ * list candidates for Sophie-Germaine primes (where q = (p-1)/2)
+ * to standard output.
+ * The list is checked against small known primes (less than 2**30).
+ */
+int
+gen_candidates(FILE *out, int memory, int power, BIGNUM *start)
+{
+       BIGNUM *q;
+       u_int32_t j, r, s, t;
+       u_int32_t smallwords = TINY_NUMBER >> 6;
+       u_int32_t tinywords = TINY_NUMBER >> 6;
+       time_t time_start, time_stop;
+       int i, ret = 0;
+
+       largememory = memory;
+
+       /*
+         * Set power to the length in bits of the prime to be generated.
+         * This is changed to 1 less than the desired safe prime moduli p.
+         */
+       if (power > TEST_MAXIMUM) {
+               error("Too many bits: %u > %lu", power, TEST_MAXIMUM);
+               return (-1);
+       } else if (power < TEST_MINIMUM) {
+               error("Too few bits: %u < %u", power, TEST_MINIMUM);
+               return (-1);
+       }
+       power--; /* decrement before squaring */
+
+       /*
+         * The density of ordinary primes is on the order of 1/bits, so the
+         * density of safe primes should be about (1/bits)**2. Set test range
+         * to something well above bits**2 to be reasonably sure (but not
+         * guaranteed) of catching at least one safe prime.
+        */
+       largewords = ((power * power) >> (SHIFT_WORD - TEST_POWER));
+
+       /*
+         * Need idea of how much memory is available. We don't have to use all
+         * of it.
+        */
+       if (largememory > LARGE_MAXIMUM) {
+               logit("Limited memory: %u MB; limit %lu MB",
+                   largememory, LARGE_MAXIMUM);
+               largememory = LARGE_MAXIMUM;
+       }
+
+       if (largewords <= (largememory << SHIFT_MEGAWORD)) {
+               logit("Increased memory: %u MB; need %u bytes",
+                   largememory, (largewords << SHIFT_BYTE));
+               largewords = (largememory << SHIFT_MEGAWORD);
+       } else if (largememory > 0) {
+               logit("Decreased memory: %u MB; want %u bytes",
+                   largememory, (largewords << SHIFT_BYTE));
+               largewords = (largememory << SHIFT_MEGAWORD);
+       }
+
+       TinySieve = calloc(tinywords, sizeof(u_int32_t));
+       if (TinySieve == NULL) {
+               error("Insufficient memory for tiny sieve: need %u bytes",
+                   tinywords << SHIFT_BYTE);
+               exit(1);
+       }
+       tinybits = tinywords << SHIFT_WORD;
+
+       SmallSieve = calloc(smallwords, sizeof(u_int32_t));
+       if (SmallSieve == NULL) {
+               error("Insufficient memory for small sieve: need %u bytes",
+                   smallwords << SHIFT_BYTE);
+               xfree(TinySieve);
+               exit(1);
+       }
+       smallbits = smallwords << SHIFT_WORD;
+
+       /*
+        * dynamically determine available memory
+        */
+       while ((LargeSieve = calloc(largewords, sizeof(u_int32_t))) == NULL)
+               largewords -= (1L << (SHIFT_MEGAWORD - 2)); /* 1/4 MB chunks */
+
+       largebits = largewords << SHIFT_WORD;
+       largenumbers = largebits * 2;   /* even numbers excluded */
+
+       /* validation check: count the number of primes tried */
+       largetries = 0;
+       q = BN_new();
+
+       /*
+         * Generate random starting point for subprime search, or use
+         * specified parameter.
+        */
+       largebase = BN_new();
+       if (start == NULL)
+               BN_rand(largebase, power, 1, 1);
+       else
+               BN_copy(largebase, start);
+
+       /* ensure odd */
+       BN_set_bit(largebase, 0);
+
+       time(&time_start);
+
+       logit("%.24s Sieve next %u plus %u-bit", ctime(&time_start), 
+           largenumbers, power);
+       debug2("start point: 0x%s", BN_bn2hex(largebase));
+
+       /*
+         * TinySieve
+         */
+       for (i = 0; i < tinybits; i++) {
+               if (BIT_TEST(TinySieve, i))
+                       continue; /* 2*i+3 is composite */
+
+               /* The next tiny prime */
+               t = 2 * i + 3;
+
+               /* Mark all multiples of t */
+               for (j = i + t; j < tinybits; j += t)
+                       BIT_SET(TinySieve, j);
+
+               sieve_large(t);
+       }
+
+       /*
+         * Start the small block search at the next possible prime. To avoid
+         * fencepost errors, the last pass is skipped.
+         */
+       for (smallbase = TINY_NUMBER + 3;
+            smallbase < (SMALL_MAXIMUM - TINY_NUMBER);
+            smallbase += TINY_NUMBER) {
+               for (i = 0; i < tinybits; i++) {
+                       if (BIT_TEST(TinySieve, i))
+                               continue; /* 2*i+3 is composite */
+
+                       /* The next tiny prime */
+                       t = 2 * i + 3;
+                       r = smallbase % t;
+
+                       if (r == 0) {
+                               s = 0; /* t divides into smallbase exactly */
+                       } else {
+                               /* smallbase+s is first entry divisible by t */
+                               s = t - r;
+                       }
+
+                       /*
+                        * The sieve omits even numbers, so ensure that
+                        * smallbase+s is odd. Then, step through the sieve
+                        * in increments of 2*t
+                        */
+                       if (s & 1)
+                               s += t; /* Make smallbase+s odd, and s even */
+
+                       /* Mark all multiples of 2*t */
+                       for (s /= 2; s < smallbits; s += t)
+                               BIT_SET(SmallSieve, s);
+               }
+
+               /*
+                 * SmallSieve
+                 */
+               for (i = 0; i < smallbits; i++) {
+                       if (BIT_TEST(SmallSieve, i))
+                               continue; /* 2*i+smallbase is composite */
+
+                       /* The next small prime */
+                       sieve_large((2 * i) + smallbase);
+               }
+
+               memset(SmallSieve, 0, smallwords << SHIFT_BYTE);
+       }
+
+       time(&time_stop);
+
+       logit("%.24s Sieved with %u small primes in %ld seconds",
+           ctime(&time_stop), largetries, (long) (time_stop - time_start));
+
+       for (j = r = 0; j < largebits; j++) {
+               if (BIT_TEST(LargeSieve, j))
+                       continue; /* Definitely composite, skip */
+
+               debug2("test q = largebase+%u", 2 * j);
+               BN_set_word(q, 2 * j);
+               BN_add(q, q, largebase);
+               if (qfileout(out, QTYPE_SOPHIE_GERMAINE, QTEST_SIEVE,
+                   largetries, (power - 1) /* MSB */, (0), q) == -1) {
+                       ret = -1;
+                       break;
+               }
+
+               r++; /* count q */
+       }
+
+       time(&time_stop);
+
+       xfree(LargeSieve);
+       xfree(SmallSieve);
+       xfree(TinySieve);
+
+       logit("%.24s Found %u candidates", ctime(&time_stop), r);
+
+       return (ret);
+}
+
+/*
+ * perform a Miller-Rabin primality test
+ * on the list of candidates
+ * (checking both q and p)
+ * The result is a list of so-call "safe" primes
+ */
+int
+prime_test(FILE *in, FILE *out, u_int32_t trials, 
+    u_int32_t generator_wanted)
+{
+       BIGNUM *q, *p, *a;
+       BN_CTX *ctx;
+       char *cp, *lp;
+       u_int32_t count_in = 0, count_out = 0, count_possible = 0;
+       u_int32_t generator_known, in_tests, in_tries, in_type, in_size;
+       time_t time_start, time_stop;
+       int res;
+
+       time(&time_start);
+
+       p = BN_new();
+       q = BN_new();
+       ctx = BN_CTX_new();
+
+       debug2("%.24s Final %u Miller-Rabin trials (%x generator)",
+           ctime(&time_start), trials, generator_wanted);
+
+       res = 0;
+       lp = xmalloc(QLINESIZE + 1);
+       while (fgets(lp, QLINESIZE, in) != NULL) {
+               int ll = strlen(lp);
+
+               count_in++;
+               if (ll < 14 || *lp == '!' || *lp == '#') {
+                       debug2("%10u: comment or short line", count_in);
+                       continue;
+               }
+
+               /* XXX - fragile parser */
+               /* time */
+               cp = &lp[14];   /* (skip) */
+
+               /* type */
+               in_type = strtoul(cp, &cp, 10);
+
+               /* tests */
+               in_tests = strtoul(cp, &cp, 10);
+
+               if (in_tests & QTEST_COMPOSITE) {
+                       debug2("%10u: known composite", count_in);
+                       continue;
+               }
+               /* tries */
+               in_tries = strtoul(cp, &cp, 10);
+
+               /* size (most significant bit) */
+               in_size = strtoul(cp, &cp, 10);
+
+               /* generator (hex) */
+               generator_known = strtoul(cp, &cp, 16);
+
+               /* Skip white space */
+               cp += strspn(cp, " ");
+
+               /* modulus (hex) */
+               switch (in_type) {
+               case QTYPE_SOPHIE_GERMAINE:
+                       debug2("%10u: (%u) Sophie-Germaine", count_in, in_type);
+                       a = q;
+                       BN_hex2bn(&a, cp);
+                       /* p = 2*q + 1 */
+                       BN_lshift(p, q, 1);
+                       BN_add_word(p, 1);
+                       in_size += 1;
+                       generator_known = 0;
+                       break;
+               default:
+                       debug2("%10u: (%u)", count_in, in_type);
+                       a = p;
+                       BN_hex2bn(&a, cp);
+                       /* q = (p-1) / 2 */
+                       BN_rshift(q, p, 1);
+                       break;
+               }
+
+               /*
+                * due to earlier inconsistencies in interpretation, check
+                * the proposed bit size.
+                */
+               if (BN_num_bits(p) != (in_size + 1)) {
+                       debug2("%10u: bit size %u mismatch", count_in, in_size);
+                       continue;
+               }
+               if (in_size < QSIZE_MINIMUM) {
+                       debug2("%10u: bit size %u too short", count_in, in_size);
+                       continue;
+               }
+
+               if (in_tests & QTEST_MILLER_RABIN)
+                       in_tries += trials;
+               else
+                       in_tries = trials;
+               /*
+                * guess unknown generator
+                */
+               if (generator_known == 0) {
+                       if (BN_mod_word(p, 24) == 11)
+                               generator_known = 2;
+                       else if (BN_mod_word(p, 12) == 5)
+                               generator_known = 3;
+                       else {
+                               u_int32_t r = BN_mod_word(p, 10);
+
+                               if (r == 3 || r == 7) {
+                                       generator_known = 5;
+                               }
+                       }
+               }
+               /*
+                * skip tests when desired generator doesn't match
+                */
+               if (generator_wanted > 0 &&
+                   generator_wanted != generator_known) {
+                       debug2("%10u: generator %d != %d",
+                           count_in, generator_known, generator_wanted);
+                       continue;
+               }
+
+               count_possible++;
+
+               /*
+                * The (1/4)^N performance bound on Miller-Rabin is 
+                * extremely pessimistic, so don't spend a lot of time 
+                * really verifying that q is prime until after we know 
+                * that p is also prime. A single pass will weed out the 
+                * vast majority of composite q's.
+                */
+               if (BN_is_prime(q, 1, NULL, ctx, NULL) <= 0) {
+                       debug2("%10u: q failed first possible prime test",
+                           count_in);
+                       continue;
+               }
+       
+               /*
+                * q is possibly prime, so go ahead and really make sure 
+                * that p is prime. If it is, then we can go back and do 
+                * the same for q. If p is composite, chances are that 
+                * will show up on the first Rabin-Miller iteration so it
+                * doesn't hurt to specify a high iteration count.
+                */
+               if (!BN_is_prime(p, trials, NULL, ctx, NULL)) {
+                       debug2("%10u: p is not prime", count_in);
+                       continue;
+               }
+               debug("%10u: p is almost certainly prime", count_in);
+
+               /* recheck q more rigorously */
+               if (!BN_is_prime(q, trials - 1, NULL, ctx, NULL)) {
+                       debug("%10u: q is not prime", count_in);
+                       continue;
+               }
+               debug("%10u: q is almost certainly prime", count_in);
+
+               if (qfileout(out, QTYPE_SAFE, (in_tests | QTEST_MILLER_RABIN), 
+                   in_tries, in_size, generator_known, p)) {
+                       res = -1;
+                       break;
+               }
+
+               count_out++;
+       }
+
+       time(&time_stop);
+       xfree(lp);
+       BN_free(p);
+       BN_free(q);
+       BN_CTX_free(ctx);
+
+       logit("%.24s Found %u safe primes of %u candidates in %ld seconds",
+           ctime(&time_stop), count_out, count_possible, 
+           (long) (time_stop - time_start));
+
+       return (res);
+}
diff --git a/openssh/moduli.h b/openssh/moduli.h
new file mode 100644 (file)
index 0000000..9cd1cd3
--- /dev/null
@@ -0,0 +1,23 @@
+/* $OpenBSD: moduli.h,v 1.1 2003/07/28 09:49:56 djm Exp $ */
+
+#include <sys/types.h>
+#include <openssl/bn.h>
+
+/*
+ * Using virtual memory can cause thrashing.  This should be the largest
+ * number that is supported without a large amount of disk activity --
+ * that would increase the run time from hours to days or weeks!
+ */
+#define LARGE_MINIMUM   (8UL)  /* megabytes */
+
+/*
+ * Do not increase this number beyond the unsigned integer bit size.
+ * Due to a multiple of 4, it must be LESS than 128 (yielding 2**30 bits).
+ */
+#define LARGE_MAXIMUM   (127UL)        /* megabytes */
+
+/* Minimum number of primality tests to perform */
+#define TRIAL_MINIMUM           (4)
+
+int gen_candidates(FILE *, int, int, BIGNUM *);
+int prime_test(FILE *, FILE *, u_int32_t, u_int32_t);
diff --git a/openssh/openbsd-compat/fake-rfc2553.c b/openssh/openbsd-compat/fake-rfc2553.c
new file mode 100644 (file)
index 0000000..b9ac085
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2000-2003 Damien Miller.  All rights reserved.
+ * Copyright (C) 1999 WIDE Project.  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.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``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 PROJECT OR CONTRIBUTORS 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.
+ */
+
+/*
+ * Pseudo-implementation of RFC2553 name / address resolution functions
+ *
+ * But these functions are not implemented correctly. The minimum subset
+ * is implemented for ssh use only. For example, this routine assumes
+ * that ai_family is AF_INET. Don't use it for another purpose.
+ */
+
+#include "includes.h"
+
+RCSID("$Id$");
+
+#ifndef HAVE_GETNAMEINFO
+int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, 
+                size_t hostlen, char *serv, size_t servlen, int flags)
+{
+       struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+       struct hostent *hp;
+       char tmpserv[16];
+
+       if (serv != NULL) {
+               snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port));
+               if (strlcpy(serv, tmpserv, servlen) >= servlen)
+                       return (EAI_MEMORY);
+       }
+
+       if (host != NULL) {
+               if (flags & NI_NUMERICHOST) {
+                       if (strlcpy(host, inet_ntoa(sin->sin_addr),
+                           hostlen) >= hostlen)
+                               return (EAI_MEMORY);
+                       else
+                               return (0);
+               } else {
+                       hp = gethostbyaddr((char *)&sin->sin_addr, 
+                           sizeof(struct in_addr), AF_INET);
+                       if (hp == NULL)
+                               return (EAI_NODATA);
+                       
+                       if (strlcpy(host, hp->h_name, hostlen) >= hostlen)
+                               return (EAI_MEMORY);
+                       else
+                               return (0);
+               }
+       }
+       return (0);
+}
+#endif /* !HAVE_GETNAMEINFO */
+
+#ifndef HAVE_GAI_STRERROR
+char *
+gai_strerror(int err)
+{
+       switch (err) {
+       case EAI_NODATA:
+               return ("no address associated with name");
+       case EAI_MEMORY:
+               return ("memory allocation failure.");
+       case EAI_NONAME:
+               return ("nodename nor servname provided, or not known");
+       default:
+               return ("unknown/invalid error.");
+       }
+}    
+#endif /* !HAVE_GAI_STRERROR */
+
+#ifndef HAVE_FREEADDRINFO
+void
+freeaddrinfo(struct addrinfo *ai)
+{
+       struct addrinfo *next;
+
+       for(; ai != NULL;) {
+               next = ai->ai_next;
+               free(ai);
+               ai = next;
+       }
+}
+#endif /* !HAVE_FREEADDRINFO */
+
+#ifndef HAVE_GETADDRINFO
+static struct
+addrinfo *malloc_ai(int port, u_long addr, const struct addrinfo *hints)
+{
+       struct addrinfo *ai;
+
+       ai = malloc(sizeof(*ai) + sizeof(struct sockaddr_in));
+       if (ai == NULL)
+               return (NULL);
+       
+       memset(ai, '\0', sizeof(*ai) + sizeof(struct sockaddr_in));
+       
+       ai->ai_addr = (struct sockaddr *)(ai + 1);
+       /* XXX -- ssh doesn't use sa_len */
+       ai->ai_addrlen = sizeof(struct sockaddr_in);
+       ai->ai_addr->sa_family = ai->ai_family = AF_INET;
+
+       ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
+       ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
+       
+       /* XXX: the following is not generally correct, but does what we want */
+       if (hints->ai_socktype)
+               ai->ai_socktype = hints->ai_socktype;
+       else
+               ai->ai_socktype = SOCK_STREAM;
+
+       if (hints->ai_protocol)
+               ai->ai_protocol = hints->ai_protocol;
+
+       return (ai);
+}
+
+int
+getaddrinfo(const char *hostname, const char *servname, 
+    const struct addrinfo *hints, struct addrinfo **res)
+{
+       struct hostent *hp;
+       struct servent *sp;
+       struct in_addr in;
+       int i;
+       long int port;
+       u_long addr;
+
+       port = 0;
+       if (servname != NULL) {
+               char *cp;
+
+               port = strtol(servname, &cp, 10);
+               if (port > 0 && port <= 65535 && *cp == '\0')
+                       port = htons(port);
+               else if ((sp = getservbyname(servname, NULL)) != NULL)
+                       port = sp->s_port;
+               else
+                       port = 0;
+       }
+
+       if (hints && hints->ai_flags & AI_PASSIVE) {
+               addr = htonl(0x00000000);
+               if (hostname && inet_aton(hostname, &in) != 0)
+                       addr = in.s_addr;
+               *res = malloc_ai(port, addr, hints);
+               if (*res == NULL) 
+                       return (EAI_MEMORY);
+               return (0);
+       }
+               
+       if (!hostname) {
+               *res = malloc_ai(port, htonl(0x7f000001), hints);
+               if (*res == NULL) 
+                       return (EAI_MEMORY);
+               return (0);
+       }
+       
+       if (inet_aton(hostname, &in)) {
+               *res = malloc_ai(port, in.s_addr, hints);
+               if (*res == NULL) 
+                       return (EAI_MEMORY);
+               return (0);
+       }
+       
+       /* Don't try DNS if AI_NUMERICHOST is set */
+       if (hints && hints->ai_flags & AI_NUMERICHOST)
+               return (EAI_NONAME);
+       
+       hp = gethostbyname(hostname);
+       if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
+               struct addrinfo *cur, *prev;
+
+               cur = prev = *res = NULL;
+               for (i = 0; hp->h_addr_list[i]; i++) {
+                       struct in_addr *in = (struct in_addr *)hp->h_addr_list[i];
+
+                       cur = malloc_ai(port, in->s_addr, hints);
+                       if (cur == NULL) {
+                               if (*res != NULL)
+                                       freeaddrinfo(*res);
+                               return (EAI_MEMORY);
+                       }
+                       if (prev)
+                               prev->ai_next = cur;
+                       else
+                               *res = cur;
+
+                       prev = cur;
+               }
+               return (0);
+       }
+       
+       return (EAI_NODATA);
+}
+#endif /* !HAVE_GETADDRINFO */
diff --git a/openssh/openbsd-compat/fake-rfc2553.h b/openssh/openbsd-compat/fake-rfc2553.h
new file mode 100644 (file)
index 0000000..1ebabf9
--- /dev/null
@@ -0,0 +1,154 @@
+/* $Id$ */
+
+/*
+ * Copyright (C) 2000-2003 Damien Miller.  All rights reserved.
+ * Copyright (C) 1999 WIDE Project.  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.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``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 PROJECT OR CONTRIBUTORS 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.
+ */
+
+/*
+ * Pseudo-implementation of RFC2553 name / address resolution functions
+ *
+ * But these functions are not implemented correctly. The minimum subset
+ * is implemented for ssh use only. For example, this routine assumes
+ * that ai_family is AF_INET. Don't use it for another purpose.
+ */
+
+#ifndef _FAKE_RFC2553_H
+#define _FAKE_RFC2553_H
+
+#include "includes.h"
+#include "sys/types.h"
+
+/*
+ * First, socket and INET6 related definitions 
+ */
+#ifndef HAVE_STRUCT_SOCKADDR_STORAGE
+# define       _SS_MAXSIZE     128     /* Implementation specific max size */
+# define       _SS_PADSIZE     (_SS_MAXSIZE - sizeof (struct sockaddr))
+struct sockaddr_storage {
+       struct sockaddr ss_sa;
+       char            __ss_pad2[_SS_PADSIZE];
+};
+# define ss_family ss_sa.sa_family
+#endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */
+
+#ifndef IN6_IS_ADDR_LOOPBACK
+# define IN6_IS_ADDR_LOOPBACK(a) \
+       (((u_int32_t *)(a))[0] == 0 && ((u_int32_t *)(a))[1] == 0 && \
+        ((u_int32_t *)(a))[2] == 0 && ((u_int32_t *)(a))[3] == htonl(1))
+#endif /* !IN6_IS_ADDR_LOOPBACK */
+
+#ifndef HAVE_STRUCT_IN6_ADDR
+struct in6_addr {
+       u_int8_t        s6_addr[16];
+};
+#endif /* !HAVE_STRUCT_IN6_ADDR */
+
+#ifndef HAVE_STRUCT_SOCKADDR_IN6
+struct sockaddr_in6 {
+       unsigned short  sin6_family;
+       u_int16_t       sin6_port;
+       u_int32_t       sin6_flowinfo;
+       struct in6_addr sin6_addr;
+};
+#endif /* !HAVE_STRUCT_SOCKADDR_IN6 */
+
+#ifndef AF_INET6
+/* Define it to something that should never appear */
+#define AF_INET6 AF_MAX
+#endif
+
+/*
+ * Next, RFC2553 name / address resolution API
+ */
+
+#ifndef NI_NUMERICHOST
+# define NI_NUMERICHOST    (1)
+#endif
+#ifndef NI_NAMEREQD
+# define NI_NAMEREQD       (1<<1)
+#endif
+#ifndef NI_NUMERICSERV
+# define NI_NUMERICSERV    (1<<2)
+#endif
+
+#ifndef AI_PASSIVE
+# define AI_PASSIVE            (1)
+#endif
+#ifndef AI_CANONNAME
+# define AI_CANONNAME          (1<<1)
+#endif
+#ifndef AI_NUMERICHOST
+# define AI_NUMERICHOST                (1<<2)
+#endif
+
+#ifndef NI_MAXSERV
+# define NI_MAXSERV 32
+#endif /* !NI_MAXSERV */
+#ifndef NI_MAXHOST
+# define NI_MAXHOST 1025
+#endif /* !NI_MAXHOST */
+
+#ifndef EAI_NODATA
+# define EAI_NODATA    1
+# define EAI_MEMORY    2
+# define EAI_NONAME    3
+#endif
+
+#ifndef HAVE_STRUCT_ADDRINFO
+struct addrinfo {
+       int     ai_flags;       /* AI_PASSIVE, AI_CANONNAME */
+       int     ai_family;      /* PF_xxx */
+       int     ai_socktype;    /* SOCK_xxx */
+       int     ai_protocol;    /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+       size_t  ai_addrlen;     /* length of ai_addr */
+       char    *ai_canonname;  /* canonical name for hostname */
+       struct sockaddr *ai_addr;       /* binary address */
+       struct addrinfo *ai_next;       /* next structure in linked list */
+};
+#endif /* !HAVE_STRUCT_ADDRINFO */
+
+#ifndef HAVE_GETADDRINFO
+int getaddrinfo(const char *, const char *, 
+    const struct addrinfo *, struct addrinfo **);
+#endif /* !HAVE_GETADDRINFO */
+
+#ifndef HAVE_GAI_STRERROR
+char *gai_strerror(int);
+#endif /* !HAVE_GAI_STRERROR */
+
+#ifndef HAVE_FREEADDRINFO
+void freeaddrinfo(struct addrinfo *);
+#endif /* !HAVE_FREEADDRINFO */
+
+#ifndef HAVE_GETNAMEINFO
+int getnameinfo(const struct sockaddr *, size_t, char *, size_t, 
+    char *, size_t, int);
+#endif /* !HAVE_GETNAMEINFO */
+
+#endif /* !_FAKE_RFC2553_H */
+
diff --git a/openssh/openbsd-compat/getrrsetbyname.c b/openssh/openbsd-compat/getrrsetbyname.c
new file mode 100644 (file)
index 0000000..44fa275
--- /dev/null
@@ -0,0 +1,578 @@
+/* $OpenBSD: getrrsetbyname.c,v 1.7 2003/03/07 07:34:14 itojun Exp $ */
+
+/*
+ * Copyright (c) 2001 Jakob Schlyter. 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.
+ */
+
+/*
+ * Portions Copyright (c) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "includes.h"
+
+#if defined(DNS) && !defined(HAVE_GETRRSETBYNAME)
+
+#include "getrrsetbyname.h"
+
+/* #include "thread_private.h" */
+
+#define ANSWER_BUFFER_SIZE 1024*64
+
+struct dns_query {
+       char                    *name;
+       u_int16_t               type;
+       u_int16_t               class;
+       struct dns_query        *next;
+};
+
+struct dns_rr {
+       char                    *name;
+       u_int16_t               type;
+       u_int16_t               class;
+       u_int16_t               ttl;
+       u_int16_t               size;
+       void                    *rdata;
+       struct dns_rr           *next;
+};
+
+struct dns_response {
+       HEADER                  header;
+       struct dns_query        *query;
+       struct dns_rr           *answer;
+       struct dns_rr           *authority;
+       struct dns_rr           *additional;
+};
+
+static struct dns_response *parse_dns_response(const u_char *, int);
+static struct dns_query *parse_dns_qsection(const u_char *, int,
+    const u_char **, int);
+static struct dns_rr *parse_dns_rrsection(const u_char *, int, const u_char **,
+    int);
+
+static void free_dns_query(struct dns_query *);
+static void free_dns_rr(struct dns_rr *);
+static void free_dns_response(struct dns_response *);
+
+static int count_dns_rr(struct dns_rr *, u_int16_t, u_int16_t);
+
+/*
+ * Inline versions of get/put short/long.  Pointer is advanced.
+ *
+ * These macros demonstrate the property of C whereby it can be
+ * portable or it can be elegant but rarely both.
+ */
+
+#ifndef INT32SZ
+# define INT32SZ       4
+#endif
+#ifndef INT16SZ
+# define INT16SZ       2
+#endif
+
+#ifndef GETSHORT
+#define GETSHORT(s, cp) { \
+       register u_char *t_cp = (u_char *)(cp); \
+       (s) = ((u_int16_t)t_cp[0] << 8) \
+           | ((u_int16_t)t_cp[1]) \
+           ; \
+       (cp) += INT16SZ; \
+}
+#endif
+
+#ifndef GETLONG
+#define GETLONG(l, cp) { \
+       register u_char *t_cp = (u_char *)(cp); \
+       (l) = ((u_int32_t)t_cp[0] << 24) \
+           | ((u_int32_t)t_cp[1] << 16) \
+           | ((u_int32_t)t_cp[2] << 8) \
+           | ((u_int32_t)t_cp[3]) \
+           ; \
+       (cp) += INT32SZ; \
+}
+#endif
+
+/*
+ * Routines to insert/extract short/long's.
+ */
+
+#ifndef HAVE__GETSHORT
+static u_int16_t
+_getshort(msgp)
+       register const u_char *msgp;
+{
+       register u_int16_t u;
+
+       GETSHORT(u, msgp);
+       return (u);
+}
+#endif
+
+#ifndef HAVE__GETLONG
+static u_int32_t
+_getlong(msgp)
+       register const u_char *msgp;
+{
+       register u_int32_t u;
+
+       GETLONG(u, msgp);
+       return (u);
+}
+#endif
+
+int
+getrrsetbyname(const char *hostname, unsigned int rdclass,
+    unsigned int rdtype, unsigned int flags,
+    struct rrsetinfo **res)
+{
+       struct __res_state *_resp = &_res;
+       int result;
+       struct rrsetinfo *rrset = NULL;
+       struct dns_response *response;
+       struct dns_rr *rr;
+       struct rdatainfo *rdata;
+       int length;
+       unsigned int index_ans, index_sig;
+       u_char answer[ANSWER_BUFFER_SIZE];
+
+       /* check for invalid class and type */
+       if (rdclass > 0xffff || rdtype > 0xffff) {
+               result = ERRSET_INVAL;
+               goto fail;
+       }
+
+       /* don't allow queries of class or type ANY */
+       if (rdclass == 0xff || rdtype == 0xff) {
+               result = ERRSET_INVAL;
+               goto fail;
+       }
+
+       /* don't allow flags yet, unimplemented */
+       if (flags) {
+               result = ERRSET_INVAL;
+               goto fail;
+       }
+
+       /* initialize resolver */
+       if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
+               result = ERRSET_FAIL;
+               goto fail;
+       }
+
+#ifdef DEBUG
+       _resp->options |= RES_DEBUG;
+#endif /* DEBUG */
+
+#ifdef RES_USE_DNSSEC
+       /* turn on DNSSEC if EDNS0 is configured */
+       if (_resp->options & RES_USE_EDNS0)
+               _resp->options |= RES_USE_DNSSEC;
+#endif /* RES_USE_DNSEC */
+
+       /* make query */
+       length = res_query(hostname, (signed int) rdclass, (signed int) rdtype,
+           answer, sizeof(answer));
+       if (length < 0) {
+               switch(h_errno) {
+               case HOST_NOT_FOUND:
+                       result = ERRSET_NONAME;
+                       goto fail;
+               case NO_DATA:
+                       result = ERRSET_NODATA;
+                       goto fail;
+               default:
+                       result = ERRSET_FAIL;
+                       goto fail;
+               }
+       }
+
+       /* parse result */
+       response = parse_dns_response(answer, length);
+       if (response == NULL) {
+               result = ERRSET_FAIL;
+               goto fail;
+       }
+
+       if (response->header.qdcount != 1) {
+               result = ERRSET_FAIL;
+               goto fail;
+       }
+
+       /* initialize rrset */
+       rrset = calloc(1, sizeof(struct rrsetinfo));
+       if (rrset == NULL) {
+               result = ERRSET_NOMEMORY;
+               goto fail;
+       }
+       rrset->rri_rdclass = response->query->class;
+       rrset->rri_rdtype = response->query->type;
+       rrset->rri_ttl = response->answer->ttl;
+       rrset->rri_nrdatas = response->header.ancount;
+
+#ifdef HAVE_HEADER_AD
+       /* check for authenticated data */
+       if (response->header.ad == 1)
+               rrset->rri_flags |= RRSET_VALIDATED;
+#endif
+
+       /* copy name from answer section */
+       length = strlen(response->answer->name);
+       rrset->rri_name = malloc(length + 1);
+       if (rrset->rri_name == NULL) {
+               result = ERRSET_NOMEMORY;
+               goto fail;
+       }
+       strlcpy(rrset->rri_name, response->answer->name, length + 1);
+
+       /* count answers */
+       rrset->rri_nrdatas = count_dns_rr(response->answer, rrset->rri_rdclass,
+           rrset->rri_rdtype);
+       rrset->rri_nsigs = count_dns_rr(response->answer, rrset->rri_rdclass,
+           T_SIG);
+
+       /* allocate memory for answers */
+       rrset->rri_rdatas = calloc(rrset->rri_nrdatas,
+           sizeof(struct rdatainfo));
+       if (rrset->rri_rdatas == NULL) {
+               result = ERRSET_NOMEMORY;
+               goto fail;
+       }
+
+       /* allocate memory for signatures */
+       rrset->rri_sigs = calloc(rrset->rri_nsigs, sizeof(struct rdatainfo));
+       if (rrset->rri_sigs == NULL) {
+               result = ERRSET_NOMEMORY;
+               goto fail;
+       }
+
+       /* copy answers & signatures */
+       for (rr = response->answer, index_ans = 0, index_sig = 0;
+           rr; rr = rr->next) {
+
+               rdata = NULL;
+
+               if (rr->class == rrset->rri_rdclass &&
+                   rr->type  == rrset->rri_rdtype)
+                       rdata = &rrset->rri_rdatas[index_ans++];
+
+               if (rr->class == rrset->rri_rdclass &&
+                   rr->type  == T_SIG)
+                       rdata = &rrset->rri_sigs[index_sig++];
+
+               if (rdata) {
+                       rdata->rdi_length = rr->size;
+                       rdata->rdi_data   = malloc(rr->size);
+
+                       if (rdata->rdi_data == NULL) {
+                               result = ERRSET_NOMEMORY;
+                               goto fail;
+                       }
+                       memcpy(rdata->rdi_data, rr->rdata, rr->size);
+               }
+       }
+
+       *res = rrset;
+       return (ERRSET_SUCCESS);
+
+fail:
+       if (rrset != NULL)
+               freerrset(rrset);
+       return (result);
+}
+
+void
+freerrset(struct rrsetinfo *rrset)
+{
+       u_int16_t i;
+
+       if (rrset == NULL)
+               return;
+
+       if (rrset->rri_rdatas) {
+               for (i = 0; i < rrset->rri_nrdatas; i++) {
+                       if (rrset->rri_rdatas[i].rdi_data == NULL)
+                               break;
+                       free(rrset->rri_rdatas[i].rdi_data);
+               }
+               free(rrset->rri_rdatas);
+       }
+
+       if (rrset->rri_sigs) {
+               for (i = 0; i < rrset->rri_nsigs; i++) {
+                       if (rrset->rri_sigs[i].rdi_data == NULL)
+                               break;
+                       free(rrset->rri_sigs[i].rdi_data);
+               }
+               free(rrset->rri_sigs);
+       }
+
+       if (rrset->rri_name)
+               free(rrset->rri_name);
+       free(rrset);
+}
+
+/*
+ * DNS response parsing routines
+ */
+static struct dns_response *
+parse_dns_response(const u_char *answer, int size)
+{
+       struct dns_response *resp;
+       const u_char *cp;
+
+       /* allocate memory for the response */
+       resp = calloc(1, sizeof(*resp));
+       if (resp == NULL)
+               return (NULL);
+
+       /* initialize current pointer */
+       cp = answer;
+
+       /* copy header */
+       memcpy(&resp->header, cp, HFIXEDSZ);
+       cp += HFIXEDSZ;
+
+       /* fix header byte order */
+       resp->header.qdcount = ntohs(resp->header.qdcount);
+       resp->header.ancount = ntohs(resp->header.ancount);
+       resp->header.nscount = ntohs(resp->header.nscount);
+       resp->header.arcount = ntohs(resp->header.arcount);
+
+       /* there must be at least one query */
+       if (resp->header.qdcount < 1) {
+               free_dns_response(resp);
+               return (NULL);
+       }
+
+       /* parse query section */
+       resp->query = parse_dns_qsection(answer, size, &cp,
+           resp->header.qdcount);
+       if (resp->header.qdcount && resp->query == NULL) {
+               free_dns_response(resp);
+               return (NULL);
+       }
+
+       /* parse answer section */
+       resp->answer = parse_dns_rrsection(answer, size, &cp,
+           resp->header.ancount);
+       if (resp->header.ancount && resp->answer == NULL) {
+               free_dns_response(resp);
+               return (NULL);
+       }
+
+       /* parse authority section */
+       resp->authority = parse_dns_rrsection(answer, size, &cp,
+           resp->header.nscount);
+       if (resp->header.nscount && resp->authority == NULL) {
+               free_dns_response(resp);
+               return (NULL);
+       }
+
+       /* parse additional section */
+       resp->additional = parse_dns_rrsection(answer, size, &cp,
+           resp->header.arcount);
+       if (resp->header.arcount && resp->additional == NULL) {
+               free_dns_response(resp);
+               return (NULL);
+       }
+
+       return (resp);
+}
+
+static struct dns_query *
+parse_dns_qsection(const u_char *answer, int size, const u_char **cp, int count)
+{
+       struct dns_query *head, *curr, *prev;
+       int i, length;
+       char name[MAXDNAME];
+
+       for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
+
+               /* allocate and initialize struct */
+               curr = calloc(1, sizeof(struct dns_query));
+               if (curr == NULL) {
+                       free_dns_query(head);
+                       return (NULL);
+               }
+               if (head == NULL)
+                       head = curr;
+               if (prev != NULL)
+                       prev->next = curr;
+
+               /* name */
+               length = dn_expand(answer, answer + size, *cp, name,
+                   sizeof(name));
+               if (length < 0) {
+                       free_dns_query(head);
+                       return (NULL);
+               }
+               curr->name = strdup(name);
+               if (curr->name == NULL) {
+                       free_dns_query(head);
+                       return (NULL);
+               }
+               *cp += length;
+
+               /* type */
+               curr->type = _getshort(*cp);
+               *cp += INT16SZ;
+
+               /* class */
+               curr->class = _getshort(*cp);
+               *cp += INT16SZ;
+       }
+
+       return (head);
+}
+
+static struct dns_rr *
+parse_dns_rrsection(const u_char *answer, int size, const u_char **cp, int count)
+{
+       struct dns_rr *head, *curr, *prev;
+       int i, length;
+       char name[MAXDNAME];
+
+       for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
+
+               /* allocate and initialize struct */
+               curr = calloc(1, sizeof(struct dns_rr));
+               if (curr == NULL) {
+                       free_dns_rr(head);
+                       return (NULL);
+               }
+               if (head == NULL)
+                       head = curr;
+               if (prev != NULL)
+                       prev->next = curr;
+
+               /* name */
+               length = dn_expand(answer, answer + size, *cp, name,
+                   sizeof(name));
+               if (length < 0) {
+                       free_dns_rr(head);
+                       return (NULL);
+               }
+               curr->name = strdup(name);
+               if (curr->name == NULL) {
+                       free_dns_rr(head);
+                       return (NULL);
+               }
+               *cp += length;
+
+               /* type */
+               curr->type = _getshort(*cp);
+               *cp += INT16SZ;
+
+               /* class */
+               curr->class = _getshort(*cp);
+               *cp += INT16SZ;
+
+               /* ttl */
+               curr->ttl = _getlong(*cp);
+               *cp += INT32SZ;
+
+               /* rdata size */
+               curr->size = _getshort(*cp);
+               *cp += INT16SZ;
+
+               /* rdata itself */
+               curr->rdata = malloc(curr->size);
+               if (curr->rdata == NULL) {
+                       free_dns_rr(head);
+                       return (NULL);
+               }
+               memcpy(curr->rdata, *cp, curr->size);
+               *cp += curr->size;
+       }
+
+       return (head);
+}
+
+static void
+free_dns_query(struct dns_query *p)
+{
+       if (p == NULL)
+               return;
+
+       if (p->name)
+               free(p->name);
+       free_dns_query(p->next);
+       free(p);
+}
+
+static void
+free_dns_rr(struct dns_rr *p)
+{
+       if (p == NULL)
+               return;
+
+       if (p->name)
+               free(p->name);
+       if (p->rdata)
+               free(p->rdata);
+       free_dns_rr(p->next);
+       free(p);
+}
+
+static void
+free_dns_response(struct dns_response *p)
+{
+       if (p == NULL)
+               return;
+
+       free_dns_query(p->query);
+       free_dns_rr(p->answer);
+       free_dns_rr(p->authority);
+       free_dns_rr(p->additional);
+       free(p);
+}
+
+static int
+count_dns_rr(struct dns_rr *p, u_int16_t class, u_int16_t type)
+{
+       int n = 0;
+
+       while(p) {
+               if (p->class == class && p->type == type)
+                       n++;
+               p = p->next;
+       }
+
+       return (n);
+}
+
+#endif /* defined(DNS) && !defined(HAVE_GETRRSETBYNAME) */
diff --git a/openssh/openbsd-compat/getrrsetbyname.h b/openssh/openbsd-compat/getrrsetbyname.h
new file mode 100644 (file)
index 0000000..6466a54
--- /dev/null
@@ -0,0 +1,100 @@
+/* $OpenBSD: getrrsetbyname.c,v 1.4 2001/08/16 18:16:43 ho Exp $ */
+
+/*
+ * Copyright (c) 2001 Jakob Schlyter. 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.
+ */
+
+/*
+ * Portions Copyright (c) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _GETRRSETBYNAME_H
+#define _GETRRSETBYNAME_H
+
+#include "includes.h"
+
+#if defined(DNS) && !defined(HAVE_GETRRSETBYNAME)
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <resolv.h>
+
+/*
+ * Flags for getrrsetbyname()
+ */
+#ifndef RRSET_VALIDATED
+# define RRSET_VALIDATED       1
+#endif
+
+/*
+ * Return codes for getrrsetbyname()
+ */
+#ifndef ERRSET_SUCCESS
+# define ERRSET_SUCCESS                0
+# define ERRSET_NOMEMORY       1
+# define ERRSET_FAIL           2
+# define ERRSET_INVAL          3
+# define ERRSET_NONAME         4
+# define ERRSET_NODATA         5
+#endif
+
+struct rdatainfo {
+       unsigned int            rdi_length;     /* length of data */
+       unsigned char           *rdi_data;      /* record data */
+};
+
+struct rrsetinfo {
+       unsigned int            rri_flags;      /* RRSET_VALIDATED ... */
+       unsigned int            rri_rdclass;    /* class number */
+       unsigned int            rri_rdtype;     /* RR type number */
+       unsigned int            rri_ttl;        /* time to live */
+       unsigned int            rri_nrdatas;    /* size of rdatas array */
+       unsigned int            rri_nsigs;      /* size of sigs array */
+       char                    *rri_name;      /* canonical name */
+       struct rdatainfo        *rri_rdatas;    /* individual records */
+       struct rdatainfo        *rri_sigs;      /* individual signatures */
+};
+
+int            getrrsetbyname(const char *, unsigned int, unsigned int, unsigned int, struct rrsetinfo **);
+void           freerrset(struct rrsetinfo *);
+
+#endif /* defined(DNS) && !defined(HAVE_GETRRSETBYNAME) */
+
+#endif /* _GETRRSETBYNAME_H */
diff --git a/openssh/openbsd-compat/xcrypt.c b/openssh/openbsd-compat/xcrypt.c
new file mode 100644 (file)
index 0000000..5b5d69c
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2003 Ben Lindstrom.  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"
+
+#if !defined(HAVE_OSF_SIA)
+
+# ifdef HAVE_CRYPT_H
+#  include <crypt.h>
+# endif
+
+# ifdef __hpux
+#  include <hpsecurity.h>
+#  include <prot.h>
+# endif
+
+# ifdef HAVE_SECUREWARE
+#  include <sys/security.h>
+#  include <sys/audit.h>
+#  include <prot.h>
+# endif 
+
+# if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW)
+#  include <shadow.h>
+# endif
+
+# if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW)
+#  include <sys/label.h>
+#  include <sys/audit.h>
+#  include <pwdadj.h>
+# endif
+
+# if defined(HAVE_MD5_PASSWORDS) && !defined(HAVE_MD5_CRYPT)
+#  include "md5crypt.h"
+# endif 
+
+char *
+xcrypt(const char *password, const char *salt)
+{
+       char *crypted;
+
+# ifdef HAVE_MD5_PASSWORDS
+        if (is_md5_salt(salt))
+                crypted = md5_crypt(password, salt);
+        else
+                crypted = crypt(password, salt);
+# elif defined(__hpux) && !defined(HAVE_SECUREWARE)
+       if (iscomsec())
+                crypted = bigcrypt(password, salt);
+        else
+                crypted = crypt(password, salt);
+# elif defined(HAVE_SECUREWARE)
+        crypted = bigcrypt(password, salt);
+# else
+        crypted = crypt(password, salt);
+# endif 
+
+       return crypted;
+}
+
+/*
+ * Handle shadowed password systems in a cleaner way for portable
+ * version.
+ */
+
+char *
+shadow_pw(struct passwd *pw)
+{
+       char *pw_password = pw->pw_passwd;
+
+# if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW)
+       struct spwd *spw = getspnam(pw->pw_name);
+
+       if (spw != NULL)
+               pw_password = spw->sp_pwdp;
+# endif
+# if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW)
+       struct passwd_adjunct *spw;
+       if (issecure() && (spw = getpwanam(pw->pw_name)) != NULL)
+               pw_password = spw->pwa_passwd;
+# elif defined(HAVE_SECUREWARE)
+       struct pr_passwd *spw = getprpwnam(pw->pw_name);
+
+       if (spw != NULL)
+               pw_password = spw->ufld.fd_encrypt;
+# elif defined(__hpux) && !defined(HAVE_SECUREWARE)
+       struct pr_passwd *spw;
+        if (iscomsec() && (spw = getprpwnam(pw->pw_name)) != NULL)
+                pw_password = spw->ufld.fd_encrypt;
+# endif
+
+       return pw_password;
+}
+
+#endif /* !defined(HAVE_OSF_SIA) */
diff --git a/openssh/regress/README.regress b/openssh/regress/README.regress
new file mode 100644 (file)
index 0000000..804917b
--- /dev/null
@@ -0,0 +1,86 @@
+Overview.
+
+$ ./configure && make tests
+
+You'll see some progress info. A failure will cause either the make to
+abort or the driver script to report a "FATAL" failure.
+
+The test consists of 2 parts. The first is the file-based tests which is
+driven by the Makefile, and the second is a set of network or proxycommand
+based tests, which are driven by a driver script (test-exec.sh) which is
+called multiple times by the Makefile.
+
+Failures in the first part will cause the Makefile to return an error.
+Failures in the second part will print a "FATAL" message for the failed
+test and continue.
+
+OpenBSD has a system-wide regression test suite. OpenSSH Portable's test
+suite is based on OpenBSD's with modifications.
+
+
+Environment variables.
+
+SUDO: path to sudo command, if desired. Note that some systems (notably
+       systems using PAM) require sudo to execute some tests.
+TEST_SSH_TRACE: set yo "yes" for verbose output from tests 
+TEST_SSH_QUIET: set to "yes" to suppress non-fatal output.
+TEST_SSH_x: path to "ssh" command under test, where x=SSH,SSHD,SSHAGENT,SSHADD
+       SSHKEYGEN,SSHKEYSCAN,SFTP,SFTPSERVER
+OBJ: used by test scripts to access build dir.
+
+
+Individual tests.
+
+You can invoke test-exec.sh directly if you set up the path to find the
+binaries under test and the test scripts themselves, for example:
+
+$ cd regress
+$ PATH=`pwd`/..:$PATH:. sh test-exec.sh `pwd` agent-timeout.sh
+ok agent timeout test
+
+
+Files.
+
+test-exec.sh: the main test driver. Sets environment, creates config files
+and keys and runs the specified test.
+
+At the time of writing, the individual tests are:
+agent-timeout.sh:      agent timeout test
+agent.sh:              simple agent test
+broken-pipe.sh:                broken pipe test
+connect-privsep.sh:    proxy connect with privsep
+connect.sh:            simple connect
+exit-status.sh:                remote exit status
+forwarding.sh:         local and remote forwarding
+keygen-change.sh:      change passphrase for key
+keyscan.sh:            keyscan
+proto-mismatch.sh:     protocol version mismatch
+proto-version.sh:      sshd version with different protocol combinations
+proxy-connect.sh:      proxy connect
+sftp.sh:               basic sftp put/get
+ssh-com-client.sh:     connect with ssh.com client
+ssh-com-keygen.sh:     ssh.com key import
+ssh-com-sftp.sh:       basic sftp put/get with ssh.com server
+ssh-com.sh:            connect to ssh.com server
+stderr-after-eof.sh:   stderr data after eof
+stderr-data.sh:                stderr data transfer
+transfer.sh:           transfer data
+try-ciphers.sh:                try ciphers
+yes-head.sh:           yes pipe head
+
+
+Problems?
+
+Run the failing test with shell tracing (-x) turned on:
+$ PATH=`pwd`/..:$PATH:. sh -x test-exec.sh `pwd` agent-timeout.sh
+
+Failed tests can be difficult to diagnose. Suggestions:
+- run the individual test via ./test-exec.sh `pwd` [testname]
+- set LogLevel to VERBOSE in test-exec.sh and enable syslogging of
+  auth.debug (eg to /var/log/authlog).
+
+
+Known Issues.
+
+
+$Id$
diff --git a/openssh/regress/dynamic-forward.sh b/openssh/regress/dynamic-forward.sh
new file mode 100644 (file)
index 0000000..2b0b825
--- /dev/null
@@ -0,0 +1,47 @@
+#      $OpenBSD: dynamic-forward.sh,v 1.2 2003/07/03 08:21:46 markus Exp $
+#      Placed in the Public Domain.
+
+tid="dynamic forwarding"
+
+PORT=4242
+FWDPORT=4243
+DATA=/bin/ls${EXEEXT}
+
+if have_prog nc && nc -h 2>&1 | grep "x proxy address" >/dev/null; then
+       proxycmd="nc -x 127.0.0.1:$FWDPORT -X"
+elif have_prog connect; then
+       proxycmd="connect -S 127.0.0.1:$FWDPORT -"
+else
+       echo "skipped (no suitable ProxyCommand found)"
+       exit 0
+fi
+trace "will use ProxyCommand $proxycmd"
+
+start_sshd
+
+for p in 1 2; do
+       trace "start dynamic forwarding, fork to background"
+       ${SSH} -$p -F $OBJ/ssh_config -f -D $FWDPORT -q somehost \
+               exec sh -c \'"echo \$\$ > $OBJ/remote_pid; exec sleep 444"\'
+
+       for s in 4 5; do
+           for h in 127.0.0.1 localhost; do
+               trace "testing ssh protocol $p socks version $s host $h"
+               ${SSH} -F $OBJ/ssh_config \
+                       -o "ProxyCommand ${proxycmd}${s} $h $PORT" \
+                       somehost cat $DATA > $OBJ/ls.copy
+               test -f $OBJ/ls.copy     || fail "failed copy $DATA"
+               cmp $DATA $OBJ/ls.copy || fail "corrupted copy of $DATA"
+           done
+       done
+
+       if [ -f $OBJ/remote_pid ]; then
+               remote=`cat $OBJ/remote_pid`
+               trace "terminate remote shell, pid $remote"
+               if [ $remote -gt 1 ]; then
+                       kill -HUP $remote
+               fi
+       else
+               fail "no pid file: $OBJ/remote_pid"
+       fi
+done
diff --git a/openssh/regress/reconfigure.sh b/openssh/regress/reconfigure.sh
new file mode 100644 (file)
index 0000000..ba6dbc6
--- /dev/null
@@ -0,0 +1,35 @@
+#      $OpenBSD: reconfigure.sh,v 1.2 2003/06/21 09:14:05 markus Exp $
+#      Placed in the Public Domain.
+
+tid="simple connect after reconfigure"
+
+# we need the full path to sshd for -HUP
+case $SSHD in
+/*)
+       # full path is OK 
+       ;;
+*)
+       # otherwise make fully qualified
+       SSHD=$OBJ/$SSHD
+esac
+
+start_sshd
+
+$SUDO kill -HUP `cat $PIDFILE`
+sleep 1
+
+trace "wait for sshd to restart"
+i=0;
+while [ ! -f $PIDFILE -a $i -lt 10 ]; do
+       i=`expr $i + 1`
+       sleep $i
+done
+
+test -f $PIDFILE || fatal "sshd did not restart"
+
+for p in 1 2; do
+       ${SSH} -o "Protocol=$p" -F $OBJ/ssh_config somehost true
+       if [ $? -ne 0 ]; then
+               fail "ssh connect with protocol $p failed after reconfigure"
+       fi
+done
diff --git a/openssh/regress/rekey.sh b/openssh/regress/rekey.sh
new file mode 100644 (file)
index 0000000..6b7e845
--- /dev/null
@@ -0,0 +1,31 @@
+#      $OpenBSD: rekey.sh,v 1.1 2003/03/28 13:58:28 markus Exp $
+#      Placed in the Public Domain.
+
+tid="rekey during transfer data"
+
+DATA=${OBJ}/data
+COPY=${OBJ}/copy
+LOG=${OBJ}/log
+
+rm -f ${COPY} ${LOG} ${DATA}
+dd if=/bin/ls${EXEEXT} of=${DATA} bs=1k seek=511 count=1 > /dev/null 2>&1
+
+for s in 16 1k 128k 256k; do
+       trace "rekeylimit ${s}"
+       rm -f ${COPY}
+       cat $DATA | \
+               ${SSH} -oCompression=no -oRekeyLimit=$s \
+                       -v -F $OBJ/ssh_proxy somehost "cat > ${COPY}" \
+               2> ${LOG}
+       if [ $? -ne 0 ]; then
+               fail "ssh failed"
+       fi
+       cmp $DATA ${COPY}               || fail "corrupted copy"
+       n=`grep 'NEWKEYS sent' ${LOG} | wc -l`
+       n=`expr $n - 1`
+       trace "$n rekeying(s)"
+       if [ $n -lt 1 ]; then
+               fail "no rekeying occured"
+       fi
+done
+rm -f ${COPY} ${LOG} ${DATA}
diff --git a/openssh/regress/sftp-badcmds.sh b/openssh/regress/sftp-badcmds.sh
new file mode 100644 (file)
index 0000000..a6a1940
--- /dev/null
@@ -0,0 +1,78 @@
+#      $OpenBSD: sftp-badcmds.sh,v 1.2 2003/05/15 04:07:12 mouring Exp $
+#      Placed in the Public Domain.
+
+tid="sftp invalid commands"
+
+DATA=/bin/ls${EXEEXT}
+DATA2=/bin/cat${EXEEXT}
+NONEXIST=/NONEXIST.$$
+COPY=${OBJ}/copy
+GLOBFILES=`(cd /bin;echo l*)`
+
+rm -rf ${COPY} ${COPY}.1 ${COPY}.2 ${COPY}.dd
+
+rm -f ${COPY}
+verbose "$tid: get nonexistent"
+echo "get $NONEXIST $COPY" | ${SFTP} -P ${SFTPSERVER} >/dev/null 2>&1 \
+       || fail "get nonexistent failed"
+test -f ${COPY} && fail "existing copy after get nonexistent"
+
+rm -f ${COPY}.dd/*
+verbose "$tid: glob get to nonexistent directory"
+echo "get /bin/l* $NONEXIST" | ${SFTP} -P ${SFTPSERVER} >/dev/null 2>&1 \
+        || fail "get nonexistent failed"
+for x in $GLOBFILES; do
+        test -f ${COPY}.dd/$x && fail "existing copy after get nonexistent"
+done
+
+rm -f ${COPY}
+verbose "$tid: put nonexistent"
+echo "put $NONEXIST $COPY" | ${SFTP} -P ${SFTPSERVER} >/dev/null 2>&1 \
+       || fail "put nonexistent failed"
+test -f ${COPY} && fail "existing copy after put nonexistent"
+
+rm -f ${COPY}.dd/*
+verbose "$tid: glob put to nonexistent directory"
+echo "put /bin/l* ${COPY}.dd" | ${SFTP} -P ${SFTPSERVER} >/dev/null 2>&1 \
+        || fail "put nonexistent failed"
+for x in $GLOBFILES; do
+        test -f ${COPY}.dd/$x && fail "existing copy after nonexistent"
+done
+
+rm -f ${COPY}
+verbose "$tid: rename nonexistent"
+echo "rename $NONEXIST ${COPY}.1" | ${SFTP} -P ${SFTPSERVER} >/dev/null 2>&1 \
+       || fail "rename nonexist failed"
+test -f ${COPY}.1 && fail "file exists after rename nonexistent"
+
+rm -f ${COPY} ${COPY}.1
+cp $DATA $COPY
+cp $DATA2 ${COPY}.1
+verbose "$tid: rename target exists"
+echo "rename $COPY ${COPY}.1" | ${SFTP} -P ${SFTPSERVER} >/dev/null 2>&1 \
+       || fail "rename target exists failed"
+test -f ${COPY} || fail "oldname missing after rename target exists"
+test -f ${COPY}.1 || fail "newname missing after rename target exists"
+cmp $DATA ${COPY} >/dev/null 2>&1 || fail "corrupted oldname after rename target exists"
+cmp $DATA2 ${COPY}.1 >/dev/null 2>&1 || fail "corrupted newname after rename target exists"
+
+rm -rf ${COPY} ${COPY}.dd
+cp $DATA $COPY
+mkdir ${COPY}.dd
+verbose "$tid: rename target exists (directory)"
+echo "rename $COPY ${COPY}.dd" | ${SFTP} -P ${SFTPSERVER} >/dev/null 2>&1 \
+       || fail "rename target exists (directory) failed"
+test -f ${COPY} || fail "oldname missing after rename target exists (directory)"
+test -d ${COPY}.dd || fail "newname missing after rename target exists (directory)"
+cmp $DATA ${COPY} >/dev/null 2>&1 || fail "corrupted oldname after rename target exists (directory)"
+
+rm -f ${COPY}.dd/*
+rm -rf ${COPY}
+cp ${DATA2} ${COPY}
+verbose "$tid: glob put files to local file"
+echo "put /bin/l* $COPY" | ${SFTP} -P ${SFTPSERVER} >/dev/null 2>&1 
+cmp ${DATA2} ${COPY} || fail "put successed when it should have failed"
+
+rm -rf ${COPY} ${COPY}.1 ${COPY}.2 ${COPY}.dd
+
+
This page took 0.420525 seconds and 5 git commands to generate.