Import OpenSSH-6.7p1.
authorPeter Avalos <pavalos@dragonflybsd.org>
Wed, 26 Nov 2014 20:54:34 +0000 (12:54 -0800)
committerPeter Avalos <pavalos@dragonflybsd.org>
Fri, 23 Jan 2015 05:39:05 +0000 (21:39 -0800)
240 files changed:
crypto/openssh/PROTOCOL
crypto/openssh/PROTOCOL.agent
crypto/openssh/PROTOCOL.chacha20poly1305 [new file with mode: 0644]
crypto/openssh/PROTOCOL.key [new file with mode: 0644]
crypto/openssh/PROTOCOL.krl [new file with mode: 0644]
crypto/openssh/README
crypto/openssh/README.DELETED
crypto/openssh/acss.c [deleted file]
crypto/openssh/acss.h [deleted file]
crypto/openssh/addrmatch.c
crypto/openssh/atomicio.c
crypto/openssh/auth-bsdauth.c
crypto/openssh/auth-chall.c
crypto/openssh/auth-krb5.c
crypto/openssh/auth-options.c
crypto/openssh/auth-pam.c
crypto/openssh/auth-passwd.c
crypto/openssh/auth-rh-rsa.c
crypto/openssh/auth-rhosts.c
crypto/openssh/auth-rsa.c
crypto/openssh/auth.c
crypto/openssh/auth.h
crypto/openssh/auth1.c
crypto/openssh/auth2-chall.c
crypto/openssh/auth2-gss.c
crypto/openssh/auth2-hostbased.c
crypto/openssh/auth2-jpake.c [deleted file]
crypto/openssh/auth2-kbdint.c
crypto/openssh/auth2-none.c
crypto/openssh/auth2-passwd.c
crypto/openssh/auth2-pubkey.c
crypto/openssh/auth2.c
crypto/openssh/authfd.c
crypto/openssh/authfile.c
crypto/openssh/authfile.h
crypto/openssh/blocks.c [new file with mode: 0644]
crypto/openssh/bufaux.c
crypto/openssh/bufbn.c
crypto/openssh/bufec.c
crypto/openssh/buffer.c
crypto/openssh/buffer.h
crypto/openssh/canohost.c
crypto/openssh/chacha.c [new file with mode: 0644]
crypto/openssh/chacha.h [new file with mode: 0644]
crypto/openssh/channels.c
crypto/openssh/channels.h
crypto/openssh/cipher-3des1.c
crypto/openssh/cipher-acss.c [deleted file]
crypto/openssh/cipher-aes.c
crypto/openssh/cipher-aesctr.h [copied from crypto/openssh/platform.h with 55% similarity]
crypto/openssh/cipher-chachapoly.c [new file with mode: 0644]
crypto/openssh/cipher-chachapoly.h [new file with mode: 0644]
crypto/openssh/cipher-ctr.c
crypto/openssh/cipher.c
crypto/openssh/cipher.h
crypto/openssh/clientloop.c
crypto/openssh/clientloop.h
crypto/openssh/compat.c
crypto/openssh/compat.h
crypto/openssh/crypto_api.h [new file with mode: 0644]
crypto/openssh/defines.h
crypto/openssh/dh.c
crypto/openssh/dh.h
crypto/openssh/digest-libc.c [new file with mode: 0644]
crypto/openssh/digest-openssl.c [new file with mode: 0644]
crypto/openssh/digest.h [new file with mode: 0644]
crypto/openssh/dns.c
crypto/openssh/dns.h
crypto/openssh/ed25519.c [new file with mode: 0644]
crypto/openssh/entropy.c
crypto/openssh/fe25519.c [new file with mode: 0644]
crypto/openssh/fe25519.h [new file with mode: 0644]
crypto/openssh/ge25519.c [new file with mode: 0644]
crypto/openssh/ge25519.h [new file with mode: 0644]
crypto/openssh/ge25519_base.data [new file with mode: 0644]
crypto/openssh/groupaccess.c
crypto/openssh/gss-genr.c
crypto/openssh/gss-serv-krb5.c
crypto/openssh/gss-serv.c
crypto/openssh/hash.c [new file with mode: 0644]
crypto/openssh/hmac.c [new file with mode: 0644]
crypto/openssh/hmac.h [new file with mode: 0644]
crypto/openssh/hostfile.c
crypto/openssh/hostfile.h
crypto/openssh/includes.h
crypto/openssh/jpake.c [deleted file]
crypto/openssh/jpake.h [deleted file]
crypto/openssh/kex.c
crypto/openssh/kex.h
crypto/openssh/kexc25519.c [copied from crypto/openssh/kexecdh.c with 57% similarity]
crypto/openssh/kexc25519c.c [copied from crypto/openssh/kexecdhc.c with 60% similarity]
crypto/openssh/kexc25519s.c [copied from crypto/openssh/kexecdhs.c with 54% similarity]
crypto/openssh/kexdh.c
crypto/openssh/kexdhc.c
crypto/openssh/kexdhs.c
crypto/openssh/kexecdh.c
crypto/openssh/kexecdhc.c
crypto/openssh/kexecdhs.c
crypto/openssh/kexgex.c
crypto/openssh/kexgexc.c
crypto/openssh/kexgexs.c
crypto/openssh/key.c
crypto/openssh/key.h
crypto/openssh/krl.c [new file with mode: 0644]
crypto/openssh/krl.h [new file with mode: 0644]
crypto/openssh/log.c
crypto/openssh/log.h
crypto/openssh/loginrec.c
crypto/openssh/mac.c
crypto/openssh/mac.h
crypto/openssh/match.c
crypto/openssh/misc.c
crypto/openssh/misc.h
crypto/openssh/moduli
crypto/openssh/moduli.5
crypto/openssh/moduli.c
crypto/openssh/monitor.c
crypto/openssh/monitor.h
crypto/openssh/monitor_fdpass.c
crypto/openssh/monitor_mm.c
crypto/openssh/monitor_mm.h
crypto/openssh/monitor_wrap.c
crypto/openssh/monitor_wrap.h
crypto/openssh/mux.c
crypto/openssh/myproposal.h
crypto/openssh/openbsd-compat/arc4random.c [new file with mode: 0644]
crypto/openssh/openbsd-compat/bcrypt_pbkdf.c [new file with mode: 0644]
crypto/openssh/openbsd-compat/blf.h [new file with mode: 0644]
crypto/openssh/openbsd-compat/blowfish.c [new file with mode: 0644]
crypto/openssh/openbsd-compat/bsd-cygwin_util.h
crypto/openssh/openbsd-compat/bsd-misc.c
crypto/openssh/openbsd-compat/bsd-misc.h
crypto/openssh/openbsd-compat/bsd-setres_id.c [new file with mode: 0644]
crypto/openssh/openbsd-compat/bsd-setres_id.h [copied from crypto/openssh/ssh-pkcs11.h with 73% similarity]
crypto/openssh/openbsd-compat/bsd-statvfs.h
crypto/openssh/openbsd-compat/chacha_private.h [new file with mode: 0644]
crypto/openssh/openbsd-compat/explicit_bzero.c [new file with mode: 0644]
crypto/openssh/openbsd-compat/getopt.h [new file with mode: 0644]
crypto/openssh/openbsd-compat/getopt_long.c [new file with mode: 0644]
crypto/openssh/openbsd-compat/kludge-fd_set.c [new file with mode: 0644]
crypto/openssh/openbsd-compat/openbsd-compat.h
crypto/openssh/openbsd-compat/openssl-compat.c
crypto/openssh/openbsd-compat/openssl-compat.h
crypto/openssh/openbsd-compat/strtoull.c [new file with mode: 0644]
crypto/openssh/openbsd-compat/sys-queue.h
crypto/openssh/openbsd-compat/sys-tree.h
crypto/openssh/packet.c
crypto/openssh/packet.h
crypto/openssh/pathnames.h
crypto/openssh/pkcs11.h
crypto/openssh/platform.c
crypto/openssh/platform.h
crypto/openssh/poly1305.c [new file with mode: 0644]
crypto/openssh/poly1305.h [new file with mode: 0644]
crypto/openssh/progressmeter.c
crypto/openssh/readconf.c
crypto/openssh/readconf.h
crypto/openssh/readpass.c
crypto/openssh/rijndael.c
crypto/openssh/rijndael.h
crypto/openssh/roaming_client.c
crypto/openssh/roaming_common.c
crypto/openssh/rsa.c
crypto/openssh/rsa.h
crypto/openssh/sandbox-capsicum.c [copied from crypto/openssh/sandbox-rlimit.c with 60% similarity]
crypto/openssh/sandbox-rlimit.c
crypto/openssh/sc25519.c [new file with mode: 0644]
crypto/openssh/sc25519.h [new file with mode: 0644]
crypto/openssh/schnorr.c [deleted file]
crypto/openssh/schnorr.h [deleted file]
crypto/openssh/scp.1
crypto/openssh/scp.c
crypto/openssh/servconf.c
crypto/openssh/servconf.h
crypto/openssh/serverloop.c
crypto/openssh/session.c
crypto/openssh/session.h
crypto/openssh/sftp-client.c
crypto/openssh/sftp-client.h
crypto/openssh/sftp-common.c
crypto/openssh/sftp-glob.c
crypto/openssh/sftp-server.8
crypto/openssh/sftp-server.c
crypto/openssh/sftp.1
crypto/openssh/sftp.c
crypto/openssh/smult_curve25519_ref.c [new file with mode: 0644]
crypto/openssh/ssh-add.1
crypto/openssh/ssh-add.c
crypto/openssh/ssh-agent.1
crypto/openssh/ssh-agent.c
crypto/openssh/ssh-dss.c
crypto/openssh/ssh-ecdsa.c
crypto/openssh/ssh-ed25519.c [new file with mode: 0644]
crypto/openssh/ssh-gss.h
crypto/openssh/ssh-keygen.1
crypto/openssh/ssh-keygen.c
crypto/openssh/ssh-keyscan.1
crypto/openssh/ssh-keyscan.c
crypto/openssh/ssh-keysign.8
crypto/openssh/ssh-keysign.c
crypto/openssh/ssh-pkcs11-client.c
crypto/openssh/ssh-pkcs11-helper.8
crypto/openssh/ssh-pkcs11-helper.c
crypto/openssh/ssh-pkcs11.c
crypto/openssh/ssh-pkcs11.h
crypto/openssh/ssh-rsa.c
crypto/openssh/ssh-sandbox.h
crypto/openssh/ssh.1
crypto/openssh/ssh.c
crypto/openssh/ssh2.h
crypto/openssh/ssh_config
crypto/openssh/ssh_config.5
crypto/openssh/sshbuf-getput-basic.c [new file with mode: 0644]
crypto/openssh/sshbuf-getput-crypto.c [new file with mode: 0644]
crypto/openssh/sshbuf-misc.c [new file with mode: 0644]
crypto/openssh/sshbuf.c [new file with mode: 0644]
crypto/openssh/sshbuf.h [new file with mode: 0644]
crypto/openssh/sshconnect.c
crypto/openssh/sshconnect.h
crypto/openssh/sshconnect1.c
crypto/openssh/sshconnect2.c
crypto/openssh/sshd.8
crypto/openssh/sshd.c
crypto/openssh/sshd_config
crypto/openssh/sshd_config.5
crypto/openssh/ssherr.c [new file with mode: 0644]
crypto/openssh/ssherr.h [new file with mode: 0644]
crypto/openssh/sshkey.c [new file with mode: 0644]
crypto/openssh/sshkey.h [new file with mode: 0644]
crypto/openssh/sshlogin.c
crypto/openssh/sshlogin.h
crypto/openssh/sshpty.c
crypto/openssh/uidswap.c
crypto/openssh/umac.c
crypto/openssh/umac.h
crypto/openssh/uuencode.c
crypto/openssh/verify.c [new file with mode: 0644]
crypto/openssh/version.h [new file with mode: 0644]
crypto/openssh/xmalloc.c
crypto/openssh/xmalloc.h

index c281960..aa59f58 100644 (file)
@@ -51,6 +51,57 @@ and ecdsa-sha2-nistp521 curves over GF(p) are supported. Elliptic
 curve points encoded using point compression are NOT accepted or
 generated.
 
+1.5 transport: Protocol 2 Encrypt-then-MAC MAC algorithms
+
+OpenSSH supports MAC algorithms, whose names contain "-etm", that
+perform the calculations in a different order to that defined in RFC
+4253. These variants use the so-called "encrypt then MAC" ordering,
+calculating the MAC over the packet ciphertext rather than the
+plaintext. This ordering closes a security flaw in the SSH transport
+protocol, where decryption of unauthenticated ciphertext provided a
+"decryption oracle" that could, in conjunction with cipher flaws, reveal
+session plaintext.
+
+Specifically, the "-etm" MAC algorithms modify the transport protocol
+to calculate the MAC over the packet ciphertext and to send the packet
+length unencrypted. This is necessary for the transport to obtain the
+length of the packet and location of the MAC tag so that it may be
+verified without decrypting unauthenticated data.
+
+As such, the MAC covers:
+
+      mac = MAC(key, sequence_number || packet_length || encrypted_packet)
+
+where "packet_length" is encoded as a uint32 and "encrypted_packet"
+contains:
+
+      byte      padding_length
+      byte[n1]  payload; n1 = packet_length - padding_length - 1
+      byte[n2]  random padding; n2 = padding_length
+
+1.6 transport: AES-GCM
+
+OpenSSH supports the AES-GCM algorithm as specified in RFC 5647.
+Because of problems with the specification of the key exchange
+the behaviour of OpenSSH differs from the RFC as follows:
+
+AES-GCM is only negotiated as the cipher algorithms
+"aes128-gcm@openssh.com" or "aes256-gcm@openssh.com" and never as
+an MAC algorithm. Additionally, if AES-GCM is selected as the cipher
+the exchanged MAC algorithms are ignored and there doesn't have to be
+a matching MAC.
+
+1.7 transport: chacha20-poly1305@openssh.com authenticated encryption
+
+OpenSSH supports authenticated encryption using ChaCha20 and Poly1305
+as described in PROTOCOL.chacha20poly1305.
+
+1.8 transport: curve25519-sha256@libssh.org key exchange algorithm
+
+OpenSSH supports the use of ECDH in Curve25519 for key exchange as
+described at:
+http://git.libssh.org/users/aris/libssh.git/plain/doc/curve25519-sha256@libssh.org.txt?h=curve25519
+
 2. Connection protocol changes
 
 2.1. connection: Channel write close extension "eow@openssh.com"
@@ -181,6 +232,56 @@ The contents of the "data" field for layer 2 packets is:
 The "frame" field contains an IEEE 802.3 Ethernet frame, including
 header.
 
+2.4. connection: Unix domain socket forwarding
+
+OpenSSH supports local and remote Unix domain socket forwarding
+using the "streamlocal" extension.  Forwarding is initiated as per
+TCP sockets but with a single path instead of a host and port.
+
+Similar to direct-tcpip, direct-streamlocal is sent by the client
+to request that the server make a connection to a Unix domain socket.
+
+       byte            SSH_MSG_CHANNEL_OPEN
+       string          "direct-streamlocal@openssh.com"
+       uint32          sender channel
+       uint32          initial window size
+       uint32          maximum packet size
+       string          socket path
+       string          reserved for future use
+
+Similar to forwarded-tcpip, forwarded-streamlocal is sent by the
+server when the client has previously send the server a streamlocal-forward
+GLOBAL_REQUEST.
+
+       byte            SSH_MSG_CHANNEL_OPEN
+       string          "forwarded-streamlocal@openssh.com"
+       uint32          sender channel
+       uint32          initial window size
+       uint32          maximum packet size
+       string          socket path
+       string          reserved for future use
+
+The reserved field is not currently defined and is ignored on the
+remote end.  It is intended to be used in the future to pass
+information about the socket file, such as ownership and mode.
+The client currently sends the empty string for this field.
+
+Similar to tcpip-forward, streamlocal-forward is sent by the client
+to request remote forwarding of a Unix domain socket.
+
+       byte            SSH2_MSG_GLOBAL_REQUEST
+       string          "streamlocal-forward@openssh.com"
+       boolean         TRUE
+       string          socket path
+
+Similar to cancel-tcpip-forward, cancel-streamlocal-forward is sent
+by the client cancel the forwarding of a Unix domain socket.
+
+       byte            SSH2_MSG_GLOBAL_REQUEST
+       string          "cancel-streamlocal-forward@openssh.com"
+       boolean         FALSE
+       string          socket path
+
 3. SFTP protocol changes
 
 3.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK
@@ -291,4 +392,18 @@ link(oldpath, newpath) and will respond with a SSH_FXP_STATUS message.
 This extension is advertised in the SSH_FXP_VERSION hello with version
 "1".
 
-$OpenBSD: PROTOCOL,v 1.17 2010/12/04 00:18:01 djm Exp $
+10. sftp: Extension request "fsync@openssh.com"
+
+This request asks the server to call fsync(2) on an open file handle.
+
+       uint32          id
+       string          "fsync@openssh.com"
+       string          handle
+
+One receiving this request, a server will call fsync(handle_fd) and will
+respond with a SSH_FXP_STATUS message.
+
+This extension is advertised in the SSH_FXP_VERSION hello with version
+"1".
+
+$OpenBSD: PROTOCOL,v 1.24 2014/07/15 15:54:14 millert Exp $
index de94d03..3fcaa14 100644 (file)
@@ -152,7 +152,7 @@ fully specified using just rsa_q, rsa_p and rsa_e at the cost of extra
 computation.
 
 "key_constraints" may only be present if the request type is
-SSH_AGENTC_ADD_RSA_IDENTITY.
+SSH_AGENTC_ADD_RSA_ID_CONSTRAINED.
 
 The agent will reply with a SSH_AGENT_SUCCESS if the key has been
 successfully added or a SSH_AGENT_FAILURE if an error occurred.
@@ -557,4 +557,4 @@ Locking and unlocking affects both protocol 1 and protocol 2 keys.
        SSH_AGENT_CONSTRAIN_LIFETIME                    1
        SSH_AGENT_CONSTRAIN_CONFIRM                     2
 
-$OpenBSD: PROTOCOL.agent,v 1.6 2010/08/31 11:54:45 djm Exp $
+$OpenBSD: PROTOCOL.agent,v 1.7 2013/01/02 00:33:49 djm Exp $
diff --git a/crypto/openssh/PROTOCOL.chacha20poly1305 b/crypto/openssh/PROTOCOL.chacha20poly1305
new file mode 100644 (file)
index 0000000..9cf73a9
--- /dev/null
@@ -0,0 +1,105 @@
+This document describes the chacha20-poly1305@openssh.com authenticated
+encryption cipher supported by OpenSSH.
+
+Background
+----------
+
+ChaCha20 is a stream cipher designed by Daniel Bernstein and described
+in [1]. It operates by permuting 128 fixed bits, 128 or 256 bits of key,
+a 64 bit nonce and a 64 bit counter into 64 bytes of output. This output
+is used as a keystream, with any unused bytes simply discarded.
+
+Poly1305[2], also by Daniel Bernstein, is a one-time Carter-Wegman MAC
+that computes a 128 bit integrity tag given a message and a single-use
+256 bit secret key.
+
+The chacha20-poly1305@openssh.com combines these two primitives into an
+authenticated encryption mode. The construction used is based on that
+proposed for TLS by Adam Langley in [3], but differs in the layout of
+data passed to the MAC and in the addition of encyption of the packet
+lengths.
+
+Negotiation
+-----------
+
+The chacha20-poly1305@openssh.com offers both encryption and
+authentication. As such, no separate MAC is required. If the
+chacha20-poly1305@openssh.com cipher is selected in key exchange,
+the offered MAC algorithms are ignored and no MAC is required to be
+negotiated.
+
+Detailed Construction
+---------------------
+
+The chacha20-poly1305@openssh.com cipher requires 512 bits of key
+material as output from the SSH key exchange. This forms two 256 bit
+keys (K_1 and K_2), used by two separate instances of chacha20.
+
+The instance keyed by K_1 is a stream cipher that is used only
+to encrypt the 4 byte packet length field. The second instance,
+keyed by K_2, is used in conjunction with poly1305 to build an AEAD
+(Authenticated Encryption with Associated Data) that is used to encrypt
+and authenticate the entire packet.
+
+Two separate cipher instances are used here so as to keep the packet
+lengths confidential but not create an oracle for the packet payload
+cipher by decrypting and using the packet length prior to checking
+the MAC. By using an independently-keyed cipher instance to encrypt the
+length, an active attacker seeking to exploit the packet input handling
+as a decryption oracle can learn nothing about the payload contents or
+its MAC (assuming key derivation, ChaCha20 and Poly1305 are secure).
+
+The AEAD is constructed as follows: for each packet, generate a Poly1305
+key by taking the first 256 bits of ChaCha20 stream output generated
+using K_2, an IV consisting of the packet sequence number encoded as an
+uint64 under the SSH wire encoding rules and a ChaCha20 block counter of
+zero. The K_2 ChaCha20 block counter is then set to the little-endian
+encoding of 1 (i.e. {1, 0, 0, 0, 0, 0, 0, 0}) and this instance is used
+for encryption of the packet payload.
+
+Packet Handling
+---------------
+
+When receiving a packet, the length must be decrypted first. When 4
+bytes of ciphertext length have been received, they may be decrypted
+using the K_1 key, a nonce consisting of the packet sequence number
+encoded as a uint64 under the usual SSH wire encoding and a zero block
+counter to obtain the plaintext length.
+
+Once the entire packet has been received, the MAC MUST be checked
+before decryption. A per-packet Poly1305 key is generated as described
+above and the MAC tag calculated using Poly1305 with this key over the
+ciphertext of the packet length and the payload together. The calculated
+MAC is then compared in constant time with the one appended to the
+packet and the packet decrypted using ChaCha20 as described above (with
+K_2, the packet sequence number as nonce and a starting block counter of
+1).
+
+To send a packet, first encode the 4 byte length and encrypt it using
+K_1. Encrypt the packet payload (using K_2) and append it to the
+encrypted length. Finally, calculate a MAC tag and append it.
+
+Rekeying
+--------
+
+ChaCha20 must never reuse a {key, nonce} for encryption nor may it be
+used to encrypt more than 2^70 bytes under the same {key, nonce}. The
+SSH Transport protocol (RFC4253) recommends a far more conservative
+rekeying every 1GB of data sent or received. If this recommendation
+is followed, then chacha20-poly1305@openssh.com requires no special
+handling in this area.
+
+References
+----------
+
+[1] "ChaCha, a variant of Salsa20", Daniel Bernstein
+    http://cr.yp.to/chacha/chacha-20080128.pdf
+
+[2] "The Poly1305-AES message-authentication code", Daniel Bernstein
+    http://cr.yp.to/mac/poly1305-20050329.pdf
+
+[3] "ChaCha20 and Poly1305 based Cipher Suites for TLS", Adam Langley
+    http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-03
+
+$OpenBSD: PROTOCOL.chacha20poly1305,v 1.2 2013/12/02 02:50:27 djm Exp $
+
diff --git a/crypto/openssh/PROTOCOL.key b/crypto/openssh/PROTOCOL.key
new file mode 100644 (file)
index 0000000..959bd7a
--- /dev/null
@@ -0,0 +1,68 @@
+This document describes the private key format for OpenSSH.
+
+1. Overall format
+
+The key consists of a header, a list of public keys, and
+an encrypted list of matching private keys.
+
+#define AUTH_MAGIC      "openssh-key-v1"
+
+       byte[]  AUTH_MAGIC
+       string  ciphername
+       string  kdfname
+       string  kdfoptions
+       int     number of keys N
+       string  publickey1
+       string  publickey2
+       ...
+       string  publickeyN
+       string  encrypted, padded list of private keys
+
+2. KDF options for kdfname "bcrypt"
+
+The options:
+
+       string salt
+       uint32 rounds
+
+are concatenated and represented as a string.
+
+3. Unencrypted list of N private keys
+
+The list of privatekey/comment pairs is padded with the
+bytes 1, 2, 3, ... until the total length is a multiple
+of the cipher block size.
+
+       uint32  checkint
+       uint32  checkint
+       string  privatekey1
+       string  comment1
+       string  privatekey2
+       string  comment2
+       ...
+       string  privatekeyN
+       string  commentN
+       char    1
+       char    2
+       char    3
+       ...
+       char    padlen % 255
+
+Before the key is encrypted, a random integer is assigned
+to both checkint fields so successful decryption can be
+quickly checked by verifying that both checkint fields
+hold the same value.
+
+4. Encryption
+
+The KDF is used to derive a key, IV (and other values required by
+the cipher) from the passphrase. These values are then used to
+encrypt the unencrypted list of private keys.
+
+5. No encryption
+
+For unencrypted keys the cipher "none" and the KDF "none"
+are used with empty passphrases. The options if the KDF "none"
+are the empty string.
+
+$OpenBSD: PROTOCOL.key,v 1.1 2013/12/06 13:34:54 markus Exp $
diff --git a/crypto/openssh/PROTOCOL.krl b/crypto/openssh/PROTOCOL.krl
new file mode 100644 (file)
index 0000000..e8caa45
--- /dev/null
@@ -0,0 +1,164 @@
+This describes the key/certificate revocation list format for OpenSSH.
+
+1. Overall format
+
+The KRL consists of a header and zero or more sections. The header is:
+
+#define KRL_MAGIC              0x5353484b524c0a00ULL  /* "SSHKRL\n\0" */
+#define KRL_FORMAT_VERSION     1
+
+       uint64  KRL_MAGIC
+       uint32  KRL_FORMAT_VERSION
+       uint64  krl_version
+       uint64  generated_date
+       uint64  flags
+       string  reserved
+       string  comment
+
+Where "krl_version" is a version number that increases each time the KRL
+is modified, "generated_date" is the time in seconds since 1970-01-01
+00:00:00 UTC that the KRL was generated, "comment" is an optional comment
+and "reserved" an extension field whose contents are currently ignored.
+No "flags" are currently defined.
+
+Following the header are zero or more sections, each consisting of:
+
+       byte    section_type
+       string  section_data
+
+Where "section_type" indicates the type of the "section_data". An exception
+to this is the KRL_SECTION_SIGNATURE section, that has a slightly different
+format (see below).
+
+The available section types are:
+
+#define KRL_SECTION_CERTIFICATES               1
+#define KRL_SECTION_EXPLICIT_KEY               2
+#define KRL_SECTION_FINGERPRINT_SHA1           3
+#define KRL_SECTION_SIGNATURE                  4
+
+3. Certificate serial section
+
+These sections use type KRL_SECTION_CERTIFICATES to revoke certificates by
+serial number or key ID. The consist of the CA key that issued the
+certificates to be revoked and a reserved field whose contents is currently
+ignored.
+
+       string ca_key
+       string reserved
+
+Followed by one or more sections:
+
+       byte    cert_section_type
+       string  cert_section_data
+
+The certificate section types are:
+
+#define KRL_SECTION_CERT_SERIAL_LIST   0x20
+#define KRL_SECTION_CERT_SERIAL_RANGE  0x21
+#define KRL_SECTION_CERT_SERIAL_BITMAP 0x22
+#define KRL_SECTION_CERT_KEY_ID                0x23
+
+2.1 Certificate serial list section
+
+This section is identified as KRL_SECTION_CERT_SERIAL_LIST. It revokes
+certificates by listing their serial numbers. The cert_section_data in this
+case contains:
+
+       uint64  revoked_cert_serial
+       uint64  ...
+
+This section may appear multiple times.
+
+2.2. Certificate serial range section
+
+These sections use type KRL_SECTION_CERT_SERIAL_RANGE and hold
+a range of serial numbers of certificates:
+
+       uint64  serial_min
+       uint64  serial_max
+
+All certificates in the range serial_min <= serial <= serial_max are
+revoked.
+
+This section may appear multiple times.
+
+2.3. Certificate serial bitmap section
+
+Bitmap sections use type KRL_SECTION_CERT_SERIAL_BITMAP and revoke keys
+by listing their serial number in a bitmap.
+
+       uint64  serial_offset
+       mpint   revoked_keys_bitmap
+
+A bit set at index N in the bitmap corresponds to revocation of a keys with
+serial number (serial_offset + N).
+
+This section may appear multiple times.
+
+2.4. Revoked key ID sections
+
+KRL_SECTION_CERT_KEY_ID sections revoke particular certificate "key
+ID" strings. This may be useful in revoking all certificates
+associated with a particular identity, e.g. a host or a user.
+
+       string  key_id[0]
+       ...
+
+This section must contain at least one "key_id". This section may appear
+multiple times.
+
+3. Explicit key sections
+
+These sections, identified as KRL_SECTION_EXPLICIT_KEY, revoke keys
+(not certificates). They are less space efficient than serial numbers,
+but are able to revoke plain keys.
+
+       string  public_key_blob[0]
+       ....
+
+This section must contain at least one "public_key_blob". The blob
+must be a raw key (i.e. not a certificate).
+
+This section may appear multiple times.
+
+4. SHA1 fingerprint sections
+
+These sections, identified as KRL_SECTION_FINGERPRINT_SHA1, revoke
+plain keys (i.e. not certificates) by listing their SHA1 hashes:
+
+       string  public_key_hash[0]
+       ....
+
+This section must contain at least one "public_key_hash". The hash blob
+is obtained by taking the SHA1 hash of the public key blob. Hashes in
+this section must appear in numeric order, treating each hash as a big-
+endian integer.
+
+This section may appear multiple times.
+
+5. KRL signature sections
+
+The KRL_SECTION_SIGNATURE section serves a different purpose to the
+preceeding ones: to provide cryptographic authentication of a KRL that
+is retrieved over a channel that does not provide integrity protection.
+Its format is slightly different to the previously-described sections:
+in order to simplify the signature generation, it includes as a "body"
+two string components instead of one.
+
+       byte    KRL_SECTION_SIGNATURE
+       string  signature_key
+       string  signature
+
+The signature is calculated over the entire KRL from the KRL_MAGIC
+to this subsection's "signature_key", including both and using the
+signature generation rules appropriate for the type of "signature_key".
+
+This section must appear last in the KRL. If multiple signature sections
+appear, they must appear consecutively at the end of the KRL file.
+
+Implementations that retrieve KRLs over untrusted channels must verify
+signatures. Signature sections are optional for KRLs distributed by
+trusted means.
+
+$OpenBSD: PROTOCOL.krl,v 1.2 2013/01/18 00:24:58 djm Exp $
index 81cb922..b21441a 100644 (file)
@@ -1,4 +1,4 @@
-See http://www.openssh.com/txt/release-6.1 for the release notes.
+See http://www.openssh.com/txt/release-6.7 for the release notes.
 
 - A Japanese translation of this document and of the OpenSSH FAQ is
 - available at http://www.unixuser.org/~haruyama/security/openssh/index.html
@@ -62,4 +62,4 @@ References -
 [6] http://www.openbsd.org/cgi-bin/man.cgi?query=style&sektion=9
 [7] http://www.openssh.com/faq.html
 
-$Id: README,v 1.81 2012/08/22 11:57:13 djm Exp $
+$Id: README,v 1.87 2014/08/10 01:35:06 djm Exp $
index 4a44fd2..b185d7d 100644 (file)
@@ -8,12 +8,14 @@ TODO
 aclocal.m4
 audit-linux.c
 buildpkg.sh.in
+cipher-aesctr.c
 config.guess
 config.h.in
 config.sub
 configure
 configure.ac
 contrib/
+fixalgorithms
 fixpaths
 fixprogs
 install-sh
@@ -27,7 +29,6 @@ openbsd-compat/Makefile.in
 openbsd-compat/base64.c
 openbsd-compat/basename.c
 openbsd-compat/bindresvport.c
-openbsd-compat/bsd-arc4random.c
 openbsd-compat/bsd-asprintf.c
 openbsd-compat/bsd-closefrom.c
 openbsd-compat/bsd-cray.c
@@ -44,7 +45,6 @@ openbsd-compat/dirname.c
 openbsd-compat/fake-rfc2553.c
 openbsd-compat/getcwd.c
 openbsd-compat/getgrouplist.c
-openbsd-compat/getopt.c
 openbsd-compat/getrrsetbyname-ldns.c
 openbsd-compat/inet_aton.c
 openbsd-compat/inet_ntoa.c
@@ -98,4 +98,3 @@ ssh_config.0
 sshd.0
 sshd_config.0
 survey.sh.in
-version.h
diff --git a/crypto/openssh/acss.c b/crypto/openssh/acss.c
deleted file mode 100644 (file)
index 86e2c01..0000000
+++ /dev/null
@@ -1,267 +0,0 @@
-/*     $Id: acss.c,v 1.4 2006/07/24 04:51:01 djm Exp $ */
-/*
- * Copyright (c) 2004 The OpenBSD project
- *
- * 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"
-
-#include <string.h>
-
-#include <openssl/evp.h>
-
-#if !defined(EVP_CTRL_SET_ACSS_MODE) && (OPENSSL_VERSION_NUMBER >= 0x00906000L)
-
-#include "acss.h"
-
-/* decryption sbox */
-static unsigned char sboxdec[] = {
-       0x33, 0x73, 0x3b, 0x26, 0x63, 0x23, 0x6b, 0x76,
-       0x3e, 0x7e, 0x36, 0x2b, 0x6e, 0x2e, 0x66, 0x7b,
-       0xd3, 0x93, 0xdb, 0x06, 0x43, 0x03, 0x4b, 0x96,
-       0xde, 0x9e, 0xd6, 0x0b, 0x4e, 0x0e, 0x46, 0x9b,
-       0x57, 0x17, 0x5f, 0x82, 0xc7, 0x87, 0xcf, 0x12,
-       0x5a, 0x1a, 0x52, 0x8f, 0xca, 0x8a, 0xc2, 0x1f,
-       0xd9, 0x99, 0xd1, 0x00, 0x49, 0x09, 0x41, 0x90,
-       0xd8, 0x98, 0xd0, 0x01, 0x48, 0x08, 0x40, 0x91,
-       0x3d, 0x7d, 0x35, 0x24, 0x6d, 0x2d, 0x65, 0x74,
-       0x3c, 0x7c, 0x34, 0x25, 0x6c, 0x2c, 0x64, 0x75,
-       0xdd, 0x9d, 0xd5, 0x04, 0x4d, 0x0d, 0x45, 0x94,
-       0xdc, 0x9c, 0xd4, 0x05, 0x4c, 0x0c, 0x44, 0x95,
-       0x59, 0x19, 0x51, 0x80, 0xc9, 0x89, 0xc1, 0x10,
-       0x58, 0x18, 0x50, 0x81, 0xc8, 0x88, 0xc0, 0x11,
-       0xd7, 0x97, 0xdf, 0x02, 0x47, 0x07, 0x4f, 0x92,
-       0xda, 0x9a, 0xd2, 0x0f, 0x4a, 0x0a, 0x42, 0x9f,
-       0x53, 0x13, 0x5b, 0x86, 0xc3, 0x83, 0xcb, 0x16,
-       0x5e, 0x1e, 0x56, 0x8b, 0xce, 0x8e, 0xc6, 0x1b,
-       0xb3, 0xf3, 0xbb, 0xa6, 0xe3, 0xa3, 0xeb, 0xf6,
-       0xbe, 0xfe, 0xb6, 0xab, 0xee, 0xae, 0xe6, 0xfb,
-       0x37, 0x77, 0x3f, 0x22, 0x67, 0x27, 0x6f, 0x72,
-       0x3a, 0x7a, 0x32, 0x2f, 0x6a, 0x2a, 0x62, 0x7f,
-       0xb9, 0xf9, 0xb1, 0xa0, 0xe9, 0xa9, 0xe1, 0xf0,
-       0xb8, 0xf8, 0xb0, 0xa1, 0xe8, 0xa8, 0xe0, 0xf1,
-       0x5d, 0x1d, 0x55, 0x84, 0xcd, 0x8d, 0xc5, 0x14,
-       0x5c, 0x1c, 0x54, 0x85, 0xcc, 0x8c, 0xc4, 0x15,
-       0xbd, 0xfd, 0xb5, 0xa4, 0xed, 0xad, 0xe5, 0xf4,
-       0xbc, 0xfc, 0xb4, 0xa5, 0xec, 0xac, 0xe4, 0xf5,
-       0x39, 0x79, 0x31, 0x20, 0x69, 0x29, 0x61, 0x70,
-       0x38, 0x78, 0x30, 0x21, 0x68, 0x28, 0x60, 0x71,
-       0xb7, 0xf7, 0xbf, 0xa2, 0xe7, 0xa7, 0xef, 0xf2,
-       0xba, 0xfa, 0xb2, 0xaf, 0xea, 0xaa, 0xe2, 0xff
-};
-
-/* encryption sbox */
-static unsigned char sboxenc[] = {
-       0x33, 0x3b, 0x73, 0x15, 0x53, 0x5b, 0x13, 0x75,
-       0x3d, 0x35, 0x7d, 0x1b, 0x5d, 0x55, 0x1d, 0x7b,
-       0x67, 0x6f, 0x27, 0x81, 0xc7, 0xcf, 0x87, 0x21,
-       0x69, 0x61, 0x29, 0x8f, 0xc9, 0xc1, 0x89, 0x2f,
-       0xe3, 0xeb, 0xa3, 0x05, 0x43, 0x4b, 0x03, 0xa5,
-       0xed, 0xe5, 0xad, 0x0b, 0x4d, 0x45, 0x0d, 0xab,
-       0xea, 0xe2, 0xaa, 0x00, 0x4a, 0x42, 0x0a, 0xa0,
-       0xe8, 0xe0, 0xa8, 0x02, 0x48, 0x40, 0x08, 0xa2,
-       0x3e, 0x36, 0x7e, 0x14, 0x5e, 0x56, 0x1e, 0x74,
-       0x3c, 0x34, 0x7c, 0x16, 0x5c, 0x54, 0x1c, 0x76,
-       0x6a, 0x62, 0x2a, 0x80, 0xca, 0xc2, 0x8a, 0x20,
-       0x68, 0x60, 0x28, 0x82, 0xc8, 0xc0, 0x88, 0x22,
-       0xee, 0xe6, 0xae, 0x04, 0x4e, 0x46, 0x0e, 0xa4,
-       0xec, 0xe4, 0xac, 0x06, 0x4c, 0x44, 0x0c, 0xa6,
-       0xe7, 0xef, 0xa7, 0x01, 0x47, 0x4f, 0x07, 0xa1,
-       0xe9, 0xe1, 0xa9, 0x0f, 0x49, 0x41, 0x09, 0xaf,
-       0x63, 0x6b, 0x23, 0x85, 0xc3, 0xcb, 0x83, 0x25,
-       0x6d, 0x65, 0x2d, 0x8b, 0xcd, 0xc5, 0x8d, 0x2b,
-       0x37, 0x3f, 0x77, 0x11, 0x57, 0x5f, 0x17, 0x71,
-       0x39, 0x31, 0x79, 0x1f, 0x59, 0x51, 0x19, 0x7f,
-       0xb3, 0xbb, 0xf3, 0x95, 0xd3, 0xdb, 0x93, 0xf5,
-       0xbd, 0xb5, 0xfd, 0x9b, 0xdd, 0xd5, 0x9d, 0xfb,
-       0xba, 0xb2, 0xfa, 0x90, 0xda, 0xd2, 0x9a, 0xf0,
-       0xb8, 0xb0, 0xf8, 0x92, 0xd8, 0xd0, 0x98, 0xf2,
-       0x6e, 0x66, 0x2e, 0x84, 0xce, 0xc6, 0x8e, 0x24,
-       0x6c, 0x64, 0x2c, 0x86, 0xcc, 0xc4, 0x8c, 0x26,
-       0x3a, 0x32, 0x7a, 0x10, 0x5a, 0x52, 0x1a, 0x70,
-       0x38, 0x30, 0x78, 0x12, 0x58, 0x50, 0x18, 0x72,
-       0xbe, 0xb6, 0xfe, 0x94, 0xde, 0xd6, 0x9e, 0xf4,
-       0xbc, 0xb4, 0xfc, 0x96, 0xdc, 0xd4, 0x9c, 0xf6,
-       0xb7, 0xbf, 0xf7, 0x91, 0xd7, 0xdf, 0x97, 0xf1,
-       0xb9, 0xb1, 0xf9, 0x9f, 0xd9, 0xd1, 0x99, 0xff
-};
-
-static unsigned char reverse[] = {
-       0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
-       0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
-       0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
-       0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
-       0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
-       0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
-       0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
-       0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
-       0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
-       0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
-       0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
-       0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
-       0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
-       0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
-       0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
-       0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
-       0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
-       0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
-       0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
-       0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
-       0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
-       0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
-       0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
-       0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
-       0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
-       0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
-       0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
-       0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
-       0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
-       0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
-       0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
-       0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
-};
-
-/*
- * Two linear feedback shift registers are used:
- *
- * lfsr17:  polynomial of degree 17, primitive modulo 2 (listed in Schneier)
- *          x^15 + x + 1
- * lfsr25:  polynomial of degree 25, not know if primitive modulo 2
- *          x^13 + x^5 + x^4 + x^1 + 1
- *
- * Output bits are discarded, instead the feedback bits are added to produce
- * the cipher stream.  Depending on the mode, feedback bytes may be inverted
- * bit-wise before addition.
- *
- * The lfsrs are seeded with bytes from the raw key:
- *
- * lfsr17:  byte 0[0:7] at bit 9
- *          byte 1[0:7] at bit 0
- *
- * lfsr25:  byte 2[0:4] at bit 16
- *          byte 2[5:7] at bit 22
- *          byte 3[0:7] at bit 8
- *          byte 4[0:7] at bit 0
- *
- * To prevent 0 cycles, 1's are inject at bit 8 in lfrs17 and bit 21 in
- * lfsr25.
- *
- */
-
-int
-acss(ACSS_KEY *key, unsigned long len, const unsigned char *in,
-    unsigned char *out)
-{
-       unsigned long i;
-       unsigned long lfsr17tmp, lfsr25tmp, lfsrsumtmp;
-
-       lfsrsumtmp = lfsr17tmp = lfsr25tmp = 0;
-
-       /* keystream is sum of lfsrs */
-       for (i = 0; i < len; i++) {
-               lfsr17tmp = key->lfsr17 ^ (key->lfsr17 >> 14);
-               key->lfsr17 = (key->lfsr17 >> 8)
-                       ^ (lfsr17tmp << 9)
-                       ^ (lfsr17tmp << 12)
-                       ^ (lfsr17tmp << 15);
-               key->lfsr17 &= 0x1ffff; /* 17 bit LFSR */
-
-               lfsr25tmp = key->lfsr25
-                       ^ (key->lfsr25 >> 3)
-                       ^ (key->lfsr25 >> 4)
-                       ^ (key->lfsr25 >> 12);
-               key->lfsr25 = (key->lfsr25 >> 8) ^ (lfsr25tmp << 17);
-               key->lfsr25 &= 0x1ffffff;       /* 25 bit LFSR */
-
-               lfsrsumtmp = key->lfsrsum;
-
-               /* addition */
-               switch (key->mode) {
-               case ACSS_AUTHENTICATE:
-               case ACSS_DATA:
-                       key->lfsrsum = 0xff & ~(key->lfsr17 >> 9);
-                       key->lfsrsum += key->lfsr25 >> 17;
-                       break;
-               case ACSS_SESSIONKEY:
-                       key->lfsrsum = key->lfsr17 >> 9;
-                       key->lfsrsum += key->lfsr25 >> 17;
-                       break;
-               case ACSS_TITLEKEY:
-                       key->lfsrsum = key->lfsr17 >> 9;
-                       key->lfsrsum += 0xff & ~(key->lfsr25 >> 17);
-                       break;
-               default:
-                       return 1;
-               }
-               key->lfsrsum += (lfsrsumtmp >> 8);
-
-               if (key->encrypt) {
-                       out[i] = sboxenc[(in[i] ^ key->lfsrsum) & 0xff];
-               } else {
-                       out[i] = (sboxdec[in[i]] ^ key->lfsrsum) & 0xff;
-               }
-       }
-
-       return 0;
-}
-
-static void
-acss_seed(ACSS_KEY *key)
-{
-       int i;
-
-       /* if available, mangle with subkey */
-       if (key->subkey_avilable) {
-               for (i = 0; i < ACSS_KEYSIZE; i++)
-                       key->seed[i] = reverse[key->data[i] ^ key->subkey[i]];
-       } else {
-               for (i = 0; i < ACSS_KEYSIZE; i++)
-                       key->seed[i] = reverse[key->data[i]];
-       }
-
-       /* seed lfsrs */
-       key->lfsr17 = key->seed[1]
-               | (key->seed[0] << 9)
-               | (1 << 8);     /* inject 1 at bit 9 */
-       key->lfsr25 = key->seed[4]
-               | (key->seed[3] << 8)
-               | ((key->seed[2] & 0x1f) << 16)
-               | ((key->seed[2] & 0xe0) << 17)
-                       | (1 << 21);    /* inject 1 at bit 22 */
-
-       key->lfsrsum = 0;
-}
-
-void
-acss_setkey(ACSS_KEY *key, const unsigned char *data, int enc, int mode)
-{
-       memcpy(key->data, data, sizeof(key->data));
-       memset(key->subkey, 0, sizeof(key->subkey));
-
-       if (enc != -1)
-               key->encrypt = enc;
-       key->mode = mode;
-       key->subkey_avilable = 0;
-
-       acss_seed(key);
-}
-
-void
-acss_setsubkey(ACSS_KEY *key, const unsigned char *subkey)
-{
-       memcpy(key->subkey, subkey, sizeof(key->subkey));
-       key->subkey_avilable = 1;
-       acss_seed(key);
-}
-#endif
diff --git a/crypto/openssh/acss.h b/crypto/openssh/acss.h
deleted file mode 100644 (file)
index 91b4895..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*     $Id: acss.h,v 1.2 2004/02/06 04:22:43 dtucker Exp $ */
-/*
- * Copyright (c) 2004 The OpenBSD project
- *
- * 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.
- */
-
-#ifndef _ACSS_H_
-#define _ACSS_H_
-
-/* 40bit key */
-#define ACSS_KEYSIZE           5
-
-/* modes of acss */
-#define ACSS_AUTHENTICATE      0
-#define ACSS_SESSIONKEY                1
-#define ACSS_TITLEKEY          2
-#define ACSS_DATA              3
-
-typedef struct acss_key_st {
-       unsigned int    lfsr17;         /* current state of lfsrs */
-       unsigned int    lfsr25;
-       unsigned int    lfsrsum;
-       unsigned char   seed[ACSS_KEYSIZE];
-       unsigned char   data[ACSS_KEYSIZE];
-       unsigned char   subkey[ACSS_KEYSIZE];
-       int             encrypt;        /* XXX make these bit flags? */
-       int             mode;
-       int             seeded;
-       int             subkey_avilable;
-} ACSS_KEY;
-
-void acss_setkey(ACSS_KEY *, const unsigned char *, int, int);
-void acss_setsubkey(ACSS_KEY *, const unsigned char *);
-int acss(ACSS_KEY *, unsigned long, const unsigned char *, unsigned char *);
-
-#endif /* ifndef _ACSS_H_ */
index 388603c..c443146 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: addrmatch.c,v 1.6 2012/06/21 00:16:07 dtucker Exp $ */
+/*     $OpenBSD: addrmatch.c,v 1.9 2014/01/19 11:21:51 dtucker Exp $ */
 
 /*
  * Copyright (c) 2004-2008 Damien Miller <djm@mindrot.org>
@@ -88,13 +88,13 @@ addr_sa_to_xaddr(struct sockaddr *sa, socklen_t slen, struct xaddr *xa)
 
        switch (sa->sa_family) {
        case AF_INET:
-               if (slen < sizeof(*in4))
+               if (slen < (socklen_t)sizeof(*in4))
                        return -1;
                xa->af = AF_INET;
                memcpy(&xa->v4, &in4->sin_addr, sizeof(xa->v4));
                break;
        case AF_INET6:
-               if (slen < sizeof(*in6))
+               if (slen < (socklen_t)sizeof(*in6))
                        return -1;
                xa->af = AF_INET6;
                memcpy(&xa->v6, &in6->sin6_addr, sizeof(xa->v6));
@@ -420,7 +420,7 @@ addr_match_list(const char *addr, const char *_list)
                                goto foundit;
                }
        }
-       xfree(o);
+       free(o);
 
        return ret;
 }
@@ -494,7 +494,7 @@ addr_match_cidr_list(const char *addr, const char *_list)
                        continue;
                }
        }
-       xfree(o);
+       free(o);
 
        return ret;
 }
index 601b3c3..2bac36c 100644 (file)
@@ -56,8 +56,10 @@ atomicio6(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n,
        ssize_t res;
        struct pollfd pfd;
 
+#ifndef BROKEN_READ_COMPARISON
        pfd.fd = fd;
        pfd.events = f == read ? POLLIN : POLLOUT;
+#endif
        while (n > pos) {
                res = (f) (fd, s + pos, n - pos);
                switch (res) {
@@ -65,7 +67,9 @@ atomicio6(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n,
                        if (errno == EINTR)
                                continue;
                        if (errno == EAGAIN || errno == EWOULDBLOCK) {
+#ifndef BROKEN_READ_COMPARISON
                                (void)poll(&pfd, 1, -1);
+#endif
                                continue;
                        }
                        return 0;
index 0b3262b..37ff893 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-bsdauth.c,v 1.11 2007/09/21 08:15:29 djm Exp $ */
+/* $OpenBSD: auth-bsdauth.c,v 1.13 2014/06/24 01:13:21 djm Exp $ */
 /*
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
  *
@@ -26,6 +26,8 @@
 #include "includes.h"
 
 #include <sys/types.h>
+#include <stdarg.h>
+#include <stdio.h>
 
 #include <stdarg.h>
 
@@ -54,6 +56,11 @@ bsdauth_query(void *ctx, char **name, char **infotxt,
        Authctxt *authctxt = ctx;
        char *challenge = NULL;
 
+       *infotxt = NULL;
+       *numprompts = 0;
+       *prompts = NULL;
+       *echo_on = NULL;
+
        if (authctxt->as != NULL) {
                debug2("bsdauth_query: try reuse session");
                challenge = auth_getitem(authctxt->as, AUTHV_CHALLENGE);
index 919b1ea..5c26a40 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-chall.c,v 1.12 2006/08/03 03:34:41 deraadt Exp $ */
+/* $OpenBSD: auth-chall.c,v 1.14 2014/06/24 01:13:21 djm Exp $ */
 /*
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
  *
@@ -26,6 +26,9 @@
 #include "includes.h"
 
 #include <sys/types.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
 
 #include <stdarg.h>
 
@@ -34,6 +37,7 @@
 #include "hostfile.h"
 #include "auth.h"
 #include "log.h"
+#include "misc.h"
 #include "servconf.h"
 
 /* limited protocol v1 interface to kbd-interactive authentication */
@@ -69,11 +73,11 @@ get_challenge(Authctxt *authctxt)
                fatal("get_challenge: numprompts < 1");
        challenge = xstrdup(prompts[0]);
        for (i = 0; i < numprompts; i++)
-               xfree(prompts[i]);
-       xfree(prompts);
-       xfree(name);
-       xfree(echo_on);
-       xfree(info);
+               free(prompts[i]);
+       free(prompts);
+       free(name);
+       free(echo_on);
+       free(info);
 
        return (challenge);
 }
@@ -102,11 +106,11 @@ verify_response(Authctxt *authctxt, const char *response)
                        authenticated = 1;
 
                for (i = 0; i < numprompts; i++)
-                       xfree(prompts[i]);
-               xfree(prompts);
-               xfree(name);
-               xfree(echo_on);
-               xfree(info);
+                       free(prompts[i]);
+               free(prompts);
+               free(name);
+               free(echo_on);
+               free(info);
                break;
        }
        device->free_ctx(authctxt->kbdintctxt);
index 922c66c..0089b18 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-krb5.c,v 1.19 2006/08/03 03:34:41 deraadt Exp $ */
+/* $OpenBSD: auth-krb5.c,v 1.20 2013/07/20 01:55:13 djm Exp $ */
 /*
  *    Kerberos v5 authentication and ticket-passing routines.
  *
@@ -40,6 +40,7 @@
 #include "packet.h"
 #include "log.h"
 #include "buffer.h"
+#include "misc.h"
 #include "servconf.h"
 #include "uidswap.h"
 #include "key.h"
@@ -79,6 +80,7 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
        krb5_ccache ccache = NULL;
        int len;
        char *client, *platform_client;
+       const char *errmsg;
 
        /* get platform-specific kerberos client principal name (if it exists) */
        platform_client = platform_krb5_get_principal_name(authctxt->pw->pw_name);
@@ -96,7 +98,12 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
                goto out;
 
 #ifdef HEIMDAL
+# ifdef HAVE_KRB5_CC_NEW_UNIQUE
+       problem = krb5_cc_new_unique(authctxt->krb5_ctx,
+            krb5_mcc_ops.prefix, NULL, &ccache);
+# else
        problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops, &ccache);
+# endif
        if (problem)
                goto out;
 
@@ -115,8 +122,13 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
        if (problem)
                goto out;
 
+# ifdef HAVE_KRB5_CC_NEW_UNIQUE
+       problem = krb5_cc_new_unique(authctxt->krb5_ctx,
+            krb5_fcc_ops.prefix, NULL, &authctxt->krb5_fwd_ccache);
+# else
        problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops,
            &authctxt->krb5_fwd_ccache);
+# endif
        if (problem)
                goto out;
 
@@ -146,7 +158,8 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
        if (problem)
                goto out;
 
-       if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, client)) {
+       if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user,
+           authctxt->pw->pw_name)) {
                problem = -1;
                goto out;
        }
@@ -181,17 +194,19 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
  out:
        restore_uid();
        
-       if (platform_client != NULL)
-               xfree(platform_client);
+       free(platform_client);
 
        if (problem) {
                if (ccache)
                        krb5_cc_destroy(authctxt->krb5_ctx, ccache);
 
-               if (authctxt->krb5_ctx != NULL && problem!=-1)
-                       debug("Kerberos password authentication failed: %s",
-                           krb5_get_err_text(authctxt->krb5_ctx, problem));
-               else
+               if (authctxt->krb5_ctx != NULL && problem!=-1) {
+                       errmsg = krb5_get_error_message(authctxt->krb5_ctx,
+                           problem);
+                       debug("Kerberos password authentication failed: %s",
+                           errmsg);
+                       krb5_free_error_message(authctxt->krb5_ctx, errmsg);
+               } else
                        debug("Kerberos password authentication failed: %d",
                            problem);
 
index 0e67bd8..f3d9c9d 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-options.c,v 1.56 2011/10/18 04:58:26 djm Exp $ */
+/* $OpenBSD: auth-options.c,v 1.64 2014/07/15 15:54:14 millert Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
 #include "log.h"
 #include "canohost.h"
 #include "buffer.h"
+#include "misc.h"
 #include "channels.h"
 #include "servconf.h"
-#include "misc.h"
 #include "key.h"
 #include "auth-options.h"
 #include "hostfile.h"
 #include "auth.h"
-#ifdef GSSAPI
-#include "ssh-gss.h"
-#endif
-#include "monitor_wrap.h"
 
 /* Flags set authorized_keys flags */
 int no_port_forwarding_flag = 0;
@@ -72,15 +68,15 @@ auth_clear_options(void)
        while (custom_environment) {
                struct envstring *ce = custom_environment;
                custom_environment = ce->next;
-               xfree(ce->s);
-               xfree(ce);
+               free(ce->s);
+               free(ce);
        }
        if (forced_command) {
-               xfree(forced_command);
+               free(forced_command);
                forced_command = NULL;
        }
        if (authorized_principals) {
-               xfree(authorized_principals);
+               free(authorized_principals);
                authorized_principals = NULL;
        }
        forced_tun_device = -1;
@@ -149,7 +145,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
                if (strncasecmp(opts, cp, strlen(cp)) == 0) {
                        opts += strlen(cp);
                        if (forced_command != NULL)
-                               xfree(forced_command);
+                               free(forced_command);
                        forced_command = xmalloc(strlen(opts) + 1);
                        i = 0;
                        while (*opts) {
@@ -167,7 +163,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
                                    file, linenum);
                                auth_debug_add("%.100s, line %lu: missing end quote",
                                    file, linenum);
-                               xfree(forced_command);
+                               free(forced_command);
                                forced_command = NULL;
                                goto bad_option;
                        }
@@ -180,7 +176,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
                if (strncasecmp(opts, cp, strlen(cp)) == 0) {
                        opts += strlen(cp);
                        if (authorized_principals != NULL)
-                               xfree(authorized_principals);
+                               free(authorized_principals);
                        authorized_principals = xmalloc(strlen(opts) + 1);
                        i = 0;
                        while (*opts) {
@@ -198,7 +194,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
                                    file, linenum);
                                auth_debug_add("%.100s, line %lu: missing end quote",
                                    file, linenum);
-                               xfree(authorized_principals);
+                               free(authorized_principals);
                                authorized_principals = NULL;
                                goto bad_option;
                        }
@@ -232,14 +228,14 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
                                    file, linenum);
                                auth_debug_add("%.100s, line %lu: missing end quote",
                                    file, linenum);
-                               xfree(s);
+                               free(s);
                                goto bad_option;
                        }
                        s[i] = '\0';
                        auth_debug_add("Adding to environment: %.900s", s);
                        debug("Adding to environment: %.900s", s);
                        opts++;
-                       new_envstring = xmalloc(sizeof(struct envstring));
+                       new_envstring = xcalloc(1, sizeof(struct envstring));
                        new_envstring->s = s;
                        new_envstring->next = custom_environment;
                        custom_environment = new_envstring;
@@ -269,7 +265,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
                                    file, linenum);
                                auth_debug_add("%.100s, line %lu: missing end quote",
                                    file, linenum);
-                               xfree(patterns);
+                               free(patterns);
                                goto bad_option;
                        }
                        patterns[i] = '\0';
@@ -277,7 +273,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
                        switch (match_host_and_ip(remote_host, remote_ip,
                            patterns)) {
                        case 1:
-                               xfree(patterns);
+                               free(patterns);
                                /* Host name matches. */
                                goto next_option;
                        case -1:
@@ -287,7 +283,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
                                    "invalid criteria", file, linenum);
                                /* FALLTHROUGH */
                        case 0:
-                               xfree(patterns);
+                               free(patterns);
                                logit("Authentication tried for %.100s with "
                                    "correct key but not from a permitted "
                                    "host (host=%.200s, ip=%.200s).",
@@ -323,12 +319,13 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
                                    file, linenum);
                                auth_debug_add("%.100s, line %lu: missing "
                                    "end quote", file, linenum);
-                               xfree(patterns);
+                               free(patterns);
                                goto bad_option;
                        }
                        patterns[i] = '\0';
                        opts++;
                        p = patterns;
+                       /* XXX - add streamlocal support */
                        host = hpdelim(&p);
                        if (host == NULL || strlen(host) >= NI_MAXHOST) {
                                debug("%.100s, line %lu: Bad permitopen "
@@ -337,7 +334,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
                                auth_debug_add("%.100s, line %lu: "
                                    "Bad permitopen specification", file,
                                    linenum);
-                               xfree(patterns);
+                               free(patterns);
                                goto bad_option;
                        }
                        host = cleanhostname(host);
@@ -346,12 +343,12 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
                                    "<%.100s>", file, linenum, p ? p : "");
                                auth_debug_add("%.100s, line %lu: "
                                    "Bad permitopen port", file, linenum);
-                               xfree(patterns);
+                               free(patterns);
                                goto bad_option;
                        }
-                       if (options.allow_tcp_forwarding)
+                       if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0)
                                channel_add_permitted_opens(host, port);
-                       xfree(patterns);
+                       free(patterns);
                        goto next_option;
                }
                cp = "tunnel=\"";
@@ -370,13 +367,13 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
                                    file, linenum);
                                auth_debug_add("%.100s, line %lu: missing end quote",
                                    file, linenum);
-                               xfree(tun);
+                               free(tun);
                                forced_tun_device = -1;
                                goto bad_option;
                        }
                        tun[i] = '\0';
                        forced_tun_device = a2tun(tun, NULL);
-                       xfree(tun);
+                       free(tun);
                        if (forced_tun_device == SSH_TUNID_ERR) {
                                debug("%.100s, line %lu: invalid tun device",
                                    file, linenum);
@@ -432,10 +429,11 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
 {
        char *command, *allowed;
        const char *remote_ip;
-       u_char *name = NULL, *data_blob = NULL;
+       char *name = NULL;
+       u_char *data_blob = NULL;
        u_int nlen, dlen, clen;
        Buffer c, data;
-       int ret = -1, found;
+       int ret = -1, result, found;
 
        buffer_init(&data);
 
@@ -484,7 +482,7 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
                                if (*cert_forced_command != NULL) {
                                        error("Certificate has multiple "
                                            "force-command options");
-                                       xfree(command);
+                                       free(command);
                                        goto out;
                                }
                                *cert_forced_command = command;
@@ -500,15 +498,16 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
                                if ((*cert_source_address_done)++) {
                                        error("Certificate has multiple "
                                            "source-address options");
-                                       xfree(allowed);
+                                       free(allowed);
                                        goto out;
                                }
                                remote_ip = get_remote_ipaddr();
-                               switch (addr_match_cidr_list(remote_ip,
-                                   allowed)) {
+                               result = addr_match_cidr_list(remote_ip,
+                                   allowed);
+                               free(allowed);
+                               switch (result) {
                                case 1:
                                        /* accepted */
-                                       xfree(allowed);
                                        break;
                                case 0:
                                        /* no match */
@@ -521,12 +520,11 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
                                            "is not permitted to use this "
                                            "certificate for login.",
                                            remote_ip);
-                                       xfree(allowed);
                                        goto out;
                                case -1:
+                               default:
                                        error("Certificate source-address "
                                            "contents invalid");
-                                       xfree(allowed);
                                        goto out;
                                }
                                found = 1;
@@ -548,9 +546,10 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
                        goto out;
                }
                buffer_clear(&data);
-               xfree(name);
-               xfree(data_blob);
-               name = data_blob = NULL;
+               free(name);
+               free(data_blob);
+               name = NULL;
+               data_blob = NULL;
        }
        /* successfully parsed all options */
        ret = 0;
@@ -559,13 +558,13 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
        if (ret != 0 &&
            cert_forced_command != NULL &&
            *cert_forced_command != NULL) {
-               xfree(*cert_forced_command);
+               free(*cert_forced_command);
                *cert_forced_command = NULL;
        }
        if (name != NULL)
-               xfree(name);
+               free(name);
        if (data_blob != NULL)
-               xfree(data_blob);
+               free(data_blob);
        buffer_free(&data);
        buffer_free(&c);
        return ret;
@@ -588,8 +587,8 @@ auth_cert_options(Key *k, struct passwd *pw)
 
        if (key_cert_is_legacy(k)) {
                /* All options are in the one field for v00 certs */
-               if (parse_option_list(buffer_ptr(&k->cert->critical),
-                   buffer_len(&k->cert->critical), pw,
+               if (parse_option_list(buffer_ptr(k->cert->critical),
+                   buffer_len(k->cert->critical), pw,
                    OPTIONS_CRITICAL|OPTIONS_EXTENSIONS, 1,
                    &cert_no_port_forwarding_flag,
                    &cert_no_agent_forwarding_flag,
@@ -601,14 +600,14 @@ auth_cert_options(Key *k, struct passwd *pw)
                        return -1;
        } else {
                /* Separate options and extensions for v01 certs */
-               if (parse_option_list(buffer_ptr(&k->cert->critical),
-                   buffer_len(&k->cert->critical), pw,
+               if (parse_option_list(buffer_ptr(k->cert->critical),
+                   buffer_len(k->cert->critical), pw,
                    OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL,
                    &cert_forced_command,
                    &cert_source_address_done) == -1)
                        return -1;
-               if (parse_option_list(buffer_ptr(&k->cert->extensions),
-                   buffer_len(&k->cert->extensions), pw,
+               if (parse_option_list(buffer_ptr(k->cert->extensions),
+                   buffer_len(k->cert->extensions), pw,
                    OPTIONS_EXTENSIONS, 1,
                    &cert_no_port_forwarding_flag,
                    &cert_no_agent_forwarding_flag,
@@ -627,7 +626,7 @@ auth_cert_options(Key *k, struct passwd *pw)
        /* CA-specified forced command supersedes key option */
        if (cert_forced_command != NULL) {
                if (forced_command != NULL)
-                       xfree(forced_command);
+                       free(forced_command);
                forced_command = cert_forced_command;
        }
        return 0;
index 675006e..d789bad 100644 (file)
@@ -412,10 +412,9 @@ sshpam_thread_conv(int n, sshpam_const struct pam_message **msg,
 
  fail:
        for(i = 0; i < n; i++) {
-               if (reply[i].resp != NULL)
-                       xfree(reply[i].resp);
+               free(reply[i].resp);
        }
-       xfree(reply);
+       free(reply);
        buffer_free(&buffer);
        return (PAM_CONV_ERR);
 }
@@ -439,8 +438,10 @@ sshpam_thread(void *ctxtp)
        const char **ptr_pam_user = &pam_user;
        char *tz = getenv("TZ");
 
-       pam_get_item(sshpam_handle, PAM_USER,
+       sshpam_err = pam_get_item(sshpam_handle, PAM_USER,
            (sshpam_const void **)ptr_pam_user);
+       if (sshpam_err != PAM_SUCCESS)
+               goto auth_fail;
 
        environ[0] = NULL;
        if (tz != NULL)
@@ -586,10 +587,9 @@ sshpam_store_conv(int n, sshpam_const struct pam_message **msg,
 
  fail:
        for(i = 0; i < n; i++) {
-               if (reply[i].resp != NULL)
-                       xfree(reply[i].resp);
+               free(reply[i].resp);
        }
-       xfree(reply);
+       free(reply);
        return (PAM_CONV_ERR);
 }
 
@@ -693,7 +693,7 @@ sshpam_init_ctx(Authctxt *authctxt)
        /* Start the authentication thread */
        if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, socks) == -1) {
                error("PAM: failed create sockets: %s", strerror(errno));
-               xfree(ctxt);
+               free(ctxt);
                return (NULL);
        }
        ctxt->pam_psock = socks[0];
@@ -703,7 +703,7 @@ sshpam_init_ctx(Authctxt *authctxt)
                    strerror(errno));
                close(socks[0]);
                close(socks[1]);
-               xfree(ctxt);
+               free(ctxt);
                return (NULL);
        }
        cleanup_ctxt = ctxt;
@@ -742,7 +742,7 @@ sshpam_query(void *ctx, char **name, char **info,
                        strlcpy(**prompts + plen, msg, len - plen);
                        plen += mlen;
                        **echo_on = (type == PAM_PROMPT_ECHO_ON);
-                       xfree(msg);
+                       free(msg);
                        return (0);
                case PAM_ERROR_MSG:
                case PAM_TEXT_INFO:
@@ -753,7 +753,7 @@ sshpam_query(void *ctx, char **name, char **info,
                        plen += mlen;
                        strlcat(**prompts + plen, "\n", len - plen);
                        plen++;
-                       xfree(msg);
+                       free(msg);
                        break;
                case PAM_ACCT_EXPIRED:
                        sshpam_account_status = 0;
@@ -766,7 +766,7 @@ sshpam_query(void *ctx, char **name, char **info,
                                *num = 0;
                                **echo_on = 0;
                                ctxt->pam_done = -1;
-                               xfree(msg);
+                               free(msg);
                                return 0;
                        }
                        /* FALLTHROUGH */
@@ -776,7 +776,7 @@ sshpam_query(void *ctx, char **name, char **info,
                                debug("PAM: %s", **prompts);
                                buffer_append(&loginmsg, **prompts,
                                    strlen(**prompts));
-                               xfree(**prompts);
+                               free(**prompts);
                                **prompts = NULL;
                        }
                        if (type == PAM_SUCCESS) {
@@ -790,7 +790,7 @@ sshpam_query(void *ctx, char **name, char **info,
                                *num = 0;
                                **echo_on = 0;
                                ctxt->pam_done = 1;
-                               xfree(msg);
+                               free(msg);
                                return (0);
                        }
                        error("PAM: %s for %s%.100s from %.100s", msg,
@@ -801,7 +801,7 @@ sshpam_query(void *ctx, char **name, char **info,
                default:
                        *num = 0;
                        **echo_on = 0;
-                       xfree(msg);
+                       free(msg);
                        ctxt->pam_done = -1;
                        return (-1);
                }
@@ -852,7 +852,7 @@ sshpam_free_ctx(void *ctxtp)
 
        debug3("PAM: %s entering", __func__);
        sshpam_thread_cleanup();
-       xfree(ctxt);
+       free(ctxt);
        /*
         * We don't call sshpam_cleanup() here because we may need the PAM
         * handle at a later stage, e.g. when setting up a session.  It's
@@ -1006,10 +1006,9 @@ sshpam_tty_conv(int n, sshpam_const struct pam_message **msg,
 
  fail:
        for(i = 0; i < n; i++) {
-               if (reply[i].resp != NULL)
-                       xfree(reply[i].resp);
+               free(reply[i].resp);
        }
-       xfree(reply);
+       free(reply);
        return (PAM_CONV_ERR);
 }
 
@@ -1081,7 +1080,7 @@ do_pam_putenv(char *name, char *value)
 
        snprintf(compound, len, "%s=%s", name, value);
        ret = pam_putenv(sshpam_handle, compound);
-       xfree(compound);
+       free(compound);
 #endif
 
        return (ret);
@@ -1108,8 +1107,8 @@ free_pam_environment(char **env)
                return;
 
        for (envp = env; *envp; envp++)
-               xfree(*envp);
-       xfree(env);
+               free(*envp);
+       free(env);
 }
 
 /*
@@ -1165,10 +1164,9 @@ sshpam_passwd_conv(int n, sshpam_const struct pam_message **msg,
 
  fail:
        for(i = 0; i < n; i++) {
-               if (reply[i].resp != NULL)
-                       xfree(reply[i].resp);
+               free(reply[i].resp);
        }
-       xfree(reply);
+       free(reply);
        return (PAM_CONV_ERR);
 }
 
index 68bbd18..63ccf3c 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-passwd.c,v 1.43 2007/09/21 08:15:29 djm Exp $ */
+/* $OpenBSD: auth-passwd.c,v 1.44 2014/07/15 15:54:14 millert Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -48,6 +48,7 @@
 #include "packet.h"
 #include "buffer.h"
 #include "log.h"
+#include "misc.h"
 #include "servconf.h"
 #include "key.h"
 #include "hostfile.h"
index b21a0f4..b7fd064 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-rh-rsa.c,v 1.43 2010/03/04 10:36:03 djm Exp $ */
+/* $OpenBSD: auth-rh-rsa.c,v 1.44 2014/07/15 15:54:14 millert Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -24,6 +24,7 @@
 #include "uidswap.h"
 #include "log.h"
 #include "buffer.h"
+#include "misc.h"
 #include "servconf.h"
 #include "key.h"
 #include "hostfile.h"
index 06ae7f0..b5bedee 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-rhosts.c,v 1.44 2010/03/07 11:57:13 dtucker Exp $ */
+/* $OpenBSD: auth-rhosts.c,v 1.45 2014/07/15 15:54:14 millert Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
 #include "uidswap.h"
 #include "pathnames.h"
 #include "log.h"
+#include "misc.h"
 #include "servconf.h"
 #include "canohost.h"
 #include "key.h"
 #include "hostfile.h"
 #include "auth.h"
-#include "misc.h"
 
 /* import */
 extern ServerOptions options;
index 4ab46cd..e9f4ede 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-rsa.c,v 1.80 2011/05/23 03:30:07 djm Exp $ */
+/* $OpenBSD: auth-rsa.c,v 1.88 2014/07/15 15:54:14 millert Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -20,7 +20,6 @@
 #include <sys/stat.h>
 
 #include <openssl/rsa.h>
-#include <openssl/md5.h>
 
 #include <pwd.h>
 #include <stdio.h>
@@ -36,6 +35,7 @@
 #include "buffer.h"
 #include "pathnames.h"
 #include "log.h"
+#include "misc.h"
 #include "servconf.h"
 #include "key.h"
 #include "auth-options.h"
@@ -46,7 +46,8 @@
 #endif
 #include "monitor_wrap.h"
 #include "ssh.h"
-#include "misc.h"
+
+#include "digest.h"
 
 /* import */
 extern ServerOptions options;
@@ -91,12 +92,13 @@ int
 auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16])
 {
        u_char buf[32], mdbuf[16];
-       MD5_CTX md;
+       struct ssh_digest_ctx *md;
        int len;
 
        /* don't allow short keys */
        if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
-               error("auth_rsa_verify_response: RSA modulus too small: %d < minimum %d bits",
+               error("%s: RSA modulus too small: %d < minimum %d bits",
+                   __func__,
                    BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE);
                return (0);
        }
@@ -104,13 +106,15 @@ auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16])
        /* The response is MD5 of decrypted challenge plus session id. */
        len = BN_num_bytes(challenge);
        if (len <= 0 || len > 32)
-               fatal("auth_rsa_verify_response: bad challenge length %d", len);
+               fatal("%s: bad challenge length %d", __func__, len);
        memset(buf, 0, 32);
        BN_bn2bin(challenge, buf + 32 - len);
-       MD5_Init(&md);
-       MD5_Update(&md, buf, 32);
-       MD5_Update(&md, session_id, 16);
-       MD5_Final(mdbuf, &md);
+       if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL ||
+           ssh_digest_update(md, buf, 32) < 0 ||
+           ssh_digest_update(md, session_id, 16) < 0 ||
+           ssh_digest_final(md, mdbuf, sizeof(mdbuf)) < 0)
+               fatal("%s: md5 failed", __func__);
+       ssh_digest_free(md);
 
        /* Verify that the response is the original challenge. */
        if (timingsafe_bcmp(response, mdbuf, 16) != 0) {
@@ -140,7 +144,8 @@ auth_rsa_challenge_dialog(Key *key)
        challenge = PRIVSEP(auth_rsa_generate_challenge(key));
 
        /* Encrypt the challenge with the public key. */
-       rsa_public_encrypt(encrypted_challenge, challenge, key->rsa);
+       if (rsa_public_encrypt(encrypted_challenge, challenge, key->rsa) != 0)
+               fatal("%s: rsa_public_encrypt failed", __func__);
 
        /* Send the encrypted challenge to the client. */
        packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE);
@@ -164,9 +169,8 @@ static int
 rsa_key_allowed_in_file(struct passwd *pw, char *file,
     const BIGNUM *client_n, Key **rkey)
 {
-       char line[SSH_MAX_PUBKEY_BYTES];
-       int allowed = 0;
-       u_int bits;
+       char *fp, line[SSH_MAX_PUBKEY_BYTES];
+       int allowed = 0, bits;
        FILE *f;
        u_long linenum = 0;
        Key *key;
@@ -227,11 +231,16 @@ rsa_key_allowed_in_file(struct passwd *pw, char *file,
 
                /* check the real bits  */
                keybits = BN_num_bits(key->rsa->n);
-               if (keybits < 0 || bits != (u_int)keybits)
+               if (keybits < 0 || bits != keybits)
                        logit("Warning: %s, line %lu: keysize mismatch: "
                            "actual %d vs. announced %d.",
                            file, linenum, BN_num_bits(key->rsa->n), bits);
 
+               fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+               debug("matching key found: file %s, line %lu %s %s",
+                   file, linenum, key_type(key), fp);
+               free(fp);
+
                /* Never accept a revoked key */
                if (auth_key_is_revoked(key))
                        break;
@@ -276,10 +285,12 @@ auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
        temporarily_use_uid(pw);
 
        for (i = 0; !allowed && i < options.num_authkeys_files; i++) {
+               if (strcasecmp(options.authorized_keys_files[i], "none") == 0)
+                       continue;
                file = expand_authorized_keys(
                    options.authorized_keys_files[i], pw);
                allowed = rsa_key_allowed_in_file(pw, file, client_n, rkey);
-               xfree(file);
+               free(file);
        }
 
        restore_uid();
@@ -296,7 +307,6 @@ int
 auth_rsa(Authctxt *authctxt, BIGNUM *client_n)
 {
        Key *key;
-       char *fp;
        struct passwd *pw = authctxt->pw;
 
        /* no user given */
@@ -326,11 +336,7 @@ auth_rsa(Authctxt *authctxt, BIGNUM *client_n)
         * options; this will be reset if the options cause the
         * authentication to be rejected.
         */
-       fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
-       verbose("Found matching %s key: %s",
-           key_type(key), fp);
-       xfree(fp);
-       key_free(key);
+       pubkey_auth_info(authctxt, key, NULL);
 
        packet_send_debug("RSA authentication accepted.");
        return (1);
index a8cffd5..5e60682 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth.c,v 1.96 2012/05/13 01:42:32 dtucker Exp $ */
+/* $OpenBSD: auth.c,v 1.106 2014/07/15 15:54:14 millert Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -56,6 +56,7 @@
 #include "groupaccess.h"
 #include "log.h"
 #include "buffer.h"
+#include "misc.h"
 #include "servconf.h"
 #include "key.h"
 #include "hostfile.h"
@@ -63,7 +64,6 @@
 #include "auth-options.h"
 #include "canohost.h"
 #include "uidswap.h"
-#include "misc.h"
 #include "packet.h"
 #include "loginrec.h"
 #ifdef GSSAPI
@@ -71,6 +71,8 @@
 #endif
 #include "authfile.h"
 #include "monitor_wrap.h"
+#include "krl.h"
+#include "compat.h"
 
 /* import */
 extern ServerOptions options;
@@ -164,17 +166,17 @@ allowed_user(struct passwd * pw)
                if (stat(shell, &st) != 0) {
                        logit("User %.100s not allowed because shell %.100s "
                            "does not exist", pw->pw_name, shell);
-                       xfree(shell);
+                       free(shell);
                        return 0;
                }
                if (S_ISREG(st.st_mode) == 0 ||
                    (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) {
                        logit("User %.100s not allowed because shell %.100s "
                            "is not executable", pw->pw_name, shell);
-                       xfree(shell);
+                       free(shell);
                        return 0;
                }
-               xfree(shell);
+               free(shell);
        }
 
        if (options.num_deny_users > 0 || options.num_allow_users > 0 ||
@@ -251,7 +253,25 @@ allowed_user(struct passwd * pw)
 }
 
 void
-auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
+auth_info(Authctxt *authctxt, const char *fmt, ...)
+{
+       va_list ap;
+        int i;
+
+       free(authctxt->info);
+       authctxt->info = NULL;
+
+       va_start(ap, fmt);
+       i = vasprintf(&authctxt->info, fmt, ap);
+       va_end(ap);
+
+       if (i < 0 || authctxt->info == NULL)
+               fatal("vasprintf failed");
+}
+
+void
+auth_log(Authctxt *authctxt, int authenticated, int partial,
+    const char *method, const char *submethod)
 {
        void (*authlog) (const char *fmt,...) = verbose;
        char *authmsg;
@@ -268,17 +288,24 @@ auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
 
        if (authctxt->postponed)
                authmsg = "Postponed";
+       else if (partial)
+               authmsg = "Partial";
        else
                authmsg = authenticated ? "Accepted" : "Failed";
 
-       authlog("%s %s for %s%.100s from %.200s port %d%s",
+       authlog("%s %s%s%s for %s%.100s from %.200s port %d %s%s%s",
            authmsg,
            method,
+           submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod,
            authctxt->valid ? "" : "invalid user ",
            authctxt->user,
            get_remote_ipaddr(),
            get_remote_port(),
-           info);
+           compat20 ? "ssh2" : "ssh1",
+           authctxt->info != NULL ? ": " : "",
+           authctxt->info != NULL ? authctxt->info : "");
+       free(authctxt->info);
+       authctxt->info = NULL;
 
 #ifdef CUSTOM_FAILED_LOGIN
        if (authenticated == 0 && !authctxt->postponed &&
@@ -299,11 +326,25 @@ auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
 #endif
 }
 
+
+void
+auth_maxtries_exceeded(Authctxt *authctxt)
+{
+       packet_disconnect("Too many authentication failures for "
+           "%s%.100s from %.200s port %d %s",
+           authctxt->valid ? "" : "invalid user ",
+           authctxt->user,
+           get_remote_ipaddr(),
+           get_remote_port(),
+           compat20 ? "ssh2" : "ssh1");
+       /* NOTREACHED */
+}
+
 /*
  * Check whether root logins are disallowed.
  */
 int
-auth_root_allowed(char *method)
+auth_root_allowed(const char *method)
 {
        switch (options.permit_root_login) {
        case PERMIT_YES:
@@ -350,7 +391,7 @@ expand_authorized_keys(const char *filename, struct passwd *pw)
        i = snprintf(ret, sizeof(ret), "%s/%s", pw->pw_dir, file);
        if (i < 0 || (size_t)i >= sizeof(ret))
                fatal("expand_authorized_keys: path too long");
-       xfree(file);
+       free(file);
        return (xstrdup(ret));
 }
 
@@ -392,7 +433,7 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
                        load_hostkeys(hostkeys, host, user_hostfile);
                        restore_uid();
                }
-               xfree(user_hostfile);
+               free(user_hostfile);
        }
        host_status = check_key_in_hostkeys(hostkeys, key, &found);
        if (host_status == HOST_REVOKED)
@@ -409,41 +450,42 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
        return host_status;
 }
 
-
 /*
- * Check a given file for security. This is defined as all components
+ * Check a given path for security. This is defined as all components
  * of the path to the file must be owned by either the owner of
  * of the file or root and no directories must be group or world writable.
  *
  * XXX Should any specific check be done for sym links ?
  *
- * Takes an open file descriptor, the file name, a uid and and
+ * Takes a file name, its stat information (preferably from fstat() to
+ * avoid races), the uid of the expected owner, their home directory and an
  * error buffer plus max size as arguments.
  *
  * Returns 0 on success and -1 on failure
  */
-static int
-secure_filename(FILE *f, const char *file, struct passwd *pw,
-    char *err, size_t errlen)
+int
+auth_secure_path(const char *name, struct stat *stp, const char *pw_dir,
+    uid_t uid, char *err, size_t errlen)
 {
-       uid_t uid = pw->pw_uid;
        char buf[MAXPATHLEN], homedir[MAXPATHLEN];
        char *cp;
        int comparehome = 0;
        struct stat st;
 
-       if (realpath(file, buf) == NULL) {
-               snprintf(err, errlen, "realpath %s failed: %s", file,
+       if (realpath(name, buf) == NULL) {
+               snprintf(err, errlen, "realpath %s failed: %s", name,
                    strerror(errno));
                return -1;
        }
-       if (realpath(pw->pw_dir, homedir) != NULL)
+       if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL)
                comparehome = 1;
 
-       /* check the open file to avoid races */
-       if (fstat(fileno(f), &st) < 0 ||
-           (st.st_uid != 0 && st.st_uid != uid) ||
-           (st.st_mode & 022) != 0) {
+       if (!S_ISREG(stp->st_mode)) {
+               snprintf(err, errlen, "%s is not a regular file", buf);
+               return -1;
+       }
+       if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) ||
+           (stp->st_mode & 022) != 0) {
                snprintf(err, errlen, "bad ownership or modes for file %s",
                    buf);
                return -1;
@@ -458,7 +500,7 @@ secure_filename(FILE *f, const char *file, struct passwd *pw,
                strlcpy(buf, cp, sizeof(buf));
 
                if (stat(buf, &st) < 0 ||
-                   (st.st_uid != 0 && st.st_uid != uid) ||
+                   (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) ||
                    (st.st_mode & 022) != 0) {
                        snprintf(err, errlen,
                            "bad ownership or modes for directory %s", buf);
@@ -479,6 +521,27 @@ secure_filename(FILE *f, const char *file, struct passwd *pw,
        return 0;
 }
 
+/*
+ * Version of secure_path() that accepts an open file descriptor to
+ * avoid races.
+ *
+ * Returns 0 on success and -1 on failure
+ */
+static int
+secure_filename(FILE *f, const char *file, struct passwd *pw,
+    char *err, size_t errlen)
+{
+       struct stat st;
+
+       /* check the open file to avoid races */
+       if (fstat(fileno(f), &st) < 0) {
+               snprintf(err, errlen, "cannot stat file %s: %s",
+                   file, strerror(errno));
+               return -1;
+       }
+       return auth_secure_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen);
+}
+
 static FILE *
 auth_openfile(const char *file, struct passwd *pw, int strict_modes,
     int log_missing, char *file_type)
@@ -610,11 +673,22 @@ getpwnamallow(const char *user)
 int
 auth_key_is_revoked(Key *key)
 {
+#ifdef WITH_OPENSSL
        char *key_fp;
 
        if (options.revoked_keys_file == NULL)
                return 0;
-
+       switch (ssh_krl_file_contains_key(options.revoked_keys_file, key)) {
+       case 0:
+               return 0;       /* Not revoked */
+       case -2:
+               break;          /* Not a KRL */
+       default:
+               goto revoked;
+       }
+#endif
+       debug3("%s: treating %s as a key list", __func__,
+           options.revoked_keys_file);
        switch (key_in_file(key, options.revoked_keys_file, 0)) {
        case 0:
                /* key not revoked */
@@ -624,13 +698,16 @@ auth_key_is_revoked(Key *key)
                error("Revoked keys file is unreadable: refusing public key "
                    "authentication");
                return 1;
+#ifdef WITH_OPENSSL
        case 1:
+ revoked:
                /* Key revoked */
                key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
                error("WARNING: authentication attempt with a revoked "
                    "%s key %s ", key_type(key), key_fp);
-               xfree(key_fp);
+               free(key_fp);
                return 1;
+#endif
        }
        fatal("key_in_file returned junk");
 }
@@ -660,7 +737,7 @@ auth_debug_send(void)
        while (buffer_len(&auth_debug)) {
                msg = buffer_get_string(&auth_debug, NULL);
                packet_send_debug("%s", msg);
-               xfree(msg);
+               free(msg);
        }
 }
 
@@ -684,10 +761,12 @@ fakepw(void)
        fake.pw_name = "NOUSER";
        fake.pw_passwd =
            "$2a$06$r3.juUaHZDlIbQaO2dS9FuYxL1W9M81R1Tc92PoSNmzvpEqLkLGrK";
+#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
        fake.pw_gecos = "NOUSER";
+#endif
        fake.pw_uid = privsep_pw == NULL ? (uid_t)-1 : privsep_pw->pw_uid;
        fake.pw_gid = privsep_pw == NULL ? (gid_t)-1 : privsep_pw->pw_gid;
-#ifdef HAVE_PW_CLASS_IN_PASSWD
+#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
        fake.pw_class = "";
 #endif
        fake.pw_dir = "/nonexist";
index 0d786c4..d081c94 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth.h,v 1.69 2011/05/23 03:30:07 djm Exp $ */
+/* $OpenBSD: auth.h,v 1.78 2014/07/03 11:16:55 djm Exp $ */
 
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
@@ -60,10 +60,12 @@ struct Authctxt {
        struct passwd   *pw;            /* set if 'valid' */
        char            *style;
        void            *kbdintctxt;
-       void            *jpake_ctx;
+       char            *info;          /* Extra info for next auth_log */
 #ifdef BSD_AUTH
        auth_session_t  *as;
 #endif
+       char            **auth_methods; /* modified from server config */
+       u_int            num_auth_methods;
 #ifdef KRB5
        krb5_context     krb5_ctx;
        krb5_ccache      krb5_fwd_ccache;
@@ -119,6 +121,12 @@ int         auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
 int     auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
 int     hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
 int     user_key_allowed(struct passwd *, Key *);
+void    pubkey_auth_info(Authctxt *, const Key *, const char *, ...)
+           __attribute__((__format__ (printf, 3, 4)));
+
+struct stat;
+int     auth_secure_path(const char *, struct stat *, const char *, uid_t,
+    char *, size_t);
 
 #ifdef KRB5
 int    auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client, krb5_data *);
@@ -142,12 +150,21 @@ void disable_forwarding(void);
 void   do_authentication(Authctxt *);
 void   do_authentication2(Authctxt *);
 
-void   auth_log(Authctxt *, int, char *, char *);
-void   userauth_finish(Authctxt *, int, char *);
+void   auth_info(Authctxt *authctxt, const char *, ...)
+           __attribute__((__format__ (printf, 2, 3)))
+           __attribute__((__nonnull__ (2)));
+void   auth_log(Authctxt *, int, int, const char *, const char *);
+void   auth_maxtries_exceeded(Authctxt *) __attribute__((noreturn));
+void   userauth_finish(Authctxt *, int, const char *, const char *);
+int    auth_root_allowed(const char *);
+
 void   userauth_send_banner(const char *);
-int    auth_root_allowed(char *);
 
 char   *auth2_read_banner(void);
+int     auth2_methods_valid(const char *, int);
+int     auth2_update_methods_lists(Authctxt *, const char *, const char *);
+int     auth2_setup_methods_lists(Authctxt *);
+int     auth2_method_allowed(Authctxt *, const char *, const char *);
 
 void   privsep_challenge_enable(void);
 
@@ -158,9 +175,6 @@ int bsdauth_respond(void *, u_int, char **);
 int    skey_query(void *, char **, char **, u_int *, char ***, u_int **);
 int    skey_respond(void *, u_int, char **);
 
-void   auth2_jpake_get_pwdata(Authctxt *, BIGNUM **, char **, char **);
-void   auth2_jpake_stop(Authctxt *);
-
 int    allowed_user(struct passwd *);
 struct passwd * getpwnamallow(const char *user);
 
@@ -181,10 +195,12 @@ check_key_in_hostfiles(struct passwd *, Key *, const char *,
 
 /* hostkey handling */
 Key    *get_hostkey_by_index(int);
+Key    *get_hostkey_public_by_index(int);
 Key    *get_hostkey_public_by_type(int);
 Key    *get_hostkey_private_by_type(int);
 int     get_hostkey_index(Key *);
 int     ssh1_session_key(BIGNUM *);
+void    sshd_hostkey_sign(Key *, Key *, u_char **, u_int *, u_char *, u_int);
 
 /* debug messages during authentication */
 void    auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2)));
@@ -195,8 +211,6 @@ struct passwd *fakepw(void);
 
 int     sys_auth_passwd(Authctxt *, const char *);
 
-#define AUTH_FAIL_MSG "Too many authentication failures for %.100s"
-
 #define SKEY_PROMPT "\nS/Key Password: "
 
 #if defined(KRB5) && !defined(HEIMDAL)
index cc85aec..5038828 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth1.c,v 1.75 2010/08/31 09:58:37 djm Exp $ */
+/* $OpenBSD: auth1.c,v 1.82 2014/07/15 15:54:14 millert Exp $ */
 /*
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
  *                    All rights reserved
@@ -27,6 +27,7 @@
 #include "packet.h"
 #include "buffer.h"
 #include "log.h"
+#include "misc.h"
 #include "servconf.h"
 #include "compat.h"
 #include "key.h"
 extern ServerOptions options;
 extern Buffer loginmsg;
 
-static int auth1_process_password(Authctxt *, char *, size_t);
-static int auth1_process_rsa(Authctxt *, char *, size_t);
-static int auth1_process_rhosts_rsa(Authctxt *, char *, size_t);
-static int auth1_process_tis_challenge(Authctxt *, char *, size_t);
-static int auth1_process_tis_response(Authctxt *, char *, size_t);
+static int auth1_process_password(Authctxt *);
+static int auth1_process_rsa(Authctxt *);
+static int auth1_process_rhosts_rsa(Authctxt *);
+static int auth1_process_tis_challenge(Authctxt *);
+static int auth1_process_tis_response(Authctxt *);
 
 static char *client_user = NULL;    /* Used to fill in remote user for PAM */
 
@@ -57,7 +58,7 @@ struct AuthMethod1 {
        int type;
        char *name;
        int *enabled;
-       int (*method)(Authctxt *, char *, size_t);
+       int (*method)(Authctxt *);
 };
 
 const struct AuthMethod1 auth1_methods[] = {
@@ -112,7 +113,7 @@ get_authname(int type)
 
 /*ARGSUSED*/
 static int
-auth1_process_password(Authctxt *authctxt, char *info, size_t infolen)
+auth1_process_password(Authctxt *authctxt)
 {
        int authenticated = 0;
        char *password;
@@ -129,15 +130,15 @@ auth1_process_password(Authctxt *authctxt, char *info, size_t infolen)
        /* Try authentication with the password. */
        authenticated = PRIVSEP(auth_password(authctxt, password));
 
-       memset(password, 0, dlen);
-       xfree(password);
+       explicit_bzero(password, dlen);
+       free(password);
 
        return (authenticated);
 }
 
 /*ARGSUSED*/
 static int
-auth1_process_rsa(Authctxt *authctxt, char *info, size_t infolen)
+auth1_process_rsa(Authctxt *authctxt)
 {
        int authenticated = 0;
        BIGNUM *n;
@@ -155,7 +156,7 @@ auth1_process_rsa(Authctxt *authctxt, char *info, size_t infolen)
 
 /*ARGSUSED*/
 static int
-auth1_process_rhosts_rsa(Authctxt *authctxt, char *info, size_t infolen)
+auth1_process_rhosts_rsa(Authctxt *authctxt)
 {
        int keybits, authenticated = 0;
        u_int bits;
@@ -187,14 +188,14 @@ auth1_process_rhosts_rsa(Authctxt *authctxt, char *info, size_t infolen)
            client_host_key);
        key_free(client_host_key);
 
-       snprintf(info, infolen, " ruser %.100s", client_user);
+       auth_info(authctxt, "ruser %.100s", client_user);
 
        return (authenticated);
 }
 
 /*ARGSUSED*/
 static int
-auth1_process_tis_challenge(Authctxt *authctxt, char *info, size_t infolen)
+auth1_process_tis_challenge(Authctxt *authctxt)
 {
        char *challenge;
 
@@ -204,7 +205,7 @@ auth1_process_tis_challenge(Authctxt *authctxt, char *info, size_t infolen)
        debug("sending challenge '%s'", challenge);
        packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
        packet_put_cstring(challenge);
-       xfree(challenge);
+       free(challenge);
        packet_send();
        packet_write_wait();
 
@@ -213,7 +214,7 @@ auth1_process_tis_challenge(Authctxt *authctxt, char *info, size_t infolen)
 
 /*ARGSUSED*/
 static int
-auth1_process_tis_response(Authctxt *authctxt, char *info, size_t infolen)
+auth1_process_tis_response(Authctxt *authctxt)
 {
        int authenticated = 0;
        char *response;
@@ -222,8 +223,8 @@ auth1_process_tis_response(Authctxt *authctxt, char *info, size_t infolen)
        response = packet_get_string(&dlen);
        packet_check_eom();
        authenticated = verify_response(authctxt, response);
-       memset(response, 'r', dlen);
-       xfree(response);
+       explicit_bzero(response, dlen);
+       free(response);
 
        return (authenticated);
 }
@@ -236,7 +237,6 @@ static void
 do_authloop(Authctxt *authctxt)
 {
        int authenticated = 0;
-       char info[1024];
        int prev = 0, type = 0;
        const struct AuthMethod1 *meth;
 
@@ -253,7 +253,8 @@ do_authloop(Authctxt *authctxt)
                if (options.use_pam && (PRIVSEP(do_pam_account())))
 #endif
                {
-                       auth_log(authctxt, 1, "without authentication", "");
+                       auth_log(authctxt, 1, 0, "without authentication",
+                           NULL);
                        return;
                }
        }
@@ -267,7 +268,6 @@ do_authloop(Authctxt *authctxt)
                /* default to fail */
                authenticated = 0;
 
-               info[0] = '\0';
 
                /* Get a packet from the client. */
                prev = type;
@@ -297,7 +297,7 @@ do_authloop(Authctxt *authctxt)
                        goto skip;
                }
 
-               authenticated = meth->method(authctxt, info, sizeof(info));
+               authenticated = meth->method(authctxt);
                if (authenticated == -1)
                        continue; /* "postponed" */
 
@@ -352,12 +352,10 @@ do_authloop(Authctxt *authctxt)
 
  skip:
                /* Log before sending the reply */
-               auth_log(authctxt, authenticated, get_authname(type), info);
+               auth_log(authctxt, authenticated, 0, get_authname(type), NULL);
 
-               if (client_user != NULL) {
-                       xfree(client_user);
-                       client_user = NULL;
-               }
+               free(client_user);
+               client_user = NULL;
 
                if (authenticated)
                        return;
@@ -366,7 +364,7 @@ do_authloop(Authctxt *authctxt)
 #ifdef SSH_AUDIT_EVENTS
                        PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
 #endif
-                       packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
+                       auth_maxtries_exceeded(authctxt);
                }
 
                packet_start(SSH_SMSG_FAILURE);
@@ -406,6 +404,11 @@ do_authentication(Authctxt *authctxt)
                authctxt->pw = fakepw();
        }
 
+       /* Configuration may have changed as a result of Match */
+       if (options.num_auth_methods != 0)
+               fatal("AuthenticationMethods is not supported with SSH "
+                   "protocol 1");
+
        setproctitle("%s%s", authctxt->valid ? user : "unknown",
            use_privsep ? " [net]" : "");
 
index e6dbffe..ea4eb69 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-chall.c,v 1.34 2008/12/09 04:32:22 djm Exp $ */
+/* $OpenBSD: auth2-chall.c,v 1.41 2014/02/02 03:44:31 djm Exp $ */
 /*
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
  * Copyright (c) 2001 Per Allansson.  All rights reserved.
@@ -41,6 +41,7 @@
 #include "packet.h"
 #include "dispatch.h"
 #include "log.h"
+#include "misc.h"
 #include "servconf.h"
 
 /* import */
@@ -111,7 +112,7 @@ kbdint_alloc(const char *devs)
                remove_kbdint_device("pam");
 #endif
 
-       kbdintctxt = xmalloc(sizeof(KbdintAuthctxt));
+       kbdintctxt = xcalloc(1, sizeof(KbdintAuthctxt));
        if (strcmp(devs, "") == 0) {
                buffer_init(&b);
                for (i = 0; devices[i]; i++) {
@@ -147,15 +148,13 @@ kbdint_free(KbdintAuthctxt *kbdintctxt)
 {
        if (kbdintctxt->device)
                kbdint_reset_device(kbdintctxt);
-       if (kbdintctxt->devices) {
-               xfree(kbdintctxt->devices);
-               kbdintctxt->devices = NULL;
-       }
-       xfree(kbdintctxt);
+       free(kbdintctxt->devices);
+       explicit_bzero(kbdintctxt, sizeof(*kbdintctxt));
+       free(kbdintctxt);
 }
 /* get next device */
 static int
-kbdint_next_device(KbdintAuthctxt *kbdintctxt)
+kbdint_next_device(Authctxt *authctxt, KbdintAuthctxt *kbdintctxt)
 {
        size_t len;
        char *t;
@@ -169,12 +168,16 @@ kbdint_next_device(KbdintAuthctxt *kbdintctxt)
 
                if (len == 0)
                        break;
-               for (i = 0; devices[i]; i++)
+               for (i = 0; devices[i]; i++) {
+                       if (!auth2_method_allowed(authctxt,
+                           "keyboard-interactive", devices[i]->name))
+                               continue;
                        if (strncmp(kbdintctxt->devices, devices[i]->name, len) == 0)
                                kbdintctxt->device = devices[i];
+               }
                t = kbdintctxt->devices;
                kbdintctxt->devices = t[len] ? xstrdup(t+len+1) : NULL;
-               xfree(t);
+               free(t);
                debug2("kbdint_next_device: devices %s", kbdintctxt->devices ?
                    kbdintctxt->devices : "<empty>");
        } while (kbdintctxt->devices && !kbdintctxt->device);
@@ -221,7 +224,7 @@ auth2_challenge_start(Authctxt *authctxt)
        debug2("auth2_challenge_start: devices %s",
            kbdintctxt->devices ?  kbdintctxt->devices : "<empty>");
 
-       if (kbdint_next_device(kbdintctxt) == 0) {
+       if (kbdint_next_device(authctxt, kbdintctxt) == 0) {
                auth2_challenge_stop(authctxt);
                return 0;
        }
@@ -268,11 +271,11 @@ send_userauth_info_request(Authctxt *authctxt)
        packet_write_wait();
 
        for (i = 0; i < kbdintctxt->nreq; i++)
-               xfree(prompts[i]);
-       xfree(prompts);
-       xfree(echo_on);
-       xfree(name);
-       xfree(instr);
+               free(prompts[i]);
+       free(prompts);
+       free(echo_on);
+       free(name);
+       free(instr);
        return 1;
 }
 
@@ -283,7 +286,8 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
        KbdintAuthctxt *kbdintctxt;
        int authenticated = 0, res;
        u_int i, nresp;
-       char **response = NULL, *method;
+       const char *devicename = NULL;
+       char **response = NULL;
 
        if (authctxt == NULL)
                fatal("input_userauth_info_response: no authctxt");
@@ -309,11 +313,10 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
        res = kbdintctxt->device->respond(kbdintctxt->ctxt, nresp, response);
 
        for (i = 0; i < nresp; i++) {
-               memset(response[i], 'r', strlen(response[i]));
-               xfree(response[i]);
+               explicit_bzero(response[i], strlen(response[i]));
+               free(response[i]);
        }
-       if (response)
-               xfree(response);
+       free(response);
 
        switch (res) {
        case 0:
@@ -329,9 +332,7 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
                /* Failure! */
                break;
        }
-
-       xasprintf(&method, "keyboard-interactive/%s", kbdintctxt->device->name);
-
+       devicename = kbdintctxt->device->name;
        if (!authctxt->postponed) {
                if (authenticated) {
                        auth2_challenge_stop(authctxt);
@@ -341,8 +342,8 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
                        auth2_challenge_start(authctxt);
                }
        }
-       userauth_finish(authctxt, authenticated, method);
-       xfree(method);
+       userauth_finish(authctxt, authenticated, "keyboard-interactive",
+           devicename);
 }
 
 void
index 0d59b21..447f896 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-gss.c,v 1.17 2011/03/10 02:52:57 djm Exp $ */
+/* $OpenBSD: auth2-gss.c,v 1.21 2014/02/26 20:28:44 djm Exp $ */
 
 /*
  * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
@@ -40,6 +40,7 @@
 #include "log.h"
 #include "dispatch.h"
 #include "buffer.h"
+#include "misc.h"
 #include "servconf.h"
 #include "packet.h"
 #include "ssh-gss.h"
@@ -62,7 +63,6 @@ userauth_gssapi(Authctxt *authctxt)
        gss_OID_desc goid = {0, NULL};
        Gssctxt *ctxt = NULL;
        int mechs;
-       gss_OID_set supported;
        int present;
        OM_uint32 ms;
        u_int len;
@@ -77,12 +77,10 @@ userauth_gssapi(Authctxt *authctxt)
                return (0);
        }
 
-       ssh_gssapi_supported_oids(&supported);
        do {
                mechs--;
 
-               if (doid)
-                       xfree(doid);
+               free(doid);
 
                present = 0;
                doid = packet_get_string(&len);
@@ -91,17 +89,14 @@ userauth_gssapi(Authctxt *authctxt)
                    doid[1] == len - 2) {
                        goid.elements = doid + 2;
                        goid.length   = len - 2;
-                       gss_test_oid_set_member(&ms, &goid, supported,
-                           &present);
+                       ssh_gssapi_test_oid_supported(&ms, &goid, &present);
                } else {
                        logit("Badly formed OID received");
                }
        } while (mechs > 0 && !present);
 
-       gss_release_oid_set(&ms, &supported);
-
        if (!present) {
-               xfree(doid);
+               free(doid);
                authctxt->server_caused_failure = 1;
                return (0);
        }
@@ -109,7 +104,7 @@ userauth_gssapi(Authctxt *authctxt)
        if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &goid)))) {
                if (ctxt != NULL)
                        ssh_gssapi_delete_ctx(&ctxt);
-               xfree(doid);
+               free(doid);
                authctxt->server_caused_failure = 1;
                return (0);
        }
@@ -122,7 +117,7 @@ userauth_gssapi(Authctxt *authctxt)
        packet_put_string(doid, len);
 
        packet_send();
-       xfree(doid);
+       free(doid);
 
        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
@@ -153,7 +148,7 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt)
        maj_status = PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok,
            &send_tok, &flags));
 
-       xfree(recv_tok.value);
+       free(recv_tok.value);
 
        if (GSS_ERROR(maj_status)) {
                if (send_tok.length != 0) {
@@ -163,7 +158,7 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt)
                }
                authctxt->postponed = 0;
                dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
-               userauth_finish(authctxt, 0, "gssapi-with-mic");
+               userauth_finish(authctxt, 0, "gssapi-with-mic", NULL);
        } else {
                if (send_tok.length != 0) {
                        packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
@@ -208,7 +203,7 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
        maj_status = PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok,
            &send_tok, NULL));
 
-       xfree(recv_tok.value);
+       free(recv_tok.value);
 
        /* We can't return anything to the client, even if we wanted to */
        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
@@ -229,14 +224,11 @@ static void
 input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
 {
        Authctxt *authctxt = ctxt;
-       Gssctxt *gssctxt;
        int authenticated;
 
        if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
                fatal("No authentication or GSSAPI context");
 
-       gssctxt = authctxt->methoddata;
-
        /*
         * We don't need to check the status, because we're only enabled in
         * the dispatcher once the exchange is complete
@@ -251,7 +243,7 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
-       userauth_finish(authctxt, authenticated, "gssapi-with-mic");
+       userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
 }
 
 static void
@@ -284,14 +276,14 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt)
                logit("GSSAPI MIC check failed");
 
        buffer_free(&b);
-       xfree(mic.value);
+       free(mic.value);
 
        authctxt->postponed = 0;
        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
-       userauth_finish(authctxt, authenticated, "gssapi-with-mic");
+       userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
 }
 
 Authmethod method_gssapi = {
index cdf442f..6787e4c 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-hostbased.c,v 1.14 2010/08/04 05:42:47 djm Exp $ */
+/* $OpenBSD: auth2-hostbased.c,v 1.18 2014/07/15 15:54:14 millert Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -36,6 +36,7 @@
 #include "packet.h"
 #include "buffer.h"
 #include "log.h"
+#include "misc.h"
 #include "servconf.h"
 #include "compat.h"
 #include "key.h"
@@ -100,6 +101,12 @@ userauth_hostbased(Authctxt *authctxt)
                    "(received %d, expected %d)", key->type, pktype);
                goto done;
        }
+       if (key_type_plain(key->type) == KEY_RSA &&
+           (datafellows & SSH_BUG_RSASIGMD5) != 0) {
+               error("Refusing RSA key because peer uses unsafe "
+                   "signature format");
+               goto done;
+       }
        service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
            authctxt->service;
        buffer_init(&b);
@@ -116,6 +123,10 @@ userauth_hostbased(Authctxt *authctxt)
 #ifdef DEBUG_PK
        buffer_dump(&b);
 #endif
+
+       pubkey_auth_info(authctxt, key,
+           "client user \"%.100s\", client host \"%.100s\"", cuser, chost);
+
        /* test for allowed key and correct signature */
        authenticated = 0;
        if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
@@ -128,11 +139,11 @@ done:
        debug2("userauth_hostbased: authenticated %d", authenticated);
        if (key != NULL)
                key_free(key);
-       xfree(pkalg);
-       xfree(pkblob);
-       xfree(cuser);
-       xfree(chost);
-       xfree(sig);
+       free(pkalg);
+       free(pkblob);
+       free(cuser);
+       free(chost);
+       free(sig);
        return authenticated;
 }
 
@@ -207,7 +218,7 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
                        verbose("Accepted %s public key %s from %s@%s",
                            key_type(key), fp, cuser, lookup);
                }
-               xfree(fp);
+               free(fp);
        }
 
        return (host_status == HOST_OK);
diff --git a/crypto/openssh/auth2-jpake.c b/crypto/openssh/auth2-jpake.c
deleted file mode 100644 (file)
index a460e82..0000000
+++ /dev/null
@@ -1,563 +0,0 @@
-/* $OpenBSD: auth2-jpake.c,v 1.4 2010/08/31 11:54:45 djm Exp $ */
-/*
- * Copyright (c) 2008 Damien Miller.  All rights reserved.
- *
- * 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.
- */
-
-/*
- * Server side of zero-knowledge password auth using J-PAKE protocol
- * as described in:
- *
- * F. Hao, P. Ryan, "Password Authenticated Key Exchange by Juggling",
- * 16th Workshop on Security Protocols, Cambridge, April 2008
- *
- * http://grouper.ieee.org/groups/1363/Research/contributions/hao-ryan-2008.pdf
- */
-
-#ifdef JPAKE
-
-#include <sys/types.h>
-#include <sys/param.h>
-
-#include <pwd.h>
-#include <stdio.h>
-#include <string.h>
-#include <login_cap.h>
-
-#include <openssl/bn.h>
-#include <openssl/evp.h>
-
-#include "xmalloc.h"
-#include "ssh2.h"
-#include "key.h"
-#include "hostfile.h"
-#include "auth.h"
-#include "buffer.h"
-#include "packet.h"
-#include "dispatch.h"
-#include "log.h"
-#include "servconf.h"
-#include "auth-options.h"
-#include "canohost.h"
-#ifdef GSSAPI
-#include "ssh-gss.h"
-#endif
-#include "monitor_wrap.h"
-
-#include "schnorr.h"
-#include "jpake.h"
-
-/*
- * XXX options->permit_empty_passwd (at the moment, they will be refused
- * anyway because they will mismatch on fake salt.
- */
-
-/* Dispatch handlers */
-static void input_userauth_jpake_client_step1(int, u_int32_t, void *);
-static void input_userauth_jpake_client_step2(int, u_int32_t, void *);
-static void input_userauth_jpake_client_confirm(int, u_int32_t, void *);
-
-static int auth2_jpake_start(Authctxt *);
-
-/* import */
-extern ServerOptions options;
-extern u_char *session_id2;
-extern u_int session_id2_len;
-
-/*
- * Attempt J-PAKE authentication.
- */
-static int
-userauth_jpake(Authctxt *authctxt)
-{
-       int authenticated = 0;
-
-       packet_check_eom();
-
-       debug("jpake-01@openssh.com requested");
-
-       if (authctxt->user != NULL) {
-               if (authctxt->jpake_ctx == NULL)
-                       authctxt->jpake_ctx = jpake_new();
-               if (options.zero_knowledge_password_authentication)
-                       authenticated = auth2_jpake_start(authctxt);
-       }
-
-       return authenticated;
-}
-
-Authmethod method_jpake = {
-       "jpake-01@openssh.com",
-       userauth_jpake,
-       &options.zero_knowledge_password_authentication
-};
-
-/* Clear context and callbacks */
-void
-auth2_jpake_stop(Authctxt *authctxt)
-{
-       /* unregister callbacks */
-       dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1, NULL);
-       dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2, NULL);
-       dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM, NULL);
-       if (authctxt->jpake_ctx != NULL) {
-               jpake_free(authctxt->jpake_ctx);
-               authctxt->jpake_ctx = NULL;
-       }
-}
-
-/* Returns 1 if 'c' is a valid crypt(3) salt character, 0 otherwise */
-static int
-valid_crypt_salt(int c)
-{
-       if (c >= 'A' && c <= 'Z')
-               return 1;
-       if (c >= 'a' && c <= 'z')
-               return 1;
-       if (c >= '.' && c <= '9')
-               return 1;
-       return 0;
-}
-
-/*
- * Derive fake salt as H(username || first_private_host_key)
- * This provides relatively stable fake salts for non-existent
- * users and avoids the jpake method becoming an account validity
- * oracle.
- */
-static void
-derive_rawsalt(const char *username, u_char *rawsalt, u_int len)
-{
-       u_char *digest;
-       u_int digest_len;
-       Buffer b;
-       Key *k;
-
-       buffer_init(&b);
-       buffer_put_cstring(&b, username);
-       if ((k = get_hostkey_by_index(0)) == NULL ||
-           (k->flags & KEY_FLAG_EXT))
-               fatal("%s: no hostkeys", __func__);
-       switch (k->type) {
-       case KEY_RSA1:
-       case KEY_RSA:
-               if (k->rsa->p == NULL || k->rsa->q == NULL)
-                       fatal("%s: RSA key missing p and/or q", __func__);
-               buffer_put_bignum2(&b, k->rsa->p);
-               buffer_put_bignum2(&b, k->rsa->q);
-               break;
-       case KEY_DSA:
-               if (k->dsa->priv_key == NULL)
-                       fatal("%s: DSA key missing priv_key", __func__);
-               buffer_put_bignum2(&b, k->dsa->priv_key);
-               break;
-       case KEY_ECDSA:
-               if (EC_KEY_get0_private_key(k->ecdsa) == NULL)
-                       fatal("%s: ECDSA key missing priv_key", __func__);
-               buffer_put_bignum2(&b, EC_KEY_get0_private_key(k->ecdsa));
-               break;
-       default:
-               fatal("%s: unknown key type %d", __func__, k->type);
-       }
-       if (hash_buffer(buffer_ptr(&b), buffer_len(&b), EVP_sha256(),
-           &digest, &digest_len) != 0)
-               fatal("%s: hash_buffer", __func__);
-       buffer_free(&b);
-       if (len > digest_len)
-               fatal("%s: not enough bytes for rawsalt (want %u have %u)",
-                   __func__, len, digest_len);
-       memcpy(rawsalt, digest, len);
-       bzero(digest, digest_len);
-       xfree(digest);
-}
-
-/* ASCII an integer [0, 64) for inclusion in a password/salt */
-static char
-pw_encode64(u_int i64)
-{
-       const u_char e64[] =
-           "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-       return e64[i64 % 64];
-}
-
-/* Generate ASCII salt bytes for user */
-static char *
-makesalt(u_int want, const char *user)
-{
-       u_char rawsalt[32];
-       static char ret[33];
-       u_int i;
-
-       if (want > sizeof(ret) - 1)
-               fatal("%s: want %u", __func__, want);
-
-       derive_rawsalt(user, rawsalt, sizeof(rawsalt));
-       bzero(ret, sizeof(ret));
-       for (i = 0; i < want; i++)
-               ret[i] = pw_encode64(rawsalt[i]);
-       bzero(rawsalt, sizeof(rawsalt));
-
-       return ret;
-}
-
-/*
- * Select the system's default password hashing scheme and generate
- * a stable fake salt under it for use by a non-existent account.
- * Prevents jpake method being used to infer the validity of accounts.
- */
-static void
-fake_salt_and_scheme(Authctxt *authctxt, char **salt, char **scheme)
-{
-       char *rounds_s, *style;
-       long long rounds;
-       login_cap_t *lc;
-
-
-       if ((lc = login_getclass(authctxt->pw->pw_class)) == NULL &&
-           (lc = login_getclass(NULL)) == NULL)
-               fatal("%s: login_getclass failed", __func__);
-       style = login_getcapstr(lc, "localcipher", NULL, NULL);
-       if (style == NULL)
-               style = xstrdup("blowfish,6");
-       login_close(lc);
-       
-       if ((rounds_s = strchr(style, ',')) != NULL)
-               *rounds_s++ = '\0';
-       rounds = strtonum(rounds_s, 1, 1<<31, NULL);
-       
-       if (strcmp(style, "md5") == 0) {
-               xasprintf(salt, "$1$%s$", makesalt(8, authctxt->user));
-               *scheme = xstrdup("md5");
-       } else if (strcmp(style, "old") == 0) {
-               *salt = xstrdup(makesalt(2, authctxt->user));
-               *scheme = xstrdup("crypt");
-       } else if (strcmp(style, "newsalt") == 0) {
-               rounds = MAX(rounds, 7250);
-               rounds = MIN(rounds, (1<<24) - 1);
-               xasprintf(salt, "_%c%c%c%c%s",
-                   pw_encode64(rounds), pw_encode64(rounds >> 6),
-                   pw_encode64(rounds >> 12), pw_encode64(rounds >> 18),
-                   makesalt(4, authctxt->user));
-               *scheme = xstrdup("crypt-extended");
-       } else {
-               /* Default to blowfish */
-               rounds = MAX(rounds, 3);
-               rounds = MIN(rounds, 31);
-               xasprintf(salt, "$2a$%02lld$%s", rounds,
-                   makesalt(22, authctxt->user));
-               *scheme = xstrdup("bcrypt");
-       }
-       xfree(style);
-       debug3("%s: fake %s salt for user %s: %s",
-           __func__, *scheme, authctxt->user, *salt);
-}
-
-/*
- * Fetch password hashing scheme, password salt and derive shared secret
- * for user. If user does not exist, a fake but stable and user-unique
- * salt will be returned.
- */
-void
-auth2_jpake_get_pwdata(Authctxt *authctxt, BIGNUM **s,
-    char **hash_scheme, char **salt)
-{
-       char *cp;
-       u_char *secret;
-       u_int secret_len, salt_len;
-
-#ifdef JPAKE_DEBUG
-       debug3("%s: valid %d pw %.5s...", __func__,
-           authctxt->valid, authctxt->pw->pw_passwd);
-#endif
-
-       *salt = NULL;
-       *hash_scheme = NULL;
-       if (authctxt->valid) {
-               if (strncmp(authctxt->pw->pw_passwd, "$2$", 3) == 0 &&
-                   strlen(authctxt->pw->pw_passwd) > 28) {
-                       /*
-                        * old-variant bcrypt:
-                        *     "$2$", 2 digit rounds, "$", 22 bytes salt
-                        */
-                       salt_len = 3 + 2 + 1 + 22 + 1;
-                       *salt = xmalloc(salt_len);
-                       strlcpy(*salt, authctxt->pw->pw_passwd, salt_len);
-                       *hash_scheme = xstrdup("bcrypt");
-               } else if (strncmp(authctxt->pw->pw_passwd, "$2a$", 4) == 0 &&
-                   strlen(authctxt->pw->pw_passwd) > 29) {
-                       /*
-                        * current-variant bcrypt:
-                        *     "$2a$", 2 digit rounds, "$", 22 bytes salt
-                        */
-                       salt_len = 4 + 2 + 1 + 22 + 1;
-                       *salt = xmalloc(salt_len);
-                       strlcpy(*salt, authctxt->pw->pw_passwd, salt_len);
-                       *hash_scheme = xstrdup("bcrypt");
-               } else if (strncmp(authctxt->pw->pw_passwd, "$1$", 3) == 0 &&
-                   strlen(authctxt->pw->pw_passwd) > 5) {
-                       /*
-                        * md5crypt:
-                        *     "$1$", salt until "$"
-                        */
-                       cp = strchr(authctxt->pw->pw_passwd + 3, '$');
-                       if (cp != NULL) {
-                               salt_len = (cp - authctxt->pw->pw_passwd) + 1;
-                               *salt = xmalloc(salt_len);
-                               strlcpy(*salt, authctxt->pw->pw_passwd,
-                                   salt_len);
-                               *hash_scheme = xstrdup("md5crypt");
-                       }
-               } else if (strncmp(authctxt->pw->pw_passwd, "_", 1) == 0 &&
-                   strlen(authctxt->pw->pw_passwd) > 9) {
-                       /*
-                        * BSDI extended crypt:
-                        *     "_", 4 digits count, 4 chars salt
-                        */
-                       salt_len = 1 + 4 + 4 + 1;
-                       *salt = xmalloc(salt_len);
-                       strlcpy(*salt, authctxt->pw->pw_passwd, salt_len);
-                       *hash_scheme = xstrdup("crypt-extended");
-               } else if (strlen(authctxt->pw->pw_passwd) == 13  &&
-                   valid_crypt_salt(authctxt->pw->pw_passwd[0]) &&
-                   valid_crypt_salt(authctxt->pw->pw_passwd[1])) {
-                       /*
-                        * traditional crypt:
-                        *     2 chars salt
-                        */
-                       salt_len = 2 + 1;
-                       *salt = xmalloc(salt_len);
-                       strlcpy(*salt, authctxt->pw->pw_passwd, salt_len);
-                       *hash_scheme = xstrdup("crypt");
-               }
-               if (*salt == NULL) {
-                       debug("%s: unrecognised crypt scheme for user %s",
-                           __func__, authctxt->pw->pw_name);
-               }
-       }
-       if (*salt == NULL)
-               fake_salt_and_scheme(authctxt, salt, hash_scheme);
-
-       if (hash_buffer(authctxt->pw->pw_passwd,
-           strlen(authctxt->pw->pw_passwd), EVP_sha256(),
-           &secret, &secret_len) != 0)
-               fatal("%s: hash_buffer", __func__);
-       if ((*s = BN_bin2bn(secret, secret_len, NULL)) == NULL)
-               fatal("%s: BN_bin2bn (secret)", __func__);
-#ifdef JPAKE_DEBUG
-       debug3("%s: salt = %s (len %u)", __func__,
-           *salt, (u_int)strlen(*salt));
-       debug3("%s: scheme = %s", __func__, *hash_scheme);
-       JPAKE_DEBUG_BN((*s, "%s: s = ", __func__));
-#endif
-       bzero(secret, secret_len);
-       xfree(secret);
-}
-
-/*
- * Begin authentication attempt.
- * Note, sets authctxt->postponed while in subprotocol
- */
-static int
-auth2_jpake_start(Authctxt *authctxt)
-{
-       struct jpake_ctx *pctx = authctxt->jpake_ctx;
-       u_char *x3_proof, *x4_proof;
-       u_int x3_proof_len, x4_proof_len;
-       char *salt, *hash_scheme;
-
-       debug("%s: start", __func__);
-
-       PRIVSEP(jpake_step1(pctx->grp,
-           &pctx->server_id, &pctx->server_id_len,
-           &pctx->x3, &pctx->x4, &pctx->g_x3, &pctx->g_x4,
-           &x3_proof, &x3_proof_len,
-           &x4_proof, &x4_proof_len));
-
-       PRIVSEP(auth2_jpake_get_pwdata(authctxt, &pctx->s,
-           &hash_scheme, &salt));
-
-       if (!use_privsep)
-               JPAKE_DEBUG_CTX((pctx, "step 1 sending in %s", __func__));
-
-       packet_start(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1);
-       packet_put_cstring(hash_scheme);
-       packet_put_cstring(salt);
-       packet_put_string(pctx->server_id, pctx->server_id_len);
-       packet_put_bignum2(pctx->g_x3);
-       packet_put_bignum2(pctx->g_x4);
-       packet_put_string(x3_proof, x3_proof_len);
-       packet_put_string(x4_proof, x4_proof_len);
-       packet_send();
-       packet_write_wait();
-
-       bzero(hash_scheme, strlen(hash_scheme));
-       bzero(salt, strlen(salt));
-       xfree(hash_scheme);
-       xfree(salt);
-       bzero(x3_proof, x3_proof_len);
-       bzero(x4_proof, x4_proof_len);
-       xfree(x3_proof);
-       xfree(x4_proof);
-
-       /* Expect step 1 packet from peer */
-       dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1,
-           input_userauth_jpake_client_step1);
-
-       authctxt->postponed = 1;
-       return 0;
-}
-
-/* ARGSUSED */
-static void
-input_userauth_jpake_client_step1(int type, u_int32_t seq, void *ctxt)
-{
-       Authctxt *authctxt = ctxt;
-       struct jpake_ctx *pctx = authctxt->jpake_ctx;
-       u_char *x1_proof, *x2_proof, *x4_s_proof;
-       u_int x1_proof_len, x2_proof_len, x4_s_proof_len;
-
-       /* Disable this message */
-       dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1, NULL);
-
-       /* Fetch step 1 values */
-       if ((pctx->g_x1 = BN_new()) == NULL ||
-           (pctx->g_x2 = BN_new()) == NULL)
-               fatal("%s: BN_new", __func__);
-       pctx->client_id = packet_get_string(&pctx->client_id_len);
-       packet_get_bignum2(pctx->g_x1);
-       packet_get_bignum2(pctx->g_x2);
-       x1_proof = packet_get_string(&x1_proof_len);
-       x2_proof = packet_get_string(&x2_proof_len);
-       packet_check_eom();
-
-       if (!use_privsep)
-               JPAKE_DEBUG_CTX((pctx, "step 1 received in %s", __func__));
-
-       PRIVSEP(jpake_step2(pctx->grp, pctx->s, pctx->g_x3,
-           pctx->g_x1, pctx->g_x2, pctx->x4,
-           pctx->client_id, pctx->client_id_len,
-           pctx->server_id, pctx->server_id_len,
-           x1_proof, x1_proof_len,
-           x2_proof, x2_proof_len,
-           &pctx->b,
-           &x4_s_proof, &x4_s_proof_len));
-
-       bzero(x1_proof, x1_proof_len);
-       bzero(x2_proof, x2_proof_len);
-       xfree(x1_proof);
-       xfree(x2_proof);
-
-       if (!use_privsep)
-               JPAKE_DEBUG_CTX((pctx, "step 2 sending in %s", __func__));
-
-       /* Send values for step 2 */
-       packet_start(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2);
-       packet_put_bignum2(pctx->b);
-       packet_put_string(x4_s_proof, x4_s_proof_len);
-       packet_send();
-       packet_write_wait();
-
-       bzero(x4_s_proof, x4_s_proof_len);
-       xfree(x4_s_proof);
-
-       /* Expect step 2 packet from peer */
-       dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2,
-           input_userauth_jpake_client_step2);
-}
-
-/* ARGSUSED */
-static void
-input_userauth_jpake_client_step2(int type, u_int32_t seq, void *ctxt)
-{
-       Authctxt *authctxt = ctxt;
-       struct jpake_ctx *pctx = authctxt->jpake_ctx;
-       u_char *x2_s_proof;
-       u_int x2_s_proof_len;
-
-       /* Disable this message */
-       dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2, NULL);
-
-       if ((pctx->a = BN_new()) == NULL)
-               fatal("%s: BN_new", __func__);
-
-       /* Fetch step 2 values */
-       packet_get_bignum2(pctx->a);
-       x2_s_proof = packet_get_string(&x2_s_proof_len);
-       packet_check_eom();
-
-       if (!use_privsep)
-               JPAKE_DEBUG_CTX((pctx, "step 2 received in %s", __func__));
-
-       /* Derive shared key and calculate confirmation hash */
-       PRIVSEP(jpake_key_confirm(pctx->grp, pctx->s, pctx->a,
-           pctx->x4, pctx->g_x3, pctx->g_x4, pctx->g_x1, pctx->g_x2,
-           pctx->server_id, pctx->server_id_len,
-           pctx->client_id, pctx->client_id_len,
-           session_id2, session_id2_len,
-           x2_s_proof, x2_s_proof_len,
-           &pctx->k,
-           &pctx->h_k_sid_sessid, &pctx->h_k_sid_sessid_len));
-
-       bzero(x2_s_proof, x2_s_proof_len);
-       xfree(x2_s_proof);
-
-       if (!use_privsep)
-               JPAKE_DEBUG_CTX((pctx, "confirm sending in %s", __func__));
-
-       /* Send key confirmation proof */
-       packet_start(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM);
-       packet_put_string(pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len);
-       packet_send();
-       packet_write_wait();
-
-       /* Expect confirmation from peer */
-       dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM,
-           input_userauth_jpake_client_confirm);
-}
-
-/* ARGSUSED */
-static void
-input_userauth_jpake_client_confirm(int type, u_int32_t seq, void *ctxt)
-{
-       Authctxt *authctxt = ctxt;
-       struct jpake_ctx *pctx = authctxt->jpake_ctx;
-       int authenticated = 0;
-
-       /* Disable this message */
-       dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM, NULL);
-
-       pctx->h_k_cid_sessid = packet_get_string(&pctx->h_k_cid_sessid_len);
-       packet_check_eom();
-
-       if (!use_privsep)
-               JPAKE_DEBUG_CTX((pctx, "confirm received in %s", __func__));
-
-       /* Verify expected confirmation hash */
-       if (PRIVSEP(jpake_check_confirm(pctx->k,
-           pctx->client_id, pctx->client_id_len,
-           session_id2, session_id2_len,
-           pctx->h_k_cid_sessid, pctx->h_k_cid_sessid_len)) == 1)
-               authenticated = authctxt->valid ? 1 : 0;
-       else
-               debug("%s: confirmation mismatch", __func__);
-               
-       /* done */
-       authctxt->postponed = 0;
-       jpake_free(authctxt->jpake_ctx);
-       authctxt->jpake_ctx = NULL;
-       userauth_finish(authctxt, authenticated, method_jpake.name);
-}
-
-#endif /* JPAKE */
-
index fae67da..bf75c60 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-kbdint.c,v 1.5 2006/08/03 03:34:41 deraadt Exp $ */
+/* $OpenBSD: auth2-kbdint.c,v 1.7 2014/07/15 15:54:14 millert Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -36,6 +36,7 @@
 #include "auth.h"
 #include "log.h"
 #include "buffer.h"
+#include "misc.h"
 #include "servconf.h"
 
 /* import */
@@ -56,8 +57,8 @@ userauth_kbdint(Authctxt *authctxt)
        if (options.challenge_response_authentication)
                authenticated = auth2_challenge(authctxt, devs);
 
-       xfree(devs);
-       xfree(lang);
+       free(devs);
+       free(lang);
        return authenticated;
 }
 
index c8c6c74..e71e221 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-none.c,v 1.16 2010/06/25 08:46:17 djm Exp $ */
+/* $OpenBSD: auth2-none.c,v 1.18 2014/07/15 15:54:14 millert Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
 #include <sys/uio.h>
 
 #include <fcntl.h>
-#include <stdarg.h>
 #include <string.h>
 #include <unistd.h>
+#include <stdarg.h>
+#include <stdio.h>
 
 #include "atomicio.h"
 #include "xmalloc.h"
@@ -42,6 +43,7 @@
 #include "packet.h"
 #include "log.h"
 #include "buffer.h"
+#include "misc.h"
 #include "servconf.h"
 #include "compat.h"
 #include "ssh2.h"
index 5f1f363..b638e87 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-passwd.c,v 1.9 2006/08/03 03:34:41 deraadt Exp $ */
+/* $OpenBSD: auth2-passwd.c,v 1.12 2014/07/15 15:54:14 millert Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -41,6 +41,7 @@
 #include "ssh-gss.h"
 #endif
 #include "monitor_wrap.h"
+#include "misc.h"
 #include "servconf.h"
 
 /* import */
@@ -59,8 +60,8 @@ userauth_passwd(Authctxt *authctxt)
        if (change) {
                /* discard new password from packet */
                newpass = packet_get_string(&newlen);
-               memset(newpass, 0, newlen);
-               xfree(newpass);
+               explicit_bzero(newpass, newlen);
+               free(newpass);
        }
        packet_check_eom();
 
@@ -68,8 +69,8 @@ userauth_passwd(Authctxt *authctxt)
                logit("password change not supported");
        else if (PRIVSEP(auth_password(authctxt, password)) == 1)
                authenticated = 1;
-       memset(password, 0, len);
-       xfree(password);
+       explicit_bzero(password, len);
+       free(password);
        return authenticated;
 }
 
index 5bccb5d..f3ca965 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-pubkey.c,v 1.30 2011/09/25 05:44:47 djm Exp $ */
+/* $OpenBSD: auth2-pubkey.c,v 1.41 2014/07/15 15:54:14 millert Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/wait.h>
 
+#include <errno.h>
 #include <fcntl.h>
+#ifdef HAVE_PATHS_H
+# include <paths.h>
+#endif
 #include <pwd.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdarg.h>
 #include <string.h>
@@ -42,6 +48,7 @@
 #include "packet.h"
 #include "buffer.h"
 #include "log.h"
+#include "misc.h"
 #include "servconf.h"
 #include "compat.h"
 #include "key.h"
@@ -55,7 +62,6 @@
 #include "ssh-gss.h"
 #endif
 #include "monitor_wrap.h"
-#include "misc.h"
 #include "authfile.h"
 #include "match.h"
 
@@ -69,7 +75,7 @@ userauth_pubkey(Authctxt *authctxt)
 {
        Buffer b;
        Key *key = NULL;
-       char *pkalg;
+       char *pkalg, *userstyle;
        u_char *pkblob, *sig;
        u_int alen, blen, slen;
        int have_sig, pktype;
@@ -110,6 +116,12 @@ userauth_pubkey(Authctxt *authctxt)
                    "(received %d, expected %d)", key->type, pktype);
                goto done;
        }
+       if (key_type_plain(key->type) == KEY_RSA &&
+           (datafellows & SSH_BUG_RSASIGMD5) != 0) {
+               logit("Refusing RSA key because client uses unsafe "
+                   "signature scheme");
+               goto done;
+       }
        if (have_sig) {
                sig = packet_get_string(&slen);
                packet_check_eom();
@@ -121,7 +133,11 @@ userauth_pubkey(Authctxt *authctxt)
                }
                /* reconstruct packet */
                buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
-               buffer_put_cstring(&b, authctxt->user);
+               xasprintf(&userstyle, "%s%s%s", authctxt->user,
+                   authctxt->style ? ":" : "",
+                   authctxt->style ? authctxt->style : "");
+               buffer_put_cstring(&b, userstyle);
+               free(userstyle);
                buffer_put_cstring(&b,
                    datafellows & SSH_BUG_PKSERVICE ?
                    "ssh-userauth" :
@@ -137,6 +153,8 @@ userauth_pubkey(Authctxt *authctxt)
 #ifdef DEBUG_PK
                buffer_dump(&b);
 #endif
+               pubkey_auth_info(authctxt, key, NULL);
+
                /* test for correct signature */
                authenticated = 0;
                if (PRIVSEP(user_key_allowed(authctxt->pw, key)) &&
@@ -144,7 +162,7 @@ userauth_pubkey(Authctxt *authctxt)
                    buffer_len(&b))) == 1)
                        authenticated = 1;
                buffer_free(&b);
-               xfree(sig);
+               free(sig);
        } else {
                debug("test whether pkalg/pkblob are acceptable");
                packet_check_eom();
@@ -172,13 +190,47 @@ done:
        debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg);
        if (key != NULL)
                key_free(key);
-       xfree(pkalg);
-       xfree(pkblob);
+       free(pkalg);
+       free(pkblob);
        return authenticated;
 }
 
+void
+pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...)
+{
+       char *fp, *extra;
+       va_list ap;
+       int i;
+
+       extra = NULL;
+       if (fmt != NULL) {
+               va_start(ap, fmt);
+               i = vasprintf(&extra, fmt, ap);
+               va_end(ap);
+               if (i < 0 || extra == NULL)
+                       fatal("%s: vasprintf failed", __func__);        
+       }
+
+       if (key_is_cert(key)) {
+               fp = key_fingerprint(key->cert->signature_key,
+                   SSH_FP_MD5, SSH_FP_HEX);
+               auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s", 
+                   key_type(key), key->cert->key_id,
+                   (unsigned long long)key->cert->serial,
+                   key_type(key->cert->signature_key), fp,
+                   extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
+               free(fp);
+       } else {
+               fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+               auth_info(authctxt, "%s %s%s%s", key_type(key), fp,
+                   extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
+               free(fp);
+       }
+       free(extra);
+}
+
 static int
-match_principals_option(const char *principal_list, struct KeyCert *cert)
+match_principals_option(const char *principal_list, struct sshkey_cert *cert)
 {
        char *result;
        u_int i;
@@ -190,7 +242,7 @@ match_principals_option(const char *principal_list, struct KeyCert *cert)
                    principal_list, NULL)) != NULL) {
                        debug3("matched principal from key options \"%.100s\"",
                            result);
-                       xfree(result);
+                       free(result);
                        return 1;
                }
        }
@@ -198,7 +250,7 @@ match_principals_option(const char *principal_list, struct KeyCert *cert)
 }
 
 static int
-match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert)
+match_principals_file(char *file, struct passwd *pw, struct sshkey_cert *cert)
 {
        FILE *f;
        char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts;
@@ -240,7 +292,7 @@ match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert)
                        if (strcmp(cp, cert->principals[i]) == 0) {
                                debug3("matched principal \"%.100s\" "
                                    "from file \"%s\" on line %lu",
-                                   cert->principals[i], file, linenum);
+                                   cert->principals[i], file, linenum);
                                if (auth_parse_options(pw, line_opts,
                                    file, linenum) != 1)
                                        continue;
@@ -253,37 +305,30 @@ match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert)
        fclose(f);
        restore_uid();
        return 0;
-}      
+}
 
-/* return 1 if user allows given key */
+/*
+ * Checks whether key is allowed in authorized_keys-format file,
+ * returns 1 if the key is allowed or 0 otherwise.
+ */
 static int
-user_key_allowed2(struct passwd *pw, Key *key, char *file)
+check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
 {
        char line[SSH_MAX_PUBKEY_BYTES];
        const char *reason;
        int found_key = 0;
-       FILE *f;
        u_long linenum = 0;
        Key *found;
        char *fp;
 
-       /* Temporarily use the user's uid. */
-       temporarily_use_uid(pw);
-
-       debug("trying public key file %s", file);
-       f = auth_openkeyfile(file, pw, options.strict_modes);
-
-       if (!f) {
-               restore_uid();
-               return 0;
-       }
-
        found_key = 0;
-       found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
 
+       found = NULL;
        while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
                char *cp, *key_options = NULL;
-
+               if (found != NULL)
+                       key_free(found);
+               found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
                auth_clear_options();
 
                /* Skip leading whitespace, empty and comment lines. */
@@ -335,7 +380,7 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
                                reason = "Certificate does not contain an "
                                    "authorized principal";
  fail_reason:
-                               xfree(fp);
+                               free(fp);
                                error("%s", reason);
                                auth_debug_add("%s", reason);
                                continue;
@@ -345,13 +390,13 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
                            &reason) != 0)
                                goto fail_reason;
                        if (auth_cert_options(key, pw) != 0) {
-                               xfree(fp);
+                               free(fp);
                                continue;
                        }
                        verbose("Accepted certificate ID \"%s\" "
                            "signed by %s CA %s via %s", key->cert->key_id,
                            key_type(found), fp, file);
-                       xfree(fp);
+                       free(fp);
                        found_key = 1;
                        break;
                } else if (key_equal(found, key)) {
@@ -361,18 +406,15 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
                        if (key_is_cert_authority)
                                continue;
                        found_key = 1;
-                       debug("matching key found: file %s, line %lu",
-                           file, linenum);
                        fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
-                       verbose("Found matching %s key: %s",
-                           key_type(found), fp);
-                       xfree(fp);
+                       debug("matching key found: file %s, line %lu %s %s",
+                           file, linenum, key_type(found), fp);
+                       free(fp);
                        break;
                }
        }
-       restore_uid();
-       fclose(f);
-       key_free(found);
+       if (found != NULL)
+               key_free(found);
        if (!found_key)
                debug2("key not found");
        return found_key;
@@ -426,14 +468,185 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
        ret = 1;
 
  out:
-       if (principals_file != NULL)
-               xfree(principals_file);
-       if (ca_fp != NULL)
-               xfree(ca_fp);
+       free(principals_file);
+       free(ca_fp);
        return ret;
 }
 
-/* check whether given key is in .ssh/authorized_keys* */
+/*
+ * Checks whether key is allowed in file.
+ * returns 1 if the key is allowed or 0 otherwise.
+ */
+static int
+user_key_allowed2(struct passwd *pw, Key *key, char *file)
+{
+       FILE *f;
+       int found_key = 0;
+
+       /* Temporarily use the user's uid. */
+       temporarily_use_uid(pw);
+
+       debug("trying public key file %s", file);
+       if ((f = auth_openkeyfile(file, pw, options.strict_modes)) != NULL) {
+               found_key = check_authkeys_file(f, file, key, pw);
+               fclose(f);
+       }
+
+       restore_uid();
+       return found_key;
+}
+
+/*
+ * Checks whether key is allowed in output of command.
+ * returns 1 if the key is allowed or 0 otherwise.
+ */
+static int
+user_key_command_allowed2(struct passwd *user_pw, Key *key)
+{
+       FILE *f;
+       int ok, found_key = 0;
+       struct passwd *pw;
+       struct stat st;
+       int status, devnull, p[2], i;
+       pid_t pid;
+       char *username, errmsg[512];
+
+       if (options.authorized_keys_command == NULL ||
+           options.authorized_keys_command[0] != '/')
+               return 0;
+
+       if (options.authorized_keys_command_user == NULL) {
+               error("No user for AuthorizedKeysCommand specified, skipping");
+               return 0;
+       }
+
+       username = percent_expand(options.authorized_keys_command_user,
+           "u", user_pw->pw_name, (char *)NULL);
+       pw = getpwnam(username);
+       if (pw == NULL) {
+               error("AuthorizedKeysCommandUser \"%s\" not found: %s",
+                   username, strerror(errno));
+               free(username);
+               return 0;
+       }
+       free(username);
+
+       temporarily_use_uid(pw);
+
+       if (stat(options.authorized_keys_command, &st) < 0) {
+               error("Could not stat AuthorizedKeysCommand \"%s\": %s",
+                   options.authorized_keys_command, strerror(errno));
+               goto out;
+       }
+       if (auth_secure_path(options.authorized_keys_command, &st, NULL, 0,
+           errmsg, sizeof(errmsg)) != 0) {
+               error("Unsafe AuthorizedKeysCommand: %s", errmsg);
+               goto out;
+       }
+
+       if (pipe(p) != 0) {
+               error("%s: pipe: %s", __func__, strerror(errno));
+               goto out;
+       }
+
+       debug3("Running AuthorizedKeysCommand: \"%s %s\" as \"%s\"",
+           options.authorized_keys_command, user_pw->pw_name, pw->pw_name);
+
+       /*
+        * Don't want to call this in the child, where it can fatal() and
+        * run cleanup_exit() code.
+        */
+       restore_uid();
+
+       switch ((pid = fork())) {
+       case -1: /* error */
+               error("%s: fork: %s", __func__, strerror(errno));
+               close(p[0]);
+               close(p[1]);
+               return 0;
+       case 0: /* child */
+               for (i = 0; i < NSIG; i++)
+                       signal(i, SIG_DFL);
+
+               if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
+                       error("%s: open %s: %s", __func__, _PATH_DEVNULL,
+                           strerror(errno));
+                       _exit(1);
+               }
+               /* Keep stderr around a while longer to catch errors */
+               if (dup2(devnull, STDIN_FILENO) == -1 ||
+                   dup2(p[1], STDOUT_FILENO) == -1) {
+                       error("%s: dup2: %s", __func__, strerror(errno));
+                       _exit(1);
+               }
+               closefrom(STDERR_FILENO + 1);
+
+               /* Don't use permanently_set_uid() here to avoid fatal() */
+               if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
+                       error("setresgid %u: %s", (u_int)pw->pw_gid,
+                           strerror(errno));
+                       _exit(1);
+               }
+               if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) {
+                       error("setresuid %u: %s", (u_int)pw->pw_uid,
+                           strerror(errno));
+                       _exit(1);
+               }
+               /* stdin is pointed to /dev/null at this point */
+               if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) {
+                       error("%s: dup2: %s", __func__, strerror(errno));
+                       _exit(1);
+               }
+
+               execl(options.authorized_keys_command,
+                   options.authorized_keys_command, user_pw->pw_name, NULL);
+
+               error("AuthorizedKeysCommand %s exec failed: %s",
+                   options.authorized_keys_command, strerror(errno));
+               _exit(127);
+       default: /* parent */
+               break;
+       }
+
+       temporarily_use_uid(pw);
+
+       close(p[1]);
+       if ((f = fdopen(p[0], "r")) == NULL) {
+               error("%s: fdopen: %s", __func__, strerror(errno));
+               close(p[0]);
+               /* Don't leave zombie child */
+               kill(pid, SIGTERM);
+               while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
+                       ;
+               goto out;
+       }
+       ok = check_authkeys_file(f, options.authorized_keys_command, key, pw);
+       fclose(f);
+
+       while (waitpid(pid, &status, 0) == -1) {
+               if (errno != EINTR) {
+                       error("%s: waitpid: %s", __func__, strerror(errno));
+                       goto out;
+               }
+       }
+       if (WIFSIGNALED(status)) {
+               error("AuthorizedKeysCommand %s exited on signal %d",
+                   options.authorized_keys_command, WTERMSIG(status));
+               goto out;
+       } else if (WEXITSTATUS(status) != 0) {
+               error("AuthorizedKeysCommand %s returned status %d",
+                   options.authorized_keys_command, WEXITSTATUS(status));
+               goto out;
+       }
+       found_key = ok;
+ out:
+       restore_uid();
+       return found_key;
+}
+
+/*
+ * Check whether key authenticates and authorises the user.
+ */
 int
 user_key_allowed(struct passwd *pw, Key *key)
 {
@@ -449,11 +662,19 @@ user_key_allowed(struct passwd *pw, Key *key)
        if (success)
                return success;
 
+       success = user_key_command_allowed2(pw, key);
+       if (success > 0)
+               return success;
+
        for (i = 0; !success && i < options.num_authkeys_files; i++) {
+
+               if (strcasecmp(options.authorized_keys_files[i], "none") == 0)
+                       continue;
                file = expand_authorized_keys(
                    options.authorized_keys_files[i], pw);
+
                success = user_key_allowed2(pw, key, file);
-               xfree(file);
+               free(file);
        }
 
        return success;
index b66bef6..d9b440a 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2.c,v 1.124 2011/12/07 05:44:38 djm Exp $ */
+/* $OpenBSD: auth2.c,v 1.132 2014/07/15 15:54:14 millert Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -41,6 +41,7 @@
 #include "packet.h"
 #include "log.h"
 #include "buffer.h"
+#include "misc.h"
 #include "servconf.h"
 #include "compat.h"
 #include "key.h"
@@ -71,18 +72,12 @@ extern Authmethod method_hostbased;
 #ifdef GSSAPI
 extern Authmethod method_gssapi;
 #endif
-#ifdef JPAKE
-extern Authmethod method_jpake;
-#endif
 
 Authmethod *authmethods[] = {
        &method_none,
        &method_pubkey,
 #ifdef GSSAPI
        &method_gssapi,
-#endif
-#ifdef JPAKE
-       &method_jpake,
 #endif
        &method_passwd,
        &method_kbdint,
@@ -96,8 +91,14 @@ static void input_service_request(int, u_int32_t, void *);
 static void input_userauth_request(int, u_int32_t, void *);
 
 /* helper */
-static Authmethod *authmethod_lookup(const char *);
-static char *authmethods_get(void);
+static Authmethod *authmethod_lookup(Authctxt *, const char *);
+static char *authmethods_get(Authctxt *authctxt);
+
+#define MATCH_NONE     0       /* method or submethod mismatch */
+#define MATCH_METHOD   1       /* method matches (no submethod specified) */
+#define MATCH_BOTH     2       /* method and submethod match */
+#define MATCH_PARTIAL  3       /* method matches, submethod can't be checked */
+static int list_starts_with(const char *, const char *, const char *);
 
 char *
 auth2_read_banner(void)
@@ -124,7 +125,7 @@ auth2_read_banner(void)
        close(fd);
 
        if (n != len) {
-               xfree(banner);
+               free(banner);
                return (NULL);
        }
        banner[n] = '\0';
@@ -160,8 +161,7 @@ userauth_banner(void)
        userauth_send_banner(banner);
 
 done:
-       if (banner)
-               xfree(banner);
+       free(banner);
 }
 
 /*
@@ -206,7 +206,7 @@ input_service_request(int type, u_int32_t seq, void *ctxt)
                debug("bad service request %s", service);
                packet_disconnect("bad service request %s", service);
        }
-       xfree(service);
+       free(service);
 }
 
 /*ARGSUSED*/
@@ -255,6 +255,8 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
                if (use_privsep)
                        mm_inform_authserv(service, style);
                userauth_banner();
+               if (auth2_setup_methods_lists(authctxt) != 0)
+                       packet_disconnect("no authentication methods enabled");
        } else if (strcmp(user, authctxt->user) != 0 ||
            strcmp(service, authctxt->service) != 0) {
                packet_disconnect("Change of username or service not allowed: "
@@ -263,9 +265,6 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
        }
        /* reset state */
        auth2_challenge_stop(authctxt);
-#ifdef JPAKE
-       auth2_jpake_stop(authctxt);
-#endif
 
 #ifdef GSSAPI
        /* XXX move to auth2_gssapi_stop() */
@@ -277,26 +276,30 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
        authctxt->server_caused_failure = 0;
 
        /* try to authenticate user */
-       m = authmethod_lookup(method);
+       m = authmethod_lookup(authctxt, method);
        if (m != NULL && authctxt->failures < options.max_authtries) {
                debug2("input_userauth_request: try method %s", method);
                authenticated = m->userauth(authctxt);
        }
-       userauth_finish(authctxt, authenticated, method);
+       userauth_finish(authctxt, authenticated, method, NULL);
 
-       xfree(service);
-       xfree(user);
-       xfree(method);
+       free(service);
+       free(user);
+       free(method);
 }
 
 void
-userauth_finish(Authctxt *authctxt, int authenticated, char *method)
+userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
+    const char *submethod)
 {
        char *methods;
+       int partial = 0;
 
        if (!authctxt->valid && authenticated)
                fatal("INTERNAL ERROR: authenticated invalid user %s",
                    authctxt->user);
+       if (authenticated && authctxt->postponed)
+               fatal("INTERNAL ERROR: authenticated and postponed");
 
        /* Special handling for root */
        if (authenticated && authctxt->pw->pw_uid == 0 &&
@@ -307,6 +310,19 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
 #endif
        }
 
+       if (authenticated && options.num_auth_methods != 0) {
+               if (!auth2_update_methods_lists(authctxt, method, submethod)) {
+                       authenticated = 0;
+                       partial = 1;
+               }
+       }
+
+       /* Log before sending the reply */
+       auth_log(authctxt, authenticated, partial, method, submethod);
+
+       if (authctxt->postponed)
+               return;
+
 #ifdef USE_PAM
        if (options.use_pam && authenticated) {
                if (!PRIVSEP(do_pam_account())) {
@@ -325,17 +341,10 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
 #ifdef _UNICOS
        if (authenticated && cray_access_denied(authctxt->user)) {
                authenticated = 0;
-               fatal("Access denied for user %s.",authctxt->user);
+               fatal("Access denied for user %s.", authctxt->user);
        }
 #endif /* _UNICOS */
 
-       /* Log before sending the reply */
-       auth_log(authctxt, authenticated, method, " ssh2");
-
-       if (authctxt->postponed)
-               return;
-
-       /* XXX todo: check if multiple auth methods are needed */
        if (authenticated == 1) {
                /* turn off userauth */
                dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
@@ -354,36 +363,66 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
 #ifdef SSH_AUDIT_EVENTS
                        PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
 #endif
-                       packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
+                       auth_maxtries_exceeded(authctxt);
                }
-               methods = authmethods_get();
+               methods = authmethods_get(authctxt);
+               debug3("%s: failure partial=%d next methods=\"%s\"", __func__,
+                   partial, methods);
                packet_start(SSH2_MSG_USERAUTH_FAILURE);
                packet_put_cstring(methods);
-               packet_put_char(0);     /* XXX partial success, unused */
+               packet_put_char(partial);
                packet_send();
                packet_write_wait();
-               xfree(methods);
+               free(methods);
        }
 }
 
+/*
+ * Checks whether method is allowed by at least one AuthenticationMethods
+ * methods list. Returns 1 if allowed, or no methods lists configured.
+ * 0 otherwise.
+ */
+int
+auth2_method_allowed(Authctxt *authctxt, const char *method,
+    const char *submethod)
+{
+       u_int i;
+
+       /*
+        * NB. authctxt->num_auth_methods might be zero as a result of
+        * auth2_setup_methods_lists(), so check the configuration.
+        */
+       if (options.num_auth_methods == 0)
+               return 1;
+       for (i = 0; i < authctxt->num_auth_methods; i++) {
+               if (list_starts_with(authctxt->auth_methods[i], method,
+                   submethod) != MATCH_NONE)
+                       return 1;
+       }
+       return 0;
+}
+
 static char *
-authmethods_get(void)
+authmethods_get(Authctxt *authctxt)
 {
        Buffer b;
        char *list;
-       int i;
+       u_int i;
 
        buffer_init(&b);
        for (i = 0; authmethods[i] != NULL; i++) {
                if (strcmp(authmethods[i]->name, "none") == 0)
                        continue;
-               if (authmethods[i]->enabled != NULL &&
-                   *(authmethods[i]->enabled) != 0) {
-                       if (buffer_len(&b) > 0)
-                               buffer_append(&b, ",", 1);
-                       buffer_append(&b, authmethods[i]->name,
-                           strlen(authmethods[i]->name));
-               }
+               if (authmethods[i]->enabled == NULL ||
+                   *(authmethods[i]->enabled) == 0)
+                       continue;
+               if (!auth2_method_allowed(authctxt, authmethods[i]->name,
+                   NULL))
+                       continue;
+               if (buffer_len(&b) > 0)
+                       buffer_append(&b, ",", 1);
+               buffer_append(&b, authmethods[i]->name,
+                   strlen(authmethods[i]->name));
        }
        buffer_append(&b, "\0", 1);
        list = xstrdup(buffer_ptr(&b));
@@ -392,7 +431,7 @@ authmethods_get(void)
 }
 
 static Authmethod *
-authmethod_lookup(const char *name)
+authmethod_lookup(Authctxt *authctxt, const char *name)
 {
        int i;
 
@@ -400,10 +439,181 @@ authmethod_lookup(const char *name)
                for (i = 0; authmethods[i] != NULL; i++)
                        if (authmethods[i]->enabled != NULL &&
                            *(authmethods[i]->enabled) != 0 &&
-                           strcmp(name, authmethods[i]->name) == 0)
+                           strcmp(name, authmethods[i]->name) == 0 &&
+                           auth2_method_allowed(authctxt,
+                           authmethods[i]->name, NULL))
                                return authmethods[i];
        debug2("Unrecognized authentication method name: %s",
            name ? name : "NULL");
        return NULL;
 }
 
+/*
+ * Check a comma-separated list of methods for validity. Is need_enable is
+ * non-zero, then also require that the methods are enabled.
+ * Returns 0 on success or -1 if the methods list is invalid.
+ */
+int
+auth2_methods_valid(const char *_methods, int need_enable)
+{
+       char *methods, *omethods, *method, *p;
+       u_int i, found;
+       int ret = -1;
+
+       if (*_methods == '\0') {
+               error("empty authentication method list");
+               return -1;
+       }
+       omethods = methods = xstrdup(_methods);
+       while ((method = strsep(&methods, ",")) != NULL) {
+               for (found = i = 0; !found && authmethods[i] != NULL; i++) {
+                       if ((p = strchr(method, ':')) != NULL)
+                               *p = '\0';
+                       if (strcmp(method, authmethods[i]->name) != 0)
+                               continue;
+                       if (need_enable) {
+                               if (authmethods[i]->enabled == NULL ||
+                                   *(authmethods[i]->enabled) == 0) {
+                                       error("Disabled method \"%s\" in "
+                                           "AuthenticationMethods list \"%s\"",
+                                           method, _methods);
+                                       goto out;
+                               }
+                       }
+                       found = 1;
+                       break;
+               }
+               if (!found) {
+                       error("Unknown authentication method \"%s\" in list",
+                           method);
+                       goto out;
+               }
+       }
+       ret = 0;
+ out:
+       free(omethods);
+       return ret;
+}
+
+/*
+ * Prune the AuthenticationMethods supplied in the configuration, removing
+ * any methods lists that include disabled methods. Note that this might
+ * leave authctxt->num_auth_methods == 0, even when multiple required auth
+ * has been requested. For this reason, all tests for whether multiple is
+ * enabled should consult options.num_auth_methods directly.
+ */
+int
+auth2_setup_methods_lists(Authctxt *authctxt)
+{
+       u_int i;
+
+       if (options.num_auth_methods == 0)
+               return 0;
+       debug3("%s: checking methods", __func__);
+       authctxt->auth_methods = xcalloc(options.num_auth_methods,
+           sizeof(*authctxt->auth_methods));
+       authctxt->num_auth_methods = 0;
+       for (i = 0; i < options.num_auth_methods; i++) {
+               if (auth2_methods_valid(options.auth_methods[i], 1) != 0) {
+                       logit("Authentication methods list \"%s\" contains "
+                           "disabled method, skipping",
+                           options.auth_methods[i]);
+                       continue;
+               }
+               debug("authentication methods list %d: %s",
+                   authctxt->num_auth_methods, options.auth_methods[i]);
+               authctxt->auth_methods[authctxt->num_auth_methods++] =
+                   xstrdup(options.auth_methods[i]);
+       }
+       if (authctxt->num_auth_methods == 0) {
+               error("No AuthenticationMethods left after eliminating "
+                   "disabled methods");
+               return -1;
+       }
+       return 0;
+}
+
+static int
+list_starts_with(const char *methods, const char *method,
+    const char *submethod)
+{
+       size_t l = strlen(method);
+       int match;
+       const char *p;
+
+       if (strncmp(methods, method, l) != 0)
+               return MATCH_NONE;
+       p = methods + l;
+       match = MATCH_METHOD;
+       if (*p == ':') {
+               if (!submethod)
+                       return MATCH_PARTIAL;
+               l = strlen(submethod);
+               p += 1;
+               if (strncmp(submethod, p, l))
+                       return MATCH_NONE;
+               p += l;
+               match = MATCH_BOTH;
+       }
+       if (*p != ',' && *p != '\0')
+               return MATCH_NONE;
+       return match;
+}
+
+/*
+ * Remove method from the start of a comma-separated list of methods.
+ * Returns 0 if the list of methods did not start with that method or 1
+ * if it did.
+ */
+static int
+remove_method(char **methods, const char *method, const char *submethod)
+{
+       char *omethods = *methods, *p;
+       size_t l = strlen(method);
+       int match;
+
+       match = list_starts_with(omethods, method, submethod);
+       if (match != MATCH_METHOD && match != MATCH_BOTH)
+               return 0;
+       p = omethods + l;
+       if (submethod && match == MATCH_BOTH)
+               p += 1 + strlen(submethod); /* include colon */
+       if (*p == ',')
+               p++;
+       *methods = xstrdup(p);
+       free(omethods);
+       return 1;
+}
+
+/*
+ * Called after successful authentication. Will remove the successful method
+ * from the start of each list in which it occurs. If it was the last method
+ * in any list, then authentication is deemed successful.
+ * Returns 1 if the method completed any authentication list or 0 otherwise.
+ */
+int
+auth2_update_methods_lists(Authctxt *authctxt, const char *method,
+    const char *submethod)
+{
+       u_int i, found = 0;
+
+       debug3("%s: updating methods list after \"%s\"", __func__, method);
+       for (i = 0; i < authctxt->num_auth_methods; i++) {
+               if (!remove_method(&(authctxt->auth_methods[i]), method,
+                   submethod))
+                       continue;
+               found = 1;
+               if (*authctxt->auth_methods[i] == '\0') {
+                       debug2("authentication methods list %d complete", i);
+                       return 1;
+               }
+               debug3("authentication methods list %d remaining: \"%s\"",
+                   i, authctxt->auth_methods[i]);
+       }
+       /* This should not happen, but would be bad if it did */
+       if (!found)
+               fatal("%s: method not in AuthenticationMethods", __func__);
+       return 0;
+}
+
+
index f037e83..2d5a8dd 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfd.c,v 1.86 2011/07/06 18:09:21 tedu Exp $ */
+/* $OpenBSD: authfd.c,v 1.93 2014/04/29 18:01:49 markus Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -41,9 +41,6 @@
 #include <sys/un.h>
 #include <sys/socket.h>
 
-#include <openssl/evp.h>
-
-#include <openssl/crypto.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <signal.h>
@@ -102,7 +99,7 @@ ssh_get_authentication_socket(void)
        if (!authsocket)
                return -1;
 
-       bzero(&sunaddr, sizeof(sunaddr));
+       memset(&sunaddr, 0, sizeof(sunaddr));
        sunaddr.sun_family = AF_UNIX;
        strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
 
@@ -206,7 +203,7 @@ ssh_get_authentication_connection(void)
        if (sock < 0)
                return NULL;
 
-       auth = xmalloc(sizeof(*auth));
+       auth = xcalloc(1, sizeof(*auth));
        auth->fd = sock;
        buffer_init(&auth->identities);
        auth->howmany = 0;
@@ -224,7 +221,7 @@ ssh_close_authentication_connection(AuthenticationConnection *auth)
 {
        buffer_free(&auth->identities);
        close(auth->fd);
-       xfree(auth);
+       free(auth);
 }
 
 /* Lock/unlock agent */
@@ -313,8 +310,10 @@ ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int versi
 Key *
 ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version)
 {
+#ifdef WITH_SSH1
        int keybits;
        u_int bits;
+#endif
        u_char *blob;
        u_int blen;
        Key *key = NULL;
@@ -328,6 +327,7 @@ ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int versio
         * error if the packet is too short or contains corrupt data.
         */
        switch (version) {
+#ifdef WITH_SSH1
        case 1:
                key = key_new(KEY_RSA1);
                bits = buffer_get_int(&auth->identities);
@@ -339,11 +339,12 @@ ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int versio
                        logit("Warning: identity keysize mismatch: actual %d, announced %u",
                            BN_num_bits(key->rsa->n), bits);
                break;
+#endif
        case 2:
                blob = buffer_get_string(&auth->identities, &blen);
                *comment = buffer_get_string(&auth->identities, NULL);
                key = key_from_blob(blob, blen);
-               xfree(blob);
+               free(blob);
                break;
        default:
                return NULL;
@@ -361,6 +362,7 @@ ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int versio
  * supported) and 1 corresponding to protocol version 1.1.
  */
 
+#ifdef WITH_SSH1
 int
 ssh_decrypt_challenge(AuthenticationConnection *auth,
     Key* key, BIGNUM *challenge,
@@ -410,6 +412,7 @@ ssh_decrypt_challenge(AuthenticationConnection *auth,
        buffer_free(&buffer);
        return success;
 }
+#endif
 
 /* ask agent to sign data, returns -1 on error, 0 on success */
 int
@@ -436,7 +439,7 @@ ssh_agent_sign(AuthenticationConnection *auth,
        buffer_put_string(&msg, blob, blen);
        buffer_put_string(&msg, data, datalen);
        buffer_put_int(&msg, flags);
-       xfree(blob);
+       free(blob);
 
        if (ssh_request_reply(auth, &msg, &msg) == 0) {
                buffer_free(&msg);
@@ -457,6 +460,7 @@ ssh_agent_sign(AuthenticationConnection *auth,
 
 /* Encode key for a message to the agent. */
 
+#ifdef WITH_SSH1
 static void
 ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment)
 {
@@ -470,62 +474,12 @@ ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment)
        buffer_put_bignum(b, key->p);   /* ssh key->q, SSL key->p */
        buffer_put_cstring(b, comment);
 }
+#endif
 
 static void
 ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment)
 {
-       buffer_put_cstring(b, key_ssh_name(key));
-       switch (key->type) {
-       case KEY_RSA:
-               buffer_put_bignum2(b, key->rsa->n);
-               buffer_put_bignum2(b, key->rsa->e);
-               buffer_put_bignum2(b, key->rsa->d);
-               buffer_put_bignum2(b, key->rsa->iqmp);
-               buffer_put_bignum2(b, key->rsa->p);
-               buffer_put_bignum2(b, key->rsa->q);
-               break;
-       case KEY_RSA_CERT_V00:
-       case KEY_RSA_CERT:
-               if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)
-                       fatal("%s: no cert/certblob", __func__);
-               buffer_put_string(b, buffer_ptr(&key->cert->certblob),
-                   buffer_len(&key->cert->certblob));
-               buffer_put_bignum2(b, key->rsa->d);
-               buffer_put_bignum2(b, key->rsa->iqmp);
-               buffer_put_bignum2(b, key->rsa->p);
-               buffer_put_bignum2(b, key->rsa->q);
-               break;
-       case KEY_DSA:
-               buffer_put_bignum2(b, key->dsa->p);
-               buffer_put_bignum2(b, key->dsa->q);
-               buffer_put_bignum2(b, key->dsa->g);
-               buffer_put_bignum2(b, key->dsa->pub_key);
-               buffer_put_bignum2(b, key->dsa->priv_key);
-               break;
-       case KEY_DSA_CERT_V00:
-       case KEY_DSA_CERT:
-               if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)
-                       fatal("%s: no cert/certblob", __func__);
-               buffer_put_string(b, buffer_ptr(&key->cert->certblob),
-                   buffer_len(&key->cert->certblob));
-               buffer_put_bignum2(b, key->dsa->priv_key);
-               break;
-#ifdef OPENSSL_HAS_ECC
-       case KEY_ECDSA:
-               buffer_put_cstring(b, key_curve_nid_to_name(key->ecdsa_nid));
-               buffer_put_ecpoint(b, EC_KEY_get0_group(key->ecdsa),
-                   EC_KEY_get0_public_key(key->ecdsa));
-               buffer_put_bignum2(b, EC_KEY_get0_private_key(key->ecdsa));
-               break;
-       case KEY_ECDSA_CERT:
-               if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)
-                       fatal("%s: no cert/certblob", __func__);
-               buffer_put_string(b, buffer_ptr(&key->cert->certblob),
-                   buffer_len(&key->cert->certblob));
-               buffer_put_bignum2(b, EC_KEY_get0_private_key(key->ecdsa));
-               break;
-#endif
-       }
+       key_private_serialize(key, b);
        buffer_put_cstring(b, comment);
 }
 
@@ -544,6 +498,7 @@ ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key,
        buffer_init(&msg);
 
        switch (key->type) {
+#ifdef WITH_SSH1
        case KEY_RSA1:
                type = constrained ?
                    SSH_AGENTC_ADD_RSA_ID_CONSTRAINED :
@@ -551,6 +506,8 @@ ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key,
                buffer_put_char(&msg, type);
                ssh_encode_identity_rsa1(&msg, key->rsa, comment);
                break;
+#endif
+#ifdef WITH_OPENSSL
        case KEY_RSA:
        case KEY_RSA_CERT:
        case KEY_RSA_CERT_V00:
@@ -559,6 +516,9 @@ ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key,
        case KEY_DSA_CERT_V00:
        case KEY_ECDSA:
        case KEY_ECDSA_CERT:
+#endif
+       case KEY_ED25519:
+       case KEY_ED25519_CERT:
                type = constrained ?
                    SSH2_AGENTC_ADD_ID_CONSTRAINED :
                    SSH2_AGENTC_ADD_IDENTITY;
@@ -601,18 +561,19 @@ ssh_remove_identity(AuthenticationConnection *auth, Key *key)
 
        buffer_init(&msg);
 
+#ifdef WITH_SSH1
        if (key->type == KEY_RSA1) {
                buffer_put_char(&msg, SSH_AGENTC_REMOVE_RSA_IDENTITY);
                buffer_put_int(&msg, BN_num_bits(key->rsa->n));
                buffer_put_bignum(&msg, key->rsa->e);
                buffer_put_bignum(&msg, key->rsa->n);
-       } else if (key_type_plain(key->type) == KEY_DSA ||
-           key_type_plain(key->type) == KEY_RSA ||
-           key_type_plain(key->type) == KEY_ECDSA) {
+       } else
+#endif
+       if (key->type != KEY_UNSPEC) {
                key_to_blob(key, &blob, &blen);
                buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY);
                buffer_put_string(&msg, blob, blen);
-               xfree(blob);
+               free(blob);
        } else {
                buffer_free(&msg);
                return 0;
index 7dd4496..e93d867 100644 (file)
@@ -1,19 +1,6 @@
-/* $OpenBSD: authfile.c,v 1.93 2012/01/25 19:36:31 markus Exp $ */
+/* $OpenBSD: authfile.c,v 1.107 2014/06/24 01:13:21 djm Exp $ */
 /*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- *                    All rights reserved
- * This file contains functions for reading and writing identity files, and
- * for reading the passphrase from the user.
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose.  Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- *
- *
- * Copyright (c) 2000 Markus Friedl.  All rights reserved.
+ * Copyright (c) 2000, 2013 Markus Friedl.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include <sys/param.h>
 #include <sys/uio.h>
 
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/pem.h>
-
-/* compatibility with old or broken OpenSSL versions */
-#include "openbsd-compat/openssl-compat.h"
-
 #include <errno.h>
 #include <fcntl.h>
-#include <stdarg.h>
 #include <stdio.h>
+#include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
-#include "xmalloc.h"
 #include "cipher.h"
-#include "buffer.h"
 #include "key.h"
 #include "ssh.h"
 #include "log.h"
 #include "rsa.h"
 #include "misc.h"
 #include "atomicio.h"
+#include "sshbuf.h"
+#include "ssherr.h"
 
 #define MAX_KEY_FILE_SIZE      (1024 * 1024)
 
-/* Version identification string for SSH v1 identity files. */
-static const char authfile_id_string[] =
-    "SSH PRIVATE KEY FILE FORMAT 1.1\n";
-
-/*
- * Serialises the authentication (private) key to a blob, encrypting it with
- * passphrase.  The identification of the blob (lowest 64 bits of n) will
- * precede the key to provide identification of the key without needing a
- * passphrase.
- */
-static int
-key_private_rsa1_to_blob(Key *key, Buffer *blob, const char *passphrase,
-    const char *comment)
-{
-       Buffer buffer, encrypted;
-       u_char buf[100], *cp;
-       int i, cipher_num;
-       CipherContext ciphercontext;
-       Cipher *cipher;
-       u_int32_t rnd;
-
-       /*
-        * If the passphrase is empty, use SSH_CIPHER_NONE to ease converting
-        * to another cipher; otherwise use SSH_AUTHFILE_CIPHER.
-        */
-       cipher_num = (strcmp(passphrase, "") == 0) ?
-           SSH_CIPHER_NONE : SSH_AUTHFILE_CIPHER;
-       if ((cipher = cipher_by_number(cipher_num)) == NULL)
-               fatal("save_private_key_rsa: bad cipher");
-
-       /* This buffer is used to built the secret part of the private key. */
-       buffer_init(&buffer);
-
-       /* Put checkbytes for checking passphrase validity. */
-       rnd = arc4random();
-       buf[0] = rnd & 0xff;
-       buf[1] = (rnd >> 8) & 0xff;
-       buf[2] = buf[0];
-       buf[3] = buf[1];
-       buffer_append(&buffer, buf, 4);
-
-       /*
-        * Store the private key (n and e will not be stored because they
-        * will be stored in plain text, and storing them also in encrypted
-        * format would just give known plaintext).
-        */
-       buffer_put_bignum(&buffer, key->rsa->d);
-       buffer_put_bignum(&buffer, key->rsa->iqmp);
-       buffer_put_bignum(&buffer, key->rsa->q);        /* reverse from SSL p */
-       buffer_put_bignum(&buffer, key->rsa->p);        /* reverse from SSL q */
-
-       /* Pad the part to be encrypted until its size is a multiple of 8. */
-       while (buffer_len(&buffer) % 8 != 0)
-               buffer_put_char(&buffer, 0);
-
-       /* This buffer will be used to contain the data in the file. */
-       buffer_init(&encrypted);
-
-       /* First store keyfile id string. */
-       for (i = 0; authfile_id_string[i]; i++)
-               buffer_put_char(&encrypted, authfile_id_string[i]);
-       buffer_put_char(&encrypted, 0);
-
-       /* Store cipher type. */
-       buffer_put_char(&encrypted, cipher_num);
-       buffer_put_int(&encrypted, 0);  /* For future extension */
-
-       /* Store public key.  This will be in plain text. */
-       buffer_put_int(&encrypted, BN_num_bits(key->rsa->n));
-       buffer_put_bignum(&encrypted, key->rsa->n);
-       buffer_put_bignum(&encrypted, key->rsa->e);
-       buffer_put_cstring(&encrypted, comment);
-
-       /* Allocate space for the private part of the key in the buffer. */
-       cp = buffer_append_space(&encrypted, buffer_len(&buffer));
-
-       cipher_set_key_string(&ciphercontext, cipher, passphrase,
-           CIPHER_ENCRYPT);
-       cipher_crypt(&ciphercontext, cp,
-           buffer_ptr(&buffer), buffer_len(&buffer));
-       cipher_cleanup(&ciphercontext);
-       memset(&ciphercontext, 0, sizeof(ciphercontext));
-
-       /* Destroy temporary data. */
-       memset(buf, 0, sizeof(buf));
-       buffer_free(&buffer);
-
-       buffer_append(blob, buffer_ptr(&encrypted), buffer_len(&encrypted));
-       buffer_free(&encrypted);
-
-       return 1;
-}
-
-/* convert SSH v2 key in OpenSSL PEM format */
-static int
-key_private_pem_to_blob(Key *key, Buffer *blob, const char *_passphrase,
-    const char *comment)
-{
-       int success = 0;
-       int blen, len = strlen(_passphrase);
-       u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
-#if (OPENSSL_VERSION_NUMBER < 0x00907000L)
-       const EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL;
-#else
-       const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
-#endif
-       const u_char *bptr;
-       BIO *bio;
-
-       if (len > 0 && len <= 4) {
-               error("passphrase too short: have %d bytes, need > 4", len);
-               return 0;
-       }
-       if ((bio = BIO_new(BIO_s_mem())) == NULL) {
-               error("%s: BIO_new failed", __func__);
-               return 0;
-       }
-       switch (key->type) {
-       case KEY_DSA:
-               success = PEM_write_bio_DSAPrivateKey(bio, key->dsa,
-                   cipher, passphrase, len, NULL, NULL);
-               break;
-#ifdef OPENSSL_HAS_ECC
-       case KEY_ECDSA:
-               success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa,
-                   cipher, passphrase, len, NULL, NULL);
-               break;
-#endif
-       case KEY_RSA:
-               success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
-                   cipher, passphrase, len, NULL, NULL);
-               break;
-       }
-       if (success) {
-               if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0)
-                       success = 0;
-               else
-                       buffer_append(blob, bptr, blen);
-       }
-       BIO_free(bio);
-       return success;
-}
-
 /* Save a key blob to a file */
 static int
-key_save_private_blob(Buffer *keybuf, const char *filename)
+sshkey_save_private_blob(struct sshbuf *keybuf, const char *filename)
 {
-       int fd;
+       int fd, oerrno;
 
-       if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) {
-               error("open %s failed: %s.", filename, strerror(errno));
-               return 0;
-       }
-       if (atomicio(vwrite, fd, buffer_ptr(keybuf),
-           buffer_len(keybuf)) != buffer_len(keybuf)) {
-               error("write to key file %s failed: %s", filename,
-                   strerror(errno));
+       if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0)
+               return SSH_ERR_SYSTEM_ERROR;
+       if (atomicio(vwrite, fd, (u_char *)sshbuf_ptr(keybuf),
+           sshbuf_len(keybuf)) != sshbuf_len(keybuf)) {
+               oerrno = errno;
                close(fd);
                unlink(filename);
-               return 0;
+               errno = oerrno;
+               return SSH_ERR_SYSTEM_ERROR;
        }
        close(fd);
-       return 1;
-}
-
-/* Serialise "key" to buffer "blob" */
-static int
-key_private_to_blob(Key *key, Buffer *blob, const char *passphrase,
-    const char *comment)
-{
-       switch (key->type) {
-       case KEY_RSA1:
-               return key_private_rsa1_to_blob(key, blob, passphrase, comment);
-       case KEY_DSA:
-       case KEY_ECDSA:
-       case KEY_RSA:
-               return key_private_pem_to_blob(key, blob, passphrase, comment);
-       default:
-               error("%s: cannot save key type %d", __func__, key->type);
-               return 0;
-       }
+       return 0;
 }
 
 int
-key_save_private(Key *key, const char *filename, const char *passphrase,
-    const char *comment)
+sshkey_save_private(struct sshkey *key, const char *filename,
+    const char *passphrase, const char *comment,
+    int force_new_format, const char *new_format_cipher, int new_format_rounds)
 {
-       Buffer keyblob;
-       int success = 0;
+       struct sshbuf *keyblob = NULL;
+       int r;
 
-       buffer_init(&keyblob);
-       if (!key_private_to_blob(key, &keyblob, passphrase, comment))
+       if ((keyblob = sshbuf_new()) == NULL)
+               return SSH_ERR_ALLOC_FAIL;
+       if ((r = sshkey_private_to_fileblob(key, keyblob, passphrase, comment,
+           force_new_format, new_format_cipher, new_format_rounds)) != 0)
                goto out;
-       if (!key_save_private_blob(&keyblob, filename))
+       if ((r = sshkey_save_private_blob(keyblob, filename)) != 0)
                goto out;
-       success = 1;
+       r = 0;
  out:
-       buffer_free(&keyblob);
-       return success;
-}
-
-/*
- * Parse the public, unencrypted portion of a RSA1 key.
- */
-static Key *
-key_parse_public_rsa1(Buffer *blob, char **commentp)
-{
-       Key *pub;
-       Buffer copy;
-
-       /* Check that it is at least big enough to contain the ID string. */
-       if (buffer_len(blob) < sizeof(authfile_id_string)) {
-               debug3("Truncated RSA1 identifier");
-               return NULL;
-       }
-
-       /*
-        * Make sure it begins with the id string.  Consume the id string
-        * from the buffer.
-        */
-       if (memcmp(buffer_ptr(blob), authfile_id_string,
-           sizeof(authfile_id_string)) != 0) {
-               debug3("Incorrect RSA1 identifier");
-               return NULL;
-       }
-       buffer_init(&copy);
-       buffer_append(&copy, buffer_ptr(blob), buffer_len(blob));
-       buffer_consume(&copy, sizeof(authfile_id_string));
-
-       /* Skip cipher type and reserved data. */
-       (void) buffer_get_char(&copy);          /* cipher type */
-       (void) buffer_get_int(&copy);           /* reserved */
-
-       /* Read the public key from the buffer. */
-       (void) buffer_get_int(&copy);
-       pub = key_new(KEY_RSA1);
-       buffer_get_bignum(&copy, pub->rsa->n);
-       buffer_get_bignum(&copy, pub->rsa->e);
-       if (commentp)
-               *commentp = buffer_get_string(&copy, NULL);
-       /* The encrypted private part is not parsed by this function. */
-       buffer_free(&copy);
-
-       return pub;
+       sshbuf_free(keyblob);
+       return r;
 }
 
 /* Load a key from a fd into a buffer */
 int
-key_load_file(int fd, const char *filename, Buffer *blob)
+sshkey_load_file(int fd, const char *filename, struct sshbuf *blob)
 {
        u_char buf[1024];
        size_t len;
        struct stat st;
+       int r;
 
-       if (fstat(fd, &st) < 0) {
-               error("%s: fstat of key file %.200s%sfailed: %.100s", __func__,
-                   filename == NULL ? "" : filename,
-                   filename == NULL ? "" : " ",
-                   strerror(errno));
-               return 0;
-       }
+       if (fstat(fd, &st) < 0)
+               return SSH_ERR_SYSTEM_ERROR;
        if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
-           st.st_size > MAX_KEY_FILE_SIZE) {
- toobig:
-               error("%s: key file %.200s%stoo large", __func__,
-                   filename == NULL ? "" : filename,
-                   filename == NULL ? "" : " ");
-               return 0;
-       }
-       buffer_clear(blob);
+           st.st_size > MAX_KEY_FILE_SIZE)
+               return SSH_ERR_INVALID_FORMAT;
        for (;;) {
                if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) {
                        if (errno == EPIPE)
                                break;
-                       debug("%s: read from key file %.200s%sfailed: %.100s",
-                           __func__, filename == NULL ? "" : filename,
-                           filename == NULL ? "" : " ", strerror(errno));
-                       buffer_clear(blob);
-                       bzero(buf, sizeof(buf));
-                       return 0;
+                       r = SSH_ERR_SYSTEM_ERROR;
+                       goto out;
                }
-               buffer_append(blob, buf, len);
-               if (buffer_len(blob) > MAX_KEY_FILE_SIZE) {
-                       buffer_clear(blob);
-                       bzero(buf, sizeof(buf));
-                       goto toobig;
+               if ((r = sshbuf_put(blob, buf, len)) != 0)
+                       goto out;
+               if (sshbuf_len(blob) > MAX_KEY_FILE_SIZE) {
+                       r = SSH_ERR_INVALID_FORMAT;
+                       goto out;
                }
        }
-       bzero(buf, sizeof(buf));
        if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
-           st.st_size != buffer_len(blob)) {
-               debug("%s: key file %.200s%schanged size while reading",
-                   __func__, filename == NULL ? "" : filename,
-                   filename == NULL ? "" : " ");
-               buffer_clear(blob);
-               return 0;
+           st.st_size != (off_t)sshbuf_len(blob)) {
+               r = SSH_ERR_FILE_CHANGED;
+               goto out;
        }
+       r = 0;
 
-       return 1;
+ out:
+       explicit_bzero(buf, sizeof(buf));
+       if (r != 0)
+               sshbuf_reset(blob);
+       return r;
 }
 
+#ifdef WITH_SSH1
 /*
  * Loads the public part of the ssh v1 key file.  Returns NULL if an error was
  * encountered (the file does not exist or is not readable), and the key
  * otherwise.
  */
-static Key *
-key_load_public_rsa1(int fd, const char *filename, char **commentp)
+static int
+sshkey_load_public_rsa1(int fd, const char *filename,
+    struct sshkey **keyp, char **commentp)
 {
-       Buffer buffer;
-       Key *pub;
-
-       buffer_init(&buffer);
-       if (!key_load_file(fd, filename, &buffer)) {
-               buffer_free(&buffer);
-               return NULL;
-       }
+       struct sshbuf *b = NULL;
+       int r;
 
-       pub = key_parse_public_rsa1(&buffer, commentp);
-       if (pub == NULL)
-               debug3("Could not load \"%s\" as a RSA1 public key", filename);
-       buffer_free(&buffer);
-       return pub;
-}
+       *keyp = NULL;
+       if (commentp != NULL)
+               *commentp = NULL;
 
-/* load public key from private-key file, works only for SSH v1 */
-Key *
-key_load_public_type(int type, const char *filename, char **commentp)
-{
-       Key *pub;
-       int fd;
-
-       if (type == KEY_RSA1) {
-               fd = open(filename, O_RDONLY);
-               if (fd < 0)
-                       return NULL;
-               pub = key_load_public_rsa1(fd, filename, commentp);
-               close(fd);
-               return pub;
-       }
-       return NULL;
+       if ((b = sshbuf_new()) == NULL)
+               return SSH_ERR_ALLOC_FAIL;
+       if ((r = sshkey_load_file(fd, filename, b)) != 0)
+               goto out;
+       if ((r = sshkey_parse_public_rsa1_fileblob(b, keyp, commentp)) != 0)
+               goto out;
+       r = 0;
+ out:
+       sshbuf_free(b);
+       return r;
 }
+#endif /* WITH_SSH1 */
 
-static Key *
-key_parse_private_rsa1(Buffer *blob, const char *passphrase, char **commentp)
+#ifdef WITH_OPENSSL
+/* XXX Deprecate? */
+int
+sshkey_load_private_pem(int fd, int type, const char *passphrase,
+    struct sshkey **keyp, char **commentp)
 {
-       int check1, check2, cipher_type;
-       Buffer decrypted;
-       u_char *cp;
-       CipherContext ciphercontext;
-       Cipher *cipher;
-       Key *prv = NULL;
-       Buffer copy;
-
-       /* Check that it is at least big enough to contain the ID string. */
-       if (buffer_len(blob) < sizeof(authfile_id_string)) {
-               debug3("Truncated RSA1 identifier");
-               return NULL;
-       }
+       struct sshbuf *buffer = NULL;
+       int r;
 
-       /*
-        * Make sure it begins with the id string.  Consume the id string
-        * from the buffer.
-        */
-       if (memcmp(buffer_ptr(blob), authfile_id_string,
-           sizeof(authfile_id_string)) != 0) {
-               debug3("Incorrect RSA1 identifier");
-               return NULL;
-       }
-       buffer_init(&copy);
-       buffer_append(&copy, buffer_ptr(blob), buffer_len(blob));
-       buffer_consume(&copy, sizeof(authfile_id_string));
-
-       /* Read cipher type. */
-       cipher_type = buffer_get_char(&copy);
-       (void) buffer_get_int(&copy);   /* Reserved data. */
-
-       /* Read the public key from the buffer. */
-       (void) buffer_get_int(&copy);
-       prv = key_new_private(KEY_RSA1);
-
-       buffer_get_bignum(&copy, prv->rsa->n);
-       buffer_get_bignum(&copy, prv->rsa->e);
-       if (commentp)
-               *commentp = buffer_get_string(&copy, NULL);
-       else
-               (void)buffer_get_string_ptr(&copy, NULL);
-
-       /* Check that it is a supported cipher. */
-       cipher = cipher_by_number(cipher_type);
-       if (cipher == NULL) {
-               debug("Unsupported RSA1 cipher %d", cipher_type);
-               buffer_free(&copy);
-               goto fail;
-       }
-       /* Initialize space for decrypted data. */
-       buffer_init(&decrypted);
-       cp = buffer_append_space(&decrypted, buffer_len(&copy));
-
-       /* Rest of the buffer is encrypted.  Decrypt it using the passphrase. */
-       cipher_set_key_string(&ciphercontext, cipher, passphrase,
-           CIPHER_DECRYPT);
-       cipher_crypt(&ciphercontext, cp,
-           buffer_ptr(&copy), buffer_len(&copy));
-       cipher_cleanup(&ciphercontext);
-       memset(&ciphercontext, 0, sizeof(ciphercontext));
-       buffer_free(&copy);
-
-       check1 = buffer_get_char(&decrypted);
-       check2 = buffer_get_char(&decrypted);
-       if (check1 != buffer_get_char(&decrypted) ||
-           check2 != buffer_get_char(&decrypted)) {
-               if (strcmp(passphrase, "") != 0)
-                       debug("Bad passphrase supplied for RSA1 key");
-               /* Bad passphrase. */
-               buffer_free(&decrypted);
-               goto fail;
-       }
-       /* Read the rest of the private key. */
-       buffer_get_bignum(&decrypted, prv->rsa->d);
-       buffer_get_bignum(&decrypted, prv->rsa->iqmp);          /* u */
-       /* in SSL and SSH v1 p and q are exchanged */
-       buffer_get_bignum(&decrypted, prv->rsa->q);             /* p */
-       buffer_get_bignum(&decrypted, prv->rsa->p);             /* q */
-
-       /* calculate p-1 and q-1 */
-       rsa_generate_additional_parameters(prv->rsa);
-
-       buffer_free(&decrypted);
-
-       /* enable blinding */
-       if (RSA_blinding_on(prv->rsa, NULL) != 1) {
-               error("%s: RSA_blinding_on failed", __func__);
-               goto fail;
-       }
-       return prv;
-
-fail:
-       if (commentp)
-               xfree(*commentp);
-       key_free(prv);
-       return NULL;
-}
+       *keyp = NULL;
+       if (commentp != NULL)
+               *commentp = NULL;
 
-static Key *
-key_parse_private_pem(Buffer *blob, int type, const char *passphrase,
-    char **commentp)
-{
-       EVP_PKEY *pk = NULL;
-       Key *prv = NULL;
-       char *name = "<no key>";
-       BIO *bio;
-
-       if ((bio = BIO_new_mem_buf(buffer_ptr(blob),
-           buffer_len(blob))) == NULL) {
-               error("%s: BIO_new_mem_buf failed", __func__);
-               return NULL;
-       }
-       
-       pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, (char *)passphrase);
-       BIO_free(bio);
-       if (pk == NULL) {
-               debug("%s: PEM_read_PrivateKey failed", __func__);
-               (void)ERR_get_error();
-       } else if (pk->type == EVP_PKEY_RSA &&
-           (type == KEY_UNSPEC||type==KEY_RSA)) {
-               prv = key_new(KEY_UNSPEC);
-               prv->rsa = EVP_PKEY_get1_RSA(pk);
-               prv->type = KEY_RSA;
-               name = "rsa w/o comment";
-#ifdef DEBUG_PK
-               RSA_print_fp(stderr, prv->rsa, 8);
-#endif
-               if (RSA_blinding_on(prv->rsa, NULL) != 1) {
-                       error("%s: RSA_blinding_on failed", __func__);
-                       key_free(prv);
-                       prv = NULL;
-               }
-       } else if (pk->type == EVP_PKEY_DSA &&
-           (type == KEY_UNSPEC||type==KEY_DSA)) {
-               prv = key_new(KEY_UNSPEC);
-               prv->dsa = EVP_PKEY_get1_DSA(pk);
-               prv->type = KEY_DSA;
-               name = "dsa w/o comment";
-#ifdef DEBUG_PK
-               DSA_print_fp(stderr, prv->dsa, 8);
-#endif
-#ifdef OPENSSL_HAS_ECC
-       } else if (pk->type == EVP_PKEY_EC &&
-           (type == KEY_UNSPEC||type==KEY_ECDSA)) {
-               prv = key_new(KEY_UNSPEC);
-               prv->ecdsa = EVP_PKEY_get1_EC_KEY(pk);
-               prv->type = KEY_ECDSA;
-               if ((prv->ecdsa_nid = key_ecdsa_key_to_nid(prv->ecdsa)) == -1 ||
-                   key_curve_nid_to_name(prv->ecdsa_nid) == NULL ||
-                   key_ec_validate_public(EC_KEY_get0_group(prv->ecdsa),
-                   EC_KEY_get0_public_key(prv->ecdsa)) != 0 ||
-                   key_ec_validate_private(prv->ecdsa) != 0) {
-                       error("%s: bad ECDSA key", __func__);
-                       key_free(prv);
-                       prv = NULL;
-               }
-               name = "ecdsa w/o comment";
-#ifdef DEBUG_PK
-               if (prv != NULL && prv->ecdsa != NULL)
-                       key_dump_ec_key(prv->ecdsa);
-#endif
-#endif /* OPENSSL_HAS_ECC */
-       } else {
-               error("%s: PEM_read_PrivateKey: mismatch or "
-                   "unknown EVP_PKEY save_type %d", __func__, pk->save_type);
-       }
-       if (pk != NULL)
-               EVP_PKEY_free(pk);
-       if (prv != NULL && commentp)
-               *commentp = xstrdup(name);
-       debug("read PEM private key done: type %s",
-           prv ? key_type(prv) : "<unknown>");
-       return prv;
-}
-
-Key *
-key_load_private_pem(int fd, int type, const char *passphrase,
-    char **commentp)
-{
-       Buffer buffer;
-       Key *prv;
-
-       buffer_init(&buffer);
-       if (!key_load_file(fd, NULL, &buffer)) {
-               buffer_free(&buffer);
-               return NULL;
-       }
-       prv = key_parse_private_pem(&buffer, type, passphrase, commentp);
-       buffer_free(&buffer);
-       return prv;
+       if ((buffer = sshbuf_new()) == NULL)
+               return SSH_ERR_ALLOC_FAIL;
+       if ((r = sshkey_load_file(fd, NULL, buffer)) != 0)
+               goto out;
+       if ((r = sshkey_parse_private_pem_fileblob(buffer, type, passphrase,
+           keyp, commentp)) != 0)
+               goto out;
+       r = 0;
+ out:
+       sshbuf_free(buffer);
+       return r;
 }
+#endif /* WITH_OPENSSL */
 
+/* XXX remove error() calls from here? */
 int
-key_perm_ok(int fd, const char *filename)
+sshkey_perm_ok(int fd, const char *filename)
 {
        struct stat st;
 
        if (fstat(fd, &st) < 0)
-               return 0;
+               return SSH_ERR_SYSTEM_ERROR;
        /*
         * if a key owned by the user is accessed, then we check the
         * permissions of the file. if the key owned by a different user,
@@ -630,290 +213,311 @@ key_perm_ok(int fd, const char *filename)
                error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
                error("Permissions 0%3.3o for '%s' are too open.",
                    (u_int)st.st_mode & 0777, filename);
-               error("It is required that your private key files are NOT accessible by others.");
+               error("It is recommended that your private key files are NOT accessible by others.");
                error("This private key will be ignored.");
-               return 0;
+               return SSH_ERR_KEY_BAD_PERMISSIONS;
        }
-       return 1;
+       return 0;
 }
 
-static Key *
-key_parse_private_type(Buffer *blob, int type, const char *passphrase,
-    char **commentp)
+/* XXX kill perm_ok now that we have SSH_ERR_KEY_BAD_PERMISSIONS? */
+int
+sshkey_load_private_type(int type, const char *filename, const char *passphrase,
+    struct sshkey **keyp, char **commentp, int *perm_ok)
 {
-       switch (type) {
-       case KEY_RSA1:
-               return key_parse_private_rsa1(blob, passphrase, commentp);
-       case KEY_DSA:
-       case KEY_ECDSA:
-       case KEY_RSA:
-       case KEY_UNSPEC:
-               return key_parse_private_pem(blob, type, passphrase, commentp);
-       default:
-               error("%s: cannot parse key type %d", __func__, type);
-               break;
-       }
-       return NULL;
-}
+       int fd, r;
+       struct sshbuf *buffer = NULL;
 
-Key *
-key_load_private_type(int type, const char *filename, const char *passphrase,
-    char **commentp, int *perm_ok)
-{
-       int fd;
-       Key *ret;
-       Buffer buffer;
-
-       fd = open(filename, O_RDONLY);
-       if (fd < 0) {
-               debug("could not open key file '%s': %s", filename,
-                   strerror(errno));
+       *keyp = NULL;
+       if (commentp != NULL)
+               *commentp = NULL;
+
+       if ((fd = open(filename, O_RDONLY)) < 0) {
                if (perm_ok != NULL)
                        *perm_ok = 0;
-               return NULL;
+               return SSH_ERR_SYSTEM_ERROR;
        }
-       if (!key_perm_ok(fd, filename)) {
+       if (sshkey_perm_ok(fd, filename) != 0) {
                if (perm_ok != NULL)
                        *perm_ok = 0;
-               error("bad permissions: ignore key: %s", filename);
-               close(fd);
-               return NULL;
+               r = SSH_ERR_KEY_BAD_PERMISSIONS;
+               goto out;
        }
        if (perm_ok != NULL)
                *perm_ok = 1;
 
-       buffer_init(&buffer);
-       if (!key_load_file(fd, filename, &buffer)) {
-               buffer_free(&buffer);
-               close(fd);
-               return NULL;
+       if ((buffer = sshbuf_new()) == NULL) {
+               r = SSH_ERR_ALLOC_FAIL;
+               goto out;
        }
+       if ((r = sshkey_load_file(fd, filename, buffer)) != 0)
+               goto out;
+       if ((r = sshkey_parse_private_fileblob_type(buffer, type, passphrase,
+           keyp, commentp)) != 0)
+               goto out;
+       r = 0;
+ out:
        close(fd);
-       ret = key_parse_private_type(&buffer, type, passphrase, commentp);
-       buffer_free(&buffer);
-       return ret;
+       if (buffer != NULL)
+               sshbuf_free(buffer);
+       return r;
 }
 
-Key *
-key_parse_private(Buffer *buffer, const char *filename,
-    const char *passphrase, char **commentp)
+/* XXX this is almost identical to sshkey_load_private_type() */
+int
+sshkey_load_private(const char *filename, const char *passphrase,
+    struct sshkey **keyp, char **commentp)
 {
-       Key *pub, *prv;
-
-       /* it's a SSH v1 key if the public key part is readable */
-       pub = key_parse_public_rsa1(buffer, commentp);
-       if (pub == NULL) {
-               prv = key_parse_private_type(buffer, KEY_UNSPEC,
-                   passphrase, NULL);
-               /* use the filename as a comment for PEM */
-               if (commentp && prv)
-                       *commentp = xstrdup(filename);
-       } else {
-               key_free(pub);
-               /* key_parse_public_rsa1() has already loaded the comment */
-               prv = key_parse_private_type(buffer, KEY_RSA1, passphrase,
-                   NULL);
-       }
-       return prv;
-}
+       struct sshbuf *buffer = NULL;
+       int r, fd;
 
-Key *
-key_load_private(const char *filename, const char *passphrase,
-    char **commentp)
-{
-       Key *prv;
-       Buffer buffer;
-       int fd;
-
-       fd = open(filename, O_RDONLY);
-       if (fd < 0) {
-               debug("could not open key file '%s': %s", filename,
-                   strerror(errno));
-               return NULL;
-       }
-       if (!key_perm_ok(fd, filename)) {
-               error("bad permissions: ignore key: %s", filename);
-               close(fd);
-               return NULL;
+       *keyp = NULL;
+       if (commentp != NULL)
+               *commentp = NULL;
+
+       if ((fd = open(filename, O_RDONLY)) < 0)
+               return SSH_ERR_SYSTEM_ERROR;
+       if (sshkey_perm_ok(fd, filename) != 0) {
+               r = SSH_ERR_KEY_BAD_PERMISSIONS;
+               goto out;
        }
 
-       buffer_init(&buffer);
-       if (!key_load_file(fd, filename, &buffer)) {
-               buffer_free(&buffer);
-               close(fd);
-               return NULL;
+       if ((buffer = sshbuf_new()) == NULL) {
+               r = SSH_ERR_ALLOC_FAIL;
+               goto out;
        }
+       if ((r = sshkey_load_file(fd, filename, buffer)) != 0 ||
+           (r = sshkey_parse_private_fileblob(buffer, passphrase, filename,
+           keyp, commentp)) != 0)
+               goto out;
+       r = 0;
+ out:
        close(fd);
-
-       prv = key_parse_private(&buffer, filename, passphrase, commentp);
-       buffer_free(&buffer);
-       return prv;
+       if (buffer != NULL)
+               sshbuf_free(buffer);
+       return r;
 }
 
 static int
-key_try_load_public(Key *k, const char *filename, char **commentp)
+sshkey_try_load_public(struct sshkey *k, const char *filename, char **commentp)
 {
        FILE *f;
        char line[SSH_MAX_PUBKEY_BYTES];
        char *cp;
        u_long linenum = 0;
+       int r;
 
-       f = fopen(filename, "r");
-       if (f != NULL) {
-               while (read_keyfile_line(f, filename, line, sizeof(line),
-                           &linenum) != -1) {
-                       cp = line;
-                       switch (*cp) {
-                       case '#':
-                       case '\n':
-                       case '\0':
-                               continue;
-                       }
-                       /* Abort loading if this looks like a private key */
-                       if (strncmp(cp, "-----BEGIN", 10) == 0)
-                               break;
-                       /* Skip leading whitespace. */
-                       for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
-                               ;
-                       if (*cp) {
-                               if (key_read(k, &cp) == 1) {
-                                       cp[strcspn(cp, "\r\n")] = '\0';
-                                       if (commentp) {
-                                               *commentp = xstrdup(*cp ?
-                                                   cp : filename);
-                                       }
-                                       fclose(f);
-                                       return 1;
+       if (commentp != NULL)
+               *commentp = NULL;
+       if ((f = fopen(filename, "r")) == NULL)
+               return SSH_ERR_SYSTEM_ERROR;
+       while (read_keyfile_line(f, filename, line, sizeof(line),
+                   &linenum) != -1) {
+               cp = line;
+               switch (*cp) {
+               case '#':
+               case '\n':
+               case '\0':
+                       continue;
+               }
+               /* Abort loading if this looks like a private key */
+               if (strncmp(cp, "-----BEGIN", 10) == 0 ||
+                   strcmp(cp, "SSH PRIVATE KEY FILE") == 0)
+                       break;
+               /* Skip leading whitespace. */
+               for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
+                       ;
+               if (*cp) {
+                       if ((r = sshkey_read(k, &cp)) == 0) {
+                               cp[strcspn(cp, "\r\n")] = '\0';
+                               if (commentp) {
+                                       *commentp = strdup(*cp ?
+                                           cp : filename);
+                                       if (*commentp == NULL)
+                                               r = SSH_ERR_ALLOC_FAIL;
                                }
+                               fclose(f);
+                               return r;
                        }
                }
-               fclose(f);
        }
-       return 0;
+       fclose(f);
+       return SSH_ERR_INVALID_FORMAT;
 }
 
 /* load public key from ssh v1 private or any pubkey file */
-Key *
-key_load_public(const char *filename, char **commentp)
+int
+sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp)
 {
-       Key *pub;
+       struct sshkey *pub = NULL;
        char file[MAXPATHLEN];
+       int r, fd;
+
+       if (keyp != NULL)
+               *keyp = NULL;
+       if (commentp != NULL)
+               *commentp = NULL;
 
+       if ((fd = open(filename, O_RDONLY)) < 0)
+               goto skip;
+#ifdef WITH_SSH1
        /* try rsa1 private key */
-       pub = key_load_public_type(KEY_RSA1, filename, commentp);
-       if (pub != NULL)
-               return pub;
+       r = sshkey_load_public_rsa1(fd, filename, keyp, commentp);
+       close(fd);
+       switch (r) {
+       case SSH_ERR_INTERNAL_ERROR:
+       case SSH_ERR_ALLOC_FAIL:
+       case SSH_ERR_INVALID_ARGUMENT:
+       case SSH_ERR_SYSTEM_ERROR:
+       case 0:
+               return r;
+       }
+#endif /* WITH_SSH1 */
+
+       /* try ssh2 public key */
+       if ((pub = sshkey_new(KEY_UNSPEC)) == NULL)
+               return SSH_ERR_ALLOC_FAIL;
+       if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) {
+               if (keyp != NULL)
+                       *keyp = pub;
+               return 0;
+       }
+       sshkey_free(pub);
 
+#ifdef WITH_SSH1
        /* try rsa1 public key */
-       pub = key_new(KEY_RSA1);
-       if (key_try_load_public(pub, filename, commentp) == 1)
-               return pub;
-       key_free(pub);
+       if ((pub = sshkey_new(KEY_RSA1)) == NULL)
+               return SSH_ERR_ALLOC_FAIL;
+       if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) {
+               if (keyp != NULL)
+                       *keyp = pub;
+               return 0;
+       }
+       sshkey_free(pub);
+#endif /* WITH_SSH1 */
 
-       /* try ssh2 public key */
-       pub = key_new(KEY_UNSPEC);
-       if (key_try_load_public(pub, filename, commentp) == 1)
-               return pub;
+ skip:
+       /* try .pub suffix */
+       if ((pub = sshkey_new(KEY_UNSPEC)) == NULL)
+               return SSH_ERR_ALLOC_FAIL;
+       r = SSH_ERR_ALLOC_FAIL; /* in case strlcpy or strlcat fail */
        if ((strlcpy(file, filename, sizeof file) < sizeof(file)) &&
            (strlcat(file, ".pub", sizeof file) < sizeof(file)) &&
-           (key_try_load_public(pub, file, commentp) == 1))
-               return pub;
-       key_free(pub);
-       return NULL;
+           (r = sshkey_try_load_public(pub, file, commentp)) == 0) {
+               if (keyp != NULL)
+                       *keyp = pub;
+               return 0;
+       }
+       sshkey_free(pub);
+       return r;
 }
 
 /* Load the certificate associated with the named private key */
-Key *
-key_load_cert(const char *filename)
+int
+sshkey_load_cert(const char *filename, struct sshkey **keyp)
 {
-       Key *pub;
-       char *file;
-
-       pub = key_new(KEY_UNSPEC);
-       xasprintf(&file, "%s-cert.pub", filename);
-       if (key_try_load_public(pub, file, NULL) == 1) {
-               xfree(file);
-               return pub;
+       struct sshkey *pub = NULL;
+       char *file = NULL;
+       int r = SSH_ERR_INTERNAL_ERROR;
+
+       *keyp = NULL;
+
+       if (asprintf(&file, "%s-cert.pub", filename) == -1)
+               return SSH_ERR_ALLOC_FAIL;
+
+       if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) {
+               goto out;
        }
-       xfree(file);
-       key_free(pub);
-       return NULL;
+       if ((r = sshkey_try_load_public(pub, file, NULL)) != 0)
+               goto out;
+
+       *keyp = pub;
+       pub = NULL;
+       r = 0;
+
+ out:
+       if (file != NULL)
+               free(file);
+       if (pub != NULL)
+               sshkey_free(pub);
+       return r;
 }
 
 /* Load private key and certificate */
-Key *
-key_load_private_cert(int type, const char *filename, const char *passphrase,
-    int *perm_ok)
+int
+sshkey_load_private_cert(int type, const char *filename, const char *passphrase,
+    struct sshkey **keyp, int *perm_ok)
 {
-       Key *key, *pub;
+       struct sshkey *key = NULL, *cert = NULL;
+       int r;
+
+       *keyp = NULL;
 
        switch (type) {
+#ifdef WITH_OPENSSL
        case KEY_RSA:
        case KEY_DSA:
        case KEY_ECDSA:
+       case KEY_ED25519:
+#endif /* WITH_OPENSSL */
+       case KEY_UNSPEC:
                break;
        default:
-               error("%s: unsupported key type", __func__);
-               return NULL;
+               return SSH_ERR_KEY_TYPE_UNKNOWN;
        }
 
-       if ((key = key_load_private_type(type, filename, 
-           passphrase, NULL, perm_ok)) == NULL)
-               return NULL;
-
-       if ((pub = key_load_cert(filename)) == NULL) {
-               key_free(key);
-               return NULL;
-       }
+       if ((r = sshkey_load_private_type(type, filename,
+           passphrase, &key, NULL, perm_ok)) != 0 ||
+           (r = sshkey_load_cert(filename, &cert)) != 0)
+               goto out;
 
        /* Make sure the private key matches the certificate */
-       if (key_equal_public(key, pub) == 0) {
-               error("%s: certificate does not match private key %s",
-                   __func__, filename);
-       } else if (key_to_certified(key, key_cert_is_legacy(pub)) != 0) {
-               error("%s: key_to_certified failed", __func__);
-       } else {
-               key_cert_copy(pub, key);
-               key_free(pub);
-               return key;
+       if (sshkey_equal_public(key, cert) == 0) {
+               r = SSH_ERR_KEY_CERT_MISMATCH;
+               goto out;
        }
 
-       key_free(key);
-       key_free(pub);
-       return NULL;
+       if ((r = sshkey_to_certified(key, sshkey_cert_is_legacy(cert))) != 0 ||
+           (r = sshkey_cert_copy(cert, key)) != 0)
+               goto out;
+       r = 0;
+       *keyp = key;
+       key = NULL;
+ out:
+       if (key != NULL)
+               sshkey_free(key);
+       if (cert != NULL)
+               sshkey_free(cert);
+       return r;
 }
 
 /*
- * Returns 1 if the specified "key" is listed in the file "filename",
- * 0 if the key is not listed or -1 on error.
+ * Returns success if the specified "key" is listed in the file "filename",
+ * SSH_ERR_KEY_NOT_FOUND: if the key is not listed or another error.
  * If strict_type is set then the key type must match exactly,
  * otherwise a comparison that ignores certficiate data is performed.
  */
 int
-key_in_file(Key *key, const char *filename, int strict_type)
+sshkey_in_file(struct sshkey *key, const char *filename, int strict_type)
 {
        FILE *f;
        char line[SSH_MAX_PUBKEY_BYTES];
        char *cp;
        u_long linenum = 0;
-       int ret = 0;
-       Key *pub;
-       int (*key_compare)(const Key *, const Key *) = strict_type ?
-           key_equal : key_equal_public;
+       int r = 0;
+       struct sshkey *pub = NULL;
+       int (*sshkey_compare)(const struct sshkey *, const struct sshkey *) =
+           strict_type ?  sshkey_equal : sshkey_equal_public;
 
        if ((f = fopen(filename, "r")) == NULL) {
-               if (errno == ENOENT) {
-                       debug("%s: keyfile \"%s\" missing", __func__, filename);
-                       return 0;
-               } else {
-                       error("%s: could not open keyfile \"%s\": %s", __func__,
-                           filename, strerror(errno));
-                       return -1;
-               }
+               if (errno == ENOENT)
+                       return SSH_ERR_KEY_NOT_FOUND;
+               else
+                       return SSH_ERR_SYSTEM_ERROR;
        }
 
        while (read_keyfile_line(f, filename, line, sizeof(line),
-                   &linenum) != -1) {
+           &linenum) != -1) {
                cp = line;
 
                /* Skip leading whitespace. */
@@ -928,19 +532,24 @@ key_in_file(Key *key, const char *filename, int strict_type)
                        continue;
                }
 
-               pub = key_new(KEY_UNSPEC);
-               if (key_read(pub, &cp) != 1) {
-                       key_free(pub);
-                       continue;
+               if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) {
+                       r = SSH_ERR_ALLOC_FAIL;
+                       goto out;
                }
-               if (key_compare(key, pub)) {
-                       ret = 1;
-                       key_free(pub);
-                       break;
+               if ((r = sshkey_read(pub, &cp)) != 0)
+                       goto out;
+               if (sshkey_compare(key, pub)) {
+                       r = 0;
+                       goto out;
                }
-               key_free(pub);
+               sshkey_free(pub);
+               pub = NULL;
        }
+       r = SSH_ERR_KEY_NOT_FOUND;
+ out:
+       if (pub != NULL)
+               sshkey_free(pub);
        fclose(f);
-       return ret;
+       return r;
 }
 
index 78349be..03bc395 100644 (file)
@@ -1,31 +1,47 @@
-/* $OpenBSD: authfile.h,v 1.16 2011/05/04 21:15:29 djm Exp $ */
+/* $OpenBSD: authfile.h,v 1.19 2014/07/03 23:18:35 djm Exp $ */
 
 /*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- *                    All rights reserved
+ * Copyright (c) 2000, 2013 Markus Friedl.  All rights reserved.
  *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose.  Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
+ * 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.
  */
 
 #ifndef AUTHFILE_H
 #define AUTHFILE_H
 
-int     key_save_private(Key *, const char *, const char *, const char *);
-int     key_load_file(int, const char *, Buffer *);
-Key    *key_load_cert(const char *);
-Key    *key_load_public(const char *, char **);
-Key    *key_load_public_type(int, const char *, char **);
-Key    *key_parse_private(Buffer *, const char *, const char *, char **);
-Key    *key_load_private(const char *, const char *, char **);
-Key    *key_load_private_cert(int, const char *, const char *, int *);
-Key    *key_load_private_type(int, const char *, const char *, char **, int *);
-Key    *key_load_private_pem(int, int, const char *, char **);
-int     key_perm_ok(int, const char *);
-int     key_in_file(Key *, const char *, int);
+struct sshbuf;
+struct sshkey;
+
+int sshkey_save_private(struct sshkey *, const char *,
+    const char *, const char *, int, const char *, int);
+int sshkey_load_file(int, const char *, struct sshbuf *);
+int sshkey_load_cert(const char *, struct sshkey **);
+int sshkey_load_public(const char *, struct sshkey **, char **);
+int sshkey_load_private(const char *, const char *, struct sshkey **, char **);
+int sshkey_load_private_cert(int, const char *, const char *,
+    struct sshkey **, int *);
+int sshkey_load_private_type(int, const char *, const char *,
+    struct sshkey **, char **, int *);
+int sshkey_load_private_pem(int, int, const char *, struct sshkey **, char **);
+int sshkey_perm_ok(int, const char *);
+int sshkey_in_file(struct sshkey *, const char *, int);
 
 #endif
diff --git a/crypto/openssh/blocks.c b/crypto/openssh/blocks.c
new file mode 100644 (file)
index 0000000..ad93fe5
--- /dev/null
@@ -0,0 +1,248 @@
+/* $OpenBSD: blocks.c,v 1.3 2013/12/09 11:03:45 markus Exp $ */
+
+/*
+ * Public Domain, Author: Daniel J. Bernstein
+ * Copied from nacl-20110221/crypto_hashblocks/sha512/ref/blocks.c
+ */
+
+#include "includes.h"
+
+#include "crypto_api.h"
+
+typedef unsigned long long uint64;
+
+static uint64 load_bigendian(const unsigned char *x)
+{
+  return
+      (uint64) (x[7]) \
+  | (((uint64) (x[6])) << 8) \
+  | (((uint64) (x[5])) << 16) \
+  | (((uint64) (x[4])) << 24) \
+  | (((uint64) (x[3])) << 32) \
+  | (((uint64) (x[2])) << 40) \
+  | (((uint64) (x[1])) << 48) \
+  | (((uint64) (x[0])) << 56)
+  ;
+}
+
+static void store_bigendian(unsigned char *x,uint64 u)
+{
+  x[7] = u; u >>= 8;
+  x[6] = u; u >>= 8;
+  x[5] = u; u >>= 8;
+  x[4] = u; u >>= 8;
+  x[3] = u; u >>= 8;
+  x[2] = u; u >>= 8;
+  x[1] = u; u >>= 8;
+  x[0] = u;
+}
+
+#define SHR(x,c) ((x) >> (c))
+#define ROTR(x,c) (((x) >> (c)) | ((x) << (64 - (c))))
+
+#define Ch(x,y,z) ((x & y) ^ (~x & z))
+#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z))
+#define Sigma0(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
+#define Sigma1(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
+#define sigma0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x,7))
+#define sigma1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x,6))
+
+#define M(w0,w14,w9,w1) w0 = sigma1(w14) + w9 + sigma0(w1) + w0;
+
+#define EXPAND \
+  M(w0 ,w14,w9 ,w1 ) \
+  M(w1 ,w15,w10,w2 ) \
+  M(w2 ,w0 ,w11,w3 ) \
+  M(w3 ,w1 ,w12,w4 ) \
+  M(w4 ,w2 ,w13,w5 ) \
+  M(w5 ,w3 ,w14,w6 ) \
+  M(w6 ,w4 ,w15,w7 ) \
+  M(w7 ,w5 ,w0 ,w8 ) \
+  M(w8 ,w6 ,w1 ,w9 ) \
+  M(w9 ,w7 ,w2 ,w10) \
+  M(w10,w8 ,w3 ,w11) \
+  M(w11,w9 ,w4 ,w12) \
+  M(w12,w10,w5 ,w13) \
+  M(w13,w11,w6 ,w14) \
+  M(w14,w12,w7 ,w15) \
+  M(w15,w13,w8 ,w0 )
+
+#define F(w,k) \
+  T1 = h + Sigma1(e) + Ch(e,f,g) + k + w; \
+  T2 = Sigma0(a) + Maj(a,b,c); \
+  h = g; \
+  g = f; \
+  f = e; \
+  e = d + T1; \
+  d = c; \
+  c = b; \
+  b = a; \
+  a = T1 + T2;
+
+int crypto_hashblocks_sha512(unsigned char *statebytes,const unsigned char *in,unsigned long long inlen)
+{
+  uint64 state[8];
+  uint64 a;
+  uint64 b;
+  uint64 c;
+  uint64 d;
+  uint64 e;
+  uint64 f;
+  uint64 g;
+  uint64 h;
+  uint64 T1;
+  uint64 T2;
+
+  a = load_bigendian(statebytes +  0); state[0] = a;
+  b = load_bigendian(statebytes +  8); state[1] = b;
+  c = load_bigendian(statebytes + 16); state[2] = c;
+  d = load_bigendian(statebytes + 24); state[3] = d;
+  e = load_bigendian(statebytes + 32); state[4] = e;
+  f = load_bigendian(statebytes + 40); state[5] = f;
+  g = load_bigendian(statebytes + 48); state[6] = g;
+  h = load_bigendian(statebytes + 56); state[7] = h;
+
+  while (inlen >= 128) {
+    uint64 w0  = load_bigendian(in +   0);
+    uint64 w1  = load_bigendian(in +   8);
+    uint64 w2  = load_bigendian(in +  16);
+    uint64 w3  = load_bigendian(in +  24);
+    uint64 w4  = load_bigendian(in +  32);
+    uint64 w5  = load_bigendian(in +  40);
+    uint64 w6  = load_bigendian(in +  48);
+    uint64 w7  = load_bigendian(in +  56);
+    uint64 w8  = load_bigendian(in +  64);
+    uint64 w9  = load_bigendian(in +  72);
+    uint64 w10 = load_bigendian(in +  80);
+    uint64 w11 = load_bigendian(in +  88);
+    uint64 w12 = load_bigendian(in +  96);
+    uint64 w13 = load_bigendian(in + 104);
+    uint64 w14 = load_bigendian(in + 112);
+    uint64 w15 = load_bigendian(in + 120);
+
+    F(w0 ,0x428a2f98d728ae22ULL)
+    F(w1 ,0x7137449123ef65cdULL)
+    F(w2 ,0xb5c0fbcfec4d3b2fULL)
+    F(w3 ,0xe9b5dba58189dbbcULL)
+    F(w4 ,0x3956c25bf348b538ULL)
+    F(w5 ,0x59f111f1b605d019ULL)
+    F(w6 ,0x923f82a4af194f9bULL)
+    F(w7 ,0xab1c5ed5da6d8118ULL)
+    F(w8 ,0xd807aa98a3030242ULL)
+    F(w9 ,0x12835b0145706fbeULL)
+    F(w10,0x243185be4ee4b28cULL)
+    F(w11,0x550c7dc3d5ffb4e2ULL)
+    F(w12,0x72be5d74f27b896fULL)
+    F(w13,0x80deb1fe3b1696b1ULL)
+    F(w14,0x9bdc06a725c71235ULL)
+    F(w15,0xc19bf174cf692694ULL)
+
+    EXPAND
+
+    F(w0 ,0xe49b69c19ef14ad2ULL)
+    F(w1 ,0xefbe4786384f25e3ULL)
+    F(w2 ,0x0fc19dc68b8cd5b5ULL)
+    F(w3 ,0x240ca1cc77ac9c65ULL)
+    F(w4 ,0x2de92c6f592b0275ULL)
+    F(w5 ,0x4a7484aa6ea6e483ULL)
+    F(w6 ,0x5cb0a9dcbd41fbd4ULL)
+    F(w7 ,0x76f988da831153b5ULL)
+    F(w8 ,0x983e5152ee66dfabULL)
+    F(w9 ,0xa831c66d2db43210ULL)
+    F(w10,0xb00327c898fb213fULL)
+    F(w11,0xbf597fc7beef0ee4ULL)
+    F(w12,0xc6e00bf33da88fc2ULL)
+    F(w13,0xd5a79147930aa725ULL)
+    F(w14,0x06ca6351e003826fULL)
+    F(w15,0x142929670a0e6e70ULL)
+
+    EXPAND
+
+    F(w0 ,0x27b70a8546d22ffcULL)
+    F(w1 ,0x2e1b21385c26c926ULL)
+    F(w2 ,0x4d2c6dfc5ac42aedULL)
+    F(w3 ,0x53380d139d95b3dfULL)
+    F(w4 ,0x650a73548baf63deULL)
+    F(w5 ,0x766a0abb3c77b2a8ULL)
+    F(w6 ,0x81c2c92e47edaee6ULL)
+    F(w7 ,0x92722c851482353bULL)
+    F(w8 ,0xa2bfe8a14cf10364ULL)
+    F(w9 ,0xa81a664bbc423001ULL)
+    F(w10,0xc24b8b70d0f89791ULL)
+    F(w11,0xc76c51a30654be30ULL)
+    F(w12,0xd192e819d6ef5218ULL)
+    F(w13,0xd69906245565a910ULL)
+    F(w14,0xf40e35855771202aULL)
+    F(w15,0x106aa07032bbd1b8ULL)
+
+    EXPAND
+
+    F(w0 ,0x19a4c116b8d2d0c8ULL)
+    F(w1 ,0x1e376c085141ab53ULL)
+    F(w2 ,0x2748774cdf8eeb99ULL)
+    F(w3 ,0x34b0bcb5e19b48a8ULL)
+    F(w4 ,0x391c0cb3c5c95a63ULL)
+    F(w5 ,0x4ed8aa4ae3418acbULL)
+    F(w6 ,0x5b9cca4f7763e373ULL)
+    F(w7 ,0x682e6ff3d6b2b8a3ULL)
+    F(w8 ,0x748f82ee5defb2fcULL)
+    F(w9 ,0x78a5636f43172f60ULL)
+    F(w10,0x84c87814a1f0ab72ULL)
+    F(w11,0x8cc702081a6439ecULL)
+    F(w12,0x90befffa23631e28ULL)
+    F(w13,0xa4506cebde82bde9ULL)
+    F(w14,0xbef9a3f7b2c67915ULL)
+    F(w15,0xc67178f2e372532bULL)
+
+    EXPAND
+
+    F(w0 ,0xca273eceea26619cULL)
+    F(w1 ,0xd186b8c721c0c207ULL)
+    F(w2 ,0xeada7dd6cde0eb1eULL)
+    F(w3 ,0xf57d4f7fee6ed178ULL)
+    F(w4 ,0x06f067aa72176fbaULL)
+    F(w5 ,0x0a637dc5a2c898a6ULL)
+    F(w6 ,0x113f9804bef90daeULL)
+    F(w7 ,0x1b710b35131c471bULL)
+    F(w8 ,0x28db77f523047d84ULL)
+    F(w9 ,0x32caab7b40c72493ULL)
+    F(w10,0x3c9ebe0a15c9bebcULL)
+    F(w11,0x431d67c49c100d4cULL)
+    F(w12,0x4cc5d4becb3e42b6ULL)
+    F(w13,0x597f299cfc657e2aULL)
+    F(w14,0x5fcb6fab3ad6faecULL)
+    F(w15,0x6c44198c4a475817ULL)
+
+    a += state[0];
+    b += state[1];
+    c += state[2];
+    d += state[3];
+    e += state[4];
+    f += state[5];
+    g += state[6];
+    h += state[7];
+  
+    state[0] = a;
+    state[1] = b;
+    state[2] = c;
+    state[3] = d;
+    state[4] = e;
+    state[5] = f;
+    state[6] = g;
+    state[7] = h;
+
+    in += 128;
+    inlen -= 128;
+  }
+
+  store_bigendian(statebytes +  0,state[0]);
+  store_bigendian(statebytes +  8,state[1]);
+  store_bigendian(statebytes + 16,state[2]);
+  store_bigendian(statebytes + 24,state[3]);
+  store_bigendian(statebytes + 32,state[4]);
+  store_bigendian(statebytes + 40,state[5]);
+  store_bigendian(statebytes + 48,state[6]);
+  store_bigendian(statebytes + 56,state[7]);
+
+  return inlen;
+}
index 00208ca..3976896 100644 (file)
@@ -1,69 +1,40 @@
-/* $OpenBSD: bufaux.c,v 1.50 2010/08/31 09:58:37 djm Exp $ */
+/* $OpenBSD: bufaux.c,v 1.60 2014/04/30 05:29:56 djm Exp $ */
 /*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- *                    All rights reserved
- * Auxiliary functions for storing and retrieving various data types to/from
- * Buffers.
+ * Copyright (c) 2012 Damien Miller <djm@mindrot.org>
  *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose.  Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
+ * 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.
  *
- *
- * SSH2 packet format added by Markus Friedl
- * Copyright (c) 2000 Markus Friedl.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  */
 
+/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */
+
 #include "includes.h"
 
 #include <sys/types.h>
 
-#include <openssl/bn.h>
-
-#include <string.h>
-#include <stdarg.h>
-
-#include "xmalloc.h"
 #include "buffer.h"
 #include "log.h"
-#include "misc.h"
-
-/*
- * Returns integers from the buffer (msb first).
- */
+#include "ssherr.h"
 
 int
-buffer_get_short_ret(u_short *ret, Buffer *buffer)
+buffer_get_short_ret(u_short *v, Buffer *buffer)
 {
-       u_char buf[2];
+       int ret;
 
-       if (buffer_get_ret(buffer, (char *) buf, 2) == -1)
-               return (-1);
-       *ret = get_u16(buf);
-       return (0);
+       if ((ret = sshbuf_get_u16(buffer, v)) != 0) {
+               error("%s: %s", __func__, ssh_err(ret));
+               return -1;
+       }
+       return 0;
 }
 
 u_short
@@ -72,21 +43,21 @@ buffer_get_short(Buffer *buffer)
        u_short ret;
 
        if (buffer_get_short_ret(&ret, buffer) == -1)
-               fatal("buffer_get_short: buffer error");
+               fatal("%s: buffer error", __func__);
 
        return (ret);
 }
 
 int
-buffer_get_int_ret(u_int *ret, Buffer *buffer)
+buffer_get_int_ret(u_int *v, Buffer *buffer)
 {
-       u_char buf[4];
+       int ret;
 
-       if (buffer_get_ret(buffer, (char *) buf, 4) == -1)
-               return (-1);
-       if (ret != NULL)
-               *ret = get_u32(buf);
-       return (0);
+       if ((ret = sshbuf_get_u32(buffer, v)) != 0) {
+               error("%s: %s", __func__, ssh_err(ret));
+               return -1;
+       }
+       return 0;
 }
 
 u_int
@@ -95,21 +66,21 @@ buffer_get_int(Buffer *buffer)
        u_int ret;
 
        if (buffer_get_int_ret(&ret, buffer) == -1)
-               fatal("buffer_get_int: buffer error");
+               fatal("%s: buffer error", __func__);
 
        return (ret);
 }
 
 int
-buffer_get_int64_ret(u_int64_t *ret, Buffer *buffer)
+buffer_get_int64_ret(u_int64_t *v, Buffer *buffer)
 {
-       u_char buf[8];
+       int ret;
 
-       if (buffer_get_ret(buffer, (char *) buf, 8) == -1)
-               return (-1);
-       if (ret != NULL)
-               *ret = get_u64(buf);
-       return (0);
+       if ((ret = sshbuf_get_u64(buffer, v)) != 0) {
+               error("%s: %s", __func__, ssh_err(ret));
+               return -1;
+       }
+       return 0;
 }
 
 u_int64_t
@@ -118,78 +89,52 @@ buffer_get_int64(Buffer *buffer)
        u_int64_t ret;
 
        if (buffer_get_int64_ret(&ret, buffer) == -1)
-               fatal("buffer_get_int: buffer error");
+               fatal("%s: buffer error", __func__);
 
        return (ret);
 }
 
-/*
- * Stores integers in the buffer, msb first.
- */
 void
 buffer_put_short(Buffer *buffer, u_short value)
 {
-       char buf[2];
+       int ret;
 
-       put_u16(buf, value);
-       buffer_append(buffer, buf, 2);
+       if ((ret = sshbuf_put_u16(buffer, value)) != 0)
+               fatal("%s: %s", __func__, ssh_err(ret));
 }
 
 void
 buffer_put_int(Buffer *buffer, u_int value)
 {
-       char buf[4];
+       int ret;
 
-       put_u32(buf, value);
-       buffer_append(buffer, buf, 4);
+       if ((ret = sshbuf_put_u32(buffer, value)) != 0)
+               fatal("%s: %s", __func__, ssh_err(ret));
 }
 
 void
 buffer_put_int64(Buffer *buffer, u_int64_t value)
 {
-       char buf[8];
+       int ret;
 
-       put_u64(buf, value);
-       buffer_append(buffer, buf, 8);
+       if ((ret = sshbuf_put_u64(buffer, value)) != 0)
+               fatal("%s: %s", __func__, ssh_err(ret));
 }
 
-/*
- * Returns an arbitrary binary string from the buffer.  The string cannot
- * be longer than 256k.  The returned value points to memory allocated
- * with xmalloc; it is the responsibility of the calling function to free
- * the data.  If length_ptr is non-NULL, the length of the returned data
- * will be stored there.  A null character will be automatically appended
- * to the returned string, and is not counted in length.
- */
 void *
 buffer_get_string_ret(Buffer *buffer, u_int *length_ptr)
 {
+       size_t len;
+       int ret;
        u_char *value;
-       u_int len;
 
-       /* Get the length. */
-       if (buffer_get_int_ret(&len, buffer) != 0) {
-               error("buffer_get_string_ret: cannot extract length");
-               return (NULL);
-       }
-       if (len > 256 * 1024) {
-               error("buffer_get_string_ret: bad string length %u", len);
-               return (NULL);
-       }
-       /* Allocate space for the string.  Add one byte for a null character. */
-       value = xmalloc(len + 1);
-       /* Get the string. */
-       if (buffer_get_ret(buffer, value, len) == -1) {
-               error("buffer_get_string_ret: buffer_get failed");
-               xfree(value);
-               return (NULL);
+       if ((ret = sshbuf_get_string(buffer, &value, &len)) != 0) {
+               error("%s: %s", __func__, ssh_err(ret));
+               return NULL;
        }
-       /* Append a null character to make processing easier. */
-       value[len] = '\0';
-       /* Optionally return the length of the string. */
-       if (length_ptr)
-               *length_ptr = len;
-       return (value);
+       if (length_ptr != NULL)
+               *length_ptr = len;  /* Safe: sshbuf never stores len > 2^31 */
+       return value;
 }
 
 void *
@@ -198,31 +143,24 @@ buffer_get_string(Buffer *buffer, u_int *length_ptr)
        void *ret;
 
        if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL)
-               fatal("buffer_get_string: buffer error");
+               fatal("%s: buffer error", __func__);
        return (ret);
 }
 
 char *
 buffer_get_cstring_ret(Buffer *buffer, u_int *length_ptr)
 {
-       u_int length;
-       char *cp, *ret = buffer_get_string_ret(buffer, &length);
+       size_t len;
+       int ret;
+       char *value;
 
-       if (ret == NULL)
+       if ((ret = sshbuf_get_cstring(buffer, &value, &len)) != 0) {
+               error("%s: %s", __func__, ssh_err(ret));
                return NULL;
-       if ((cp = memchr(ret, '\0', length)) != NULL) {
-               /* XXX allow \0 at end-of-string for a while, remove later */
-               if (cp == ret + length - 1)
-                       error("buffer_get_cstring_ret: string contains \\0");
-               else {
-                       bzero(ret, length);
-                       xfree(ret);
-                       return NULL;
-               }
        }
        if (length_ptr != NULL)
-               *length_ptr = length;
-       return ret;
+               *length_ptr = len;  /* Safe: sshbuf never stores len > 2^31 */
+       return value;
 }
 
 char *
@@ -231,67 +169,64 @@ buffer_get_cstring(Buffer *buffer, u_int *length_ptr)
        char *ret;
 
        if ((ret = buffer_get_cstring_ret(buffer, length_ptr)) == NULL)
-               fatal("buffer_get_cstring: buffer error");
+               fatal("%s: buffer error", __func__);
        return ret;
 }
 
-void *
+const void *
 buffer_get_string_ptr_ret(Buffer *buffer, u_int *length_ptr)
 {
-       void *ptr;
-       u_int len;
+       size_t len;
+       int ret;
+       const u_char *value;
 
-       if (buffer_get_int_ret(&len, buffer) != 0)
-               return NULL;
-       if (len > 256 * 1024) {
-               error("buffer_get_string_ptr: bad string length %u", len);
+       if ((ret = sshbuf_get_string_direct(buffer, &value, &len)) != 0) {
+               error("%s: %s", __func__, ssh_err(ret));
                return NULL;
        }
-       ptr = buffer_ptr(buffer);
-       buffer_consume(buffer, len);
-       if (length_ptr)
-               *length_ptr = len;
-       return (ptr);
+       if (length_ptr != NULL)
+               *length_ptr = len;  /* Safe: sshbuf never stores len > 2^31 */
+       return value;
 }
 
-void *
+const void *
 buffer_get_string_ptr(Buffer *buffer, u_int *length_ptr)
 {
-       void *ret;
+       const void *ret;
 
        if ((ret = buffer_get_string_ptr_ret(buffer, length_ptr)) == NULL)
-               fatal("buffer_get_string_ptr: buffer error");
+               fatal("%s: buffer error", __func__);
        return (ret);
 }
 
-/*
- * Stores and arbitrary binary string in the buffer.
- */
 void
 buffer_put_string(Buffer *buffer, const void *buf, u_int len)
 {
-       buffer_put_int(buffer, len);
-       buffer_append(buffer, buf, len);
+       int ret;
+
+       if ((ret = sshbuf_put_string(buffer, buf, len)) != 0)
+               fatal("%s: %s", __func__, ssh_err(ret));
 }
+
 void
 buffer_put_cstring(Buffer *buffer, const char *s)
 {
-       if (s == NULL)
-               fatal("buffer_put_cstring: s == NULL");
-       buffer_put_string(buffer, s, strlen(s));
+       int ret;
+
+       if ((ret = sshbuf_put_cstring(buffer, s)) != 0)
+               fatal("%s: %s", __func__, ssh_err(ret));
 }
 
-/*
- * Returns a character from the buffer (0 - 255).
- */
 int
-buffer_get_char_ret(char *ret, Buffer *buffer)
+buffer_get_char_ret(char *v, Buffer *buffer)
 {
-       if (buffer_get_ret(buffer, ret, 1) == -1) {
-               error("buffer_get_char_ret: buffer_get_ret failed");
-               return (-1);
+       int ret;
+
+       if ((ret = sshbuf_get_u8(buffer, (u_char *)v)) != 0) {
+               error("%s: %s", __func__, ssh_err(ret));
+               return -1;
        }
-       return (0);
+       return 0;
 }
 
 int
@@ -300,17 +235,25 @@ buffer_get_char(Buffer *buffer)
        char ch;
 
        if (buffer_get_char_ret(&ch, buffer) == -1)
-               fatal("buffer_get_char: buffer error");
+               fatal("%s: buffer error", __func__);
        return (u_char) ch;
 }
 
-/*
- * Stores a character in the buffer.
- */
 void
 buffer_put_char(Buffer *buffer, int value)
 {
-       char ch = value;
+       int ret;
+
+       if ((ret = sshbuf_put_u8(buffer, value)) != 0)
+               fatal("%s: %s", __func__, ssh_err(ret));
+}
+
+void
+buffer_put_bignum2_from_string(Buffer *buffer, const u_char *s, u_int l)
+{
+       int ret;
 
-       buffer_append(buffer, &ch, 1);
+       if ((ret = sshbuf_put_bignum2_bytes(buffer, s, l)) != 0)
+               fatal("%s: %s", __func__, ssh_err(ret));
 }
+
index 251cd09..b7f7cb1 100644 (file)
-/* $OpenBSD: bufbn.c,v 1.6 2007/06/02 09:04:58 djm Exp $*/
+/* $OpenBSD: bufbn.c,v 1.12 2014/04/30 05:29:56 djm Exp $ */
+
 /*
- * Author: Tatu Ylonen <ylo@cs.hut.fi>
- * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
- *                    All rights reserved
- * Auxiliary functions for storing and retrieving various data types to/from
- * Buffers.
- *
- * As far as I am concerned, the code I have written for this software
- * can be used freely for any purpose.  Any derived versions of this
- * software must be clearly marked as such, and if the derived work is
- * incompatible with the protocol description in the RFC file, it must be
- * called by a name other than "ssh" or "Secure Shell".
- *
- *
- * SSH2 packet format added by Markus Friedl
- * Copyright (c) 2000 Markus Friedl.  All rights reserved.
+ * Copyright (c) 2012 Damien Miller <djm@mindrot.org>
  *
- * 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.
+ * 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.
  *
- * 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,