diff --git a/.gitignore b/.gitignore index e2a63f31f..250288eac 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ openbsd-compat/regress/Makefile openssh.xml opensshd.init survey.sh +**/*.0 **/*.o **/*.out **/*.a diff --git a/.skipped-commit-ids b/.skipped-commit-ids index 2e6399028..f4c457228 100644 --- a/.skipped-commit-ids +++ b/.skipped-commit-ids @@ -16,3 +16,4 @@ f6ae971186ba68d066cd102e57d5b0b2c211a5ee systrace is dead. 1e6b51ddf767cbad0a4e63eb08026c127e654308 integrity.sh reliability fe5b31f69a60d47171836911f144acff77810217 Makefile.inc bits 5781670c0578fe89663c9085ed3ba477cf7e7913 Delete sshconnect1.c +ea80f445e819719ccdcb237022cacfac990fdc5c Makefile.inc warning flags diff --git a/PROTOCOL b/PROTOCOL index 192da55b2..4e9e87575 100644 --- a/PROTOCOL +++ b/PROTOCOL @@ -33,8 +33,8 @@ The method is documented in: https://www.openssh.com/txt/draft-miller-secsh-compression-delayed-00.txt -1.3. transport: New public key algorithms "ssh-rsa-cert-v00@openssh.com", - "ssh-dsa-cert-v00@openssh.com", +1.3. transport: New public key algorithms "ssh-rsa-cert-v01@openssh.com", + "ssh-dsa-cert-v01@openssh.com", "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ecdsa-sha2-nistp384-cert-v01@openssh.com" and "ecdsa-sha2-nistp521-cert-v01@openssh.com" @@ -454,4 +454,4 @@ respond with a SSH_FXP_STATUS message. This extension is advertised in the SSH_FXP_VERSION hello with version "1". -$OpenBSD: PROTOCOL,v 1.30 2016/04/08 06:35:54 djm Exp $ +$OpenBSD: PROTOCOL,v 1.31 2017/05/26 01:40:07 djm Exp $ diff --git a/PROTOCOL.agent b/PROTOCOL.agent index 60d36f912..54cf2be4d 100644 --- a/PROTOCOL.agent +++ b/PROTOCOL.agent @@ -1,582 +1,3 @@ -This describes the protocol used by OpenSSH's ssh-agent. - -OpenSSH's agent supports managing keys for the standard SSH protocol -2 as well as the legacy SSH protocol 1. Support for these key types -is almost completely disjoint - in all but a few cases, operations on -protocol 2 keys cannot see or affect protocol 1 keys and vice-versa. - -Protocol 1 and protocol 2 keys are separated because of the differing -cryptographic usage: protocol 1 private RSA keys are used to decrypt -challenges that were encrypted with the corresponding public key, -whereas protocol 2 RSA private keys are used to sign challenges with -a private key for verification with the corresponding public key. It -is considered unsound practice to use the same key for signing and -encryption. - -With a couple of exceptions, the protocol message names used in this -document indicate which type of key the message relates to. SSH_* -messages refer to protocol 1 keys only. SSH2_* messages refer to -protocol 2 keys. Furthermore, the names also indicate whether the -message is a request to the agent (*_AGENTC_*) or a reply from the -agent (*_AGENT_*). Section 3 below contains the mapping of the -protocol message names to their integer values. - -1. Data types - -Because of support for legacy SSH protocol 1 keys, OpenSSH's agent -protocol makes use of some data types not defined in RFC 4251. - -1.1 uint16 - -The "uint16" data type is a simple MSB-first 16 bit unsigned integer -encoded in two bytes. - -1.2 mpint1 - -The "mpint1" type represents an arbitrary precision integer (bignum). -Its format is as follows: - - uint16 bits - byte[(bits + 7) / 8] bignum - -"bignum" contains an unsigned arbitrary precision integer encoded as -eight bits per byte in big-endian (MSB first) format. - -Note the difference between the "mpint1" encoding and the "mpint" -encoding defined in RFC 4251. Also note that the length of the encoded -integer is specified in bits, not bytes and that the byte length of -the integer must be calculated by rounding up the number of bits to the -nearest eight. - -2. Protocol Messages - -All protocol messages are prefixed with their length in bytes, encoded -as a 32 bit unsigned integer. Specifically: - - uint32 message_length - byte[message_length] message - -The following message descriptions refer only to the content the -"message" field. - -2.1 Generic server responses - -The following generic messages may be sent by the server in response to -requests from the client. On success the agent may reply either with: - - byte SSH_AGENT_SUCCESS - -or a request-specific success message. - -On failure, the agent may reply with: - - byte SSH_AGENT_FAILURE - -SSH_AGENT_FAILURE messages are also sent in reply to unknown request -types. - -2.2 Adding keys to the agent - -Keys are added to the agent using the SSH_AGENTC_ADD_RSA_IDENTITY and -SSH2_AGENTC_ADD_IDENTITY requests for protocol 1 and protocol 2 keys -respectively. - -Two variants of these requests are SSH_AGENTC_ADD_RSA_ID_CONSTRAINED -and SSH2_AGENTC_ADD_ID_CONSTRAINED - these add keys with optional -"constraints" on their usage. - -OpenSSH may be built with support for keys hosted on a smartcard -or other hardware security module. These keys may be added -to the agent using the SSH_AGENTC_ADD_SMARTCARD_KEY and -SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED requests. - -2.2.1 Key constraints - -The OpenSSH agent supports some basic optional constraints on key usage. -At present there are two constraints defined. - -The first constraint limits the validity duration of a key. It is -encoded as: - - byte SSH_AGENT_CONSTRAIN_LIFETIME - uint32 seconds - -Where "seconds" contains the number of seconds that the key shall remain -valid measured from the moment that the agent receives it. After the -validity period has expired, OpenSSH's agent will erase these keys from -memory. - -The second constraint requires the agent to seek explicit user -confirmation before performing private key operations with the loaded -key. This constraint is encoded as: - - byte SSH_AGENT_CONSTRAIN_CONFIRM - -Zero or more constraints may be specified when adding a key with one -of the *_CONSTRAINED requests. Multiple constraints are appended -consecutively to the end of the request: - - byte constraint1_type - .... constraint1_data - byte constraint2_type - .... constraint2_data - .... - byte constraintN_type - .... constraintN_data - -Such a sequence of zero or more constraints will be referred to below -as "constraint[]". Agents may determine whether there are constraints -by checking whether additional data exists in the "add key" request -after the key data itself. OpenSSH will refuse to add a key if it -contains unknown constraints. - -2.2.2 Add protocol 1 key - -A client may add a protocol 1 key to an agent with the following -request: - - byte SSH_AGENTC_ADD_RSA_IDENTITY or - SSH_AGENTC_ADD_RSA_ID_CONSTRAINED - uint32 ignored - mpint1 rsa_n - mpint1 rsa_e - mpint1 rsa_d - mpint1 rsa_iqmp - mpint1 rsa_q - mpint1 rsa_p - string key_comment - constraint[] key_constraints - -Note that there is some redundancy in the key parameters; a key could be -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_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. - -2.2.3 Add protocol 2 key - -The OpenSSH agent supports DSA, ECDSA and RSA keys for protocol 2. DSA -keys may be added using the following request - - byte SSH2_AGENTC_ADD_IDENTITY or - SSH2_AGENTC_ADD_ID_CONSTRAINED - string "ssh-dss" - mpint dsa_p - mpint dsa_q - mpint dsa_g - mpint dsa_public_key - mpint dsa_private_key - string key_comment - constraint[] key_constraints - -DSA certificates may be added with: - byte SSH2_AGENTC_ADD_IDENTITY or - SSH2_AGENTC_ADD_ID_CONSTRAINED - string "ssh-dss-cert-v00@openssh.com" - string certificate - mpint dsa_private_key - string key_comment - constraint[] key_constraints - -ECDSA keys may be added using the following request - - byte SSH2_AGENTC_ADD_IDENTITY or - SSH2_AGENTC_ADD_ID_CONSTRAINED - string "ecdsa-sha2-nistp256" | - "ecdsa-sha2-nistp384" | - "ecdsa-sha2-nistp521" - string ecdsa_curve_name - string ecdsa_public_key - mpint ecdsa_private - string key_comment - constraint[] key_constraints - -ECDSA certificates may be added with: - byte SSH2_AGENTC_ADD_IDENTITY or - SSH2_AGENTC_ADD_ID_CONSTRAINED - string "ecdsa-sha2-nistp256-cert-v01@openssh.com" | - "ecdsa-sha2-nistp384-cert-v01@openssh.com" | - "ecdsa-sha2-nistp521-cert-v01@openssh.com" - string certificate - mpint ecdsa_private_key - string key_comment - constraint[] key_constraints - -ED25519 keys may be added using the following request - byte SSH2_AGENTC_ADD_IDENTITY or - SSH2_AGENTC_ADD_ID_CONSTRAINED - string "ssh-ed25519" - string ed25519_public_key - string ed25519_private_key || ed25519_public_key - string key_comment - constraint[] key_constraints - -ED25519 certificates may be added with: - byte SSH2_AGENTC_ADD_IDENTITY or - SSH2_AGENTC_ADD_ID_CONSTRAINED - string "ssh-ed25519-cert-v01@openssh.com" - string certificate - string ed25519_public_key - string ed25519_private_key || ed25519_public_key - string key_comment - constraint[] key_constraints - -For both ssh-ed25519 and ssh-ed25519-cert-v01@openssh.com keys, the private -key has the public key appended (for historical reasons). - -RSA keys may be added with this request: - - byte SSH2_AGENTC_ADD_IDENTITY or - SSH2_AGENTC_ADD_ID_CONSTRAINED - string "ssh-rsa" - mpint rsa_n - mpint rsa_e - mpint rsa_d - mpint rsa_iqmp - mpint rsa_p - mpint rsa_q - string key_comment - constraint[] key_constraints - -RSA certificates may be added with this request: - - byte SSH2_AGENTC_ADD_IDENTITY or - SSH2_AGENTC_ADD_ID_CONSTRAINED - string "ssh-rsa-cert-v00@openssh.com" - string certificate - mpint rsa_d - mpint rsa_iqmp - mpint rsa_p - mpint rsa_q - string key_comment - constraint[] key_constraints - -Note that the 'rsa_p' and 'rsa_q' parameters are sent in the reverse -order to the protocol 1 add keys message. As with the corresponding -protocol 1 "add key" request, the private key is overspecified to avoid -redundant processing. - -For DSA, ECDSA and RSA key add requests, "key_constraints" may only be -present if the request type is SSH2_AGENTC_ADD_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. - -2.2.4 Loading keys from a smartcard - -The OpenSSH agent may have optional smartcard support built in to it. If -so, it supports an operation to load keys from a smartcard. Technically, -only the public components of the keys are loaded into the agent so -this operation really arranges for future private key operations to be -delegated to the smartcard. - - byte SSH_AGENTC_ADD_SMARTCARD_KEY or - SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED - string reader_id - string pin - constraint[] key_constraints - -"reader_id" is an identifier to a smartcard reader and "pin" -is a PIN or passphrase used to unlock the private key(s) on the -device. "key_constraints" may only be present if the request type is -SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED. - -This operation may load all SSH keys that are unlocked using the -"pin" on the specified reader. The type of key loaded (protocol 1 -or protocol 2) will be specified by the smartcard itself, it is not -client-specified. - -The agent will reply with a SSH_AGENT_SUCCESS if one or more keys have -been successfully loaded or a SSH_AGENT_FAILURE if an error occurred. -The agent will also return SSH_AGENT_FAILURE if it does not support -smartcards. - -2.3 Removing multiple keys - -A client may request that an agent delete all protocol 1 keys using the -following request: - - byte SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES - -This message requests the deletion of all protocol 2 keys: - - byte SSH2_AGENTC_REMOVE_ALL_IDENTITIES - -On success, the agent will delete all keys of the requested type and -reply with a SSH_AGENT_SUCCESS message. If an error occurred, the agent -will reply with SSH_AGENT_FAILURE. - -Note that, to delete all keys (both protocol 1 and 2), a client -must send both a SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES and a -SSH2_AGENTC_REMOVE_ALL_IDENTITIES request. - -2.4 Removing specific keys - -2.4.1 Removing a protocol 1 key - -Removal of a protocol 1 key may be requested with the following message: - - byte SSH_AGENTC_REMOVE_RSA_IDENTITY - uint32 key_bits - mpint1 rsa_e - mpint1 rsa_n - -Note that key_bits is strictly redundant, as it may be inferred by the -length of rsa_n. - -The agent will delete any private key matching the specified public key -and return SSH_AGENT_SUCCESS. If no such key was found, the agent will -return SSH_AGENT_FAILURE. - -2.4.2 Removing a protocol 2 key - -Protocol 2 keys may be removed with the following request: - - byte SSH2_AGENTC_REMOVE_IDENTITY - string key_blob - -Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key -Algorithms" for any of the supported protocol 2 key types. - -The agent will delete any private key matching the specified public key -and return SSH_AGENT_SUCCESS. If no such key was found, the agent will -return SSH_AGENT_FAILURE. - -2.4.3 Removing keys loaded from a smartcard - -A client may request that a server remove one or more smartcard-hosted -keys using this message: - - byte SSH_AGENTC_REMOVE_SMARTCARD_KEY - string reader_id - string pin - -"reader_id" the an identifier to a smartcard reader and "pin" is a PIN -or passphrase used to unlock the private key(s) on the device. - -When this message is received, and if the agent supports -smartcard-hosted keys, it will delete all keys that are hosted on the -specified smartcard that may be accessed with the given "pin". - -The agent will reply with a SSH_AGENT_SUCCESS if one or more keys have -been successfully removed or a SSH_AGENT_FAILURE if an error occurred. -The agent will also return SSH_AGENT_FAILURE if it does not support -smartcards. - -2.5 Requesting a list of known keys - -An agent may be requested to list which keys it holds. Different -requests exist for protocol 1 and protocol 2 keys. - -2.5.1 Requesting a list of protocol 1 keys - -To request a list of protocol 1 keys that are held in the agent, a -client may send the following message: - - byte SSH_AGENTC_REQUEST_RSA_IDENTITIES - -The agent will reply with the following message: - - byte SSH_AGENT_RSA_IDENTITIES_ANSWER - uint32 num_keys - -Followed by zero or more consecutive keys, encoded as: - - uint32 bits - mpint1 rsa_e - mpint1 rsa_n - string key_comment - -2.5.2 Requesting a list of protocol 2 keys - -A client may send the following message to request a list of -protocol 2 keys that are stored in the agent: - - byte SSH2_AGENTC_REQUEST_IDENTITIES - -The agent will reply with the following message header: - - byte SSH2_AGENT_IDENTITIES_ANSWER - uint32 num_keys - -Followed by zero or more consecutive keys, encoded as: - - string key_blob - string key_comment - -Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key -Algorithms" for any of the supported protocol 2 key types. - -2.6 Private key operations - -The purpose of the agent is to perform private key operations, such as -signing and encryption without requiring a passphrase to unlock the -key and without allowing the private key itself to be exposed. There -are separate requests for the protocol 1 and protocol 2 private key -operations. - -2.6.1 Protocol 1 private key challenge - -The private key operation used in version 1 of the SSH protocol is -decrypting a challenge that has been encrypted with a public key. -It may be requested using this message: - - byte SSH_AGENTC_RSA_CHALLENGE - uint32 ignored - mpint1 rsa_e - mpint1 rsa_n - mpint1 encrypted_challenge - byte[16] session_id - uint32 response_type /* must be 1 */ - -"rsa_e" and "rsa_n" are used to identify which private key to use. -"encrypted_challenge" is a challenge blob that has (presumably) -been encrypted with the public key and must be in the range -1 <= encrypted_challenge < 2^256. "session_id" is the SSH protocol 1 -session ID (computed from the server host key, the server semi-ephemeral -key and the session cookie). - -"ignored" and "response_type" exist for compatibility with legacy -implementations. "response_type" must be equal to 1; other response -types are not supported. - -On receiving this request, the server decrypts the "encrypted_challenge" -using the private key matching the supplied (rsa_e, rsa_n) values. For -the response derivation, the decrypted challenge is represented as an -unsigned, big-endian integer encoded in a 32 byte buffer (i.e. values -smaller than 2^248 will have leading 0 bytes). - -The response value is then calculated as: - - response = MD5(decrypted_challenge || session_id) - -and returned in the following message - - byte SSH_AGENT_RSA_RESPONSE - byte[16] response - -If the agent cannot find the key specified by the supplied (rsa_e, -rsa_n) then it will return SSH_AGENT_FAILURE. - -2.6.2 Protocol 2 private key signature request - -A client may use the following message to request signing of data using -a protocol 2 key: - - byte SSH2_AGENTC_SIGN_REQUEST - string key_blob - string data - uint32 flags - -Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key -Algorithms" for any of the supported protocol 2 key types. "flags" is -a bit-mask, but at present only one possible value is defined (see below -for its meaning): - - SSH_AGENT_OLD_SIGNATURE 1 - -Upon receiving this request, the agent will look up the private key that -corresponds to the public key contained in key_blob. It will use this -private key to sign the "data" and produce a signature blob using the -key type-specific method described in RFC 4253 section 6.6 "Public Key -Algorithms". - -An exception to this is for "ssh-dss" keys where the "flags" word -contains the value SSH_AGENT_OLD_SIGNATURE. In this case, a legacy -signature encoding is used in lieu of the standard one. In this case, -the DSA signature blob is encoded as: - - byte[40] signature - -The signature will be returned in the response message: - - byte SSH2_AGENT_SIGN_RESPONSE - string signature_blob - -If the agent cannot find the key specified by the supplied key_blob then -it will return SSH_AGENT_FAILURE. - -2.7 Locking or unlocking an agent - -The agent supports temporary locking with a passphrase to suspend -processing of sensitive operations until it has been unlocked with the -same passphrase. To lock an agent, a client send the following request: - - byte SSH_AGENTC_LOCK - string passphrase - -Upon receipt of this message and if the agent is not already locked, -it will suspend processing requests and return a SSH_AGENT_SUCCESS -reply. If the agent is already locked, it will return SSH_AGENT_FAILURE. - -While locked, the agent will refuse all requests except -SSH_AGENTC_UNLOCK, SSH_AGENTC_REQUEST_RSA_IDENTITIES and -SSH2_AGENTC_REQUEST_IDENTITIES. The "request identities" requests are -treated specially by a locked agent: it will always return an empty list -of keys. - -To unlock an agent, a client may request: - - byte SSH_AGENTC_UNLOCK - string passphrase - -If the passphrase matches and the agent is locked, then it will resume -processing all requests and return SSH_AGENT_SUCCESS. If the agent -is not locked or the passphrase does not match then it will return -SSH_AGENT_FAILURE. - -Locking and unlocking affects both protocol 1 and protocol 2 keys. - -3. Protocol message numbers - -3.1 Requests from client to agent for protocol 1 key operations - - SSH_AGENTC_REQUEST_RSA_IDENTITIES 1 - SSH_AGENTC_RSA_CHALLENGE 3 - SSH_AGENTC_ADD_RSA_IDENTITY 7 - SSH_AGENTC_REMOVE_RSA_IDENTITY 8 - SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9 - SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24 - -3.2 Requests from client to agent for protocol 2 key operations - - SSH2_AGENTC_REQUEST_IDENTITIES 11 - SSH2_AGENTC_SIGN_REQUEST 13 - SSH2_AGENTC_ADD_IDENTITY 17 - SSH2_AGENTC_REMOVE_IDENTITY 18 - SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19 - SSH2_AGENTC_ADD_ID_CONSTRAINED 25 - -3.3 Key-type independent requests from client to agent - - SSH_AGENTC_ADD_SMARTCARD_KEY 20 - SSH_AGENTC_REMOVE_SMARTCARD_KEY 21 - SSH_AGENTC_LOCK 22 - SSH_AGENTC_UNLOCK 23 - SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26 - -3.4 Generic replies from agent to client - - SSH_AGENT_FAILURE 5 - SSH_AGENT_SUCCESS 6 - -3.5 Replies from agent to client for protocol 1 key operations - - SSH_AGENT_RSA_IDENTITIES_ANSWER 2 - SSH_AGENT_RSA_RESPONSE 4 - -3.6 Replies from agent to client for protocol 2 key operations - - SSH2_AGENT_IDENTITIES_ANSWER 12 - SSH2_AGENT_SIGN_RESPONSE 14 - -3.7 Key constraint identifiers - - SSH_AGENT_CONSTRAIN_LIFETIME 1 - SSH_AGENT_CONSTRAIN_CONFIRM 2 - -$OpenBSD: PROTOCOL.agent,v 1.11 2016/05/19 07:45:32 djm Exp $ +This file used to contain a description of the SSH agent protocol +implemented by OpenSSH. It has since been superseded by +https://tools.ietf.org/html/draft-miller-ssh-agent-00 diff --git a/PROTOCOL.certkeys b/PROTOCOL.certkeys index 734b606bb..42aa8c2a1 100644 --- a/PROTOCOL.certkeys +++ b/PROTOCOL.certkeys @@ -224,6 +224,9 @@ option-specific information (see below). All options are "critical", if an implementation does not recognise a option then the validating party should refuse to accept the certificate. +Custom options should append the originating author or organisation's +domain name to the option name, e.g. "my-option@example.com". + No critical options are defined for host certificates at present. The supported user certificate options and the contents and structure of their data fields are: @@ -255,6 +258,9 @@ as is the requirement that each name appear only once. If an implementation does not recognise an extension, then it should ignore it. +Custom options should append the originating author or organisation's +domain name to the option name, e.g. "my-option@example.com". + No extensions are defined for host certificates at present. The supported user certificate extensions and the contents and structure of their data fields are: @@ -285,4 +291,4 @@ permit-user-rc empty Flag indicating that execution of of this script will not be permitted if this option is not present. -$OpenBSD: PROTOCOL.certkeys,v 1.11 2017/05/16 16:54:05 djm Exp $ +$OpenBSD: PROTOCOL.certkeys,v 1.12 2017/05/31 04:29:44 djm Exp $ diff --git a/auth-options.c b/auth-options.c index 57b49f7fd..0a191dbba 100644 --- a/auth-options.c +++ b/auth-options.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-options.c,v 1.72 2016/11/30 02:57:40 djm Exp $ */ +/* $OpenBSD: auth-options.c,v 1.73 2017/05/31 10:54:00 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -119,7 +119,8 @@ match_flag(const char *opt, int allow_negate, char **optsp, const char *msg) * side effect: sets key option flags */ int -auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) +auth_parse_options(struct passwd *pw, char *opts, const char *file, + u_long linenum) { struct ssh *ssh = active_state; /* XXX */ const char *cp; diff --git a/auth-options.h b/auth-options.h index 52cbb42aa..547f01635 100644 --- a/auth-options.h +++ b/auth-options.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-options.h,v 1.22 2016/11/30 02:57:40 djm Exp $ */ +/* $OpenBSD: auth-options.h,v 1.23 2017/05/31 10:54:00 markus Exp $ */ /* * Author: Tatu Ylonen @@ -33,7 +33,7 @@ extern int forced_tun_device; extern int key_is_cert_authority; extern char *authorized_principals; -int auth_parse_options(struct passwd *, char *, char *, u_long); +int auth_parse_options(struct passwd *, char *, const char *, u_long); void auth_clear_options(void); int auth_cert_options(struct sshkey *, struct passwd *, const char **); diff --git a/auth.c b/auth.c index ad0c80182..9084958f9 100644 --- a/auth.c +++ b/auth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.c,v 1.120 2017/05/17 01:24:17 djm Exp $ */ +/* $OpenBSD: auth.c,v 1.121 2017/05/30 08:52:19 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -429,7 +429,7 @@ authorized_principals_file(struct passwd *pw) /* return ok if key exists in sysfile or userfile */ HostStatus -check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host, +check_key_in_hostfiles(struct passwd *pw, struct sshkey *key, const char *host, const char *sysfile, const char *userfile) { char *user_hostfile; @@ -711,7 +711,7 @@ getpwnamallow(const char *user) /* Returns 1 if key is revoked by revoked_keys_file, 0 otherwise */ int -auth_key_is_revoked(Key *key) +auth_key_is_revoked(struct sshkey *key) { char *fp = NULL; int r; diff --git a/auth.h b/auth.h index 338a62da7..677935463 100644 --- a/auth.h +++ b/auth.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.h,v 1.89 2016/08/13 17:47:41 markus Exp $ */ +/* $OpenBSD: auth.h,v 1.91 2017/05/30 14:29:59 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -91,7 +91,7 @@ struct Authctxt { struct Authmethod { char *name; - int (*userauth)(Authctxt *authctxt); + int (*userauth)(struct ssh *); int *enabled; }; @@ -117,9 +117,10 @@ auth_rhosts2(struct passwd *, const char *, const char *, const char *); int auth_password(Authctxt *, const char *); -int hostbased_key_allowed(struct passwd *, const char *, char *, Key *); -int user_key_allowed(struct passwd *, Key *, int); -void pubkey_auth_info(Authctxt *, const Key *, const char *, ...) +int hostbased_key_allowed(struct passwd *, const char *, char *, + struct sshkey *); +int user_key_allowed(struct passwd *, struct sshkey *, int); +void pubkey_auth_info(Authctxt *, const struct sshkey *, const char *, ...) __attribute__((__format__ (printf, 3, 4))); void auth2_record_userkey(Authctxt *, struct sshkey *); int auth2_userkey_already_used(Authctxt *, struct sshkey *); @@ -154,7 +155,7 @@ void auth_info(Authctxt *authctxt, const char *, ...) __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 *); +void userauth_finish(struct ssh *, int, const char *, const char *); int auth_root_allowed(const char *); void userauth_send_banner(const char *); @@ -167,8 +168,8 @@ int auth2_method_allowed(Authctxt *, const char *, const char *); void privsep_challenge_enable(void); -int auth2_challenge(Authctxt *, char *); -void auth2_challenge_stop(Authctxt *); +int auth2_challenge(struct ssh *, char *); +void auth2_challenge_stop(struct ssh *); int bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **); int bsdauth_respond(void *, u_int, char **); int skey_query(void *, char **, char **, u_int *, char ***, u_int **); @@ -182,22 +183,22 @@ char *authorized_principals_file(struct passwd *); FILE *auth_openkeyfile(const char *, struct passwd *, int); FILE *auth_openprincipals(const char *, struct passwd *, int); -int auth_key_is_revoked(Key *); +int auth_key_is_revoked(struct sshkey *); const char *auth_get_canonical_hostname(struct ssh *, int); HostStatus -check_key_in_hostfiles(struct passwd *, Key *, const char *, +check_key_in_hostfiles(struct passwd *, struct sshkey *, const char *, const char *, const char *); /* hostkey handling */ -Key *get_hostkey_by_index(int); -Key *get_hostkey_public_by_index(int, struct ssh *); -Key *get_hostkey_public_by_type(int, int, struct ssh *); -Key *get_hostkey_private_by_type(int, int, struct ssh *); -int get_hostkey_index(Key *, int, struct ssh *); -int sshd_hostkey_sign(Key *, Key *, u_char **, size_t *, - const u_char *, size_t, const char *, u_int); +struct sshkey *get_hostkey_by_index(int); +struct sshkey *get_hostkey_public_by_index(int, struct ssh *); +struct sshkey *get_hostkey_public_by_type(int, int, struct ssh *); +struct sshkey *get_hostkey_private_by_type(int, int, struct ssh *); +int get_hostkey_index(struct sshkey *, int, struct ssh *); +int sshd_hostkey_sign(struct sshkey *, struct sshkey *, u_char **, + size_t *, const u_char *, size_t, const char *, u_int); /* debug messages during authentication */ void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2))); diff --git a/auth2-chall.c b/auth2-chall.c index ead480318..11c8d31b3 100644 --- a/auth2-chall.c +++ b/auth2-chall.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-chall.c,v 1.44 2016/05/02 08:49:03 djm Exp $ */ +/* $OpenBSD: auth2-chall.c,v 1.48 2017/05/30 14:29:59 markus Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2001 Per Allansson. All rights reserved. @@ -47,9 +47,9 @@ /* import */ extern ServerOptions options; -static int auth2_challenge_start(Authctxt *); +static int auth2_challenge_start(struct ssh *); static int send_userauth_info_request(Authctxt *); -static int input_userauth_info_response(int, u_int32_t, void *); +static int input_userauth_info_response(int, u_int32_t, struct ssh *); #ifdef BSD_AUTH extern KbdintDevice bsdauth_device; @@ -195,8 +195,9 @@ kbdint_next_device(Authctxt *authctxt, KbdintAuthctxt *kbdintctxt) * wait for the response. */ int -auth2_challenge(Authctxt *authctxt, char *devs) +auth2_challenge(struct ssh *ssh, char *devs) { + Authctxt *authctxt = ssh->authctxt; debug("auth2_challenge: user=%s devs=%s", authctxt->user ? authctxt->user : "", devs ? devs : ""); @@ -205,15 +206,16 @@ auth2_challenge(Authctxt *authctxt, char *devs) return 0; if (authctxt->kbdintctxt == NULL) authctxt->kbdintctxt = kbdint_alloc(devs); - return auth2_challenge_start(authctxt); + return auth2_challenge_start(ssh); } /* unregister kbd-int callbacks and context */ void -auth2_challenge_stop(Authctxt *authctxt) +auth2_challenge_stop(struct ssh *ssh) { + Authctxt *authctxt = ssh->authctxt; /* unregister callback */ - dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL); if (authctxt->kbdintctxt != NULL) { kbdint_free(authctxt->kbdintctxt); authctxt->kbdintctxt = NULL; @@ -222,29 +224,30 @@ auth2_challenge_stop(Authctxt *authctxt) /* side effect: sets authctxt->postponed if a reply was sent*/ static int -auth2_challenge_start(Authctxt *authctxt) +auth2_challenge_start(struct ssh *ssh) { + Authctxt *authctxt = ssh->authctxt; KbdintAuthctxt *kbdintctxt = authctxt->kbdintctxt; debug2("auth2_challenge_start: devices %s", kbdintctxt->devices ? kbdintctxt->devices : ""); if (kbdint_next_device(authctxt, kbdintctxt) == 0) { - auth2_challenge_stop(authctxt); + auth2_challenge_stop(ssh); return 0; } debug("auth2_challenge_start: trying authentication method '%s'", kbdintctxt->device->name); if ((kbdintctxt->ctxt = kbdintctxt->device->init_ctx(authctxt)) == NULL) { - auth2_challenge_stop(authctxt); + auth2_challenge_stop(ssh); return 0; } if (send_userauth_info_request(authctxt) == 0) { - auth2_challenge_stop(authctxt); + auth2_challenge_stop(ssh); return 0; } - dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_RESPONSE, &input_userauth_info_response); authctxt->postponed = 1; @@ -285,9 +288,9 @@ send_userauth_info_request(Authctxt *authctxt) } static int -input_userauth_info_response(int type, u_int32_t seq, void *ctxt) +input_userauth_info_response(int type, u_int32_t seq, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; KbdintAuthctxt *kbdintctxt; int authenticated = 0, res; u_int i, nresp; @@ -340,14 +343,14 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt) devicename = kbdintctxt->device->name; if (!authctxt->postponed) { if (authenticated) { - auth2_challenge_stop(authctxt); + auth2_challenge_stop(ssh); } else { /* start next device */ /* may set authctxt->postponed */ - auth2_challenge_start(authctxt); + auth2_challenge_start(ssh); } } - userauth_finish(authctxt, authenticated, "keyboard-interactive", + userauth_finish(ssh, authenticated, "keyboard-interactive", devicename); return 0; } diff --git a/auth2-gss.c b/auth2-gss.c index 1ca835773..680d5e712 100644 --- a/auth2-gss.c +++ b/auth2-gss.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-gss.c,v 1.22 2015/01/19 20:07:45 markus Exp $ */ +/* $OpenBSD: auth2-gss.c,v 1.25 2017/05/30 14:29:59 markus Exp $ */ /* * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. @@ -48,18 +48,19 @@ extern ServerOptions options; -static int input_gssapi_token(int type, u_int32_t plen, void *ctxt); -static int input_gssapi_mic(int type, u_int32_t plen, void *ctxt); -static int input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt); -static int input_gssapi_errtok(int, u_int32_t, void *); +static int input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh); +static int input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh); +static int input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh); +static int input_gssapi_errtok(int, u_int32_t, struct ssh *); /* * We only support those mechanisms that we know about (ie ones that we know * how to check local user kuserok and the like) */ static int -userauth_gssapi(Authctxt *authctxt) +userauth_gssapi(struct ssh *ssh) { + Authctxt *authctxt = ssh->authctxt; gss_OID_desc goid = {0, NULL}; Gssctxt *ctxt = NULL; int mechs; @@ -119,17 +120,17 @@ userauth_gssapi(Authctxt *authctxt) packet_send(); free(doid); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok); authctxt->postponed = 1; return (0); } static int -input_gssapi_token(int type, u_int32_t plen, void *ctxt) +input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; Gssctxt *gssctxt; gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; gss_buffer_desc recv_tok; @@ -157,8 +158,8 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt) packet_send(); } authctxt->postponed = 0; - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); - userauth_finish(authctxt, 0, "gssapi-with-mic", NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); + userauth_finish(ssh, 0, "gssapi-with-mic", NULL); } else { if (send_tok.length != 0) { packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN); @@ -166,12 +167,12 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt) packet_send(); } if (maj_status == GSS_S_COMPLETE) { - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); if (flags & GSS_C_INTEG_FLAG) - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_MIC, &input_gssapi_mic); else - dispatch_set( + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, &input_gssapi_exchange_complete); } @@ -182,9 +183,9 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt) } static int -input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) +input_gssapi_errtok(int type, u_int32_t plen, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; Gssctxt *gssctxt; gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; gss_buffer_desc recv_tok; @@ -207,8 +208,8 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) 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); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); /* The client will have already moved on to the next auth */ @@ -223,9 +224,9 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) */ static int -input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) +input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; int authenticated; if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) @@ -241,18 +242,18 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); 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", NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); + userauth_finish(ssh, authenticated, "gssapi-with-mic", NULL); return 0; } static int -input_gssapi_mic(int type, u_int32_t plen, void *ctxt) +input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; Gssctxt *gssctxt; int authenticated = 0; Buffer b; @@ -282,11 +283,11 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt) 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", NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); + userauth_finish(ssh, authenticated, "gssapi-with-mic", NULL); return 0; } diff --git a/auth2-hostbased.c b/auth2-hostbased.c index 1b3c3b202..63fe9ae65 100644 --- a/auth2-hostbased.c +++ b/auth2-hostbased.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-hostbased.c,v 1.26 2016/03/07 19:02:43 djm Exp $ */ +/* $OpenBSD: auth2-hostbased.c,v 1.30 2017/05/30 14:29:59 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -39,7 +39,7 @@ #include "misc.h" #include "servconf.h" #include "compat.h" -#include "key.h" +#include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "canohost.h" @@ -48,6 +48,7 @@ #endif #include "monitor_wrap.h" #include "pathnames.h" +#include "ssherr.h" #include "match.h" /* import */ @@ -56,54 +57,56 @@ extern u_char *session_id2; extern u_int session_id2_len; static int -userauth_hostbased(Authctxt *authctxt) +userauth_hostbased(struct ssh *ssh) { - Buffer b; - Key *key = NULL; + Authctxt *authctxt = ssh->authctxt; + struct sshbuf *b; + struct sshkey *key = NULL; char *pkalg, *cuser, *chost, *service; u_char *pkblob, *sig; - u_int alen, blen, slen; - int pktype; - int authenticated = 0; + size_t alen, blen, slen; + int r, pktype, authenticated = 0; if (!authctxt->valid) { - debug2("userauth_hostbased: disabled because of invalid user"); + debug2("%s: disabled because of invalid user", __func__); return 0; } - pkalg = packet_get_string(&alen); - pkblob = packet_get_string(&blen); - chost = packet_get_string(NULL); - cuser = packet_get_string(NULL); - sig = packet_get_string(&slen); + /* XXX use sshkey_froms() */ + if ((r = sshpkt_get_cstring(ssh, &pkalg, &alen)) != 0 || + (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0 || + (r = sshpkt_get_cstring(ssh, &chost, NULL)) != 0 || + (r = sshpkt_get_cstring(ssh, &cuser, NULL)) != 0 || + (r = sshpkt_get_string(ssh, &sig, &slen)) != 0) + fatal("%s: packet parsing: %s", __func__, ssh_err(r)); - debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d", + debug("%s: cuser %s chost %s pkalg %s slen %zu", __func__, cuser, chost, pkalg, slen); #ifdef DEBUG_PK debug("signature:"); - buffer_init(&b); - buffer_append(&b, sig, slen); - buffer_dump(&b); - buffer_free(&b); + sshbuf_dump_data(sig, siglen, stderr); #endif - pktype = key_type_from_name(pkalg); + pktype = sshkey_type_from_name(pkalg); if (pktype == KEY_UNSPEC) { /* this is perfectly legal */ - logit("userauth_hostbased: unsupported " - "public key algorithm: %s", pkalg); + logit("%s: unsupported public key algorithm: %s", + __func__, pkalg); + goto done; + } + if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { + error("%s: key_from_blob: %s", __func__, ssh_err(r)); goto done; } - key = key_from_blob(pkblob, blen); if (key == NULL) { - error("userauth_hostbased: cannot decode key: %s", pkalg); + error("%s: cannot decode key: %s", __func__, pkalg); goto done; } if (key->type != pktype) { - error("userauth_hostbased: type mismatch for decoded key " - "(received %d, expected %d)", key->type, pktype); + error("%s: type mismatch for decoded key " + "(received %d, expected %d)", __func__, key->type, pktype); goto done; } - if (key_type_plain(key->type) == KEY_RSA && - (datafellows & SSH_BUG_RSASIGMD5) != 0) { + if (sshkey_type_plain(key->type) == KEY_RSA && + (ssh->compat & SSH_BUG_RSASIGMD5) != 0) { error("Refusing RSA key because peer uses unsafe " "signature format"); goto done; @@ -115,21 +118,23 @@ userauth_hostbased(Authctxt *authctxt) goto done; } - service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" : + service = ssh->compat & SSH_BUG_HBSERVICE ? "ssh-userauth" : authctxt->service; - buffer_init(&b); - buffer_put_string(&b, session_id2, session_id2_len); + if ((b = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); /* reconstruct packet */ - buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); - buffer_put_cstring(&b, authctxt->user); - buffer_put_cstring(&b, service); - buffer_put_cstring(&b, "hostbased"); - buffer_put_string(&b, pkalg, alen); - buffer_put_string(&b, pkblob, blen); - buffer_put_cstring(&b, chost); - buffer_put_cstring(&b, cuser); + if ((r = sshbuf_put_string(b, session_id2, session_id2_len)) != 0 || + (r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || + (r = sshbuf_put_cstring(b, authctxt->user)) != 0 || + (r = sshbuf_put_cstring(b, service)) != 0 || + (r = sshbuf_put_cstring(b, "hostbased")) != 0 || + (r = sshbuf_put_string(b, pkalg, alen)) != 0 || + (r = sshbuf_put_string(b, pkblob, blen)) != 0 || + (r = sshbuf_put_cstring(b, chost)) != 0 || + (r = sshbuf_put_cstring(b, cuser)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); #ifdef DEBUG_PK - buffer_dump(&b); + sshbuf_dump(b, stderr); #endif pubkey_auth_info(authctxt, key, @@ -138,15 +143,15 @@ userauth_hostbased(Authctxt *authctxt) /* test for allowed key and correct signature */ authenticated = 0; if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) && - PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), - buffer_len(&b))) == 1) + PRIVSEP(sshkey_verify(key, sig, slen, + sshbuf_ptr(b), sshbuf_len(b), ssh->compat)) == 0) authenticated = 1; - buffer_free(&b); + sshbuf_free(b); done: - debug2("userauth_hostbased: authenticated %d", authenticated); + debug2("%s: authenticated %d", __func__, authenticated); if (key != NULL) - key_free(key); + sshkey_free(key); free(pkalg); free(pkblob); free(cuser); @@ -158,7 +163,7 @@ done: /* return 1 if given hostkey is allowed */ int hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, - Key *key) + struct sshkey *key) { struct ssh *ssh = active_state; /* XXX */ const char *resolvedname, *ipaddr, *lookup, *reason; @@ -203,8 +208,8 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, } debug2("%s: access allowed by auth_rhosts2", __func__); - if (key_is_cert(key) && - key_cert_check_authority(key, 1, 0, lookup, &reason)) { + if (sshkey_is_cert(key) && + sshkey_cert_check_authority(key, 1, 0, lookup, &reason)) { error("%s", reason); auth_debug_add("%s", reason); return 0; @@ -223,20 +228,20 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, } if (host_status == HOST_OK) { - if (key_is_cert(key)) { + if (sshkey_is_cert(key)) { if ((fp = sshkey_fingerprint(key->cert->signature_key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) fatal("%s: sshkey_fingerprint fail", __func__); verbose("Accepted certificate ID \"%s\" signed by " "%s CA %s from %s@%s", key->cert->key_id, - key_type(key->cert->signature_key), fp, + sshkey_type(key->cert->signature_key), fp, cuser, lookup); } else { if ((fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) fatal("%s: sshkey_fingerprint fail", __func__); verbose("Accepted %s public key %s from %s@%s", - key_type(key), fp, cuser, lookup); + sshkey_type(key), fp, cuser, lookup); } free(fp); } diff --git a/auth2-kbdint.c b/auth2-kbdint.c index bf75c6059..86aad8ddc 100644 --- a/auth2-kbdint.c +++ b/auth2-kbdint.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-kbdint.c,v 1.7 2014/07/15 15:54:14 millert Exp $ */ +/* $OpenBSD: auth2-kbdint.c,v 1.8 2017/05/30 14:29:59 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -43,7 +43,7 @@ extern ServerOptions options; static int -userauth_kbdint(Authctxt *authctxt) +userauth_kbdint(struct ssh *ssh) { int authenticated = 0; char *lang, *devs; @@ -55,7 +55,7 @@ userauth_kbdint(Authctxt *authctxt) debug("keyboard-interactive devs %s", devs); if (options.challenge_response_authentication) - authenticated = auth2_challenge(authctxt, devs); + authenticated = auth2_challenge(ssh, devs); free(devs); free(lang); diff --git a/auth2-none.c b/auth2-none.c index e71e2219c..35d25fa63 100644 --- a/auth2-none.c +++ b/auth2-none.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-none.c,v 1.18 2014/07/15 15:54:14 millert Exp $ */ +/* $OpenBSD: auth2-none.c,v 1.20 2017/05/30 14:29:59 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -37,7 +37,7 @@ #include "atomicio.h" #include "xmalloc.h" -#include "key.h" +#include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "packet.h" @@ -47,6 +47,7 @@ #include "servconf.h" #include "compat.h" #include "ssh2.h" +#include "ssherr.h" #ifdef GSSAPI #include "ssh-gss.h" #endif @@ -59,12 +60,15 @@ extern ServerOptions options; static int none_enabled = 1; static int -userauth_none(Authctxt *authctxt) +userauth_none(struct ssh *ssh) { + int r; + none_enabled = 0; - packet_check_eom(); + if ((r = sshpkt_get_end(ssh)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); if (options.permit_empty_passwd && options.password_authentication) - return (PRIVSEP(auth_password(authctxt, ""))); + return (PRIVSEP(auth_password(ssh->authctxt, ""))); return (0); } diff --git a/auth2-passwd.c b/auth2-passwd.c index b638e8715..5f7ba3244 100644 --- a/auth2-passwd.c +++ b/auth2-passwd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-passwd.c,v 1.12 2014/07/15 15:54:14 millert Exp $ */ +/* $OpenBSD: auth2-passwd.c,v 1.14 2017/05/30 14:29:59 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -30,10 +30,10 @@ #include #include -#include "xmalloc.h" #include "packet.h" +#include "ssherr.h" #include "log.h" -#include "key.h" +#include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "buffer.h" @@ -48,26 +48,22 @@ extern ServerOptions options; static int -userauth_passwd(Authctxt *authctxt) +userauth_passwd(struct ssh *ssh) { - char *password, *newpass; - int authenticated = 0; - int change; - u_int len, newlen; + char *password; + int authenticated = 0, r; + u_char change; + size_t len; - change = packet_get_char(); - password = packet_get_string(&len); - if (change) { - /* discard new password from packet */ - newpass = packet_get_string(&newlen); - explicit_bzero(newpass, newlen); - free(newpass); - } - packet_check_eom(); + if ((r = sshpkt_get_u8(ssh, &change)) != 0 || + (r = sshpkt_get_cstring(ssh, &password, &len)) != 0 || + (change && (r = sshpkt_get_cstring(ssh, NULL, NULL)) != 0) || + (r = sshpkt_get_end(ssh)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); if (change) logit("password change not supported"); - else if (PRIVSEP(auth_password(authctxt, password)) == 1) + else if (PRIVSEP(auth_password(ssh->authctxt, password)) == 1) authenticated = 1; explicit_bzero(password, len); free(password); diff --git a/auth2-pubkey.c b/auth2-pubkey.c index 55de2055c..366e83c3d 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-pubkey.c,v 1.62 2017/01/30 01:03:00 djm Exp $ */ +/* $OpenBSD: auth2-pubkey.c,v 1.67 2017/05/31 10:54:00 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -52,7 +52,7 @@ #include "misc.h" #include "servconf.h" #include "compat.h" -#include "key.h" +#include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "pathnames.h" @@ -76,42 +76,52 @@ extern u_char *session_id2; extern u_int session_id2_len; static int -userauth_pubkey(Authctxt *authctxt) +userauth_pubkey(struct ssh *ssh) { - Buffer b; - Key *key = NULL; - char *pkalg, *userstyle, *fp = NULL; - u_char *pkblob, *sig; - u_int alen, blen, slen; - int have_sig, pktype; + Authctxt *authctxt = ssh->authctxt; + struct sshbuf *b; + struct sshkey *key = NULL; + char *pkalg, *userstyle = NULL, *fp = NULL; + u_char *pkblob, *sig, have_sig; + size_t blen, slen; + int r, pktype; int authenticated = 0; if (!authctxt->valid) { debug2("%s: disabled because of invalid user", __func__); return 0; } - have_sig = packet_get_char(); - if (datafellows & SSH_BUG_PKAUTH) { + if ((r = sshpkt_get_u8(ssh, &have_sig)) != 0) + fatal("%s: sshpkt_get_u8 failed: %s", __func__, ssh_err(r)); + if (ssh->compat & SSH_BUG_PKAUTH) { debug2("%s: SSH_BUG_PKAUTH", __func__); + if ((b = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); /* no explicit pkalg given */ - pkblob = packet_get_string(&blen); - buffer_init(&b); - buffer_append(&b, pkblob, blen); /* so we have to extract the pkalg from the pkblob */ - pkalg = buffer_get_string(&b, &alen); - buffer_free(&b); + /* XXX use sshbuf_from() */ + if ((r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0 || + (r = sshbuf_put(b, pkblob, blen)) != 0 || + (r = sshbuf_get_cstring(b, &pkalg, NULL)) != 0) + fatal("%s: failed: %s", __func__, ssh_err(r)); + sshbuf_free(b); } else { - pkalg = packet_get_string(&alen); - pkblob = packet_get_string(&blen); + if ((r = sshpkt_get_cstring(ssh, &pkalg, NULL)) != 0 || + (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0) + fatal("%s: sshpkt_get_cstring failed: %s", + __func__, ssh_err(r)); } - pktype = key_type_from_name(pkalg); + pktype = sshkey_type_from_name(pkalg); if (pktype == KEY_UNSPEC) { /* this is perfectly legal */ logit("%s: unsupported public key algorithm: %s", __func__, pkalg); goto done; } - key = key_from_blob(pkblob, blen); + if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { + error("%s: could not parse key: %s", __func__, ssh_err(r)); + goto done; + } if (key == NULL) { error("%s: cannot decode key: %s", __func__, pkalg); goto done; @@ -121,15 +131,15 @@ userauth_pubkey(Authctxt *authctxt) "(received %d, expected %d)", __func__, key->type, pktype); goto done; } - if (key_type_plain(key->type) == KEY_RSA && - (datafellows & SSH_BUG_RSASIGMD5) != 0) { + if (sshkey_type_plain(key->type) == KEY_RSA && + (ssh->compat & SSH_BUG_RSASIGMD5) != 0) { logit("Refusing RSA key because client uses unsafe " "signature scheme"); goto done; } fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT); if (auth2_userkey_already_used(authctxt, key)) { - logit("refusing previously-used %s key", key_type(key)); + logit("refusing previously-used %s key", sshkey_type(key)); goto done; } if (match_pattern_list(sshkey_ssh_name(key), @@ -142,35 +152,48 @@ userauth_pubkey(Authctxt *authctxt) if (have_sig) { debug3("%s: have signature for %s %s", __func__, sshkey_type(key), fp); - sig = packet_get_string(&slen); - packet_check_eom(); - buffer_init(&b); - if (datafellows & SSH_OLD_SESSIONID) { - buffer_append(&b, session_id2, session_id2_len); + if ((r = sshpkt_get_string(ssh, &sig, &slen)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); + if ((b = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if (ssh->compat & SSH_OLD_SESSIONID) { + if ((r = sshbuf_put(b, session_id2, + session_id2_len)) != 0) + fatal("%s: sshbuf_put session id: %s", + __func__, ssh_err(r)); } else { - buffer_put_string(&b, session_id2, session_id2_len); + if ((r = sshbuf_put_string(b, session_id2, + session_id2_len)) != 0) + fatal("%s: sshbuf_put_string session id: %s", + __func__, ssh_err(r)); } /* reconstruct packet */ - buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); 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" : - authctxt->service); - if (datafellows & SSH_BUG_PKAUTH) { - buffer_put_char(&b, have_sig); + if ((r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || + (r = sshbuf_put_cstring(b, userstyle)) != 0 || + (r = sshbuf_put_cstring(b, ssh->compat & SSH_BUG_PKSERVICE ? + "ssh-userauth" : authctxt->service)) != 0) + fatal("%s: build packet failed: %s", + __func__, ssh_err(r)); + if (ssh->compat & SSH_BUG_PKAUTH) { + if ((r = sshbuf_put_u8(b, have_sig)) != 0) + fatal("%s: build packet failed: %s", + __func__, ssh_err(r)); } else { - buffer_put_cstring(&b, "publickey"); - buffer_put_char(&b, have_sig); - buffer_put_cstring(&b, pkalg); + if ((r = sshbuf_put_cstring(b, "publickey")) != 0 || + (r = sshbuf_put_u8(b, have_sig)) != 0 || + (r = sshbuf_put_cstring(b, pkalg) != 0)) + fatal("%s: build packet failed: %s", + __func__, ssh_err(r)); } - buffer_put_string(&b, pkblob, blen); + if ((r = sshbuf_put_string(b, pkblob, blen)) != 0) + fatal("%s: build packet failed: %s", + __func__, ssh_err(r)); #ifdef DEBUG_PK - buffer_dump(&b); + sshbuf_dump(b, stderr); #endif pubkey_auth_info(authctxt, key, NULL); @@ -222,21 +245,22 @@ userauth_pubkey(Authctxt *authctxt) #else /* !WINDOWS */ if (PRIVSEP(user_key_allowed(authctxt->pw, key, 1)) && - PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), - buffer_len(&b))) == 1) { + PRIVSEP(sshkey_verify(key, sig, slen, sshbuf_ptr(b), + sshbuf_len(b), ssh->compat)) == 0) { authenticated = 1; /* Record the successful key to prevent reuse */ auth2_record_userkey(authctxt, key); key = NULL; /* Don't free below */ } - buffer_free(&b); + sshbuf_free(b); free(sig); #endif /* !WINDOWS */ } else { debug("%s: test whether pkalg/pkblob are acceptable for %s %s", __func__, sshkey_type(key), fp); - packet_check_eom(); + if ((r = sshpkt_get_end(ssh)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); /* XXX fake reply and always send PK_OK ? */ /* @@ -247,11 +271,13 @@ userauth_pubkey(Authctxt *authctxt) * issue? -markus */ if (PRIVSEP(user_key_allowed(authctxt->pw, key, 0))) { - packet_start(SSH2_MSG_USERAUTH_PK_OK); - packet_put_string(pkalg, alen); - packet_put_string(pkblob, blen); - packet_send(); - packet_write_wait(); + if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_PK_OK)) + != 0 || + (r = sshpkt_put_cstring(ssh, pkalg)) != 0 || + (r = sshpkt_put_string(ssh, pkblob, blen)) != 0 || + (r = sshpkt_send(ssh)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); + ssh_packet_write_wait(ssh); authctxt->postponed = 1; } } @@ -260,7 +286,8 @@ userauth_pubkey(Authctxt *authctxt) done: debug2("%s: authenticated %d pkalg %s", __func__, authenticated, pkalg); if (key != NULL) - key_free(key); + sshkey_free(key); + free(userstyle); free(pkalg); free(pkblob); free(fp); @@ -268,7 +295,8 @@ done: } void -pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...) +pubkey_auth_info(Authctxt *authctxt, const struct sshkey *key, + const char *fmt, ...) { char *fp, *extra; va_list ap; @@ -280,23 +308,23 @@ pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...) i = vasprintf(&extra, fmt, ap); va_end(ap); if (i < 0 || extra == NULL) - fatal("%s: vasprintf failed", __func__); + fatal("%s: vasprintf failed", __func__); } - if (key_is_cert(key)) { + if (sshkey_is_cert(key)) { fp = sshkey_fingerprint(key->cert->signature_key, options.fingerprint_hash, SSH_FP_DEFAULT); auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s", - key_type(key), key->cert->key_id, + sshkey_type(key), key->cert->key_id, (unsigned long long)key->cert->serial, - key_type(key->cert->signature_key), + sshkey_type(key->cert->signature_key), fp == NULL ? "(null)" : fp, extra == NULL ? "" : ", ", extra == NULL ? "" : extra); free(fp); } else { fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT); - auth_info(authctxt, "%s %s%s%s", key_type(key), + auth_info(authctxt, "%s %s%s%s", sshkey_type(key), fp == NULL ? "(null)" : fp, extra == NULL ? "" : ", ", extra == NULL ? "" : extra); free(fp); @@ -612,7 +640,7 @@ match_principals_option(const char *principal_list, struct sshkey_cert *cert) } static int -process_principals(FILE *f, char *file, struct passwd *pw, +process_principals(FILE *f, const char *file, struct passwd *pw, const struct sshkey_cert *cert) { char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts; @@ -650,8 +678,7 @@ process_principals(FILE *f, char *file, struct passwd *pw, for (i = 0; i < cert->nprincipals; i++) { if (strcmp(cp, cert->principals[i]) == 0) { debug3("%s:%lu: matched principal \"%.100s\"", - file == NULL ? "(command)" : file, - linenum, cert->principals[i]); + file, linenum, cert->principals[i]); if (auth_parse_options(pw, line_opts, file, linenum) != 1) continue; @@ -782,7 +809,7 @@ match_principals_command(struct passwd *user_pw, const struct sshkey *key) uid_swapped = 1; temporarily_use_uid(pw); - ok = process_principals(f, NULL, pw, cert); + ok = process_principals(f, "(command)", pw, cert); fclose(f); f = NULL; @@ -814,16 +841,13 @@ match_principals_command(struct passwd *user_pw, const struct sshkey *key) * returns 1 if the key is allowed or 0 otherwise. */ static int -check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) +check_authkeys_file(FILE *f, char *file, struct sshkey *key, struct passwd *pw) { char line[SSH_MAX_PUBKEY_BYTES]; int found_key = 0; u_long linenum = 0; - Key *found; + struct sshkey *found = NULL; - found_key = 0; - - found = NULL; while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) { char *cp, *key_options = NULL, *fp = NULL; const char *reason = NULL; @@ -832,8 +856,10 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) if (found_key) continue; if (found != NULL) - key_free(found); - found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type); + sshkey_free(found); + found = sshkey_new(sshkey_is_cert(key) ? KEY_UNSPEC : key->type); + if (found == NULL) + goto done; auth_clear_options(); /* Skip leading whitespace, empty and comment lines. */ @@ -842,7 +868,7 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) if (!*cp || *cp == '\n' || *cp == '#') continue; - if (key_read(found, &cp) != 1) { + if (sshkey_read(found, &cp) != 0) { /* no key? check if there are options for this key */ int quoted = 0; debug2("user_key_allowed: check options: '%s'", cp); @@ -856,14 +882,14 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) /* Skip remaining whitespace. */ for (; *cp == ' ' || *cp == '\t'; cp++) ; - if (key_read(found, &cp) != 1) { + if (sshkey_read(found, &cp) != 0) { debug2("user_key_allowed: advance: '%s'", cp); /* still no key? advance to next line*/ continue; } } - if (key_is_cert(key)) { - if (!key_equal(found, key->cert->signature_key)) + if (sshkey_is_cert(key)) { + if (!sshkey_equal(found, key->cert->signature_key)) continue; if (auth_parse_options(pw, key_options, file, linenum) != 1) @@ -874,7 +900,7 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) continue; debug("matching CA found: file %s, line %lu, %s %s", - file, linenum, key_type(found), fp); + file, linenum, sshkey_type(found), fp); /* * If the user has specified a list of principals as * a key option, then prefer that list to matching @@ -891,7 +917,7 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) auth_debug_add("%s", reason); continue; } - if (key_cert_check_authority(key, 0, 0, + if (sshkey_cert_check_authority(key, 0, 0, authorized_principals == NULL ? pw->pw_name : NULL, &reason) != 0) goto fail_reason; @@ -900,11 +926,11 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) verbose("Accepted certificate ID \"%s\" (serial %llu) " "signed by %s CA %s via %s", key->cert->key_id, (unsigned long long)key->cert->serial, - key_type(found), fp, file); + sshkey_type(found), fp, file); free(fp); found_key = 1; break; - } else if (key_equal(found, key)) { + } else if (sshkey_equal(found, key)) { if (auth_parse_options(pw, key_options, file, linenum) != 1) continue; @@ -914,14 +940,15 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) continue; debug("matching key found: file %s, line %lu %s %s", - file, linenum, key_type(found), fp); + file, linenum, sshkey_type(found), fp); free(fp); found_key = 1; continue; } } + done: if (found != NULL) - key_free(found); + sshkey_free(found); if (!found_key) debug2("key not found"); return found_key; @@ -929,24 +956,24 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) /* Authenticate a certificate key against TrustedUserCAKeys */ static int -user_cert_trusted_ca(struct passwd *pw, Key *key) +user_cert_trusted_ca(struct passwd *pw, struct sshkey *key) { char *ca_fp, *principals_file = NULL; const char *reason; - int ret = 0, found_principal = 0, use_authorized_principals; + int r, ret = 0, found_principal = 0, use_authorized_principals; - if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL) + if (!sshkey_is_cert(key) || options.trusted_user_ca_keys == NULL) return 0; if ((ca_fp = sshkey_fingerprint(key->cert->signature_key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) return 0; - if (sshkey_in_file(key->cert->signature_key, - options.trusted_user_ca_keys, 1, 0) != 0) { - debug2("%s: CA %s %s is not listed in %s", __func__, - key_type(key->cert->signature_key), ca_fp, - options.trusted_user_ca_keys); + if ((r = sshkey_in_file(key->cert->signature_key, + options.trusted_user_ca_keys, 1, 0)) != 0) { + debug2("%s: CA %s %s is not listed in %s: %s", __func__, + sshkey_type(key->cert->signature_key), ca_fp, + options.trusted_user_ca_keys, ssh_err(r)); goto out; } /* @@ -971,7 +998,7 @@ user_cert_trusted_ca(struct passwd *pw, Key *key) auth_debug_add("%s", reason); goto out; } - if (key_cert_check_authority(key, 0, 1, + if (sshkey_cert_check_authority(key, 0, 1, use_authorized_principals ? NULL : pw->pw_name, &reason) != 0) goto fail_reason; if (auth_cert_options(key, pw, &reason) != 0) @@ -980,7 +1007,7 @@ user_cert_trusted_ca(struct passwd *pw, Key *key) verbose("Accepted certificate ID \"%s\" (serial %llu) signed by " "%s CA %s via %s", key->cert->key_id, (unsigned long long)key->cert->serial, - key_type(key->cert->signature_key), ca_fp, + sshkey_type(key->cert->signature_key), ca_fp, options.trusted_user_ca_keys); ret = 1; @@ -995,7 +1022,7 @@ user_cert_trusted_ca(struct passwd *pw, Key *key) * returns 1 if the key is allowed or 0 otherwise. */ static int -user_key_allowed2(struct passwd *pw, Key *key, char *file) +user_key_allowed2(struct passwd *pw, struct sshkey *key, char *file) { FILE *f; int found_key = 0; @@ -1018,7 +1045,7 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file) * returns 1 if the key is allowed or 0 otherwise. */ static int -user_key_command_allowed2(struct passwd *user_pw, Key *key) +user_key_command_allowed2(struct passwd *user_pw, struct sshkey *key) { FILE *f = NULL; int r, ok, found_key = 0; @@ -1141,14 +1168,15 @@ user_key_command_allowed2(struct passwd *user_pw, Key *key) * Check whether key authenticates and authorises the user. */ int -user_key_allowed(struct passwd *pw, Key *key, int auth_attempt) +user_key_allowed(struct passwd *pw, struct sshkey *key, int auth_attempt) { u_int success, i; char *file; if (auth_key_is_revoked(key)) return 0; - if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key)) + if (sshkey_is_cert(key) && + auth_key_is_revoked(key->cert->signature_key)) return 0; success = user_cert_trusted_ca(pw, key); @@ -1180,9 +1208,10 @@ auth2_record_userkey(Authctxt *authctxt, struct sshkey *key) struct sshkey **tmp; if (authctxt->nprev_userkeys >= INT_MAX || - (tmp = reallocarray(authctxt->prev_userkeys, - authctxt->nprev_userkeys + 1, sizeof(*tmp))) == NULL) - fatal("%s: reallocarray failed", __func__); + (tmp = recallocarray(authctxt->prev_userkeys, + authctxt->nprev_userkeys, authctxt->nprev_userkeys + 1, + sizeof(*tmp))) == NULL) + fatal("%s: recallocarray failed", __func__); authctxt->prev_userkeys = tmp; authctxt->prev_userkeys[authctxt->nprev_userkeys] = key; authctxt->nprev_userkeys++; diff --git a/auth2.c b/auth2.c index 97dd2ef0a..cb4c2fd5d 100644 --- a/auth2.c +++ b/auth2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2.c,v 1.137 2017/02/03 23:05:57 djm Exp $ */ +/* $OpenBSD: auth2.c,v 1.142 2017/05/31 07:00:13 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -87,8 +87,8 @@ Authmethod *authmethods[] = { /* protocol */ -static int input_service_request(int, u_int32_t, void *); -static int input_userauth_request(int, u_int32_t, void *); +static int input_service_request(int, u_int32_t, struct ssh *); +static int input_userauth_request(int, u_int32_t, struct ssh *); /* helper */ static Authmethod *authmethod_lookup(Authctxt *, const char *); @@ -168,16 +168,19 @@ done: void do_authentication2(Authctxt *authctxt) { - dispatch_init(&dispatch_protocol_error); - dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request); - dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt); + struct ssh *ssh = active_state; /* XXX */ + ssh->authctxt = authctxt; /* XXX move to caller */ + ssh_dispatch_init(ssh, &dispatch_protocol_error); + ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_REQUEST, &input_service_request); + ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt->success); + ssh->authctxt = NULL; } /*ARGSUSED*/ static int -input_service_request(int type, u_int32_t seq, void *ctxt) +input_service_request(int type, u_int32_t seq, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; u_int len; int acceptit = 0; char *service = packet_get_cstring(&len); @@ -190,7 +193,7 @@ input_service_request(int type, u_int32_t seq, void *ctxt) if (!authctxt->success) { acceptit = 1; /* now we can handle user-auth requests */ - dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request); } } /* XXX all other service requests are denied */ @@ -210,10 +213,9 @@ input_service_request(int type, u_int32_t seq, void *ctxt) /*ARGSUSED*/ static int -input_userauth_request(int type, u_int32_t seq, void *ctxt) +input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = active_state; /* XXX */ - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; Authmethod *m = NULL; char *user, *service, *method, *style = NULL; int authenticated = 0; @@ -267,12 +269,12 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) authctxt->user, authctxt->service, user, service); } /* reset state */ - auth2_challenge_stop(authctxt); + auth2_challenge_stop(ssh); #ifdef GSSAPI /* XXX move to auth2_gssapi_stop() */ - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); #endif authctxt->postponed = 0; @@ -282,9 +284,9 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) 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); + authenticated = m->userauth(ssh); } - userauth_finish(authctxt, authenticated, method, NULL); + userauth_finish(ssh, authenticated, method, NULL); free(service); free(user); @@ -293,10 +295,10 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) } void -userauth_finish(Authctxt *authctxt, int authenticated, const char *method, +userauth_finish(struct ssh *ssh, int authenticated, const char *method, const char *submethod) { - struct ssh *ssh = active_state; /* XXX */ + Authctxt *authctxt = ssh->authctxt; char *methods; int partial = 0; @@ -352,7 +354,7 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method, if (authenticated == 1) { /* turn off userauth */ - dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore); packet_start(SSH2_MSG_USERAUTH_SUCCESS); packet_send(); packet_write_wait(); diff --git a/authfile.c b/authfile.c index 807d2816e..2f5475715 100644 --- a/authfile.c +++ b/authfile.c @@ -1,4 +1,4 @@ -/* $OpenBSD: authfile.c,v 1.124 2017/04/30 23:10:43 djm Exp $ */ +/* $OpenBSD: authfile.c,v 1.126 2017/05/31 09:15:42 deraadt Exp $ */ /* * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved. * @@ -101,25 +101,13 @@ sshkey_load_file(int fd, struct sshbuf *blob) u_char buf[1024]; size_t len; struct stat st; - int r, dontmax = 0; + int r; 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) return SSH_ERR_INVALID_FORMAT; - /* - * Pre-allocate the buffer used for the key contents and clamp its - * maximum size. This ensures that key contents are never leaked via - * implicit realloc() in the sshbuf code. - */ - if ((st.st_mode & S_IFREG) == 0 || st.st_size <= 0) { - st.st_size = 64*1024; /* 64k ought to be enough for anybody. :) */ - dontmax = 1; - } - if ((r = sshbuf_allocate(blob, st.st_size)) != 0 || - (dontmax && (r = sshbuf_set_max_size(blob, st.st_size)) != 0)) - return r; for (;;) { if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) { if (errno == EPIPE) @@ -326,50 +314,48 @@ sshkey_try_load_public(struct sshkey *k, const char *filename, char **commentp) return SSH_ERR_INVALID_FORMAT; } -/* load public key from ssh v1 private or any pubkey file */ +/* load public key from any pubkey file */ int sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp) { struct sshkey *pub = NULL; - char file[PATH_MAX]; - int r, fd; + char *file = NULL; + int r; if (keyp != NULL) *keyp = NULL; if (commentp != NULL) *commentp = NULL; - /* XXX should load file once and attempt to parse each format */ - - if ((fd = open(filename, O_RDONLY)) < 0) - goto skip; - close(fd); - - /* 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) + if (keyp != NULL) { *keyp = pub; - return 0; + pub = NULL; + } + r = 0; + goto out; } sshkey_free(pub); - - skip: /* try .pub suffix */ - if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) + if (asprintf(&file, "%s.pub", filename) == -1) 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)) && - (r = sshkey_try_load_public(pub, file, commentp)) == 0) { - if (keyp != NULL) - *keyp = pub; - return 0; + if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; } + if ((r = sshkey_try_load_public(pub, file, commentp)) == 0) { + if (keyp != NULL) { + *keyp = pub; + pub = NULL; + } + r = 0; + } + out: + free(file); sshkey_free(pub); - return r; } diff --git a/bitmap.c b/bitmap.c index 3d7aa1379..5089b0407 100644 --- a/bitmap.c +++ b/bitmap.c @@ -87,10 +87,10 @@ reserve(struct bitmap *b, u_int n) return -1; /* invalid */ nlen = (n / BITMAP_BITS) + 1; if (b->len < nlen) { - if ((tmp = reallocarray(b->d, nlen, BITMAP_BYTES)) == NULL) + if ((tmp = recallocarray(b->d, b->len, + nlen, BITMAP_BYTES)) == NULL) return -1; b->d = tmp; - memset(b->d + b->len, 0, (nlen - b->len) * BITMAP_BYTES); b->len = nlen; } return 0; @@ -189,7 +189,7 @@ bitmap_from_string(struct bitmap *b, const void *p, size_t l) { int r; size_t i, offset, shift; - u_char *s = (u_char *)p; + const u_char *s = (const u_char *)p; if (l > BITMAP_MAX / 8) return -1; diff --git a/channels.c b/channels.c index b40ce53a3..4b21c2182 100644 --- a/channels.c +++ b/channels.c @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.c,v 1.359 2017/04/30 23:28:41 djm Exp $ */ +/* $OpenBSD: channels.c,v 1.365 2017/05/31 08:58:52 deraadt Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -242,8 +242,6 @@ channel_lookup(int id) case SSH_CHANNEL_DYNAMIC: case SSH_CHANNEL_OPENING: case SSH_CHANNEL_OPEN: - case SSH_CHANNEL_INPUT_DRAINING: - case SSH_CHANNEL_OUTPUT_DRAINING: case SSH_CHANNEL_ABANDONED: case SSH_CHANNEL_MUX_PROXY: return (c); @@ -481,8 +479,6 @@ channel_free(Channel *c) debug3("channel %d: status: %s", c->self, s); free(s); - if (c->sock != -1) - shutdown(c->sock, SHUT_RDWR); channel_close_fds(c); buffer_free(&c->input); buffer_free(&c->output); @@ -614,9 +610,6 @@ channel_still_open(void) case SSH_CHANNEL_MUX_CLIENT: case SSH_CHANNEL_MUX_PROXY: return 1; - case SSH_CHANNEL_INPUT_DRAINING: - case SSH_CHANNEL_OUTPUT_DRAINING: - fatal("cannot happen: OUT_DRAIN"); default: fatal("%s: bad channel type %d", __func__, c->type); /* NOTREACHED */ @@ -657,9 +650,6 @@ channel_find_open(void) case SSH_CHANNEL_OPEN: case SSH_CHANNEL_X11_OPEN: return i; - case SSH_CHANNEL_INPUT_DRAINING: - case SSH_CHANNEL_OUTPUT_DRAINING: - fatal("cannot happen: OUT_DRAIN"); default: fatal("%s: bad channel type %d", __func__, c->type); /* NOTREACHED */ @@ -706,8 +696,6 @@ channel_open_message(void) case SSH_CHANNEL_DYNAMIC: case SSH_CHANNEL_OPEN: case SSH_CHANNEL_X11_OPEN: - case SSH_CHANNEL_INPUT_DRAINING: - case SSH_CHANNEL_OUTPUT_DRAINING: case SSH_CHANNEL_MUX_PROXY: case SSH_CHANNEL_MUX_CLIENT: snprintf(buf, sizeof buf, @@ -1085,9 +1073,11 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) buffer_get(&c->input, (char *)&s4_req.dest_addr, 4); have = buffer_len(&c->input); p = (char *)buffer_ptr(&c->input); - if (memchr(p, '\0', have) == NULL) - fatal("channel %d: decode socks4: user not nul terminated", + if (memchr(p, '\0', have) == NULL) { + error("channel %d: decode socks4: user not nul terminated", c->self); + return -1; + } len = strlen(p); debug2("channel %d: decode socks4: user %s/%d", c->self, p, len); len++; /* trailing '\0' */ @@ -1105,13 +1095,15 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) } else { /* SOCKS4A: two strings */ have = buffer_len(&c->input); p = (char *)buffer_ptr(&c->input); + if (memchr(p, '\0', have) == NULL) { + error("channel %d: decode socks4a: host not nul " + "terminated", c->self); + return -1; + } len = strlen(p); debug2("channel %d: decode socks4a: host %s/%d", c->self, p, len); len++; /* trailing '\0' */ - if (len > have) - fatal("channel %d: decode socks4a: len %d > have %d", - c->self, len, have); if (len > NI_MAXHOST) { error("channel %d: hostname \"%.100s\" too long", c->self, p); @@ -2406,9 +2398,8 @@ channel_proxy_downstream(Channel *downstream) * replaces local (proxy) channel ID with downstream channel ID. */ int -channel_proxy_upstream(Channel *c, int type, u_int32_t seq, void *ctxt) +channel_proxy_upstream(Channel *c, int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = active_state; struct sshbuf *b = NULL; Channel *downstream; const u_char *cp = NULL; @@ -2488,7 +2479,7 @@ channel_proxy_upstream(Channel *c, int type, u_int32_t seq, void *ctxt) /* ARGSUSED */ int -channel_input_data(int type, u_int32_t seq, void *ctxt) +channel_input_data(int type, u_int32_t seq, struct ssh *ssh) { int id; const u_char *data; @@ -2500,7 +2491,7 @@ channel_input_data(int type, u_int32_t seq, void *ctxt) c = channel_lookup(id); if (c == NULL) packet_disconnect("Received data for nonexistent channel %d.", id); - if (channel_proxy_upstream(c, type, seq, ctxt)) + if (channel_proxy_upstream(c, type, seq, ssh)) return 0; /* Ignore any data for non-open channels (might happen on close) */ @@ -2548,7 +2539,7 @@ channel_input_data(int type, u_int32_t seq, void *ctxt) /* ARGSUSED */ int -channel_input_extended_data(int type, u_int32_t seq, void *ctxt) +channel_input_extended_data(int type, u_int32_t seq, struct ssh *ssh) { int id; char *data; @@ -2561,7 +2552,7 @@ channel_input_extended_data(int type, u_int32_t seq, void *ctxt) if (c == NULL) packet_disconnect("Received extended_data for bad channel %d.", id); - if (channel_proxy_upstream(c, type, seq, ctxt)) + if (channel_proxy_upstream(c, type, seq, ssh)) return 0; if (c->type != SSH_CHANNEL_OPEN) { logit("channel %d: ext data for non open", id); @@ -2598,7 +2589,7 @@ channel_input_extended_data(int type, u_int32_t seq, void *ctxt) /* ARGSUSED */ int -channel_input_ieof(int type, u_int32_t seq, void *ctxt) +channel_input_ieof(int type, u_int32_t seq, struct ssh *ssh) { int id; Channel *c; @@ -2608,7 +2599,7 @@ channel_input_ieof(int type, u_int32_t seq, void *ctxt) c = channel_lookup(id); if (c == NULL) packet_disconnect("Received ieof for nonexistent channel %d.", id); - if (channel_proxy_upstream(c, type, seq, ctxt)) + if (channel_proxy_upstream(c, type, seq, ssh)) return 0; chan_rcvd_ieof(c); @@ -2622,17 +2613,16 @@ channel_input_ieof(int type, u_int32_t seq, void *ctxt) return 0; } -/* proto version 1.5 overloads CLOSE_CONFIRMATION with OCLOSE */ /* ARGSUSED */ int -channel_input_oclose(int type, u_int32_t seq, void *ctxt) +channel_input_oclose(int type, u_int32_t seq, struct ssh *ssh) { int id = packet_get_int(); Channel *c = channel_lookup(id); if (c == NULL) packet_disconnect("Received oclose for nonexistent channel %d.", id); - if (channel_proxy_upstream(c, type, seq, ctxt)) + if (channel_proxy_upstream(c, type, seq, ssh)) return 0; packet_check_eom(); chan_rcvd_oclose(c); @@ -2641,27 +2631,7 @@ channel_input_oclose(int type, u_int32_t seq, void *ctxt) /* ARGSUSED */ int -channel_input_close_confirmation(int type, u_int32_t seq, void *ctxt) -{ - int id = packet_get_int(); - Channel *c = channel_lookup(id); - - if (c == NULL) - packet_disconnect("Received close confirmation for " - "out-of-range channel %d.", id); - if (channel_proxy_upstream(c, type, seq, ctxt)) - return 0; - packet_check_eom(); - if (c->type != SSH_CHANNEL_CLOSED && c->type != SSH_CHANNEL_ABANDONED) - packet_disconnect("Received close confirmation for " - "non-closed channel %d (type %d).", id, c->type); - channel_free(c); - return 0; -} - -/* ARGSUSED */ -int -channel_input_open_confirmation(int type, u_int32_t seq, void *ctxt) +channel_input_open_confirmation(int type, u_int32_t seq, struct ssh *ssh) { int id, remote_id; Channel *c; @@ -2672,7 +2642,7 @@ channel_input_open_confirmation(int type, u_int32_t seq, void *ctxt) if (c==NULL) packet_disconnect("Received open confirmation for " "unknown channel %d.", id); - if (channel_proxy_upstream(c, type, seq, ctxt)) + if (channel_proxy_upstream(c, type, seq, ssh)) return 0; if (c->type != SSH_CHANNEL_OPENING) packet_disconnect("Received open confirmation for " @@ -2713,7 +2683,7 @@ reason2txt(int reason) /* ARGSUSED */ int -channel_input_open_failure(int type, u_int32_t seq, void *ctxt) +channel_input_open_failure(int type, u_int32_t seq, struct ssh *ssh) { int id, reason; char *msg = NULL, *lang = NULL; @@ -2725,7 +2695,7 @@ channel_input_open_failure(int type, u_int32_t seq, void *ctxt) if (c==NULL) packet_disconnect("Received open failure for " "unknown channel %d.", id); - if (channel_proxy_upstream(c, type, seq, ctxt)) + if (channel_proxy_upstream(c, type, seq, ssh)) return 0; if (c->type != SSH_CHANNEL_OPENING) packet_disconnect("Received open failure for " @@ -2752,7 +2722,7 @@ channel_input_open_failure(int type, u_int32_t seq, void *ctxt) /* ARGSUSED */ int -channel_input_window_adjust(int type, u_int32_t seq, void *ctxt) +channel_input_window_adjust(int type, u_int32_t seq, struct ssh *ssh) { Channel *c; int id; @@ -2766,7 +2736,7 @@ channel_input_window_adjust(int type, u_int32_t seq, void *ctxt) logit("Received window adjust for non-open channel %d.", id); return 0; } - if (channel_proxy_upstream(c, type, seq, ctxt)) + if (channel_proxy_upstream(c, type, seq, ssh)) return 0; adjust = packet_get_int(); packet_check_eom(); @@ -2780,7 +2750,7 @@ channel_input_window_adjust(int type, u_int32_t seq, void *ctxt) /* ARGSUSED */ int -channel_input_status_confirm(int type, u_int32_t seq, void *ctxt) +channel_input_status_confirm(int type, u_int32_t seq, struct ssh *ssh) { Channel *c; struct channel_confirm *cc; @@ -2796,7 +2766,7 @@ channel_input_status_confirm(int type, u_int32_t seq, void *ctxt) logit("channel_input_status_confirm: %d: unknown", id); return 0; } - if (channel_proxy_upstream(c, type, seq, ctxt)) + if (channel_proxy_upstream(c, type, seq, ssh)) return 0; packet_check_eom(); if ((cc = TAILQ_FIRST(&c->status_confirms)) == NULL) @@ -3224,7 +3194,7 @@ channel_cancel_lport_listener(struct Forward *fwd, int cport, struct ForwardOpti return channel_cancel_lport_listener_tcpip(fwd->listen_host, fwd->listen_port, cport, fwd_opts); } -/* protocol local port fwd, used by ssh (and sshd in v1) */ +/* protocol local port fwd, used by ssh */ int channel_setup_local_fwd_listener(struct Forward *fwd, struct ForwardOptions *fwd_opts) { diff --git a/channels.h b/channels.h index 4e9b77de1..36e5363aa 100644 --- a/channels.h +++ b/channels.h @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.h,v 1.123 2017/04/30 23:28:41 djm Exp $ */ +/* $OpenBSD: channels.h,v 1.126 2017/05/30 14:23:52 markus Exp $ */ /* * Author: Tatu Ylonen @@ -46,8 +46,6 @@ #define SSH_CHANNEL_CLOSED 5 /* waiting for close confirmation */ #define SSH_CHANNEL_AUTH_SOCKET 6 /* authentication socket */ #define SSH_CHANNEL_X11_OPEN 7 /* reading first X11 packet */ -#define SSH_CHANNEL_INPUT_DRAINING 8 /* sending remaining data to conn */ -#define SSH_CHANNEL_OUTPUT_DRAINING 9 /* sending remaining data to app */ #define SSH_CHANNEL_LARVAL 10 /* larval session */ #define SSH_CHANNEL_RPORT_LISTENER 11 /* Listening to a R-style port */ #define SSH_CHANNEL_CONNECTING 12 @@ -63,6 +61,7 @@ #define CHANNEL_CANCEL_PORT_STATIC -1 +struct ssh; struct Channel; typedef struct Channel Channel; @@ -234,19 +233,19 @@ void channel_send_window_changes(void); /* mux proxy support */ int channel_proxy_downstream(Channel *mc); -int channel_proxy_upstream(Channel *, int, u_int32_t, void *); +int channel_proxy_upstream(Channel *, int, u_int32_t, struct ssh *); /* protocol handler */ -int channel_input_close_confirmation(int, u_int32_t, void *); -int channel_input_data(int, u_int32_t, void *); -int channel_input_extended_data(int, u_int32_t, void *); -int channel_input_ieof(int, u_int32_t, void *); -int channel_input_oclose(int, u_int32_t, void *); -int channel_input_open_confirmation(int, u_int32_t, void *); -int channel_input_open_failure(int, u_int32_t, void *); -int channel_input_window_adjust(int, u_int32_t, void *); -int channel_input_status_confirm(int, u_int32_t, void *); +int channel_input_data(int, u_int32_t, struct ssh *); +int channel_input_extended_data(int, u_int32_t, struct ssh *); +int channel_input_ieof(int, u_int32_t, struct ssh *); +int channel_input_oclose(int, u_int32_t, struct ssh *); +int channel_input_open_confirmation(int, u_int32_t, struct ssh *); +int channel_input_open_failure(int, u_int32_t, struct ssh *); +int channel_input_port_open(int, u_int32_t, struct ssh *); +int channel_input_window_adjust(int, u_int32_t, struct ssh *); +int channel_input_status_confirm(int, u_int32_t, struct ssh *); /* file descriptor handling (read/write) */ diff --git a/clientloop.c b/clientloop.c index a9ec39246..284b08e65 100644 --- a/clientloop.c +++ b/clientloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.c,v 1.296 2017/05/03 21:08:09 naddy Exp $ */ +/* $OpenBSD: clientloop.c,v 1.299 2017/05/31 09:15:42 deraadt Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -459,7 +459,7 @@ client_check_window_change(void) } static int -client_global_request_reply(int type, u_int32_t seq, void *ctxt) +client_global_request_reply(int type, u_int32_t seq, struct ssh *ssh) { struct global_confirm *gc; @@ -1171,7 +1171,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, static void client_process_buffered_input_packets(void) { - dispatch_run(DISPATCH_NONBLOCK, &quit_pending, active_state); + ssh_dispatch_run_fatal(active_state, DISPATCH_NONBLOCK, &quit_pending); } /* scan buf[] for '~' before sending data to the peer */ @@ -1646,7 +1646,7 @@ client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun) /* XXXX move to generic input handler */ static int -client_input_channel_open(int type, u_int32_t seq, void *ctxt) +client_input_channel_open(int type, u_int32_t seq, struct ssh *ssh) { Channel *c = NULL; char *ctype; @@ -1702,7 +1702,7 @@ client_input_channel_open(int type, u_int32_t seq, void *ctxt) } static int -client_input_channel_req(int type, u_int32_t seq, void *ctxt) +client_input_channel_req(int type, u_int32_t seq, struct ssh *ssh) { Channel *c = NULL; int exitval, id, reply, success = 0; @@ -1710,7 +1710,7 @@ client_input_channel_req(int type, u_int32_t seq, void *ctxt) id = packet_get_int(); c = channel_lookup(id); - if (channel_proxy_upstream(c, type, seq, ctxt)) + if (channel_proxy_upstream(c, type, seq, ssh)) return 0; rtype = packet_get_string(NULL); reply = packet_get_char(); @@ -1816,9 +1816,9 @@ hostkeys_find(struct hostkey_foreach_line *l, void *_ctx) /* This line contained a key that not offered by the server */ debug3("%s: deprecated %s key at %s:%ld", __func__, sshkey_ssh_name(l->key), l->path, l->linenum); - if ((tmp = reallocarray(ctx->old_keys, ctx->nold + 1, + if ((tmp = recallocarray(ctx->old_keys, ctx->nold, ctx->nold + 1, sizeof(*ctx->old_keys))) == NULL) - fatal("%s: reallocarray failed nold = %zu", + fatal("%s: recallocarray failed nold = %zu", __func__, ctx->nold); ctx->old_keys = tmp; ctx->old_keys[ctx->nold++] = l->key; @@ -2050,9 +2050,9 @@ client_input_hostkeys(void) } } /* Key is good, record it */ - if ((tmp = reallocarray(ctx->keys, ctx->nkeys + 1, + if ((tmp = recallocarray(ctx->keys, ctx->nkeys, ctx->nkeys + 1, sizeof(*ctx->keys))) == NULL) - fatal("%s: reallocarray failed nkeys = %zu", + fatal("%s: recallocarray failed nkeys = %zu", __func__, ctx->nkeys); ctx->keys = tmp; ctx->keys[ctx->nkeys++] = key; @@ -2140,7 +2140,7 @@ client_input_hostkeys(void) } static int -client_input_global_request(int type, u_int32_t seq, void *ctxt) +client_input_global_request(int type, u_int32_t seq, struct ssh *ssh) { char *rtype; int want_reply; diff --git a/configure.ac b/configure.ac index 5cfea38c0..46f7d4957 100644 --- a/configure.ac +++ b/configure.ac @@ -1678,6 +1678,7 @@ AC_CHECK_FUNCS([ \ getgrouplist \ getnameinfo \ getopt \ + getpagesize \ getpeereid \ getpeerucred \ getpgid \ @@ -1708,6 +1709,7 @@ AC_CHECK_FUNCS([ \ readpassphrase \ reallocarray \ recvmsg \ + recallocarray \ rresvport_af \ sendmsg \ setdtablesize \ @@ -3162,7 +3164,8 @@ AC_RUN_IFELSE( select_works_with_rlimit=yes], [AC_MSG_RESULT([no]) select_works_with_rlimit=no], - [AC_MSG_WARN([cross compiling: assuming yes])] + [AC_MSG_WARN([cross compiling: assuming yes]) + select_works_with_rlimit=yes] ) AC_MSG_CHECKING([if setrlimit(RLIMIT_NOFILE,{0,0}) works]) @@ -3188,7 +3191,8 @@ AC_RUN_IFELSE( rlimit_nofile_zero_works=yes], [AC_MSG_RESULT([no]) rlimit_nofile_zero_works=no], - [AC_MSG_WARN([cross compiling: assuming yes])] + [AC_MSG_WARN([cross compiling: assuming yes]) + rlimit_nofile_zero_works=yes] ) AC_MSG_CHECKING([if setrlimit RLIMIT_FSIZE works]) diff --git a/dispatch.c b/dispatch.c index 7ef9a38c7..0b3ea614e 100644 --- a/dispatch.c +++ b/dispatch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dispatch.c,v 1.29 2017/04/30 23:28:42 djm Exp $ */ +/* $OpenBSD: dispatch.c,v 1.31 2017/05/31 07:00:13 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -38,9 +38,8 @@ #include "ssherr.h" int -dispatch_protocol_error(int type, u_int32_t seq, void *ctx) +dispatch_protocol_error(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = active_state; /* XXX */ int r; logit("dispatch_protocol_error: type %d seq %u", type, seq); @@ -53,7 +52,7 @@ dispatch_protocol_error(int type, u_int32_t seq, void *ctx) } int -dispatch_protocol_ignore(int type, u_int32_t seq, void *ssh) +dispatch_protocol_ignore(int type, u_int32_t seq, struct ssh *ssh) { logit("dispatch_protocol_ignore: type %d seq %u", type, seq); return 0; @@ -86,8 +85,7 @@ ssh_dispatch_set(struct ssh *ssh, int type, dispatch_fn *fn) } int -ssh_dispatch_run(struct ssh *ssh, int mode, volatile sig_atomic_t *done, - void *ctxt) +ssh_dispatch_run(struct ssh *ssh, int mode, volatile sig_atomic_t *done) { int r; u_char type; @@ -112,8 +110,7 @@ ssh_dispatch_run(struct ssh *ssh, int mode, volatile sig_atomic_t *done, ssh->dispatch_skip_packets--; continue; } - /* XXX 'ssh' will replace 'ctxt' later */ - r = (*ssh->dispatch[type])(type, seqnr, ctxt); + r = (*ssh->dispatch[type])(type, seqnr, ssh); if (r != 0) return r; } else { @@ -129,11 +126,10 @@ ssh_dispatch_run(struct ssh *ssh, int mode, volatile sig_atomic_t *done, } void -ssh_dispatch_run_fatal(struct ssh *ssh, int mode, volatile sig_atomic_t *done, - void *ctxt) +ssh_dispatch_run_fatal(struct ssh *ssh, int mode, volatile sig_atomic_t *done) { int r; - if ((r = ssh_dispatch_run(ssh, mode, done, ctxt)) != 0) + if ((r = ssh_dispatch_run(ssh, mode, done)) != 0) sshpkt_fatal(ssh, __func__, r); } diff --git a/dispatch.h b/dispatch.h index cd51dbc0b..17a6f3db6 100644 --- a/dispatch.h +++ b/dispatch.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dispatch.h,v 1.12 2015/01/19 20:07:45 markus Exp $ */ +/* $OpenBSD: dispatch.h,v 1.14 2017/05/31 07:00:13 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -36,15 +36,15 @@ enum { struct ssh; -typedef int dispatch_fn(int, u_int32_t, void *); +typedef int dispatch_fn(int, u_int32_t, struct ssh *); -int dispatch_protocol_error(int, u_int32_t, void *); -int dispatch_protocol_ignore(int, u_int32_t, void *); +int dispatch_protocol_error(int, u_int32_t, struct ssh *); +int dispatch_protocol_ignore(int, u_int32_t, struct ssh *); void ssh_dispatch_init(struct ssh *, dispatch_fn *); void ssh_dispatch_set(struct ssh *, int, dispatch_fn *); void ssh_dispatch_range(struct ssh *, u_int, u_int, dispatch_fn *); -int ssh_dispatch_run(struct ssh *, int, volatile sig_atomic_t *, void *); -void ssh_dispatch_run_fatal(struct ssh *, int, volatile sig_atomic_t *, void *); +int ssh_dispatch_run(struct ssh *, int, volatile sig_atomic_t *); +void ssh_dispatch_run_fatal(struct ssh *, int, volatile sig_atomic_t *); #define dispatch_init(dflt) \ ssh_dispatch_init(active_state, (dflt)) @@ -52,7 +52,5 @@ void ssh_dispatch_run_fatal(struct ssh *, int, volatile sig_atomic_t *, void *); ssh_dispatch_range(active_state, (from), (to), (fn)) #define dispatch_set(type, fn) \ ssh_dispatch_set(active_state, (type), (fn)) -#define dispatch_run(mode, done, ctxt) \ - ssh_dispatch_run_fatal(active_state, (mode), (done), (ctxt)) #endif diff --git a/hostfile.c b/hostfile.c index 4b5483fb7..6a485d1f7 100644 --- a/hostfile.c +++ b/hostfile.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hostfile.c,v 1.70 2017/04/30 23:18:44 djm Exp $ */ +/* $OpenBSD: hostfile.c,v 1.71 2017/05/31 09:15:42 deraadt Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -251,7 +251,7 @@ record_hostkey(struct hostkey_foreach_line *l, void *_ctx) l->marker == MRK_NONE ? "" : (l->marker == MRK_CA ? "ca " : "revoked "), sshkey_type(l->key), l->path, l->linenum); - if ((tmp = reallocarray(hostkeys->entries, + if ((tmp = recallocarray(hostkeys->entries, hostkeys->num_entries, hostkeys->num_entries + 1, sizeof(*hostkeys->entries))) == NULL) return SSH_ERR_ALLOC_FAIL; hostkeys->entries = tmp; diff --git a/kex.c b/kex.c index 9a40759c1..cf44fbc04 100644 --- a/kex.c +++ b/kex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.132 2017/04/30 23:10:43 djm Exp $ */ +/* $OpenBSD: kex.c,v 1.133 2017/05/30 14:23:52 markus Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * @@ -56,7 +56,7 @@ /* prototype */ static int kex_choose_conf(struct ssh *); -static int kex_input_newkeys(int, u_int32_t, void *); +static int kex_input_newkeys(int, u_int32_t, struct ssh *); static const char *proposal_names[PROPOSAL_MAX] = { "KEX algorithms", @@ -315,9 +315,8 @@ kex_prop_free(char **proposal) /* ARGSUSED */ static int -kex_protocol_error(int type, u_int32_t seq, void *ctxt) +kex_protocol_error(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = active_state; /* XXX */ int r; error("kex protocol error: type %d seq %u", type, seq); @@ -375,9 +374,8 @@ kex_send_newkeys(struct ssh *ssh) } int -kex_input_ext_info(int type, u_int32_t seq, void *ctxt) +kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; u_int32_t i, ninfo; char *name, *val, *found; @@ -414,9 +412,8 @@ kex_input_ext_info(int type, u_int32_t seq, void *ctxt) } static int -kex_input_newkeys(int type, u_int32_t seq, void *ctxt) +kex_input_newkeys(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; int r; @@ -467,9 +464,8 @@ kex_send_kexinit(struct ssh *ssh) /* ARGSUSED */ int -kex_input_kexinit(int type, u_int32_t seq, void *ctxt) +kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; const u_char *ptr; u_int i; diff --git a/kex.h b/kex.h index 13b22351f..01bb3986a 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.82 2017/05/03 21:08:09 naddy Exp $ */ +/* $OpenBSD: kex.h,v 1.83 2017/05/30 14:23:52 markus Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -181,8 +181,8 @@ int kex_prop2buf(struct sshbuf *, char *proposal[PROPOSAL_MAX]); void kex_prop_free(char **); int kex_send_kexinit(struct ssh *); -int kex_input_kexinit(int, u_int32_t, void *); -int kex_input_ext_info(int, u_int32_t, void *); +int kex_input_kexinit(int, u_int32_t, struct ssh *); +int kex_input_ext_info(int, u_int32_t, struct ssh *); int kex_derive_keys(struct ssh *, u_char *, u_int, const struct sshbuf *); int kex_derive_keys_bn(struct ssh *, u_char *, u_int, const BIGNUM *); int kex_send_newkeys(struct ssh *); diff --git a/kexc25519c.c b/kexc25519c.c index b7ef65dc3..e488013e9 100644 --- a/kexc25519c.c +++ b/kexc25519c.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519c.c,v 1.7 2015/01/26 06:10:03 djm Exp $ */ +/* $OpenBSD: kexc25519c.c,v 1.8 2017/05/31 04:17:12 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -44,7 +44,7 @@ #include "ssherr.h" static int -input_kex_c25519_reply(int type, u_int32_t seq, void *ctxt); +input_kex_c25519_reply(int type, u_int32_t seq, struct ssh *ssh); int kexc25519_client(struct ssh *ssh) @@ -69,9 +69,8 @@ kexc25519_client(struct ssh *ssh) } static int -input_kex_c25519_reply(int type, u_int32_t seq, void *ctxt) +input_kex_c25519_reply(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; struct sshkey *server_host_key = NULL; struct sshbuf *shared_secret = NULL; diff --git a/kexc25519s.c b/kexc25519s.c index 4e77622b0..0a008d447 100644 --- a/kexc25519s.c +++ b/kexc25519s.c @@ -41,7 +41,7 @@ #include "sshbuf.h" #include "ssherr.h" -static int input_kex_c25519_init(int, u_int32_t, void *); +static int input_kex_c25519_init(int, u_int32_t, struct ssh *); int kexc25519_server(struct ssh *ssh) @@ -52,9 +52,8 @@ kexc25519_server(struct ssh *ssh) } static int -input_kex_c25519_init(int type, u_int32_t seq, void *ctxt) +input_kex_c25519_init(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; struct sshkey *server_host_private, *server_host_public; struct sshbuf *shared_secret = NULL; diff --git a/kexdhc.c b/kexdhc.c index ad3975f09..9864ee2ec 100644 --- a/kexdhc.c +++ b/kexdhc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdhc.c,v 1.19 2016/05/02 10:26:04 djm Exp $ */ +/* $OpenBSD: kexdhc.c,v 1.20 2017/05/30 14:23:52 markus Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -49,7 +49,7 @@ #include "ssherr.h" #include "sshbuf.h" -static int input_kex_dh(int, u_int32_t, void *); +static int input_kex_dh(int, u_int32_t, struct ssh *); int kexdh_client(struct ssh *ssh) @@ -100,9 +100,8 @@ kexdh_client(struct ssh *ssh) } static int -input_kex_dh(int type, u_int32_t seq, void *ctxt) +input_kex_dh(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; BIGNUM *dh_server_pub = NULL, *shared_secret = NULL; struct sshkey *server_host_key = NULL; diff --git a/kexdhs.c b/kexdhs.c index 108f66427..81ce56d7a 100644 --- a/kexdhs.c +++ b/kexdhs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdhs.c,v 1.24 2016/05/02 10:26:04 djm Exp $ */ +/* $OpenBSD: kexdhs.c,v 1.25 2017/05/30 14:23:52 markus Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -49,7 +49,7 @@ #include "ssherr.h" #include "sshbuf.h" -static int input_kex_dh_init(int, u_int32_t, void *); +static int input_kex_dh_init(int, u_int32_t, struct ssh *); int kexdh_server(struct ssh *ssh) @@ -91,9 +91,8 @@ kexdh_server(struct ssh *ssh) } int -input_kex_dh_init(int type, u_int32_t seq, void *ctxt) +input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; struct sshkey *server_host_public, *server_host_private; diff --git a/kexecdhc.c b/kexecdhc.c index 90220ce82..d8a8b660f 100644 --- a/kexecdhc.c +++ b/kexecdhc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdhc.c,v 1.10 2015/01/26 06:10:03 djm Exp $ */ +/* $OpenBSD: kexecdhc.c,v 1.11 2017/05/30 14:23:52 markus Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -49,7 +49,7 @@ #include "ssherr.h" #include "sshbuf.h" -static int input_kex_ecdh_reply(int, u_int32_t, void *); +static int input_kex_ecdh_reply(int, u_int32_t, struct ssh *); int kexecdh_client(struct ssh *ssh) @@ -95,9 +95,8 @@ kexecdh_client(struct ssh *ssh) } static int -input_kex_ecdh_reply(int type, u_int32_t seq, void *ctxt) +input_kex_ecdh_reply(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; const EC_GROUP *group; EC_POINT *server_public = NULL; diff --git a/kexecdhs.c b/kexecdhs.c index ccdbf70b1..dc24a3af6 100644 --- a/kexecdhs.c +++ b/kexecdhs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdhs.c,v 1.15 2015/12/04 16:41:28 markus Exp $ */ +/* $OpenBSD: kexecdhs.c,v 1.16 2017/05/30 14:23:52 markus Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -47,7 +47,7 @@ #include "ssherr.h" #include "sshbuf.h" -static int input_kex_ecdh_init(int, u_int32_t, void *); +static int input_kex_ecdh_init(int, u_int32_t, struct ssh *); int kexecdh_server(struct ssh *ssh) @@ -58,9 +58,8 @@ kexecdh_server(struct ssh *ssh) } static int -input_kex_ecdh_init(int type, u_int32_t seq, void *ctxt) +input_kex_ecdh_init(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; EC_POINT *client_public; EC_KEY *server_key = NULL; diff --git a/kexgexc.c b/kexgexc.c index b881c4e97..cd1128752 100644 --- a/kexgexc.c +++ b/kexgexc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexc.c,v 1.24 2017/05/16 16:56:15 djm Exp $ */ +/* $OpenBSD: kexgexc.c,v 1.25 2017/05/30 14:23:52 markus Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -51,8 +51,8 @@ #include "sshbuf.h" #include "misc.h" -static int input_kex_dh_gex_group(int, u_int32_t, void *); -static int input_kex_dh_gex_reply(int, u_int32_t, void *); +static int input_kex_dh_gex_group(int, u_int32_t, struct ssh *); +static int input_kex_dh_gex_reply(int, u_int32_t, struct ssh *); int kexgex_client(struct ssh *ssh) @@ -89,9 +89,8 @@ kexgex_client(struct ssh *ssh) } static int -input_kex_dh_gex_group(int type, u_int32_t seq, void *ctxt) +input_kex_dh_gex_group(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; BIGNUM *p = NULL, *g = NULL; int r, bits; @@ -143,9 +142,8 @@ out: } static int -input_kex_dh_gex_reply(int type, u_int32_t seq, void *ctxt) +input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; BIGNUM *dh_server_pub = NULL, *shared_secret = NULL; struct sshkey *server_host_key = NULL; diff --git a/kexgexs.c b/kexgexs.c index 449603592..c5dd00578 100644 --- a/kexgexs.c +++ b/kexgexs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexs.c,v 1.30 2016/09/12 01:22:38 deraadt Exp $ */ +/* $OpenBSD: kexgexs.c,v 1.31 2017/05/30 14:23:52 markus Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -54,8 +54,8 @@ #include "sshbuf.h" #include "misc.h" -static int input_kex_dh_gex_request(int, u_int32_t, void *); -static int input_kex_dh_gex_init(int, u_int32_t, void *); +static int input_kex_dh_gex_request(int, u_int32_t, struct ssh *); +static int input_kex_dh_gex_init(int, u_int32_t, struct ssh *); int kexgex_server(struct ssh *ssh) @@ -67,9 +67,8 @@ kexgex_server(struct ssh *ssh) } static int -input_kex_dh_gex_request(int type, u_int32_t seq, void *ctxt) +input_kex_dh_gex_request(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; int r; u_int min = 0, max = 0, nbits = 0; @@ -120,9 +119,8 @@ input_kex_dh_gex_request(int type, u_int32_t seq, void *ctxt) } static int -input_kex_dh_gex_init(int type, u_int32_t seq, void *ctxt) +input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; struct sshkey *server_host_public, *server_host_private; diff --git a/key.c b/key.c index 93f4ccb24..6e338c495 100644 --- a/key.c +++ b/key.c @@ -1,4 +1,4 @@ -/* $OpenBSD: key.c,v 1.130 2016/05/02 09:36:42 djm Exp $ */ +/* $OpenBSD: key.c,v 1.131 2017/05/30 14:16:41 markus Exp $ */ /* * placed in the public domain */ @@ -20,68 +20,6 @@ #include "log.h" #include "authfile.h" -void -key_add_private(Key *k) -{ - int r; - - if ((r = sshkey_add_private(k)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); -} - -Key * -key_new_private(int type) -{ - Key *ret = NULL; - - if ((ret = sshkey_new_private(type)) == NULL) - fatal("%s: failed", __func__); - return ret; -} - -int -key_read(Key *ret, char **cpp) -{ - return sshkey_read(ret, cpp) == 0 ? 1 : -1; -} - -int -key_write(const Key *key, FILE *f) -{ - return sshkey_write(key, f) == 0 ? 1 : 0; -} - -Key * -key_generate(int type, u_int bits) -{ - int r; - Key *ret = NULL; - - if ((r = sshkey_generate(type, bits, &ret)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); - return ret; -} - -void -key_cert_copy(const Key *from_key, Key *to_key) -{ - int r; - - if ((r = sshkey_cert_copy(from_key, to_key)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); -} - -Key * -key_from_private(const Key *k) -{ - int r; - Key *ret = NULL; - - if ((r = sshkey_from_private(k, &ret)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); - return ret; -} - static void fatal_on_fatal_errors(int r, const char *func, int extra_fatal) { @@ -183,19 +121,6 @@ key_demote(const Key *k) return ret; } -int -key_to_certified(Key *k) -{ - int r; - - if ((r = sshkey_to_certified(k)) != 0) { - fatal_on_fatal_errors(r, __func__, 0); - error("%s: %s", __func__, ssh_err(r)); - return -1; - } - return 0; -} - int key_drop_cert(Key *k) { @@ -209,19 +134,6 @@ key_drop_cert(Key *k) return 0; } -int -key_certify(Key *k, Key *ca) -{ - int r; - - if ((r = sshkey_certify(k, ca, NULL)) != 0) { - fatal_on_fatal_errors(r, __func__, 0); - error("%s: %s", __func__, ssh_err(r)); - return -1; - } - return 0; -} - int key_cert_check_authority(const Key *k, int want_host, int require_principal, const char *name, const char **reason) @@ -237,88 +149,8 @@ key_cert_check_authority(const Key *k, int want_host, int require_principal, return 0; } -#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) -int -key_ec_validate_public(const EC_GROUP *group, const EC_POINT *public) -{ - int r; - - if ((r = sshkey_ec_validate_public(group, public)) != 0) { - fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); - error("%s: %s", __func__, ssh_err(r)); - return -1; - } - return 0; -} - -int -key_ec_validate_private(const EC_KEY *key) -{ - int r; - - if ((r = sshkey_ec_validate_private(key)) != 0) { - fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); - error("%s: %s", __func__, ssh_err(r)); - return -1; - } - return 0; -} -#endif /* WITH_OPENSSL */ - -void -key_private_serialize(const Key *key, struct sshbuf *b) -{ - int r; - - if ((r = sshkey_private_serialize(key, b)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); -} - -Key * -key_private_deserialize(struct sshbuf *blob) -{ - int r; - Key *ret = NULL; - - if ((r = sshkey_private_deserialize(blob, &ret)) != 0) { - fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); - error("%s: %s", __func__, ssh_err(r)); - return NULL; - } - return ret; -} - /* authfile.c */ -int -key_save_private(Key *key, const char *filename, const char *passphrase, - const char *comment, int force_new_format, const char *new_format_cipher, - int new_format_rounds) -{ - int r; - - if ((r = sshkey_save_private(key, filename, passphrase, comment, - force_new_format, new_format_cipher, new_format_rounds)) != 0) { - fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); - error("%s: %s", __func__, ssh_err(r)); - return 0; - } - return 1; -} - -int -key_load_file(int fd, const char *filename, struct sshbuf *blob) -{ - int r; - - if ((r = sshkey_load_file(fd, blob)) != 0) { - fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); - error("%s: %s", __func__, ssh_err(r)); - return 0; - } - return 1; -} - Key * key_load_cert(const char *filename) { @@ -417,10 +249,3 @@ key_load_private_type(int type, const char *filename, const char *passphrase, } return ret; } - -int -key_perm_ok(int fd, const char *filename) -{ - return sshkey_perm_ok(fd, filename) == 0 ? 1 : 0; -} - diff --git a/key.h b/key.h index 2e501a9f4..a14f37037 100644 --- a/key.h +++ b/key.h @@ -1,4 +1,4 @@ -/* $OpenBSD: key.h,v 1.50 2016/09/12 23:31:27 djm Exp $ */ +/* $OpenBSD: key.h,v 1.51 2017/05/30 14:16:41 markus Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -35,51 +35,24 @@ typedef struct sshkey Key; #define fp_rep sshkey_fp_rep #ifndef SSH_KEY_NO_DEFINE -#define key_new sshkey_new #define key_free sshkey_free #define key_equal_public sshkey_equal_public #define key_equal sshkey_equal #define key_type sshkey_type -#define key_cert_type sshkey_cert_type #define key_ssh_name sshkey_ssh_name #define key_ssh_name_plain sshkey_ssh_name_plain #define key_type_from_name sshkey_type_from_name -#define key_ecdsa_nid_from_name sshkey_ecdsa_nid_from_name -#define key_type_is_cert sshkey_type_is_cert -#define key_size sshkey_size -#define key_ecdsa_bits_to_nid sshkey_ecdsa_bits_to_nid -#define key_ecdsa_key_to_nid sshkey_ecdsa_key_to_nid #define key_is_cert sshkey_is_cert #define key_type_plain sshkey_type_plain -#define key_curve_name_to_nid sshkey_curve_name_to_nid -#define key_curve_nid_to_bits sshkey_curve_nid_to_bits -#define key_curve_nid_to_name sshkey_curve_nid_to_name -#define key_ec_nid_to_hash_alg sshkey_ec_nid_to_hash_alg -#define key_dump_ec_point sshkey_dump_ec_point -#define key_dump_ec_key sshkey_dump_ec_key #endif -void key_add_private(Key *); -Key *key_new_private(int); void key_free(Key *); Key *key_demote(const Key *); -int key_write(const Key *, FILE *); -int key_read(Key *, char **); -Key *key_generate(int, u_int); -Key *key_from_private(const Key *); -int key_to_certified(Key *); int key_drop_cert(Key *); -int key_certify(Key *, Key *); -void key_cert_copy(const Key *, Key *); int key_cert_check_authority(const Key *, int, int, const char *, const char **); -#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) -int key_ec_validate_public(const EC_GROUP *, const EC_POINT *); -int key_ec_validate_private(const EC_KEY *); -#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */ - Key *key_from_blob(const u_char *, u_int); int key_to_blob(const Key *, u_char **, u_int *); @@ -87,18 +60,11 @@ int key_sign(const Key *, u_char **, u_int *, const u_char *, u_int, const char *); int key_verify(const Key *, const u_char *, u_int, const u_char *, u_int); -void key_private_serialize(const Key *, struct sshbuf *); -Key *key_private_deserialize(struct sshbuf *); - /* authfile.c */ -int key_save_private(Key *, const char *, const char *, const char *, - int, const char *, int); -int key_load_file(int, const char *, struct sshbuf *); Key *key_load_cert(const char *); Key *key_load_public(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 *); -int key_perm_ok(int, const char *); #endif diff --git a/krl.c b/krl.c index 3f28178b7..086fc20e5 100644 --- a/krl.c +++ b/krl.c @@ -14,7 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $OpenBSD: krl.c,v 1.39 2017/03/10 07:18:32 dtucker Exp $ */ +/* $OpenBSD: krl.c,v 1.40 2017/05/31 09:15:42 deraadt Exp $ */ #include "includes.h" @@ -1026,7 +1026,7 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp, } } /* Record keys used to sign the KRL */ - tmp_ca_used = reallocarray(ca_used, nca_used + 1, + tmp_ca_used = recallocarray(ca_used, nca_used, nca_used + 1, sizeof(*ca_used)); if (tmp_ca_used == NULL) { r = SSH_ERR_ALLOC_FAIL; diff --git a/misc.c b/misc.c index 70bf51735..83da00114 100644 --- a/misc.c +++ b/misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.109 2017/03/14 00:55:37 dtucker Exp $ */ +/* $OpenBSD: misc.c,v 1.110 2017/05/31 09:15:42 deraadt Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2005,2006 Damien Miller. All rights reserved. @@ -554,7 +554,7 @@ addargs(arglist *args, char *fmt, ...) } else if (args->num+2 >= nalloc) nalloc *= 2; - args->list = xreallocarray(args->list, nalloc, sizeof(char *)); + args->list = xrecallocarray(args->list, args->nalloc, nalloc, sizeof(char *)); args->nalloc = nalloc; args->list[args->num++] = cp; args->list[args->num] = NULL; diff --git a/monitor.c b/monitor.c index 96d22b7e4..8897f6a82 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.167 2017/02/03 23:05:57 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.171 2017/05/31 10:04:29 markus Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -1119,7 +1119,7 @@ mm_answer_pam_free_ctx(int sock, Buffer *m) int mm_answer_keyallowed(int sock, Buffer *m) { - Key *key; + struct sshkey *key; char *cuser, *chost; u_char *blob; u_int bloblen, pubkey_auth_attempt; @@ -1330,25 +1330,25 @@ monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser, } int -mm_answer_keyverify(int sock, Buffer *m) +mm_answer_keyverify(int sock, struct sshbuf *m) { - Key *key; + struct sshkey *key; u_char *signature, *data, *blob; - u_int signaturelen, datalen, bloblen; - int verified = 0; - int valid_data = 0; + size_t signaturelen, datalen, bloblen; + int r, ret, valid_data = 0, encoded_ret; - blob = buffer_get_string(m, &bloblen); - signature = buffer_get_string(m, &signaturelen); - data = buffer_get_string(m, &datalen); + if ((r = sshbuf_get_string(m, &blob, &bloblen)) != 0 || + (r = sshbuf_get_string(m, &signature, &signaturelen)) != 0 || + (r = sshbuf_get_string(m, &data, &datalen)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (hostbased_cuser == NULL || hostbased_chost == NULL || !monitor_allowed_key(blob, bloblen)) fatal("%s: bad key, not previously allowed", __func__); - key = key_from_blob(blob, bloblen); - if (key == NULL) - fatal("%s: bad public key blob", __func__); + /* XXX use sshkey_froms here; need to change key_blob, etc. */ + if ((r = sshkey_from_blob(blob, bloblen, &key)) != 0) + fatal("%s: bad public key blob: %s", __func__, ssh_err(r)); switch (key_blobtype) { case MM_USERKEY: @@ -1365,15 +1365,16 @@ mm_answer_keyverify(int sock, Buffer *m) if (!valid_data) fatal("%s: bad signature data blob", __func__); - verified = key_verify(key, signature, signaturelen, data, datalen); + ret = sshkey_verify(key, signature, signaturelen, data, datalen, + active_state->compat); debug3("%s: key %p signature %s", - __func__, key, (verified == 1) ? "verified" : "unverified"); + __func__, key, (ret == 0) ? "verified" : "unverified"); /* If auth was successful then record key to ensure it isn't reused */ - if (verified == 1 && key_blobtype == MM_USERKEY) + if (ret == 0 && key_blobtype == MM_USERKEY) auth2_record_userkey(authctxt, key); else - key_free(key); + sshkey_free(key); free(blob); free(signature); @@ -1383,11 +1384,15 @@ mm_answer_keyverify(int sock, Buffer *m) monitor_reset_key_state(); - buffer_clear(m); - buffer_put_int(m, verified); + sshbuf_reset(m); + + /* encode ret != 0 as positive integer, since we're sending u32 */ + encoded_ret = (ret != 0); + if ((r = sshbuf_put_u32(m, encoded_ret)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); - return (verified == 1); + return ret == 0; } static void @@ -1578,6 +1583,17 @@ mm_answer_audit_command(int socket, Buffer *m) } #endif /* SSH_AUDIT_EVENTS */ +void +monitor_clear_keystate(struct monitor *pmonitor) +{ + struct ssh *ssh = active_state; /* XXX */ + + ssh_clear_newkeys(ssh, MODE_IN); + ssh_clear_newkeys(ssh, MODE_OUT); + sshbuf_free(child_state); + child_state = NULL; +} + void monitor_apply_keystate(struct monitor *pmonitor) { @@ -1639,9 +1655,18 @@ static void monitor_openfds(struct monitor *mon, int do_logfds) { int pair[2]; +#ifdef SO_ZEROIZE + int on = 1; +#endif if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) fatal("%s: socketpair: %s", __func__, strerror(errno)); +#ifdef SO_ZEROIZE + if (setsockopt(pair[0], SOL_SOCKET, SO_ZEROIZE, &on, sizeof(on)) < 0) + error("setsockopt SO_ZEROIZE(0): %.100s", strerror(errno)); + if (setsockopt(pair[1], SOL_SOCKET, SO_ZEROIZE, &on, sizeof(on)) < 0) + error("setsockopt SO_ZEROIZE(1): %.100s", strerror(errno)); +#endif FD_CLOSEONEXEC(pair[0]); FD_CLOSEONEXEC(pair[1]); mon->m_recvfd = pair[0]; diff --git a/monitor_wrap.c b/monitor_wrap.c index f2eec5a77..25f3e9678 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.c,v 1.90 2017/05/17 01:24:17 djm Exp $ */ +/* $OpenBSD: monitor_wrap.c,v 1.92 2017/05/30 14:10:53 markus Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -216,7 +216,7 @@ mm_choose_dh(int min, int nbits, int max) #endif int -mm_key_sign(Key *key, u_char **sigp, u_int *lenp, +mm_key_sign(struct sshkey *key, u_char **sigp, u_int *lenp, const u_char *data, u_int datalen, const char *hostkey_alg) { struct kex *kex = *pmonitor->m_pkex; @@ -375,7 +375,8 @@ mm_auth_password(Authctxt *authctxt, char *password) } int -mm_user_key_allowed(struct passwd *pw, Key *key, int pubkey_auth_attempt) +mm_user_key_allowed(struct passwd *pw, struct sshkey *key, + int pubkey_auth_attempt) { return (mm_key_allowed(MM_USERKEY, NULL, NULL, key, pubkey_auth_attempt)); @@ -383,14 +384,14 @@ mm_user_key_allowed(struct passwd *pw, Key *key, int pubkey_auth_attempt) int mm_hostbased_key_allowed(struct passwd *pw, const char *user, const char *host, - Key *key) + struct sshkey *key) { return (mm_key_allowed(MM_HOSTKEY, user, host, key, 0)); } int mm_key_allowed(enum mm_keytype type, const char *user, const char *host, - Key *key, int pubkey_auth_attempt) + struct sshkey *key, int pubkey_auth_attempt) { Buffer m; u_char *blob; @@ -435,12 +436,13 @@ mm_key_allowed(enum mm_keytype type, const char *user, const char *host, */ int -mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) +mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen, + const u_char *data, size_t datalen, u_int compat) { Buffer m; u_char *blob; u_int len; - int verified = 0; + u_int encoded_ret = 0; debug3("%s entering", __func__); @@ -459,11 +461,13 @@ mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, &m); - verified = buffer_get_int(&m); + encoded_ret = buffer_get_int(&m); buffer_free(&m); - return (verified); + if (encoded_ret != 0) + return SSH_ERR_SIGNATURE_INVALID; + return 0; } void diff --git a/monitor_wrap.h b/monitor_wrap.h index db5902f55..9e032d204 100644 --- a/monitor_wrap.h +++ b/monitor_wrap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.h,v 1.32 2016/09/28 16:33:07 djm Exp $ */ +/* $OpenBSD: monitor_wrap.h,v 1.35 2017/05/31 08:09:45 markus Exp $ */ /* * Copyright 2002 Niels Provos @@ -34,22 +34,24 @@ extern int use_privsep; enum mm_keytype { MM_NOKEY, MM_HOSTKEY, MM_USERKEY }; struct monitor; -struct mm_master; struct Authctxt; void mm_log_handler(LogLevel, const char *, void *); int mm_is_monitor(void); DH *mm_choose_dh(int, int, int); -int mm_key_sign(Key *, u_char **, u_int *, const u_char *, u_int, const char *); +int mm_key_sign(struct sshkey *, u_char **, u_int *, const u_char *, u_int, + const char *); void mm_inform_authserv(char *, char *); struct passwd *mm_getpwnamallow(const char *); char *mm_auth2_read_banner(void); int mm_auth_password(struct Authctxt *, char *); -int mm_key_allowed(enum mm_keytype, const char *, const char *, Key *, int); -int mm_user_key_allowed(struct passwd *, Key *, int); +int mm_key_allowed(enum mm_keytype, const char *, const char *, struct sshkey *, + int); +int mm_user_key_allowed(struct passwd *, struct sshkey *, int); int mm_hostbased_key_allowed(struct passwd *, const char *, - const char *, Key *); -int mm_key_verify(Key *, u_char *, u_int, u_char *, u_int); + const char *, struct sshkey *); +int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t, + const u_char *, size_t, u_int); #ifdef GSSAPI OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID); @@ -83,6 +85,7 @@ void mm_session_pty_cleanup2(struct Session *); struct newkeys *mm_newkeys_from_blob(u_char *, int); int mm_newkeys_to_blob(int, u_char **, u_int *); +void monitor_clear_keystate(struct monitor *); void monitor_apply_keystate(struct monitor *); void mm_get_keystate(struct monitor *); void mm_send_keystate(struct monitor*); diff --git a/opacket.h b/opacket.h index 46d31f805..c49d0c04a 100644 --- a/opacket.h +++ b/opacket.h @@ -149,5 +149,7 @@ void packet_disconnect(const char *, ...) ssh_packet_set_mux(active_state) #define packet_get_mux() \ ssh_packet_get_mux(active_state) +#define packet_clear_keys() \ + ssh_packet_clear_keys(active_state) #endif /* _OPACKET_H */ diff --git a/openbsd-compat/Makefile.in b/openbsd-compat/Makefile.in index d51eacf65..b5088c479 100644 --- a/openbsd-compat/Makefile.in +++ b/openbsd-compat/Makefile.in @@ -16,9 +16,9 @@ RANLIB=@RANLIB@ INSTALL=@INSTALL@ LDFLAGS=-L. @LDFLAGS@ -OPENBSD=base64.o basename.o bcrypt_pbkdf.o bindresvport.o blowfish.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt_long.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o pwcache.o readpassphrase.o reallocarray.o realpath.o rresvport.o setenv.o setproctitle.o sha1.o sha2.o rmd160.o md5.o sigact.o strcasestr.o strlcat.o strlcpy.o strmode.o strnlen.o strptime.o strsep.o strtonum.o strtoll.o strtoul.o strtoull.o timingsafe_bcmp.o vis.o blowfish.o bcrypt_pbkdf.o explicit_bzero.o +OPENBSD=base64.o basename.o bcrypt_pbkdf.o bindresvport.o blowfish.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt_long.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o pwcache.o readpassphrase.o reallocarray.o realpath.o recallocarray.o rresvport.o setenv.o setproctitle.o sha1.o sha2.o rmd160.o md5.o sigact.o strcasestr.o strlcat.o strlcpy.o strmode.o strnlen.o strptime.o strsep.o strtonum.o strtoll.o strtoul.o strtoull.o timingsafe_bcmp.o vis.o blowfish.o bcrypt_pbkdf.o explicit_bzero.o -COMPAT=arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-err.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xcrypt.o kludge-fd_set.o +COMPAT=arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-err.o bsd-getpagesize.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xcrypt.o kludge-fd_set.o PORTS=port-aix.o port-irix.o port-linux.o port-solaris.o port-tun.o port-uw.o diff --git a/openbsd-compat/bsd-getpagesize.c b/openbsd-compat/bsd-getpagesize.c new file mode 100644 index 000000000..9daddfbd3 --- /dev/null +++ b/openbsd-compat/bsd-getpagesize.c @@ -0,0 +1,23 @@ +/* Placed in the public domain */ + +#ifndef HAVE_GETPAGESIZE + +#include +#include + +int +getpagesize(void) +{ +#if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE) + long r = sysconf(_SC_PAGESIZE); + if (r > 0 && r < INT_MAX) + return (int)r; +#endif + /* + * This is at the lower end of common values and appropriate for + * our current use of getpagesize() in recallocarray(). + */ + return 4096; +} + +#endif /* HAVE_GETPAGESIZE */ diff --git a/openbsd-compat/openbsd-compat.h b/openbsd-compat/openbsd-compat.h index 2beb30011..58ab08592 100644 --- a/openbsd-compat/openbsd-compat.h +++ b/openbsd-compat/openbsd-compat.h @@ -60,6 +60,10 @@ int bindresvport_sa(int sd, struct sockaddr *sa); void closefrom(int); #endif +#ifndef HAVE_GETPAGESIZE +int getpagesize(void); +#endif + #ifndef HAVE_GETCWD char *getcwd(char *pt, size_t size); #endif @@ -68,6 +72,10 @@ char *getcwd(char *pt, size_t size); void *reallocarray(void *, size_t, size_t); #endif +#ifndef HAVE_RECALLOCARRAY +void *recallocarray(void *, size_t, size_t, size_t); +#endif + #if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) /* * glibc's FORTIFY_SOURCE can redefine this and prevent us picking up the diff --git a/openbsd-compat/recallocarray.c b/openbsd-compat/recallocarray.c new file mode 100644 index 000000000..c281f75e9 --- /dev/null +++ b/openbsd-compat/recallocarray.c @@ -0,0 +1,88 @@ +/* $OpenBSD: recallocarray.c,v 1.1 2017/03/06 18:44:21 otto Exp $ */ +/* + * Copyright (c) 2008, 2017 Otto Moerbeek + * + * 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/stdlib/recallocarray.c */ + +#include "includes.h" +#ifndef HAVE_RECALLOCARRAY + +#include +#include +#include +#include +#include + +/* + * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX + * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW + */ +#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) + +void * +recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size) +{ + size_t oldsize, newsize; + void *newptr; + + if (ptr == NULL) + return calloc(newnmemb, size); + + if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + newnmemb > 0 && SIZE_MAX / newnmemb < size) { + errno = ENOMEM; + return NULL; + } + newsize = newnmemb * size; + + if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + oldnmemb > 0 && SIZE_MAX / oldnmemb < size) { + errno = EINVAL; + return NULL; + } + oldsize = oldnmemb * size; + + /* + * Don't bother too much if we're shrinking just a bit, + * we do not shrink for series of small steps, oh well. + */ + if (newsize <= oldsize) { + size_t d = oldsize - newsize; + + if (d < oldsize / 2 && d < (size_t)getpagesize()) { + memset((char *)ptr + newsize, 0, d); + return ptr; + } + } + + newptr = malloc(newsize); + if (newptr == NULL) + return NULL; + + if (newsize > oldsize) { + memcpy(newptr, ptr, oldsize); + memset((char *)newptr + oldsize, 0, newsize - oldsize); + } else + memcpy(newptr, ptr, newsize); + + explicit_bzero(ptr, oldsize); + free(ptr); + + return newptr; +} +/* DEF_WEAK(recallocarray); */ + +#endif /* HAVE_RECALLOCARRAY */ diff --git a/packet.c b/packet.c index 46dcc5b5f..7c7486886 100644 --- a/packet.c +++ b/packet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.c,v 1.256 2017/05/08 06:03:39 djm Exp $ */ +/* $OpenBSD: packet.c,v 1.260 2017/06/06 09:12:17 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -559,8 +559,8 @@ ssh_local_port(struct ssh *ssh) /* Closes the connection and clears and frees internal data structures. */ -void -ssh_packet_close(struct ssh *ssh) +static void +ssh_packet_close_internal(struct ssh *ssh, int do_close) { struct session_state *state = ssh->state; u_int mode; @@ -568,20 +568,25 @@ ssh_packet_close(struct ssh *ssh) if (!state->initialized) return; state->initialized = 0; - if (state->connection_in == state->connection_out) { - shutdown(state->connection_out, SHUT_RDWR); - close(state->connection_out); - } else { - close(state->connection_in); - close(state->connection_out); + if (do_close) { + if (state->connection_in == state->connection_out) { + close(state->connection_out); + } else { + close(state->connection_in); + close(state->connection_out); + } } sshbuf_free(state->input); sshbuf_free(state->output); sshbuf_free(state->outgoing_packet); sshbuf_free(state->incoming_packet); - for (mode = 0; mode < MODE_MAX; mode++) - kex_free_newkeys(state->newkeys[mode]); - if (state->compression_buffer) { + for (mode = 0; mode < MODE_MAX; mode++) { + kex_free_newkeys(state->newkeys[mode]); /* current keys */ + state->newkeys[mode] = NULL; + ssh_clear_newkeys(ssh, mode); /* next keys */ + } + /* comression state is in shared mem, so we can only release it once */ + if (do_close && state->compression_buffer) { sshbuf_free(state->compression_buffer); if (state->compression_out_started) { z_streamp stream = &state->compression_out_stream; @@ -595,7 +600,7 @@ ssh_packet_close(struct ssh *ssh) deflateEnd(stream); } if (state->compression_in_started) { - z_streamp stream = &state->compression_out_stream; + z_streamp stream = &state->compression_in_stream; debug("compress incoming: " "raw data %llu, compressed %llu, factor %.2f", (unsigned long long)stream->total_out, @@ -609,10 +614,24 @@ ssh_packet_close(struct ssh *ssh) cipher_free(state->send_context); cipher_free(state->receive_context); state->send_context = state->receive_context = NULL; - free(ssh->remote_ipaddr); - ssh->remote_ipaddr = NULL; - free(ssh->state); - ssh->state = NULL; + if (do_close) { + free(ssh->remote_ipaddr); + ssh->remote_ipaddr = NULL; + free(ssh->state); + ssh->state = NULL; + } +} + +void +ssh_packet_close(struct ssh *ssh) +{ + ssh_packet_close_internal(ssh, 1); +} + +void +ssh_packet_clear_keys(struct ssh *ssh) +{ + ssh_packet_close_internal(ssh, 0); } /* Sets remote side protocol flags. */ @@ -791,6 +810,15 @@ uncompress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out) /* NOTREACHED */ } +void +ssh_clear_newkeys(struct ssh *ssh, int mode) +{ + if (ssh->kex && ssh->kex->newkeys[mode]) { + kex_free_newkeys(ssh->kex->newkeys[mode]); + ssh->kex->newkeys[mode] = NULL; + } +} + int ssh_set_newkeys(struct ssh *ssh, int mode) { @@ -801,45 +829,33 @@ ssh_set_newkeys(struct ssh *ssh, int mode) struct sshcipher_ctx **ccp; struct packet_state *ps; u_int64_t *max_blocks; - const char *wmsg, *dir; + const char *wmsg; int r, crypt_type; debug2("set_newkeys: mode %d", mode); if (mode == MODE_OUT) { - dir = "output"; ccp = &state->send_context; crypt_type = CIPHER_ENCRYPT; ps = &state->p_send; max_blocks = &state->max_blocks_out; } else { - dir = "input"; ccp = &state->receive_context; crypt_type = CIPHER_DECRYPT; ps = &state->p_read; max_blocks = &state->max_blocks_in; } if (state->newkeys[mode] != NULL) { - debug("%s: rekeying after %llu %s blocks" - " (%llu bytes total)", __func__, - (unsigned long long)ps->blocks, dir, - (unsigned long long)ps->bytes); + debug("set_newkeys: rekeying, input %llu bytes %llu blocks, " + "output %llu bytes %llu blocks", + (unsigned long long)state->p_read.bytes, + (unsigned long long)state->p_read.blocks, + (unsigned long long)state->p_send.bytes, + (unsigned long long)state->p_send.blocks); cipher_free(*ccp); *ccp = NULL; - enc = &state->newkeys[mode]->enc; - mac = &state->newkeys[mode]->mac; - comp = &state->newkeys[mode]->comp; - mac_clear(mac); - explicit_bzero(enc->iv, enc->iv_len); - explicit_bzero(enc->key, enc->key_len); - explicit_bzero(mac->key, mac->key_len); - free(enc->name); - free(enc->iv); - free(enc->key); - free(mac->name); - free(mac->key); - free(comp->name); - free(state->newkeys[mode]); + kex_free_newkeys(state->newkeys[mode]); + state->newkeys[mode] = NULL; } /* note that both bytes and the seqnr are not reset */ ps->packets = ps->blocks = 0; @@ -1784,15 +1800,20 @@ sshpkt_fatal(struct ssh *ssh, const char *tag, int r) switch (r) { case SSH_ERR_CONN_CLOSED: + ssh_packet_clear_keys(ssh); logdie("Connection closed by %s", remote_id); case SSH_ERR_CONN_TIMEOUT: + ssh_packet_clear_keys(ssh); logdie("Connection %s %s timed out", ssh->state->server_side ? "from" : "to", remote_id); case SSH_ERR_DISCONNECTED: + ssh_packet_clear_keys(ssh); logdie("Disconnected from %s", remote_id); case SSH_ERR_SYSTEM_ERROR: - if (errno == ECONNRESET) + if (errno == ECONNRESET) { + ssh_packet_clear_keys(ssh); logdie("Connection reset by %s", remote_id); + } /* FALLTHROUGH */ case SSH_ERR_NO_CIPHER_ALG_MATCH: case SSH_ERR_NO_MAC_ALG_MATCH: @@ -1800,12 +1821,14 @@ sshpkt_fatal(struct ssh *ssh, const char *tag, int r) case SSH_ERR_NO_KEX_ALG_MATCH: case SSH_ERR_NO_HOSTKEY_ALG_MATCH: if (ssh && ssh->kex && ssh->kex->failed_choice) { + ssh_packet_clear_keys(ssh); logdie("Unable to negotiate with %s: %s. " "Their offer: %s", remote_id, ssh_err(r), ssh->kex->failed_choice); } /* FALLTHROUGH */ default: + ssh_packet_clear_keys(ssh); logdie("%s%sConnection %s %s: %s", tag != NULL ? tag : "", tag != NULL ? ": " : "", ssh->state->server_side ? "from" : "to", diff --git a/packet.h b/packet.h index b82f45a75..6ce6dd560 100644 --- a/packet.h +++ b/packet.h @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.h,v 1.79 2017/05/03 21:08:09 naddy Exp $ */ +/* $OpenBSD: packet.h,v 1.81 2017/05/31 08:09:45 markus Exp $ */ /* * Author: Tatu Ylonen @@ -77,6 +77,9 @@ struct ssh { TAILQ_HEAD(, key_entry) private_keys; TAILQ_HEAD(, key_entry) public_keys; + /* Client/Server authentication context */ + void *authctxt; + /* APP data */ void *app_data; }; @@ -94,6 +97,8 @@ int ssh_packet_get_connection_in(struct ssh *); int ssh_packet_get_connection_out(struct ssh *); void ssh_packet_close(struct ssh *); void ssh_packet_set_input_hook(struct ssh *, ssh_packet_hook_fn *, void *); +void ssh_packet_clear_keys(struct ssh *); +void ssh_clear_newkeys(struct ssh *, int); int ssh_packet_is_rekeying(struct ssh *); void ssh_packet_set_protocol_flags(struct ssh *, u_int); diff --git a/readconf.c b/readconf.c index 4baee2ee7..6375602c8 100644 --- a/readconf.c +++ b/readconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.c,v 1.275 2017/04/30 23:18:22 djm Exp $ */ +/* $OpenBSD: readconf.c,v 1.277 2017/05/30 18:58:37 bluhm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -164,7 +164,8 @@ typedef enum { oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, oSendEnv, oControlPath, oControlMaster, oControlPersist, oHashKnownHosts, - oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, + oTunnel, oTunnelDevice, + oLocalCommand, oPermitLocalCommand, oRemoteCommand, oVisualHostKey, oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, @@ -285,6 +286,7 @@ static struct { { "tunneldevice", oTunnelDevice }, { "localcommand", oLocalCommand }, { "permitlocalcommand", oPermitLocalCommand }, + { "remotecommand", oRemoteCommand }, { "visualhostkey", oVisualHostKey }, { "kexalgorithms", oKexAlgorithms }, { "ipqos", oIPQoS }, @@ -439,8 +441,8 @@ add_identity_file(Options *options, const char *dir, const char *filename, if (dir == NULL) /* no dir, filename is absolute */ path = xstrdup(filename); - else - (void)xasprintf(&path, "%.100s%.100s", dir, filename); + else if (xasprintf(&path, "%s%s", dir, filename) >= PATH_MAX) + fatal("Identity file path %s too long", path); /* Avoid registering duplicates */ for (i = 0; i < options->num_identity_files; i++) { @@ -1446,6 +1448,10 @@ parse_keytypes: intptr = &options->permit_local_command; goto parse_flag; + case oRemoteCommand: + charptr = &options->remote_command; + goto parse_command; + case oVisualHostKey: intptr = &options->visual_host_key; goto parse_flag; @@ -1845,6 +1851,7 @@ initialize_options(Options * options) options->tun_remote = -1; options->local_command = NULL; options->permit_local_command = -1; + options->remote_command = NULL; options->add_keys_to_agent = -1; options->identity_agent = NULL; options->visual_host_key = -1; @@ -2049,6 +2056,7 @@ fill_default_options(Options * options) } \ } while(0) CLEAR_ON_NONE(options->local_command); + CLEAR_ON_NONE(options->remote_command); CLEAR_ON_NONE(options->proxy_command); CLEAR_ON_NONE(options->control_path); CLEAR_ON_NONE(options->revoked_host_keys); @@ -2526,6 +2534,7 @@ dump_client_config(Options *o, const char *host) dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices); dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX); dump_cfg_string(oLocalCommand, o->local_command); + dump_cfg_string(oRemoteCommand, o->remote_command); dump_cfg_string(oLogLevel, log_level_name(o->log_level)); dump_cfg_string(oMacs, o->macs ? o->macs : KEX_CLIENT_MAC); #ifdef ENABLE_PKCS11 diff --git a/readconf.h b/readconf.h index f47f53402..94dd427f5 100644 --- a/readconf.h +++ b/readconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.h,v 1.121 2017/04/30 23:18:22 djm Exp $ */ +/* $OpenBSD: readconf.h,v 1.122 2017/05/30 18:58:37 bluhm Exp $ */ /* * Author: Tatu Ylonen @@ -134,6 +134,7 @@ typedef struct { char *local_command; int permit_local_command; + char *remote_command; int visual_host_key; int request_tty; diff --git a/regress/proto-version.sh b/regress/proto-version.sh index 5faeb758c..1f33b1f00 100644 --- a/regress/proto-version.sh +++ b/regress/proto-version.sh @@ -1,4 +1,4 @@ -# $OpenBSD: proto-version.sh,v 1.6 2017/04/30 23:34:55 djm Exp $ +# $OpenBSD: proto-version.sh,v 1.7 2017/06/07 01:48:15 djm Exp $ # Placed in the Public Domain. tid="sshd version with different protocol combinations" @@ -6,7 +6,7 @@ tid="sshd version with different protocol combinations" # we just start sshd in inetd mode and check the banner check_version () { - expect=$2 + expect=$1 banner=`printf '' | ${SSHD} -i -f ${OBJ}/sshd_proxy` case ${banner} in SSH-1.99-*) diff --git a/scp.c b/scp.c index 158cacee5..7f72ef3c5 100644 --- a/scp.c +++ b/scp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: scp.c,v 1.191 2017/05/02 08:06:33 jmc Exp $ */ +/* $OpenBSD: scp.c,v 1.192 2017/05/31 09:15:42 deraadt Exp $ */ /* * scp - secure remote copy. This is basically patched BSD rcp which * uses ssh to do the data transfer (instead of using rcmd). @@ -1475,11 +1475,7 @@ allocbuf(BUF *bp, int fd, int blksize) #endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */ if (bp->cnt >= size) return (bp); - if (bp->buf == NULL) - bp->buf = xmalloc(size); - else - bp->buf = xreallocarray(bp->buf, 1, size); - memset(bp->buf, 0, size); + bp->buf = xrecallocarray(bp->buf, bp->cnt, size, 1); bp->cnt = size; return (bp); } diff --git a/serverloop.c b/serverloop.c index 2976f5594..b5eb3440a 100644 --- a/serverloop.c +++ b/serverloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: serverloop.c,v 1.191 2017/02/01 02:59:09 dtucker Exp $ */ +/* $OpenBSD: serverloop.c,v 1.193 2017/05/31 07:00:13 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -323,7 +323,7 @@ process_output(fd_set *writeset, int connection_out) static void process_buffered_input_packets(void) { - dispatch_run(DISPATCH_NONBLOCK, NULL, active_state); + ssh_dispatch_run_fatal(active_state, DISPATCH_NONBLOCK, NULL); } static void @@ -417,7 +417,7 @@ server_loop2(Authctxt *authctxt) } static int -server_input_keep_alive(int type, u_int32_t seq, void *ctxt) +server_input_keep_alive(int type, u_int32_t seq, struct ssh *ssh) { debug("Got %d/%u for keepalive", type, seq); /* @@ -579,7 +579,7 @@ server_request_session(void) } static int -server_input_channel_open(int type, u_int32_t seq, void *ctxt) +server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh) { Channel *c = NULL; char *ctype; @@ -703,7 +703,7 @@ server_input_hostkeys_prove(struct sshbuf **respp) } static int -server_input_global_request(int type, u_int32_t seq, void *ctxt) +server_input_global_request(int type, u_int32_t seq, struct ssh *ssh) { char *rtype; int want_reply; @@ -810,7 +810,7 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt) } static int -server_input_channel_req(int type, u_int32_t seq, void *ctxt) +server_input_channel_req(int type, u_int32_t seq, struct ssh *ssh) { Channel *c; int id, reply, success = 0; diff --git a/session.c b/session.c index 0e830ef24..5904d203e 100644 --- a/session.c +++ b/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.286 2016/11/30 03:00:05 djm Exp $ */ +/* $OpenBSD: session.c,v 1.288 2017/05/31 09:15:42 deraadt Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -1740,6 +1740,7 @@ do_child(Session *s, const char *command) /* remove hostkey from the child's memory */ destroy_sensitive_data(); + packet_clear_keys(); /* Force a password change */ if (s->authctxt->force_pwchange) { @@ -1965,8 +1966,8 @@ session_new(void) return NULL; debug2("%s: allocate (allocated %d max %d)", __func__, sessions_nalloc, options.max_sessions); - tmp = xreallocarray(sessions, sessions_nalloc + 1, - sizeof(*sessions)); + tmp = xrecallocarray(sessions, sessions_nalloc, + sessions_nalloc + 1, sizeof(*sessions)); if (tmp == NULL) { error("%s: cannot allocate %d sessions", __func__, sessions_nalloc + 1); @@ -2290,8 +2291,8 @@ session_env_req(Session *s) for (i = 0; i < options.num_accept_env; i++) { if (match_pattern(name, options.accept_env[i])) { debug2("Setting env %d: %s=%s", s->num_env, name, val); - s->env = xreallocarray(s->env, s->num_env + 1, - sizeof(*s->env)); + s->env = xrecallocarray(s->env, s->num_env, + s->num_env + 1, sizeof(*s->env)); s->env[s->num_env].name = name; s->env[s->num_env].val = val; s->num_env++; diff --git a/ssh-add.c b/ssh-add.c index a1e0d464b..438c1c25a 100644 --- a/ssh-add.c +++ b/ssh-add.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-add.c,v 1.131 2017/05/05 10:42:49 naddy Exp $ */ +/* $OpenBSD: ssh-add.c,v 1.132 2017/05/30 14:16:41 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -306,7 +306,7 @@ add_file(int agent_fd, const char *filename, int key_only) goto out; } if ((r = sshkey_cert_copy(cert, private)) != 0) { - error("%s: key_cert_copy: %s", __func__, ssh_err(r)); + error("%s: sshkey_cert_copy: %s", __func__, ssh_err(r)); sshkey_free(cert); goto out; } diff --git a/ssh-keygen.c b/ssh-keygen.c index 74fa63702..d73f5eccb 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keygen.c,v 1.303 2017/05/07 23:15:59 djm Exp $ */ +/* $OpenBSD: ssh-keygen.c,v 1.304 2017/05/30 14:16:41 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland @@ -493,7 +493,7 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) return NULL; } if ((key = sshkey_new_private(ktype)) == NULL) - fatal("key_new_private failed"); + fatal("sshkey_new_private failed"); free(type); switch (key->type) { @@ -775,7 +775,7 @@ do_print_public(struct passwd *pw) fatal("%s: %s", identity_file, strerror(errno)); prv = load_identity(identity_file); if ((r = sshkey_write(prv, stdout)) != 0) - error("key_write failed: %s", ssh_err(r)); + error("sshkey_write failed: %s", ssh_err(r)); sshkey_free(prv); fprintf(stdout, "\n"); exit(0); @@ -1024,7 +1024,7 @@ do_gen_all_hostkeys(struct passwd *pw) bits = 0; type_bits_valid(type, NULL, &bits); if ((r = sshkey_generate(type, bits, &private)) != 0) { - error("key_generate failed: %s", ssh_err(r)); + error("sshkey_generate failed: %s", ssh_err(r)); first = 0; continue; } @@ -1492,7 +1492,7 @@ do_change_comment(struct passwd *pw) explicit_bzero(passphrase, strlen(passphrase)); free(passphrase); if ((r = sshkey_from_private(private, &public)) != 0) - fatal("key_from_private failed: %s", ssh_err(r)); + fatal("sshkey_from_private failed: %s", ssh_err(r)); sshkey_free(private); strlcat(identity_file, ".pub", sizeof(identity_file)); @@ -1680,7 +1680,7 @@ do_ca_sign(struct passwd *pw, int argc, char **argv) OPTIONS_EXTENSIONS); if ((r = sshkey_from_private(ca, &public->cert->signature_key)) != 0) - fatal("key_from_private (ca key): %s", ssh_err(r)); + fatal("sshkey_from_private (ca key): %s", ssh_err(r)); if ((r = sshkey_certify(public, ca, key_type_name)) != 0) fatal("Couldn't certify key %s: %s", tmp, ssh_err(r)); @@ -1998,7 +1998,7 @@ do_show_cert(struct passwd *pw) if (*cp == '#' || *cp == '\0') continue; if ((key = sshkey_new(KEY_UNSPEC)) == NULL) - fatal("key_new"); + fatal("sshkey_new"); if ((r = sshkey_read(key, &cp)) != 0) { error("%s:%lu: invalid key: %s", path, lnum, ssh_err(r)); @@ -2144,7 +2144,7 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca, */ } if ((key = sshkey_new(KEY_UNSPEC)) == NULL) - fatal("key_new"); + fatal("sshkey_new"); if ((r = sshkey_read(key, &cp)) != 0) fatal("%s:%lu: invalid key: %s", path, lnum, ssh_err(r)); @@ -2685,9 +2685,9 @@ main(int argc, char **argv) printf("Generating public/private %s key pair.\n", key_type_name); if ((r = sshkey_generate(type, bits, &private)) != 0) - fatal("key_generate failed"); + fatal("sshkey_generate failed"); if ((r = sshkey_from_private(private, &public)) != 0) - fatal("key_from_private failed: %s\n", ssh_err(r)); + fatal("sshkey_from_private failed: %s\n", ssh_err(r)); if (!have_identity) ask_filename(pw, "Enter file in which to save the key"); diff --git a/ssh-keyscan.c b/ssh-keyscan.c index d320e4eea..0c863e470 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keyscan.c,v 1.113 2017/04/30 23:28:42 djm Exp $ */ +/* $OpenBSD: ssh-keyscan.c,v 1.114 2017/05/31 07:00:13 markus Exp $ */ /* * Copyright 1995, 1996 by David Mazieres . * @@ -276,7 +276,7 @@ keygrab_ssh2(con *c) * do the key-exchange until an error occurs or until * the key_print_wrapper() callback sets c_done. */ - ssh_dispatch_run(c->c_ssh, DISPATCH_BLOCK, &c->c_done, c->c_ssh); + ssh_dispatch_run(c->c_ssh, DISPATCH_BLOCK, &c->c_done); } static void diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c index fac0167e6..a79c87210 100644 --- a/ssh-pkcs11-client.c +++ b/ssh-pkcs11-client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-pkcs11-client.c,v 1.6 2015/12/11 00:20:04 mmcc Exp $ */ +/* $OpenBSD: ssh-pkcs11-client.c,v 1.7 2017/05/30 08:52:19 markus Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * @@ -106,7 +106,7 @@ static int pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding) { - Key key; + struct sshkey key; /* XXX */ u_char *blob, *signature = NULL; u_int blen, slen = 0; int ret = -1; @@ -186,7 +186,7 @@ pkcs11_start_helper(void) int pkcs11_add_provider(char *name, char *pin, Key ***keysp) { - Key *k; + struct sshkey *k; int i, nkeys; u_char *blob; u_int blen; diff --git a/ssh-pkcs11-helper.c b/ssh-pkcs11-helper.c index 53f41c555..fd3039c14 100644 --- a/ssh-pkcs11-helper.c +++ b/ssh-pkcs11-helper.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-pkcs11-helper.c,v 1.12 2016/02/15 09:47:49 dtucker Exp $ */ +/* $OpenBSD: ssh-pkcs11-helper.c,v 1.13 2017/05/30 08:52:19 markus Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * @@ -42,7 +42,7 @@ /* borrows code from sftp-server and ssh-agent */ struct pkcs11_keyinfo { - Key *key; + struct sshkey *key; char *providername; TAILQ_ENTRY(pkcs11_keyinfo) next; }; @@ -60,7 +60,7 @@ Buffer iqueue; Buffer oqueue; static void -add_key(Key *k, char *name) +add_key(struct sshkey *k, char *name) { struct pkcs11_keyinfo *ki; @@ -87,8 +87,8 @@ del_keys_by_name(char *name) } /* lookup matching 'private' key */ -static Key * -lookup_key(Key *k) +static struct sshkey * +lookup_key(struct sshkey *k) { struct pkcs11_keyinfo *ki; @@ -114,7 +114,7 @@ static void process_add(void) { char *name, *pin; - Key **keys; + struct sshkey **keys; int i, nkeys; u_char *blob; u_int blen; @@ -170,7 +170,7 @@ process_sign(void) u_char *blob, *data, *signature = NULL; u_int blen, dlen, slen = 0; int ok = -1; - Key *key, *found; + struct sshkey *key, *found; Buffer msg; blob = get_string(&blen); diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c index aaf712d9a..b37491c5d 100644 --- a/ssh-pkcs11.c +++ b/ssh-pkcs11.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-pkcs11.c,v 1.23 2016/10/28 03:33:52 djm Exp $ */ +/* $OpenBSD: ssh-pkcs11.c,v 1.25 2017/05/31 09:15:42 deraadt Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * @@ -537,7 +537,8 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, } if (rsa && rsa->n && rsa->e && pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) { - key = sshkey_new(KEY_UNSPEC); + if ((key = sshkey_new(KEY_UNSPEC)) == NULL) + fatal("sshkey_new failed"); key->rsa = rsa; key->type = KEY_RSA; key->flags |= SSHKEY_FLAG_EXT; @@ -545,8 +546,8 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, sshkey_free(key); } else { /* expand key array and add key */ - *keysp = xreallocarray(*keysp, *nkeys + 1, - sizeof(struct sshkey *)); + *keysp = xrecallocarray(*keysp, *nkeys, + *nkeys + 1, sizeof(struct sshkey *)); (*keysp)[*nkeys] = key; *nkeys = *nkeys + 1; debug("have %d keys", *nkeys); diff --git a/ssh.1 b/ssh.1 index 10633d92b..47cd0211d 100644 --- a/ssh.1 +++ b/ssh.1 @@ -33,8 +33,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: ssh.1,v 1.381 2017/05/05 10:41:58 naddy Exp $ -.Dd $Mdocdate: May 5 2017 $ +.\" $OpenBSD: ssh.1,v 1.382 2017/05/30 18:58:37 bluhm Exp $ +.Dd $Mdocdate: May 30 2017 $ .Dt SSH 1 .Os .Sh NAME @@ -518,6 +518,7 @@ For full details of the options listed below, and their possible values, see .It PubkeyAcceptedKeyTypes .It PubkeyAuthentication .It RekeyLimit +.It RemoteCommand .It RemoteForward .It RequestTTY .It SendEnv diff --git a/ssh.c b/ssh.c index 3713be1da..8bb7e909a 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.459 2017/05/02 08:06:33 jmc Exp $ */ +/* $OpenBSD: ssh.c,v 1.461 2017/05/30 18:58:37 bluhm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -973,12 +973,6 @@ main(int ac, char **av) } } - /* Cannot fork to background if no command. */ - if (fork_after_authentication_flag && buffer_len(&command) == 0 && - !no_shell_flag) - fatal("Cannot fork into background without a command " - "to execute."); - /* * Initialize "log" output. Since we are the client all output * goes to stderr unless otherwise specified by -y or -E. @@ -1133,6 +1127,15 @@ main(int ac, char **av) options.use_privileged_port = 0; #endif + if (buffer_len(&command) != 0 && options.remote_command != NULL) + fatal("Cannot execute command-line and remote command."); + + /* Cannot fork to background if no command. */ + if (fork_after_authentication_flag && buffer_len(&command) == 0 && + options.remote_command == NULL && !no_shell_flag) + fatal("Cannot fork into background without a command " + "to execute."); + /* reinit */ log_init(argv0, options.log_level, options.log_facility, !use_syslog); @@ -1141,7 +1144,7 @@ main(int ac, char **av) tty_flag = 1; /* Allocate a tty by default if no command specified. */ - if (buffer_len(&command) == 0) + if (buffer_len(&command) == 0 && options.remote_command == NULL) tty_flag = options.request_tty != REQUEST_TTY_NO; /* Force no tty */ @@ -1197,6 +1200,27 @@ main(int ac, char **av) free(cp); } + if (options.remote_command != NULL) { + debug3("expanding RemoteCommand: %s", options.remote_command); + cp = options.remote_command; + options.remote_command = percent_expand(cp, + "C", conn_hash_hex, + "L", shorthost, + "d", pw->pw_dir, + "h", host, + "l", thishost, + "n", host_arg, + "p", portstr, + "r", options.user, + "u", pw->pw_name, + (char *)NULL); + debug3("expanded RemoteCommand: %s", options.remote_command); + free(cp); + buffer_append(&command, options.remote_command, + strlen(options.remote_command)); + + } + if (options.control_path != NULL) { cp = tilde_expand_filename(options.control_path, original_real_uid); @@ -1278,7 +1302,7 @@ main(int ac, char **av) if (options.hostbased_authentication) { sensitive_data.nkeys = 9; sensitive_data.keys = xcalloc(sensitive_data.nkeys, - sizeof(Key)); + sizeof(struct sshkey)); /* XXX */ for (i = 0; i < sensitive_data.nkeys; i++) sensitive_data.keys[i] = NULL; @@ -1858,16 +1882,16 @@ load_public_identity_files(void) { char *filename, *cp, thishost[NI_MAXHOST]; char *pwdir = NULL, *pwname = NULL; - Key *public; + struct sshkey *public; struct passwd *pw; int i; u_int n_ids, n_certs; char *identity_files[SSH_MAX_IDENTITY_FILES]; - Key *identity_keys[SSH_MAX_IDENTITY_FILES]; + struct sshkey *identity_keys[SSH_MAX_IDENTITY_FILES]; char *certificate_files[SSH_MAX_CERTIFICATE_FILES]; struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES]; #ifdef ENABLE_PKCS11 - Key **keys; + struct sshkey **keys; int nkeys; #endif /* PKCS11 */ diff --git a/ssh_config.5 b/ssh_config.5 index db37b92cd..4277f9eac 100644 --- a/ssh_config.5 +++ b/ssh_config.5 @@ -33,8 +33,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: ssh_config.5,v 1.248 2017/05/07 23:12:57 djm Exp $ -.Dd $Mdocdate: May 7 2017 $ +.\" $OpenBSD: ssh_config.5,v 1.250 2017/05/30 19:38:17 jmc Exp $ +.Dd $Mdocdate: May 30 2017 $ .Dt SSH_CONFIG 5 .Os .Sh NAME @@ -1287,6 +1287,16 @@ is .Cm default none , which means that rekeying is performed after the cipher's default amount of data has been sent or received and no time based rekeying is done. +.It Cm RemoteCommand +Specifies a command to execute on the remote machine after successfully +connecting to the server. +The command string extends to the end of the line, and is executed with +the user's shell. +Arguments to +.Cm RemoteCommand +accept the tokens described in the +.Sx TOKENS +section. .It Cm RemoteForward Specifies that a TCP port on the remote machine be forwarded over the secure channel to the specified host and port from the local machine. @@ -1702,6 +1712,9 @@ accepts the tokens %%, %C, %d, %h, %l, %n, %p, %r, and %u. .Pp .Cm ProxyCommand accepts the tokens %%, %h, %p, and %r. +.Pp +.Cm RemoteCommand +accepts the tokens %%, %C, %d, %h, %l, %n, %p, %r, and %u. .Sh FILES .Bl -tag -width Ds .It Pa ~/.ssh/config diff --git a/sshbuf-getput-basic.c b/sshbuf-getput-basic.c index 74c49be7c..50648258f 100644 --- a/sshbuf-getput-basic.c +++ b/sshbuf-getput-basic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshbuf-getput-basic.c,v 1.6 2016/06/16 11:00:17 dtucker Exp $ */ +/* $OpenBSD: sshbuf-getput-basic.c,v 1.7 2017/06/01 04:51:58 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller * @@ -365,7 +365,7 @@ sshbuf_put_string(struct sshbuf *buf, const void *v, size_t len) int sshbuf_put_cstring(struct sshbuf *buf, const char *v) { - return sshbuf_put_string(buf, (u_char *)v, v == NULL ? 0 : strlen(v)); + return sshbuf_put_string(buf, v, v == NULL ? 0 : strlen(v)); } int diff --git a/sshbuf.c b/sshbuf.c index cbf7ed4a4..de783a363 100644 --- a/sshbuf.c +++ b/sshbuf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshbuf.c,v 1.8 2016/11/25 23:22:04 djm Exp $ */ +/* $OpenBSD: sshbuf.c,v 1.11 2017/06/01 06:58:25 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller * @@ -193,15 +193,16 @@ sshbuf_reset(struct sshbuf *buf) buf->off = buf->size; return; } - if (sshbuf_check_sanity(buf) == 0) - explicit_bzero(buf->d, buf->alloc); + (void) sshbuf_check_sanity(buf); buf->off = buf->size = 0; if (buf->alloc != SSHBUF_SIZE_INIT) { - if ((d = realloc(buf->d, SSHBUF_SIZE_INIT)) != NULL) { + if ((d = recallocarray(buf->d, buf->alloc, SSHBUF_SIZE_INIT, + 1)) != NULL) { buf->cd = buf->d = d; buf->alloc = SSHBUF_SIZE_INIT; } } + explicit_bzero(buf->d, SSHBUF_SIZE_INIT); } size_t @@ -253,9 +254,8 @@ sshbuf_set_max_size(struct sshbuf *buf, size_t max_size) rlen = ROUNDUP(buf->size, SSHBUF_SIZE_INC); if (rlen > max_size) rlen = max_size; - explicit_bzero(buf->d + buf->size, buf->alloc - buf->size); SSHBUF_DBG(("new alloc = %zu", rlen)); - if ((dp = realloc(buf->d, rlen)) == NULL) + if ((dp = recallocarray(buf->d, buf->alloc, rlen, 1)) == NULL) return SSH_ERR_ALLOC_FAIL; buf->cd = buf->d = dp; buf->alloc = rlen; @@ -344,7 +344,7 @@ sshbuf_allocate(struct sshbuf *buf, size_t len) if (rlen > buf->max_size) rlen = buf->alloc + need; SSHBUF_DBG(("adjusted rlen %zu", rlen)); - if ((dp = realloc(buf->d, rlen)) == NULL) { + if ((dp = recallocarray(buf->d, buf->alloc, rlen, 1)) == NULL) { SSHBUF_DBG(("realloc fail")); return SSH_ERR_ALLOC_FAIL; } @@ -391,6 +391,9 @@ sshbuf_consume(struct sshbuf *buf, size_t len) if (len > sshbuf_len(buf)) return SSH_ERR_MESSAGE_INCOMPLETE; buf->off += len; + /* deal with empty buffer */ + if (buf->off == buf->size) + buf->off = buf->size = 0; SSHBUF_TELL("done"); return 0; } diff --git a/sshconnect.c b/sshconnect.c index 8da712f07..11c848a53 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.c,v 1.278 2017/05/01 02:27:11 djm Exp $ */ +/* $OpenBSD: sshconnect.c,v 1.280 2017/05/30 14:13:40 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -67,7 +67,7 @@ char *client_version_string = NULL; char *server_version_string = NULL; -Key *previous_host_key = NULL; +struct sshkey *previous_host_key = NULL; static int matching_host_key_dns = 0; @@ -79,8 +79,8 @@ extern char *__progname; extern uid_t original_real_uid; extern uid_t original_effective_uid; -static int show_other_keys(struct hostkeys *, Key *); -static void warn_changed_key(Key *); +static int show_other_keys(struct hostkeys *, struct sshkey *); +static void warn_changed_key(struct sshkey *); /* Expand a proxy command */ static char * @@ -687,7 +687,7 @@ confirm(const char *prompt) } static int -check_host_cert(const char *host, const Key *host_key) +check_host_cert(const char *host, const struct sshkey *host_key) { const char *reason; @@ -785,13 +785,13 @@ get_hostfile_hostname_ipaddr(char *hostname, struct sockaddr *hostaddr, #define ROQUIET 2 static int check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, - Key *host_key, int readonly, + struct sshkey *host_key, int readonly, char **user_hostfiles, u_int num_user_hostfiles, char **system_hostfiles, u_int num_system_hostfiles) { HostStatus host_status; HostStatus ip_status; - Key *raw_key = NULL; + struct sshkey *raw_key = NULL; char *ip = NULL, *host = NULL; char hostline[1000], *hostp, *fp, *ra; char msg[1024]; @@ -799,7 +799,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, const struct hostkey_entry *host_found, *ip_found; int len, cancelled_forwarding = 0; int local = sockaddr_is_local(hostaddr); - int r, want_cert = key_is_cert(host_key), host_ip_differ = 0; + int r, want_cert = sshkey_is_cert(host_key), host_ip_differ = 0; int hostkey_trusted = 0; /* Known or explicitly accepted by user */ struct hostkeys *host_hostkeys, *ip_hostkeys; u_int i; @@ -850,8 +850,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, retry: /* Reload these as they may have changed on cert->key downgrade */ - want_cert = key_is_cert(host_key); - type = key_type(host_key); + want_cert = sshkey_is_cert(host_key); + type = sshkey_type(host_key); /* * Check if the host key is present in the user's list of known @@ -871,7 +871,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, if (host_status == HOST_CHANGED && (ip_status != HOST_CHANGED || (ip_found != NULL && - !key_equal(ip_found->key, host_found->key)))) + !sshkey_equal(ip_found->key, host_found->key)))) host_ip_differ = 1; } else ip_status = host_status; @@ -1068,7 +1068,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, warn_changed_key(host_key); error("Add correct host key in %.100s to get rid of this message.", user_hostfiles[0]); - error("Offending %s key in %s:%lu", key_type(host_found->key), + error("Offending %s key in %s:%lu", + sshkey_type(host_found->key), host_found->file, host_found->line); /* @@ -1197,14 +1198,16 @@ fail: * search normally. */ debug("No matching CA found. Retry with plain key"); - raw_key = key_from_private(host_key); - if (key_drop_cert(raw_key) != 0) - fatal("Couldn't drop certificate"); + if ((r = sshkey_from_private(host_key, &raw_key)) != 0) + fatal("%s: sshkey_from_private: %s", + __func__, ssh_err(r)); + if ((r = sshkey_drop_cert(raw_key)) != 0) + fatal("Couldn't drop certificate: %s", ssh_err(r)); host_key = raw_key; goto retry; } if (raw_key != NULL) - key_free(raw_key); + sshkey_free(raw_key); free(ip); free(host); if (host_hostkeys != NULL) @@ -1216,7 +1219,7 @@ fail: /* returns 0 if key verifies or -1 if key does NOT verify */ int -verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) +verify_host_key(char *host, struct sockaddr *hostaddr, struct sshkey *host_key) { u_int i; int r = -1, flags = 0; @@ -1320,8 +1323,8 @@ out: free(fp); free(cafp); if (r == 0 && host_key != NULL) { - key_free(previous_host_key); - previous_host_key = key_from_private(host_key); + sshkey_free(previous_host_key); + r = sshkey_from_private(host_key, &previous_host_key); } return r; @@ -1382,7 +1385,7 @@ ssh_put_password(char *password) /* print all known host keys for a given host, but skip keys of given type */ static int -show_other_keys(struct hostkeys *hostkeys, Key *key) +show_other_keys(struct hostkeys *hostkeys, struct sshkey *key) { int type[] = { KEY_RSA, @@ -1422,7 +1425,7 @@ show_other_keys(struct hostkeys *hostkeys, Key *key) } static void -warn_changed_key(Key *host_key) +warn_changed_key(struct sshkey *host_key) { char *fp; @@ -1490,7 +1493,7 @@ ssh_local_cmd(const char *args) } void -maybe_add_key_to_agent(char *authfile, Key *private, char *comment, +maybe_add_key_to_agent(char *authfile, struct sshkey *private, char *comment, char *passphrase) { int auth_sock = -1, r; diff --git a/sshconnect.h b/sshconnect.h index cf1851a95..f4e73f7b1 100644 --- a/sshconnect.h +++ b/sshconnect.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.h,v 1.29 2015/11/15 22:26:49 jcs Exp $ */ +/* $OpenBSD: sshconnect.h,v 1.30 2017/05/30 08:52:19 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -26,9 +26,9 @@ typedef struct Sensitive Sensitive; struct Sensitive { - Key **keys; - int nkeys; - int external_keysign; + struct sshkey **keys; + int nkeys; + int external_keysign; }; struct addrinfo; @@ -41,7 +41,7 @@ void ssh_login(Sensitive *, const char *, struct sockaddr *, u_short, void ssh_exchange_identification(int); -int verify_host_key(char *, struct sockaddr *, Key *); +int verify_host_key(char *, struct sockaddr *, struct sshkey *); void get_hostfile_hostname_ipaddr(char *, struct sockaddr *, u_short, char **, char **); @@ -55,7 +55,7 @@ void ssh_userauth2(const char *, const char *, char *, Sensitive *); void ssh_put_password(char *); int ssh_local_cmd(const char *); -void maybe_add_key_to_agent(char *, Key *, char *, char *); +void maybe_add_key_to_agent(char *, struct sshkey *, char *, char *); /* * Macros to raise/lower permissions. diff --git a/sshconnect2.c b/sshconnect2.c index 819485b57..ad4f3dafd 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.258 2017/05/05 10:42:49 naddy Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.263 2017/05/31 07:00:13 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -93,7 +93,7 @@ char *xxx_host; struct sockaddr *xxx_hostaddr; static int -verify_host_key_callback(Key *hostkey, struct ssh *ssh) +verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh) { if (verify_host_key(xxx_host, xxx_hostaddr, hostkey) == -1) fatal("Host key verification failed."); @@ -222,7 +222,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) kex->server_version_string=server_version_string; kex->verify_host_key=&verify_host_key_callback; - dispatch_run(DISPATCH_BLOCK, &kex->done, active_state); + ssh_dispatch_run_fatal(active_state, DISPATCH_BLOCK, &kex->done); /* remove ext-info from the KEX proposals for rekeying */ myproposal[PROPOSAL_KEX_ALGS] = @@ -292,16 +292,16 @@ struct cauthmethod { int *batch_flag; /* flag in option struct that disables method */ }; -int input_userauth_service_accept(int, u_int32_t, void *); -int input_userauth_ext_info(int, u_int32_t, void *); -int input_userauth_success(int, u_int32_t, void *); -int input_userauth_success_unexpected(int, u_int32_t, void *); -int input_userauth_failure(int, u_int32_t, void *); -int input_userauth_banner(int, u_int32_t, void *); -int input_userauth_error(int, u_int32_t, void *); -int input_userauth_info_req(int, u_int32_t, void *); -int input_userauth_pk_ok(int, u_int32_t, void *); -int input_userauth_passwd_changereq(int, u_int32_t, void *); +int input_userauth_service_accept(int, u_int32_t, struct ssh *); +int input_userauth_ext_info(int, u_int32_t, struct ssh *); +int input_userauth_success(int, u_int32_t, struct ssh *); +int input_userauth_success_unexpected(int, u_int32_t, struct ssh *); +int input_userauth_failure(int, u_int32_t, struct ssh *); +int input_userauth_banner(int, u_int32_t, struct ssh *); +int input_userauth_error(int, u_int32_t, struct ssh *); +int input_userauth_info_req(int, u_int32_t, struct ssh *); +int input_userauth_pk_ok(int, u_int32_t, struct ssh *); +int input_userauth_passwd_changereq(int, u_int32_t, struct ssh *); int userauth_none(Authctxt *); int userauth_pubkey(Authctxt *); @@ -311,11 +311,11 @@ int userauth_hostbased(Authctxt *); #ifdef GSSAPI int userauth_gssapi(Authctxt *authctxt); -int input_gssapi_response(int type, u_int32_t, void *); -int input_gssapi_token(int type, u_int32_t, void *); -int input_gssapi_hash(int type, u_int32_t, void *); -int input_gssapi_error(int, u_int32_t, void *); -int input_gssapi_errtok(int, u_int32_t, void *); +int input_gssapi_response(int type, u_int32_t, struct ssh *); +int input_gssapi_token(int type, u_int32_t, struct ssh *); +int input_gssapi_hash(int type, u_int32_t, struct ssh *); +int input_gssapi_error(int, u_int32_t, struct ssh *); +int input_gssapi_errtok(int, u_int32_t, struct ssh *); #endif void userauth(Authctxt *, char *); @@ -324,7 +324,7 @@ static int sign_and_send_pubkey(Authctxt *, Identity *); static void pubkey_prepare(Authctxt *); static void pubkey_cleanup(Authctxt *); static void pubkey_reset(Authctxt *); -static Key *load_identity_file(Identity *); +static struct sshkey *load_identity_file(Identity *); static Authmethod *authmethod_get(char *authlist); static Authmethod *authmethod_lookup(const char *name); @@ -402,10 +402,12 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host, (r = sshpkt_send(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); + ssh->authctxt = &authctxt; ssh_dispatch_init(ssh, &input_userauth_error); ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &input_userauth_ext_info); ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_ACCEPT, &input_userauth_service_accept); - ssh_dispatch_run(ssh, DISPATCH_BLOCK, &authctxt.success, &authctxt); /* loop until success */ + ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt.success); /* loop until success */ + ssh->authctxt = NULL; pubkey_cleanup(&authctxt); ssh_dispatch_range(ssh, SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL); @@ -417,10 +419,9 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host, /* ARGSUSED */ int -input_userauth_service_accept(int type, u_int32_t seqnr, void *ctxt) +input_userauth_service_accept(int type, u_int32_t seq, struct ssh *ssh) { - Authctxt *authctxt = ctxt; - struct ssh *ssh = active_state; + Authctxt *authctxt = ssh->authctxt; int r; if (ssh_packet_remaining(ssh) > 0) { @@ -451,9 +452,9 @@ input_userauth_service_accept(int type, u_int32_t seqnr, void *ctxt) /* ARGSUSED */ int -input_userauth_ext_info(int type, u_int32_t seqnr, void *ctxt) +input_userauth_ext_info(int type, u_int32_t seqnr, struct ssh *ssh) { - return kex_input_ext_info(type, seqnr, active_state); + return kex_input_ext_info(type, seqnr, ssh); } void @@ -493,7 +494,7 @@ userauth(Authctxt *authctxt, char *authlist) /* ARGSUSED */ int -input_userauth_error(int type, u_int32_t seq, void *ctxt) +input_userauth_error(int type, u_int32_t seq, struct ssh *ssh) { fatal("input_userauth_error: bad message during authentication: " "type %d", type); @@ -502,7 +503,7 @@ input_userauth_error(int type, u_int32_t seq, void *ctxt) /* ARGSUSED */ int -input_userauth_banner(int type, u_int32_t seq, void *ctxt) +input_userauth_banner(int type, u_int32_t seq, struct ssh *ssh) { char *msg, *lang; u_int len; @@ -519,9 +520,9 @@ input_userauth_banner(int type, u_int32_t seq, void *ctxt) /* ARGSUSED */ int -input_userauth_success(int type, u_int32_t seq, void *ctxt) +input_userauth_success(int type, u_int32_t seq, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; if (authctxt == NULL) fatal("input_userauth_success: no authentication context"); @@ -536,9 +537,9 @@ input_userauth_success(int type, u_int32_t seq, void *ctxt) } int -input_userauth_success_unexpected(int type, u_int32_t seq, void *ctxt) +input_userauth_success_unexpected(int type, u_int32_t seq, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; if (authctxt == NULL) fatal("%s: no authentication context", __func__); @@ -550,9 +551,9 @@ input_userauth_success_unexpected(int type, u_int32_t seq, void *ctxt) /* ARGSUSED */ int -input_userauth_failure(int type, u_int32_t seq, void *ctxt) +input_userauth_failure(int type, u_int32_t seq, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; char *authlist = NULL; int partial; @@ -576,10 +577,10 @@ input_userauth_failure(int type, u_int32_t seq, void *ctxt) /* ARGSUSED */ int -input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt) +input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh) { - Authctxt *authctxt = ctxt; - Key *key = NULL; + Authctxt *authctxt = ssh->authctxt; + struct sshkey *key = NULL; Identity *id = NULL; Buffer b; int pktype, sent = 0; @@ -707,9 +708,9 @@ userauth_gssapi(Authctxt *authctxt) } static OM_uint32 -process_gssapi_token(void *ctxt, gss_buffer_t recv_tok) +process_gssapi_token(struct ssh *ssh, gss_buffer_t recv_tok) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; Gssctxt *gssctxt = authctxt->methoddata; gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; gss_buffer_desc mic = GSS_C_EMPTY_BUFFER; @@ -762,9 +763,9 @@ process_gssapi_token(void *ctxt, gss_buffer_t recv_tok) /* ARGSUSED */ int -input_gssapi_response(int type, u_int32_t plen, void *ctxt) +input_gssapi_response(int type, u_int32_t plen, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; Gssctxt *gssctxt; int oidlen; char *oidv; @@ -792,7 +793,7 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt) free(oidv); - if (GSS_ERROR(process_gssapi_token(ctxt, GSS_C_NO_BUFFER))) { + if (GSS_ERROR(process_gssapi_token(ssh, GSS_C_NO_BUFFER))) { /* Start again with next method on list */ debug("Trying to start again"); userauth(authctxt, NULL); @@ -803,9 +804,9 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt) /* ARGSUSED */ int -input_gssapi_token(int type, u_int32_t plen, void *ctxt) +input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; gss_buffer_desc recv_tok; OM_uint32 status; u_int slen; @@ -818,7 +819,7 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt) packet_check_eom(); - status = process_gssapi_token(ctxt, &recv_tok); + status = process_gssapi_token(ssh, &recv_tok); free(recv_tok.value); @@ -832,9 +833,9 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt) /* ARGSUSED */ int -input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) +input_gssapi_errtok(int type, u_int32_t plen, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; Gssctxt *gssctxt; gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; gss_buffer_desc recv_tok; @@ -863,7 +864,7 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) /* ARGSUSED */ int -input_gssapi_error(int type, u_int32_t plen, void *ctxt) +input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh) { char *msg; char *lang; @@ -934,9 +935,9 @@ userauth_passwd(Authctxt *authctxt) */ /* ARGSUSED */ int -input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt) +input_userauth_passwd_changereq(int type, u_int32_t seqnr, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; char *info, *lang, *password = NULL, *retype = NULL; char prompt[150]; const char *host; @@ -1020,7 +1021,7 @@ static int identity_sign(struct identity *id, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, u_int compat) { - Key *prv; + struct sshkey *prv; int ret; /* the agent supports this key */ @@ -1230,10 +1231,10 @@ send_pubkey_test(Authctxt *authctxt, Identity *id) return 1; } -static Key * +static struct sshkey * load_identity_file(Identity *id) { - Key *private = NULL; + struct sshkey *private = NULL; char prompt[300], *passphrase, *comment; int r, perm_ok = 0, quit = 0, i; struct stat st; @@ -1564,9 +1565,9 @@ userauth_kbdint(Authctxt *authctxt) * parse INFO_REQUEST, prompt user and send INFO_RESPONSE */ int -input_userauth_info_req(int type, u_int32_t seq, void *ctxt) +input_userauth_info_req(int type, u_int32_t seq, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; char *name, *inst, *lang, *prompt, *response; u_int num_prompts, i; int echo = 0; diff --git a/sshd.c b/sshd.c index 1248d9617..552f12ed0 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.487 2017/04/30 23:18:44 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.490 2017/05/31 08:09:45 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -200,10 +200,10 @@ int have_agent = 0; * not very useful. Currently, memory locking is not implemented. */ struct { - Key **host_keys; /* all private host keys */ - Key **host_pubkeys; /* all public host keys */ - Key **host_certificates; /* all public host certificates */ - int have_ssh2_key; + struct sshkey **host_keys; /* all private host keys */ + struct sshkey **host_pubkeys; /* all public host keys */ + struct sshkey **host_certificates; /* all public host certificates */ + int have_ssh2_key; } sensitive_data; /* This is set to true when a signal is received. */ @@ -504,7 +504,7 @@ destroy_sensitive_data(void) void demote_sensitive_data(void) { - Key *tmp; + struct sshkey *tmp; int i; for (i = 0; i < options.num_host_key_files; i++) { @@ -690,6 +690,7 @@ privsep_postauth(Authctxt *authctxt) else if (pmonitor->m_pid != 0) { verbose("User child is on pid %ld", (long)pmonitor->m_pid); buffer_clear(&loginmsg); + monitor_clear_keystate(pmonitor); monitor_child_postauth(pmonitor); /* NEVERREACHED */ @@ -729,7 +730,7 @@ list_hostkey_types(void) const char *p; char *ret; int i; - Key *key; + struct sshkey *key; buffer_init(&b); for (i = 0; i < options.num_host_key_files; i++) { @@ -785,11 +786,11 @@ list_hostkey_types(void) return ret; } -static Key * +static struct sshkey * get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) { int i; - Key *key; + struct sshkey *key; for (i = 0; i < options.num_host_key_files; i++) { switch (type) { @@ -813,19 +814,19 @@ get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) return NULL; } -Key * +struct sshkey * get_hostkey_public_by_type(int type, int nid, struct ssh *ssh) { return get_hostkey_by_type(type, nid, 0, ssh); } -Key * +struct sshkey * get_hostkey_private_by_type(int type, int nid, struct ssh *ssh) { return get_hostkey_by_type(type, nid, 1, ssh); } -Key * +struct sshkey * get_hostkey_by_index(int ind) { if (ind < 0 || ind >= options.num_host_key_files) @@ -833,7 +834,7 @@ get_hostkey_by_index(int ind) return (sensitive_data.host_keys[ind]); } -Key * +struct sshkey * get_hostkey_public_by_index(int ind, struct ssh *ssh) { if (ind < 0 || ind >= options.num_host_key_files) @@ -842,7 +843,7 @@ get_hostkey_public_by_index(int ind, struct ssh *ssh) } int -get_hostkey_index(Key *key, int compare, struct ssh *ssh) +get_hostkey_index(struct sshkey *key, int compare, struct ssh *ssh) { int i; @@ -1450,8 +1451,8 @@ main(int ac, char **av) u_int n; u_int64_t ibytes, obytes; mode_t new_umask; - Key *key; - Key *pubkey; + struct sshkey *key; + struct sshkey *pubkey; int keytype; Authctxt *authctxt; struct connection_info *connection_info = get_connection_info(0, 0); @@ -1750,9 +1751,9 @@ main(int ac, char **av) /* load host keys */ sensitive_data.host_keys = xcalloc(options.num_host_key_files, - sizeof(Key *)); + sizeof(struct sshkey *)); sensitive_data.host_pubkeys = xcalloc(options.num_host_key_files, - sizeof(Key *)); + sizeof(struct sshkey *)); if (options.host_key_agent) { if (strcmp(options.host_key_agent, SSH_AUTHSOCKET_ENV_NAME)) @@ -1818,7 +1819,7 @@ main(int ac, char **av) * indices to the public keys that they relate to. */ sensitive_data.host_certificates = xcalloc(options.num_host_key_files, - sizeof(Key *)); + sizeof(struct sshkey *)); for (i = 0; i < options.num_host_key_files; i++) sensitive_data.host_certificates[i] = NULL; @@ -2154,6 +2155,7 @@ main(int ac, char **av) */ if (use_privsep) { mm_send_keystate(pmonitor); + packet_clear_keys(); exit(0); } @@ -2231,8 +2233,9 @@ main(int ac, char **av) } int -sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, size_t *slen, - const u_char *data, size_t dlen, const char *alg, u_int flag) +sshd_hostkey_sign(struct sshkey *privkey, struct sshkey *pubkey, + u_char **signature, size_t *slen, const u_char *data, size_t dlen, + const char *alg, u_int flag) { int r; u_int xxx_slen, xxx_dlen = dlen; @@ -2312,7 +2315,7 @@ do_ssh2_kex(void) kex->host_key_index=&get_hostkey_index; kex->sign = sshd_hostkey_sign; - dispatch_run(DISPATCH_BLOCK, &kex->done, active_state); + ssh_dispatch_run_fatal(active_state, DISPATCH_BLOCK, &kex->done); session_id2 = kex->session_id; session_id2_len = kex->session_id_len; diff --git a/sshkey.c b/sshkey.c index f9518bd77..9a3f0be58 100644 --- a/sshkey.c +++ b/sshkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey.c,v 1.50 2017/05/08 06:11:06 djm Exp $ */ +/* $OpenBSD: sshkey.c,v 1.51 2017/05/31 09:15:42 deraadt Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * Copyright (c) 2008 Alexander von Gernler. All rights reserved. @@ -1764,8 +1764,9 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf) goto out; } oprincipals = key->cert->principals; - key->cert->principals = reallocarray(key->cert->principals, - key->cert->nprincipals + 1, sizeof(*key->cert->principals)); + key->cert->principals = recallocarray(key->cert->principals, + key->cert->nprincipals, key->cert->nprincipals + 1, + sizeof(*key->cert->principals)); if (key->cert->principals == NULL) { free(principal); key->cert->principals = oprincipals; diff --git a/umac.c b/umac.c index 6eb55b26e..9f2187c9a 100644 --- a/umac.c +++ b/umac.c @@ -1,4 +1,4 @@ -/* $OpenBSD: umac.c,v 1.11 2014/07/22 07:13:42 guenther Exp $ */ +/* $OpenBSD: umac.c,v 1.12 2017/05/31 08:09:45 markus Exp $ */ /* ----------------------------------------------------------------------- * * umac.c -- C Implementation UMAC Message Authentication @@ -203,6 +203,8 @@ static void kdf(void *bufp, aes_int_key key, UINT8 ndx, int nbytes) aes_encryption(in_buf, out_buf, key); memcpy(dst_buf,out_buf,nbytes); } + explicit_bzero(in_buf, sizeof(in_buf)); + explicit_bzero(out_buf, sizeof(out_buf)); } /* The final UHASH result is XOR'd with the output of a pseudorandom @@ -227,6 +229,7 @@ static void pdf_init(pdf_ctx *pc, aes_int_key prf_key) /* Initialize pdf and cache */ memset(pc->nonce, 0, sizeof(pc->nonce)); aes_encryption(pc->nonce, pc->cache, pc->prf_key); + explicit_bzero(buf, sizeof(buf)); } static void pdf_gen_xor(pdf_ctx *pc, const UINT8 nonce[8], UINT8 buf[8]) @@ -991,6 +994,7 @@ static void uhash_init(uhash_ctx_t ahc, aes_int_key prf_key) kdf(ahc->ip_trans, prf_key, 4, STREAMS * sizeof(UINT32)); endian_convert_if_le(ahc->ip_trans, sizeof(UINT32), STREAMS * sizeof(UINT32)); + explicit_bzero(buf, sizeof(buf)); } /* ---------------------------------------------------------------------- */ @@ -1200,6 +1204,7 @@ int umac_delete(struct umac_ctx *ctx) if (ctx) { if (ALLOC_BOUNDARY) ctx = (struct umac_ctx *)ctx->free_ptr; + explicit_bzero(ctx, sizeof(*ctx) + ALLOC_BOUNDARY); free(ctx); } return (1); @@ -1227,6 +1232,7 @@ struct umac_ctx *umac_new(const u_char key[]) aes_key_setup(key, prf_key); pdf_init(&ctx->pdf, prf_key); uhash_init(&ctx->hash, prf_key); + explicit_bzero(prf_key, sizeof(prf_key)); } return (ctx); diff --git a/utf8.c b/utf8.c index da5778138..bc131385f 100644 --- a/utf8.c +++ b/utf8.c @@ -1,4 +1,4 @@ -/* $OpenBSD: utf8.c,v 1.6 2017/04/17 14:31:23 schwarze Exp $ */ +/* $OpenBSD: utf8.c,v 1.7 2017/05/31 09:15:42 deraadt Exp $ */ /* * Copyright (c) 2016 Ingo Schwarze * @@ -76,7 +76,7 @@ grow_dst(char **dst, size_t *sz, size_t maxsz, char **dp, size_t need) tsz = *sz + 128; if (tsz > maxsz) tsz = maxsz; - if ((tp = realloc(*dst, tsz)) == NULL) + if ((tp = recallocarray(*dst, *sz, tsz, 1)) == NULL) return -1; *dp = tp + (*dp - *dst); *dst = tp; diff --git a/xmalloc.c b/xmalloc.c index b58323677..5cc0310a4 100644 --- a/xmalloc.c +++ b/xmalloc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: xmalloc.c,v 1.33 2016/02/15 09:47:49 dtucker Exp $ */ +/* $OpenBSD: xmalloc.c,v 1.34 2017/05/31 09:15:42 deraadt Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -77,6 +77,18 @@ xreallocarray(void *ptr, size_t nmemb, size_t size) return new_ptr; } +void * +xrecallocarray(void *ptr, size_t onmemb, size_t nmemb, size_t size) +{ + void *new_ptr; + + new_ptr = recallocarray(ptr, onmemb, nmemb, size); + if (new_ptr == NULL) + fatal("xrecallocarray: out of memory (%zu elements of %zu bytes)", + nmemb, size); + return new_ptr; +} + char * xstrdup(const char *str) { diff --git a/xmalloc.h b/xmalloc.h index e49928932..cf38ddfa4 100644 --- a/xmalloc.h +++ b/xmalloc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: xmalloc.h,v 1.16 2016/02/15 09:47:49 dtucker Exp $ */ +/* $OpenBSD: xmalloc.h,v 1.17 2017/05/31 09:15:42 deraadt Exp $ */ /* * Author: Tatu Ylonen @@ -20,6 +20,7 @@ void ssh_malloc_init(void); void *xmalloc(size_t); void *xcalloc(size_t, size_t); void *xreallocarray(void *, size_t, size_t); +void *xrecallocarray(void *, size_t, size_t, size_t); char *xstrdup(const char *); int xasprintf(char **, const char *, ...) __attribute__((__format__ (printf, 2, 3)))