diff options
Diffstat (limited to 'include/libssh')
53 files changed, 1318 insertions, 247 deletions
diff --git a/include/libssh/CMakeLists.txt b/include/libssh/CMakeLists.txt index 83e7b9f8..93445680 100644 --- a/include/libssh/CMakeLists.txt +++ b/include/libssh/CMakeLists.txt @@ -20,6 +20,13 @@ if (WITH_SERVER) ${libssh_HDRS} server.h ) + + if (WITH_SFTP) + set(libssh_HDRS + ${libssh_HDRS} + sftpserver.h + ) + endif (WITH_SFTP) endif (WITH_SERVER) install( diff --git a/include/libssh/agent.h b/include/libssh/agent.h index d4eefbbf..caf8d3e2 100644 --- a/include/libssh/agent.h +++ b/include/libssh/agent.h @@ -70,6 +70,10 @@ #define SSH_AGENT_RSA_SHA2_256 0x02 #define SSH_AGENT_RSA_SHA2_512 0x04 +#ifdef __cplusplus +extern "C" { +#endif + struct ssh_agent_struct { struct ssh_socket_struct *sock; ssh_buffer ident; @@ -77,7 +81,6 @@ struct ssh_agent_struct { ssh_channel channel; }; -#ifndef _WIN32 /* agent.c */ /** * @brief Create a new ssh agent structure. @@ -115,6 +118,9 @@ ssh_key ssh_agent_get_first_ident(struct ssh_session_struct *session, ssh_string ssh_agent_sign_data(ssh_session session, const ssh_key pubkey, struct ssh_buffer_struct *data); + +#ifdef __cplusplus +} #endif #endif /* __AGENT_H */ diff --git a/include/libssh/auth.h b/include/libssh/auth.h index 90b377d4..b358b7a2 100644 --- a/include/libssh/auth.h +++ b/include/libssh/auth.h @@ -23,6 +23,10 @@ #include "config.h" #include "libssh/callbacks.h" +#ifdef __cplusplus +extern "C" { +#endif + SSH_PACKET_CALLBACK(ssh_packet_userauth_banner); SSH_PACKET_CALLBACK(ssh_packet_userauth_failure); SSH_PACKET_CALLBACK(ssh_packet_userauth_success); @@ -100,4 +104,8 @@ enum ssh_auth_service_state_e { SSH_AUTH_SERVICE_DENIED, }; +#ifdef __cplusplus +} +#endif + #endif /* AUTH_H_ */ diff --git a/include/libssh/bignum.h b/include/libssh/bignum.h index 726ed7b9..6b5dc1a2 100644 --- a/include/libssh/bignum.h +++ b/include/libssh/bignum.h @@ -25,9 +25,16 @@ #include "libssh/libgcrypt.h" #include "libssh/libmbedcrypto.h" +#ifdef __cplusplus +extern "C" { +#endif + bignum ssh_make_string_bn(ssh_string string); ssh_string ssh_make_bignum_string(bignum num); void ssh_print_bignum(const char *which, const_bignum num); +#ifdef __cplusplus +} +#endif #endif /* BIGNUM_H_ */ diff --git a/include/libssh/bind.h b/include/libssh/bind.h index 6b5f19dd..cd9199b6 100644 --- a/include/libssh/bind.h +++ b/include/libssh/bind.h @@ -25,6 +25,10 @@ #include "libssh/kex.h" #include "libssh/session.h" +#ifdef __cplusplus +extern "C" { +#endif + struct ssh_bind_struct { struct ssh_common_struct common; /* stuff common to ssh_bind and ssh_session */ struct ssh_bind_callbacks_struct *bind_callbacks; @@ -35,11 +39,9 @@ struct ssh_bind_struct { char *wanted_methods[SSH_KEX_METHODS]; char *banner; char *ecdsakey; - char *dsakey; char *rsakey; char *ed25519key; ssh_key ecdsa; - ssh_key dsa; ssh_key rsa; ssh_key ed25519; char *bindaddr; @@ -50,10 +52,15 @@ struct ssh_bind_struct { bool config_processed; char *config_dir; char *pubkey_accepted_key_types; + char* moduli_file; + int rsa_min_size; }; struct ssh_poll_handle_struct *ssh_bind_get_poll(struct ssh_bind_struct *sshbind); +#ifdef __cplusplus +} +#endif #endif /* BIND_H_ */ diff --git a/include/libssh/bind_config.h b/include/libssh/bind_config.h index cb68da89..5f2dccce 100644 --- a/include/libssh/bind_config.h +++ b/include/libssh/bind_config.h @@ -28,6 +28,10 @@ #include "libssh/server.h" +#ifdef __cplusplus +extern "C" { +#endif + enum ssh_bind_config_opcode_e { /* Known but not allowed in Match block */ BIND_CFG_NOT_ALLOWED_IN_MATCH = -4, @@ -61,4 +65,18 @@ enum ssh_bind_config_opcode_e { */ int ssh_bind_config_parse_file(ssh_bind sshbind, const char *filename); +/* @brief Parse configuration string and set the options to the given bind session + * + * @params[in] bind The ssh bind session + * @params[in] input Null terminated string containing the configuration + * + * @returns SSH_OK on successful parsing the configuration string, + * SSH_ERROR on error + */ +int ssh_bind_config_parse_string(ssh_bind bind, const char *input); + +#ifdef __cplusplus +} +#endif + #endif /* BIND_CONFIG_H_ */ diff --git a/include/libssh/blf.h b/include/libssh/blf.h index ce131e6b..201821a2 100644 --- a/include/libssh/blf.h +++ b/include/libssh/blf.h @@ -49,6 +49,10 @@ #define BLF_MAXKEYLEN ((BLF_N-2)*4) /* 448 bits */ #define BLF_MAXUTILIZED ((BLF_N+2)*4) /* 576 bits */ +#ifdef __cplusplus +extern "C" { +#endif + /* Blowfish context */ typedef struct BlowfishContext { uint32_t S[4][256]; /* S-Boxes */ @@ -84,4 +88,9 @@ void ssh_blf_cbc_decrypt(ssh_blf_ctx *, uint8_t *, uint8_t *, uint32_t); uint32_t Blowfish_stream2word(const uint8_t *, uint16_t , uint16_t *); #endif /* !defined(HAVE_BCRYPT_PBKDF) && !defined(HAVE_BLH_H) */ + +#ifdef __cplusplus +} +#endif + #endif /* _BLF_H */ diff --git a/include/libssh/buffer.h b/include/libssh/buffer.h index cd2dea6a..1fce7b76 100644 --- a/include/libssh/buffer.h +++ b/include/libssh/buffer.h @@ -27,6 +27,10 @@ #define SSH_BUFFER_PACK_END ((uint32_t) 0x4f65feb3) +#ifdef __cplusplus +extern "C" { +#endif + void ssh_buffer_set_secure(ssh_buffer buffer); int ssh_buffer_add_ssh_string(ssh_buffer buffer, ssh_string string); int ssh_buffer_add_u8(ssh_buffer buffer, uint8_t data); @@ -63,9 +67,9 @@ int ssh_buffer_prepend_data(ssh_buffer buffer, const void *data, uint32_t len); int ssh_buffer_add_buffer(ssh_buffer buffer, ssh_buffer source); /* buffer_read_*() returns the number of bytes read, except for ssh strings */ -int ssh_buffer_get_u8(ssh_buffer buffer, uint8_t *data); -int ssh_buffer_get_u32(ssh_buffer buffer, uint32_t *data); -int ssh_buffer_get_u64(ssh_buffer buffer, uint64_t *data); +uint32_t ssh_buffer_get_u8(ssh_buffer buffer, uint8_t *data); +uint32_t ssh_buffer_get_u32(ssh_buffer buffer, uint32_t *data); +uint32_t ssh_buffer_get_u64(ssh_buffer buffer, uint64_t *data); /* ssh_buffer_get_ssh_string() is an exception. if the String read is too large or invalid, it will answer NULL. */ ssh_string ssh_buffer_get_ssh_string(ssh_buffer buffer); @@ -74,4 +78,8 @@ ssh_string ssh_buffer_get_ssh_string(ssh_buffer buffer); uint32_t ssh_buffer_pass_bytes_end(ssh_buffer buffer, uint32_t len); uint32_t ssh_buffer_pass_bytes(ssh_buffer buffer, uint32_t len); +#ifdef __cplusplus +} +#endif + #endif /* BUFFER_H_ */ diff --git a/include/libssh/callbacks.h b/include/libssh/callbacks.h index 972314cb..29c1d391 100644 --- a/include/libssh/callbacks.h +++ b/include/libssh/callbacks.h @@ -27,6 +27,7 @@ #include <libssh/libssh.h> #include <string.h> +#include <stdbool.h> #ifdef __cplusplus extern "C" { @@ -56,7 +57,7 @@ typedef void (*ssh_callback_int) (int code, void *user); * @returns number of bytes processed by the callee. The remaining bytes will * be sent in the next callback message, when more data is available. */ -typedef int (*ssh_callback_data) (const void *data, size_t len, void *user); +typedef size_t (*ssh_callback_data) (const void *data, size_t len, void *user); typedef void (*ssh_callback_int_int) (int code, int errno_code, void *user); @@ -81,9 +82,9 @@ typedef void (*ssh_log_callback) (ssh_session session, int priority, * * @param priority Priority of the log, the smaller being the more important. * - * @param function The function name calling the the logging fucntions. + * @param function The function name calling the logging functions. * - * @param message The actual message + * @param buffer The actual message * * @param userdata Userdata to be passed to the callback function. */ @@ -117,6 +118,8 @@ typedef void (*ssh_global_request_callback) (ssh_session session, * sends back an X11 connection attempt. This is a client-side API * @param session current session handler * @param userdata Userdata to be passed to the callback function. + * @param originator_address IP address of the machine who sent the request + * @param originator_port port number of the machine who sent the request * @returns a valid ssh_channel handle if the request is to be allowed * @returns NULL if the request should not be allowed * @warning The channel pointer returned by this callback must be closed by the application. @@ -137,6 +140,26 @@ typedef ssh_channel (*ssh_channel_open_request_auth_agent_callback) (ssh_session void *userdata); /** + * @brief Handles an SSH new channel open "forwarded-tcpip" request. This + * happens when the server forwards an incoming TCP connection on a port it was + * previously requested to listen on. This is a client-side API + * @param session current session handler + * @param destination_address the address that the TCP connection connected to + * @param destination_port the port that the TCP connection connected to + * @param originator_address the originator IP address + * @param originator_port the originator port + * @param userdata Userdata to be passed to the callback function. + * @returns a valid ssh_channel handle if the request is to be allowed + * @returns NULL if the request should not be allowed + * @warning The channel pointer returned by this callback must be closed by the + * application. + */ +typedef ssh_channel (*ssh_channel_open_request_forwarded_tcpip_callback) (ssh_session session, + const char *destination_address, int destination_port, + const char *originator_address, int originator_port, + void *userdata); + +/** * The structure to replace libssh functions with appropriate callbacks. */ struct ssh_callbacks_struct { @@ -169,6 +192,11 @@ struct ssh_callbacks_struct { /** This function will be called when an incoming "auth-agent" request is received. */ ssh_channel_open_request_auth_agent_callback channel_open_request_auth_agent_function; + /** + * This function will be called when an incoming "forwarded-tcpip" + * request is received. + */ + ssh_channel_open_request_forwarded_tcpip_callback channel_open_request_forwarded_tcpip_function; }; typedef struct ssh_callbacks_struct *ssh_callbacks; @@ -221,8 +249,8 @@ typedef int (*ssh_auth_gssapi_mic_callback) (ssh_session session, const char *us * @param user User that wants to authenticate * @param pubkey public key used for authentication * @param signature_state SSH_PUBLICKEY_STATE_NONE if the key is not signed (simple public key probe), - * SSH_PUBLICKEY_STATE_VALID if the signature is valid. Others values should be - * replied with a SSH_AUTH_DENIED. + * SSH_PUBLICKEY_STATE_VALID if the signature is valid. Others values should be + * replied with a SSH_AUTH_DENIED. * @param userdata Userdata to be passed to the callback function. * @returns SSH_AUTH_SUCCESS Authentication is accepted. * @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed. @@ -268,11 +296,11 @@ typedef ssh_string (*ssh_gssapi_select_oid_callback) (ssh_session session, const int n_oid, ssh_string *oids, void *userdata); /* - * @brief handle the negociation of a security context, server side. + * @brief handle the negotiation of a security context, server side. * @param session current session handler * @param[in] input_token input token provided by client * @param[out] output_token output of the gssapi accept_sec_context method, - * NULL after completion. + * NULL after completion. * @returns SSH_OK if the token was generated correctly or accept_sec_context * returned GSS_S_COMPLETE * @returns SSH_ERROR in case of error @@ -397,7 +425,7 @@ struct ssh_socket_callbacks_struct { */ ssh_callback_int_int exception; /** This function is called when the ssh_socket_connect was used on the socket - * on nonblocking state, and the connection successed. + * on nonblocking state, and the connection succeeded. */ ssh_callback_int_int connected; }; @@ -625,6 +653,7 @@ typedef void (*ssh_channel_signal_callback) (ssh_session session, * @brief SSH channel exit status callback. Called when a channel has received an exit status * @param session Current session handler * @param channel the actual channel + * @param exit_status Exit status of the ran command * @param userdata Userdata to be passed to the callback function. */ typedef void (*ssh_channel_exit_status_callback) (ssh_session session, @@ -637,7 +666,7 @@ typedef void (*ssh_channel_exit_status_callback) (ssh_session session, * @param session Current session handler * @param channel the actual channel * @param signal the signal name (without the SIG prefix) - * @param core a boolean telling wether a core has been dumped or not + * @param core a boolean telling whether a core has been dumped or not * @param errmsg the description of the exception * @param lang the language of the description (format: RFC 3066) * @param userdata Userdata to be passed to the callback function. @@ -652,12 +681,13 @@ typedef void (*ssh_channel_exit_signal_callback) (ssh_session session, /** * @brief SSH channel PTY request from a client. + * @param session the session * @param channel the channel * @param term The type of terminal emulation * @param width width of the terminal, in characters * @param height height of the terminal, in characters * @param pxwidth width of the terminal, in pixels - * @param pxheight height of the terminal, in pixels + * @param pwheight height of the terminal, in pixels * @param userdata Userdata to be passed to the callback function. * @returns 0 if the pty request is accepted * @returns -1 if the request is denied @@ -671,6 +701,7 @@ typedef int (*ssh_channel_pty_request_callback) (ssh_session session, /** * @brief SSH channel Shell request from a client. + * @param session the session * @param channel the channel * @param userdata Userdata to be passed to the callback function. * @returns 0 if the shell request is accepted @@ -683,6 +714,7 @@ typedef int (*ssh_channel_shell_request_callback) (ssh_session session, * @brief SSH auth-agent-request from the client. This request is * sent by a client when agent forwarding is available. * Server is free to ignore this callback, no answer is expected. + * @param session the session * @param channel the channel * @param userdata Userdata to be passed to the callback function. */ @@ -694,7 +726,12 @@ typedef void (*ssh_channel_auth_agent_req_callback) (ssh_session session, * @brief SSH X11 request from the client. This request is * sent by a client when X11 forwarding is requested(and available). * Server is free to ignore this callback, no answer is expected. + * @param session the session * @param channel the channel + * @param single_connection If true, only one channel should be forwarded + * @param auth_protocol The X11 authentication method to be used + * @param auth_cookie Authentication cookie encoded hexadecimal + * @param screen_number Screen number * @param userdata Userdata to be passed to the callback function. */ typedef void (*ssh_channel_x11_req_callback) (ssh_session session, @@ -706,11 +743,12 @@ typedef void (*ssh_channel_x11_req_callback) (ssh_session session, void *userdata); /** * @brief SSH channel PTY windows change (terminal size) from a client. + * @param session the session * @param channel the channel * @param width width of the terminal, in characters * @param height height of the terminal, in characters * @param pxwidth width of the terminal, in pixels - * @param pxheight height of the terminal, in pixels + * @param pwheight height of the terminal, in pixels * @param userdata Userdata to be passed to the callback function. * @returns 0 if the pty request is accepted * @returns -1 if the request is denied @@ -723,6 +761,7 @@ typedef int (*ssh_channel_pty_window_change_callback) (ssh_session session, /** * @brief SSH channel Exec request from a client. + * @param session the session * @param channel the channel * @param command the shell command to be executed * @param userdata Userdata to be passed to the callback function. @@ -736,6 +775,7 @@ typedef int (*ssh_channel_exec_request_callback) (ssh_session session, /** * @brief SSH channel environment request from a client. + * @param session the session * @param channel the channel * @param env_name name of the environment value to be set * @param env_value value of the environment value to be set @@ -752,6 +792,7 @@ typedef int (*ssh_channel_env_request_callback) (ssh_session session, void *userdata); /** * @brief SSH channel subsystem request from a client. + * @param session the session * @param channel the channel * @param subsystem the subsystem required * @param userdata Userdata to be passed to the callback function. @@ -766,6 +807,8 @@ typedef int (*ssh_channel_subsystem_request_callback) (ssh_session session, /** * @brief SSH channel write will not block (flow control). * + * @param session the session + * * @param channel the channel * * @param[in] bytes size of the remote window in bytes. Writing as much data @@ -777,9 +820,31 @@ typedef int (*ssh_channel_subsystem_request_callback) (ssh_session session, */ typedef int (*ssh_channel_write_wontblock_callback) (ssh_session session, ssh_channel channel, - size_t bytes, + uint32_t bytes, void *userdata); +/** + * @brief SSH channel open callback. Called when a channel open succeeds or fails. + * @param session Current session handler + * @param channel the actual channel + * @param is_success is 1 when the open succeeds, and 0 otherwise. + * @param userdata Userdata to be passed to the callback function. + */ +typedef void (*ssh_channel_open_resp_callback) (ssh_session session, + ssh_channel channel, + bool is_success, + void *userdata); + +/** + * @brief SSH channel request response callback. Called when a response to the pending request is received. + * @param session Current session handler + * @param channel the actual channel + * @param userdata Userdata to be passed to the callback function. + */ +typedef void (*ssh_channel_request_resp_callback) (ssh_session session, + ssh_channel channel, + void *userdata); + struct ssh_channel_callbacks_struct { /** DON'T SET THIS use ssh_callbacks_init() instead. */ size_t size; @@ -847,6 +912,14 @@ struct ssh_channel_callbacks_struct { * not to block. */ ssh_channel_write_wontblock_callback channel_write_wontblock_function; + /** + * This functions will be called when the channel has received a channel open confirmation or failure. + */ + ssh_channel_open_resp_callback channel_open_response_function; + /** + * This functions will be called when the channel has received the response to the pending request. + */ + ssh_channel_request_resp_callback channel_request_response_function; }; typedef struct ssh_channel_callbacks_struct *ssh_channel_callbacks; @@ -917,7 +990,7 @@ LIBSSH_API int ssh_remove_channel_callbacks(ssh_channel channel, /** @} */ -/** @group libssh_threads +/** @addtogroup libssh_threads * @{ */ @@ -983,13 +1056,14 @@ LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_pthread(void); * @see ssh_threads_set_callbacks */ LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_noop(void); +/** @} */ /** * @brief Set the logging callback function. * * @param[in] cb The callback to set. * - * @return 0 on success, < 0 on errror. + * @return 0 on success, < 0 on error. */ LIBSSH_API int ssh_set_log_callback(ssh_logging_callback cb); @@ -1000,7 +1074,6 @@ LIBSSH_API int ssh_set_log_callback(ssh_logging_callback cb); */ LIBSSH_API ssh_logging_callback ssh_get_log_callback(void); -/** @} */ #ifdef __cplusplus } #endif diff --git a/include/libssh/chacha.h b/include/libssh/chacha.h index 867f532d..ab3fe492 100644 --- a/include/libssh/chacha.h +++ b/include/libssh/chacha.h @@ -18,6 +18,10 @@ struct chacha_ctx { #define CHACHA_CTRLEN 8 #define CHACHA_STATELEN (CHACHA_NONCELEN+CHACHA_CTRLEN) +#ifdef __cplusplus +extern "C" { +#endif + void chacha_keysetup(struct chacha_ctx *x, const uint8_t *k, uint32_t kbits) #ifdef HAVE_GCC_BOUNDED_ATTRIBUTE __attribute__((__bounded__(__minbytes__, 2, CHACHA_MINKEYLEN))) @@ -37,4 +41,8 @@ void chacha_encrypt_bytes(struct chacha_ctx *x, const uint8_t *m, #endif ; +#ifdef __cplusplus +} +#endif + #endif /* CHACHA_H */ diff --git a/include/libssh/channels.h b/include/libssh/channels.h index bbabcfd1..cb2bea43 100644 --- a/include/libssh/channels.h +++ b/include/libssh/channels.h @@ -22,6 +22,10 @@ #define CHANNELS_H_ #include "libssh/priv.h" +#ifdef __cplusplus +extern "C" { +#endif + /** @internal * Describes the different possible states in a * outgoing (client) channel request @@ -35,7 +39,7 @@ enum ssh_channel_request_state_e { SSH_CHANNEL_REQ_STATE_ACCEPTED, /** A request has been replied and refused */ SSH_CHANNEL_REQ_STATE_DENIED, - /** A request has been replied and an error happend */ + /** A request has been replied and an error happened */ SSH_CHANNEL_REQ_STATE_ERROR }; @@ -98,7 +102,7 @@ SSH_PACKET_CALLBACK(channel_rcv_request); SSH_PACKET_CALLBACK(channel_rcv_data); int channel_default_bufferize(ssh_channel channel, - void *data, size_t len, + void *data, uint32_t len, bool is_stderr); int ssh_channel_flush(ssh_channel channel); uint32_t ssh_channel_new_id(ssh_session session); @@ -109,4 +113,8 @@ int ssh_global_request(ssh_session session, ssh_buffer buffer, int reply); +#ifdef __cplusplus +} +#endif + #endif /* CHANNELS_H_ */ diff --git a/include/libssh/config.h b/include/libssh/config.h index f2b9b57c..4f8a9b6f 100644 --- a/include/libssh/config.h +++ b/include/libssh/config.h @@ -42,7 +42,6 @@ enum ssh_config_opcode_e { SOC_MACS, SOC_COMPRESSION, SOC_TIMEOUT, - SOC_PROTOCOL, SOC_STRICTHOSTKEYCHECK, SOC_KNOWNHOSTS, SOC_PROXYCOMMAND, @@ -60,8 +59,13 @@ enum ssh_config_opcode_e { SOC_KBDINTERACTIVEAUTHENTICATION, SOC_PASSWORDAUTHENTICATION, SOC_PUBKEYAUTHENTICATION, - SOC_PUBKEYACCEPTEDTYPES, + SOC_PUBKEYACCEPTEDKEYTYPES, SOC_REKEYLIMIT, + SOC_IDENTITYAGENT, + SOC_IDENTITIESONLY, + SOC_CONTROLMASTER, + SOC_CONTROLPATH, + SOC_CERTIFICATE, SOC_MAX /* Keep this one last in the list */ }; diff --git a/include/libssh/config_parser.h b/include/libssh/config_parser.h index e974917c..4648614c 100644 --- a/include/libssh/config_parser.h +++ b/include/libssh/config_parser.h @@ -26,6 +26,12 @@ #ifndef CONFIG_PARSER_H_ #define CONFIG_PARSER_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdbool.h> + char *ssh_config_get_cmd(char **str); char *ssh_config_get_token(char **str); @@ -45,13 +51,20 @@ int ssh_config_get_yesno(char **str, int notfound); * be stored or NULL if we do not care about the result. * @param[out] port Pointer to the location, where the new port will * be stored or NULL if we do not care about the result. + * @param[in] ignore_port Set to true if we should not attempt to parse + * port number. * * @returns SSH_OK if the provided string is in format of SSH URI, * SSH_ERROR on failure */ int ssh_config_parse_uri(const char *tok, - char **username, - char **hostname, - char **port); + char **username, + char **hostname, + char **port, + bool ignore_port); + +#ifdef __cplusplus +} +#endif #endif /* LIBSSH_CONFIG_H_ */ diff --git a/include/libssh/crypto.h b/include/libssh/crypto.h index 67d98392..32016827 100644 --- a/include/libssh/crypto.h +++ b/include/libssh/crypto.h @@ -111,7 +111,11 @@ struct ssh_crypto_struct { #endif /* WITH_GEX */ #ifdef HAVE_ECDH #ifdef HAVE_OPENSSL_ECC +#if OPENSSL_VERSION_NUMBER < 0x30000000L EC_KEY *ecdh_privkey; +#else + EVP_PKEY *ecdh_privkey; +#endif /* OPENSSL_VERSION_NUMBER */ #elif defined HAVE_GCRYPT_ECC gcry_sexp_t ecdh_privkey; #elif defined HAVE_LIBMBEDCRYPTO @@ -126,8 +130,9 @@ struct ssh_crypto_struct { ssh_curve25519_pubkey curve25519_server_pubkey; #endif ssh_string dh_server_signature; /* information used by dh_handshake. */ - size_t digest_len; /* len of the two fields below */ + size_t session_id_len; unsigned char *session_id; + size_t digest_len; /* len of the secret hash */ unsigned char *secret_hash; /* Secret hash is same as session id until re-kex */ unsigned char *encryptIV; unsigned char *decryptIV; @@ -207,12 +212,23 @@ struct ssh_cipher_struct { void (*cleanup)(struct ssh_cipher_struct *cipher); }; +#ifdef __cplusplus +extern "C" { +#endif + const struct ssh_cipher_struct *ssh_get_chacha20poly1305_cipher(void); int sshkdf_derive_key(struct ssh_crypto_struct *crypto, unsigned char *key, size_t key_len, - int key_type, unsigned char *output, + uint8_t key_type, unsigned char *output, size_t requested_len); int secure_memcmp(const void *s1, const void *s2, size_t n); +#if defined(HAVE_LIBCRYPTO) && !defined(WITH_PKCS11_PROVIDER) +ENGINE *pki_get_engine(void); +#endif /* HAVE_LIBCRYPTO */ + +#ifdef __cplusplus +} +#endif #endif /* _CRYPTO_H_ */ diff --git a/include/libssh/curve25519.h b/include/libssh/curve25519.h index f0cc6348..a55f52c7 100644 --- a/include/libssh/curve25519.h +++ b/include/libssh/curve25519.h @@ -33,6 +33,10 @@ #define crypto_scalarmult crypto_scalarmult_curve25519 #else +#ifdef __cplusplus +extern "C" { +#endif + #define CURVE25519_PUBKEY_SIZE 32 #define CURVE25519_PRIVKEY_SIZE 32 int crypto_scalarmult_base(unsigned char *q, const unsigned char *n); @@ -48,9 +52,14 @@ typedef unsigned char ssh_curve25519_privkey[CURVE25519_PRIVKEY_SIZE]; int ssh_client_curve25519_init(ssh_session session); +void ssh_client_curve25519_remove_callbacks(ssh_session session); #ifdef WITH_SERVER void ssh_server_curve25519_init(ssh_session session); #endif /* WITH_SERVER */ +#ifdef __cplusplus +} +#endif + #endif /* CURVE25519_H_ */ diff --git a/include/libssh/dh-gex.h b/include/libssh/dh-gex.h index 4fc23d82..0f547e37 100644 --- a/include/libssh/dh-gex.h +++ b/include/libssh/dh-gex.h @@ -23,10 +23,19 @@ #ifndef SRC_DH_GEX_H_ #define SRC_DH_GEX_H_ +#ifdef __cplusplus +extern "C" { +#endif + int ssh_client_dhgex_init(ssh_session session); +void ssh_client_dhgex_remove_callbacks(ssh_session session); #ifdef WITH_SERVER void ssh_server_dhgex_init(ssh_session session); #endif /* WITH_SERVER */ +#ifdef __cplusplus +} +#endif + #endif /* SRC_DH_GEX_H_ */ diff --git a/include/libssh/dh.h b/include/libssh/dh.h index 390b30da..34c4a7ed 100644 --- a/include/libssh/dh.h +++ b/include/libssh/dh.h @@ -30,20 +30,34 @@ struct dh_ctx; #define DH_CLIENT_KEYPAIR 0 #define DH_SERVER_KEYPAIR 1 +#ifdef __cplusplus +extern "C" { +#endif + /* functions implemented by crypto backends */ int ssh_dh_init_common(struct ssh_crypto_struct *crypto); void ssh_dh_cleanup(struct ssh_crypto_struct *crypto); +#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L int ssh_dh_get_parameters(struct dh_ctx *ctx, const_bignum *modulus, const_bignum *generator); +#else +int ssh_dh_get_parameters(struct dh_ctx *ctx, + bignum *modulus, bignum *generator); +#endif /* OPENSSL_VERSION_NUMBER */ int ssh_dh_set_parameters(struct dh_ctx *ctx, const bignum modulus, const bignum generator); int ssh_dh_keypair_gen_keys(struct dh_ctx *ctx, int peer); +#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L int ssh_dh_keypair_get_keys(struct dh_ctx *ctx, int peer, const_bignum *priv, const_bignum *pub); +#else +int ssh_dh_keypair_get_keys(struct dh_ctx *ctx, int peer, + bignum *priv, bignum *pub); +#endif /* OPENSSL_VERSION_NUMBER */ int ssh_dh_keypair_set_keys(struct dh_ctx *ctx, int peer, - const bignum priv, const bignum pub); + bignum priv, bignum pub); int ssh_dh_compute_shared_secret(struct dh_ctx *ctx, int local, int remote, bignum *dest); @@ -63,8 +77,10 @@ int ssh_dh_get_current_server_publickey_blob(ssh_session session, ssh_key ssh_dh_get_next_server_publickey(ssh_session session); int ssh_dh_get_next_server_publickey_blob(ssh_session session, ssh_string *pubkey_blob); +int dh_handshake(ssh_session session); int ssh_client_dh_init(ssh_session session); +void ssh_client_dh_remove_callbacks(ssh_session session); #ifdef WITH_SERVER void ssh_server_dh_init(ssh_session session); #endif /* WITH_SERVER */ @@ -72,4 +88,8 @@ int ssh_server_dh_process_init(ssh_session session, ssh_buffer packet); int ssh_fallback_group(uint32_t pmax, bignum *p, bignum *g); bool ssh_dh_is_known_group(bignum modulus, bignum generator); +#ifdef __cplusplus +} +#endif + #endif /* DH_H_ */ diff --git a/include/libssh/ecdh.h b/include/libssh/ecdh.h index 17fe02e7..4c4c54eb 100644 --- a/include/libssh/ecdh.h +++ b/include/libssh/ecdh.h @@ -42,9 +42,14 @@ #define HAVE_ECDH 1 #endif +#ifdef __cplusplus +extern "C" { +#endif + extern struct ssh_packet_callbacks_struct ssh_ecdh_client_callbacks; /* Backend-specific functions. */ int ssh_client_ecdh_init(ssh_session session); +void ssh_client_ecdh_remove_callbacks(ssh_session session); int ecdh_build_k(ssh_session session); #ifdef WITH_SERVER @@ -53,4 +58,8 @@ void ssh_server_ecdh_init(ssh_session session); SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init); #endif /* WITH_SERVER */ +#ifdef __cplusplus +} +#endif + #endif /* ECDH_H_ */ diff --git a/include/libssh/ed25519.h b/include/libssh/ed25519.h index 8a3263c8..72a86c0b 100644 --- a/include/libssh/ed25519.h +++ b/include/libssh/ed25519.h @@ -24,10 +24,10 @@ /** * @defgroup ed25519 ed25519 API - * @internal * @brief API for DJB's ed25519 * - * @{ */ + * @{ + */ #define ED25519_PK_LEN 32 #define ED25519_SK_LEN 64 @@ -37,6 +37,10 @@ typedef uint8_t ed25519_pubkey[ED25519_PK_LEN]; typedef uint8_t ed25519_privkey[ED25519_SK_LEN]; typedef uint8_t ed25519_signature[ED25519_SIG_LEN]; +#ifdef __cplusplus +extern "C" { +#endif + /** @internal * @brief generate an ed25519 key pair * @param[out] pk generated public key @@ -76,4 +80,8 @@ int crypto_sign_ed25519_open( const ed25519_pubkey pk); /** @} */ +#ifdef __cplusplus +} +#endif + #endif /* ED25519_H_ */ diff --git a/include/libssh/fe25519.h b/include/libssh/fe25519.h index 438d85db..0dfb0613 100644 --- a/include/libssh/fe25519.h +++ b/include/libssh/fe25519.h @@ -33,6 +33,10 @@ typedef struct { uint32_t v[32]; } fe25519; +#ifdef __cplusplus +extern "C" { +#endif + void fe25519_freeze(fe25519 *r); void fe25519_unpack(fe25519 *r, const unsigned char x[32]); @@ -65,4 +69,8 @@ void fe25519_invert(fe25519 *r, const fe25519 *x); void fe25519_pow2523(fe25519 *r, const fe25519 *x); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/libssh/ge25519.h b/include/libssh/ge25519.h index 329bd042..480f29dc 100644 --- a/include/libssh/ge25519.h +++ b/include/libssh/ge25519.h @@ -28,6 +28,10 @@ typedef struct fe25519 t; } ge25519; +#ifdef __cplusplus +extern "C" { +#endif + extern const ge25519 ge25519_base; int ge25519_unpackneg_vartime(ge25519 *r, const unsigned char p[32]); @@ -40,4 +44,8 @@ void ge25519_double_scalarmult_vartime(ge25519 *r, const ge25519 *p1, const sc25 void ge25519_scalarmult_base(ge25519 *r, const sc25519 *s); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/libssh/gssapi.h b/include/libssh/gssapi.h index ccd83664..b0c74c73 100644 --- a/include/libssh/gssapi.h +++ b/include/libssh/gssapi.h @@ -29,6 +29,10 @@ typedef struct ssh_gssapi_struct *ssh_gssapi; +#ifdef __cplusplus +extern "C" { +#endif + #ifdef WITH_SERVER int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n_oid, ssh_string *oids); SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_server); @@ -42,4 +46,8 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_response); int ssh_gssapi_auth_mic(ssh_session session); +#ifdef __cplusplus +} +#endif + #endif /* GSSAPI_H */ diff --git a/include/libssh/kex.h b/include/libssh/kex.h index 3a1f4a6f..4a2ecb99 100644 --- a/include/libssh/kex.h +++ b/include/libssh/kex.h @@ -31,15 +31,24 @@ struct ssh_kex_struct { char *methods[SSH_KEX_METHODS]; }; +#ifdef __cplusplus +extern "C" { +#endif + SSH_PACKET_CALLBACK(ssh_packet_kexinit); -int ssh_send_kex(ssh_session session, int server_kex); +int ssh_send_kex(ssh_session session); void ssh_list_kex(struct ssh_kex_struct *kex); int ssh_set_client_kex(ssh_session session); +int ssh_kex_append_extensions(ssh_session session, struct ssh_kex_struct *pkex); int ssh_kex_select_methods(ssh_session session); int ssh_verify_existing_algo(enum ssh_kex_types_e algo, const char *name); char *ssh_keep_known_algos(enum ssh_kex_types_e algo, const char *list); char *ssh_keep_fips_algos(enum ssh_kex_types_e algo, const char *list); +char *ssh_add_to_default_algos(enum ssh_kex_types_e algo, const char *list); +char *ssh_remove_from_default_algos(enum ssh_kex_types_e algo, + const char *list); +char *ssh_prefix_default_algos(enum ssh_kex_types_e algo, const char *list); char **ssh_space_tokenize(const char *chain); int ssh_get_kex1(ssh_session session); char *ssh_find_matching(const char *in_d, const char *what_d); @@ -56,4 +65,8 @@ int ssh_hashbufin_add_cookie(ssh_session session, unsigned char *cookie); int ssh_hashbufout_add_cookie(ssh_session session); int ssh_generate_session_keys(ssh_session session); +#ifdef __cplusplus +} +#endif + #endif /* KEX_H_ */ diff --git a/include/libssh/keys.h b/include/libssh/keys.h index 7b138612..1379539e 100644 --- a/include/libssh/keys.h +++ b/include/libssh/keys.h @@ -29,34 +29,36 @@ struct ssh_public_key_struct { int type; const char *type_c; /* Don't free it ! it is static */ #if defined(HAVE_LIBGCRYPT) - gcry_sexp_t dsa_pub; gcry_sexp_t rsa_pub; #elif defined(HAVE_LIBCRYPTO) - DSA *dsa_pub; - RSA *rsa_pub; + EVP_PKEY *key_pub; #elif defined(HAVE_LIBMBEDCRYPTO) mbedtls_pk_context *rsa_pub; - void *dsa_pub; #endif }; struct ssh_private_key_struct { int type; #if defined(HAVE_LIBGCRYPT) - gcry_sexp_t dsa_priv; gcry_sexp_t rsa_priv; #elif defined(HAVE_LIBCRYPTO) - DSA *dsa_priv; - RSA *rsa_priv; + EVP_PKEY *key_priv; #elif defined(HAVE_LIBMBEDCRYPTO) mbedtls_pk_context *rsa_priv; - void *dsa_priv; #endif }; +#ifdef __cplusplus +extern "C" { +#endif + const char *ssh_type_to_char(int type); int ssh_type_from_name(const char *name); ssh_public_key publickey_from_string(ssh_session session, ssh_string pubkey_s); +#ifdef __cplusplus +} +#endif + #endif /* KEYS_H_ */ diff --git a/include/libssh/knownhosts.h b/include/libssh/knownhosts.h index 44e434c0..b50018cd 100644 --- a/include/libssh/knownhosts.h +++ b/include/libssh/knownhosts.h @@ -22,6 +22,10 @@ #ifndef SSH_KNOWNHOSTS_H_ #define SSH_KNOWNHOSTS_H_ +#ifdef __cplusplus +extern "C" { +#endif + struct ssh_list *ssh_known_hosts_get_algorithms(ssh_session session); char *ssh_known_hosts_get_algorithms_names(ssh_session session); enum ssh_known_hosts_e @@ -29,4 +33,8 @@ ssh_session_get_known_hosts_entry_file(ssh_session session, const char *filename, struct ssh_knownhosts_entry **pentry); +#ifdef __cplusplus +} +#endif + #endif /* SSH_KNOWNHOSTS_H_ */ diff --git a/include/libssh/legacy.h b/include/libssh/legacy.h index 911173ee..38bef4da 100644 --- a/include/libssh/legacy.h +++ b/include/libssh/legacy.h @@ -31,6 +31,10 @@ typedef struct ssh_private_key_struct* ssh_private_key; typedef struct ssh_public_key_struct* ssh_public_key; +#ifdef __cplusplus +extern "C" { +#endif + LIBSSH_API int ssh_auth_list(ssh_session session); LIBSSH_API int ssh_userauth_offer_pubkey(ssh_session session, const char *username, int type, ssh_string publickey); LIBSSH_API int ssh_userauth_pubkey(ssh_session session, const char *username, ssh_string publickey, ssh_private_key privatekey); @@ -88,19 +92,19 @@ SSH_DEPRECATED LIBSSH_API int channel_select(ssh_channel *readchans, ssh_channel SSH_DEPRECATED LIBSSH_API void channel_set_blocking(ssh_channel channel, int blocking); SSH_DEPRECATED LIBSSH_API int channel_write(ssh_channel channel, const void *data, uint32_t len); -LIBSSH_API void privatekey_free(ssh_private_key prv); -LIBSSH_API ssh_private_key privatekey_from_file(ssh_session session, const char *filename, +SSH_DEPRECATED LIBSSH_API void privatekey_free(ssh_private_key prv); +SSH_DEPRECATED LIBSSH_API ssh_private_key privatekey_from_file(ssh_session session, const char *filename, int type, const char *passphrase); -LIBSSH_API void publickey_free(ssh_public_key key); -LIBSSH_API int ssh_publickey_to_file(ssh_session session, const char *file, +SSH_DEPRECATED LIBSSH_API void publickey_free(ssh_public_key key); +SSH_DEPRECATED LIBSSH_API int ssh_publickey_to_file(ssh_session session, const char *file, ssh_string pubkey, int type); -LIBSSH_API ssh_string publickey_from_file(ssh_session session, const char *filename, +SSH_DEPRECATED LIBSSH_API ssh_string publickey_from_file(ssh_session session, const char *filename, int *type); -LIBSSH_API ssh_public_key publickey_from_privatekey(ssh_private_key prv); -LIBSSH_API ssh_string publickey_to_string(ssh_public_key key); -LIBSSH_API int ssh_try_publickey_from_file(ssh_session session, const char *keyfile, +SSH_DEPRECATED LIBSSH_API ssh_public_key publickey_from_privatekey(ssh_private_key prv); +SSH_DEPRECATED LIBSSH_API ssh_string publickey_to_string(ssh_public_key key); +SSH_DEPRECATED LIBSSH_API int ssh_try_publickey_from_file(ssh_session session, const char *keyfile, ssh_string *publickey, int *type); -LIBSSH_API enum ssh_keytypes_e ssh_privatekey_type(ssh_private_key privatekey); +SSH_DEPRECATED LIBSSH_API enum ssh_keytypes_e ssh_privatekey_type(ssh_private_key privatekey); LIBSSH_API ssh_string ssh_get_pubkey(ssh_session session); @@ -117,4 +121,8 @@ SSH_DEPRECATED LIBSSH_API size_t string_len(ssh_string str); SSH_DEPRECATED LIBSSH_API ssh_string string_new(size_t size); SSH_DEPRECATED LIBSSH_API char *string_to_char(ssh_string str); +#ifdef __cplusplus +} +#endif + #endif /* LEGACY_H_ */ diff --git a/include/libssh/libcrypto.h b/include/libssh/libcrypto.h index 403c2d22..2f6bdc0a 100644 --- a/include/libssh/libcrypto.h +++ b/include/libssh/libcrypto.h @@ -25,13 +25,14 @@ #ifdef HAVE_LIBCRYPTO -#include <openssl/dsa.h> +#include "libssh/libssh.h" #include <openssl/rsa.h> #include <openssl/sha.h> #include <openssl/md5.h> #include <openssl/hmac.h> #include <openssl/evp.h> #include <openssl/crypto.h> +#include <openssl/ec.h> typedef EVP_MD_CTX* SHACTX; typedef EVP_MD_CTX* SHA256CTX; @@ -39,11 +40,6 @@ typedef EVP_MD_CTX* SHA384CTX; typedef EVP_MD_CTX* SHA512CTX; typedef EVP_MD_CTX* MD5CTX; typedef EVP_MD_CTX* HMACCTX; -#ifdef HAVE_ECC -typedef EVP_MD_CTX *EVPCTX; -#else -typedef void *EVPCTX; -#endif #define SHA_DIGEST_LEN SHA_DIGEST_LENGTH #define SHA256_DIGEST_LEN SHA256_DIGEST_LENGTH @@ -58,8 +54,15 @@ typedef void *EVPCTX; #define EVP_DIGEST_LEN EVP_MAX_MD_SIZE #endif +/* Use ssh_crypto_free() to release memory allocated by bignum_bn2dec(), + bignum_bn2hex() and other functions that use crypto-library functions that + are documented to allocate memory that needs to be de-allocate with + OPENSSL_free. */ +#define ssh_crypto_free(x) OPENSSL_free(x) + #include <openssl/bn.h> #include <openssl/opensslv.h> + typedef BIGNUM* bignum; typedef const BIGNUM* const_bignum; typedef BN_CTX* bignum_CTX; @@ -110,10 +113,14 @@ typedef BN_CTX* bignum_CTX; /* Returns true if the OpenSSL is operating in FIPS mode */ #ifdef HAVE_OPENSSL_FIPS_MODE #define ssh_fips_mode() (FIPS_mode() != 0) +#elif OPENSSL_VERSION_NUMBER >= 0x30000000L +#define ssh_fips_mode() EVP_default_properties_is_fips_enabled(NULL) #else #define ssh_fips_mode() false #endif +ssh_string pki_key_make_ecpoint_string(const EC_GROUP *g, const EC_POINT *p); +int pki_key_ecgroup_name_to_nid(const char *group); #endif /* HAVE_LIBCRYPTO */ #endif /* LIBCRYPTO_H_ */ diff --git a/include/libssh/libgcrypt.h b/include/libssh/libgcrypt.h index 347d851b..a8044545 100644 --- a/include/libssh/libgcrypt.h +++ b/include/libssh/libgcrypt.h @@ -32,7 +32,6 @@ typedef gcry_md_hd_t SHA384CTX; typedef gcry_md_hd_t SHA512CTX; typedef gcry_md_hd_t MD5CTX; typedef gcry_md_hd_t HMACCTX; -typedef gcry_md_hd_t EVPCTX; #define SHA_DIGEST_LENGTH 20 #define SHA_DIGEST_LEN SHA_DIGEST_LENGTH #define MD5_DIGEST_LEN 16 @@ -49,6 +48,8 @@ typedef gcry_md_hd_t EVPCTX; #define EVP_DIGEST_LEN EVP_MAX_MD_SIZE +#define ssh_crypto_free(x) gcry_free(x) + typedef gcry_mpi_t bignum; typedef const struct gcry_mpi *const_bignum; typedef void* bignum_CTX; @@ -104,6 +105,10 @@ int ssh_gcry_rand_range(bignum rnd, bignum max); } while(0) /* Helper functions for data conversions. */ +#ifdef __cplusplus +extern "C" { +#endif + /* Extract an MPI from the given s-expression SEXP named NAME which is encoded using INFORMAT and store it in a newly allocated ssh_string encoded using OUTFORMAT. */ @@ -114,6 +119,10 @@ ssh_string ssh_sexp_extract_mpi(const gcry_sexp_t sexp, #define ssh_fips_mode() false +#ifdef __cplusplus +} +#endif + #endif /* HAVE_LIBGCRYPT */ #endif /* LIBGCRYPT_H_ */ diff --git a/include/libssh/libmbedcrypto.h b/include/libssh/libmbedcrypto.h index fe53019b..918fe293 100644 --- a/include/libssh/libmbedcrypto.h +++ b/include/libssh/libmbedcrypto.h @@ -34,6 +34,7 @@ #include <mbedtls/cipher.h> #include <mbedtls/entropy.h> #include <mbedtls/ctr_drbg.h> +#include <mbedtls/platform.h> typedef mbedtls_md_context_t *SHACTX; typedef mbedtls_md_context_t *SHA256CTX; @@ -41,7 +42,6 @@ typedef mbedtls_md_context_t *SHA384CTX; typedef mbedtls_md_context_t *SHA512CTX; typedef mbedtls_md_context_t *MD5CTX; typedef mbedtls_md_context_t *HMACCTX; -typedef mbedtls_md_context_t *EVPCTX; #define SHA_DIGEST_LENGTH 20 #define SHA_DIGEST_LEN SHA_DIGEST_LENGTH @@ -59,6 +59,8 @@ typedef mbedtls_md_context_t *EVPCTX; #define EVP_DIGEST_LEN EVP_MAX_MD_SIZE +#define ssh_crypto_free(x) mbedtls_free(x) + typedef mbedtls_mpi *bignum; typedef const mbedtls_mpi *const_bignum; typedef void* bignum_CTX; @@ -73,9 +75,13 @@ struct mbedtls_ecdsa_sig { bignum s; }; +#ifdef __cplusplus +extern "C" { +#endif + bignum ssh_mbedcry_bn_new(void); void ssh_mbedcry_bn_free(bignum num); -unsigned char *ssh_mbedcry_bn2num(const_bignum num, int radix); +char *ssh_mbedcry_bn2num(const_bignum num, int radix); int ssh_mbedcry_rand(bignum rnd, int bits, int top, int bottom); int ssh_mbedcry_is_bit_set(bignum num, size_t pos); int ssh_mbedcry_rand_range(bignum dest, bignum max); @@ -101,7 +107,7 @@ int ssh_mbedcry_hex2bn(bignum *dest, char *data); } while(0) #define bignum_bn2dec(num) ssh_mbedcry_bn2num(num, 10) #define bignum_dec2bn(data, bn) mbedtls_mpi_read_string(bn, 10, data) -#define bignum_bn2hex(num, dest) (*dest)=ssh_mbedcry_bn2num(num, 16) +#define bignum_bn2hex(num, dest) (*dest)=(unsigned char *)ssh_mbedcry_bn2num(num, 16) #define bignum_hex2bn(data, dest) ssh_mbedcry_hex2bn(dest, data) #define bignum_rand(rnd, bits) ssh_mbedcry_rand((rnd), (bits), 0, 1) #define bignum_rand_range(rnd, max) ssh_mbedcry_rand_range(rnd, max) @@ -136,5 +142,9 @@ ssh_string make_ecpoint_string(const mbedtls_ecp_group *g, const #define ssh_fips_mode() false +#ifdef __cplusplus +} +#endif + #endif /* HAVE_LIBMBEDCRYPTO */ #endif /* LIBMBEDCRYPTO_H_ */ diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h index 4f401056..13f1b812 100644 --- a/include/libssh/libssh.h +++ b/include/libssh/libssh.h @@ -1,7 +1,7 @@ /* * This file is part of the SSH Library * - * Copyright (c) 2003-2021 by Aris Adamantiadis and the libssh team + * Copyright (c) 2003-2024 by Aris Adamantiadis and the libssh team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -49,17 +49,14 @@ #endif #endif +#include <stdarg.h> +#include <stdint.h> +#include <inttypes.h> + #ifdef _MSC_VER - /* Visual Studio hasn't inttypes.h so it doesn't know uint32_t */ - typedef int int32_t; - typedef unsigned int uint32_t; - typedef unsigned short uint16_t; - typedef unsigned char uint8_t; - typedef unsigned long long uint64_t; typedef int mode_t; #else /* _MSC_VER */ #include <unistd.h> - #include <inttypes.h> #include <sys/types.h> #endif /* _MSC_VER */ @@ -80,7 +77,7 @@ #define PRINTF_ATTRIBUTE(a,b) #endif /* __GNUC__ */ -#ifdef __GNUC__ +#if !defined(SSH_SUPPRESS_DEPRECATED) && defined(__GNUC__) #define SSH_DEPRECATED __attribute__ ((deprecated)) #else #define SSH_DEPRECATED @@ -194,7 +191,8 @@ enum ssh_global_requests_e { SSH_GLOBAL_REQUEST_UNKNOWN=0, SSH_GLOBAL_REQUEST_TCPIP_FORWARD, SSH_GLOBAL_REQUEST_CANCEL_TCPIP_FORWARD, - SSH_GLOBAL_REQUEST_KEEPALIVE + SSH_GLOBAL_REQUEST_KEEPALIVE, + SSH_GLOBAL_REQUEST_NO_MORE_SESSIONS }; enum ssh_publickey_state_e { @@ -275,12 +273,12 @@ enum ssh_error_types_e { /* some types for keys */ enum ssh_keytypes_e{ SSH_KEYTYPE_UNKNOWN=0, - SSH_KEYTYPE_DSS=1, + SSH_KEYTYPE_DSS=1, /* deprecated */ SSH_KEYTYPE_RSA, SSH_KEYTYPE_RSA1, SSH_KEYTYPE_ECDSA, /* deprecated */ SSH_KEYTYPE_ED25519, - SSH_KEYTYPE_DSS_CERT01, + SSH_KEYTYPE_DSS_CERT01, /* deprecated */ SSH_KEYTYPE_RSA_CERT01, SSH_KEYTYPE_ECDSA_P256, SSH_KEYTYPE_ECDSA_P384, @@ -297,7 +295,8 @@ enum ssh_keytypes_e{ enum ssh_keycmp_e { SSH_KEY_CMP_PUBLIC = 0, - SSH_KEY_CMP_PRIVATE + SSH_KEY_CMP_PRIVATE = 1, + SSH_KEY_CMP_CERTIFICATE = 2, }; #define SSH_ADDRSTRLEN 46 @@ -326,16 +325,16 @@ enum { /** No logging at all */ SSH_LOG_NOLOG=0, - /** Only warnings + /** Only unrecoverable errors */ SSH_LOG_WARNING, - /** High level protocol information + /** Information for the users */ SSH_LOG_PROTOCOL, - /** Lower level protocol infomations, packet level + /** Debug information, to see what is going on */ SSH_LOG_PACKET, - /** Every function path + /** Trace information and recoverable error messages */ SSH_LOG_FUNCTIONS }; @@ -351,17 +350,25 @@ enum { /** No logging at all */ #define SSH_LOG_NONE 0 -/** Show only warnings */ +/** Show only fatal warnings */ #define SSH_LOG_WARN 1 /** Get some information what's going on */ #define SSH_LOG_INFO 2 -/** Get detailed debuging information **/ +/** Get detailed debugging information **/ #define SSH_LOG_DEBUG 3 /** Get trace output, packet information, ... */ #define SSH_LOG_TRACE 4 /** @} */ +enum ssh_control_master_options_e { + SSH_CONTROL_MASTER_NO, + SSH_CONTROL_MASTER_AUTO, + SSH_CONTROL_MASTER_YES, + SSH_CONTROL_MASTER_ASK, + SSH_CONTROL_MASTER_AUTOASK +}; + enum ssh_options_e { SSH_OPTIONS_HOST, SSH_OPTIONS_PORT, @@ -404,6 +411,12 @@ enum ssh_options_e { SSH_OPTIONS_PROCESS_CONFIG, SSH_OPTIONS_REKEY_DATA, SSH_OPTIONS_REKEY_TIME, + SSH_OPTIONS_RSA_MIN_SIZE, + SSH_OPTIONS_IDENTITY_AGENT, + SSH_OPTIONS_IDENTITIES_ONLY, + SSH_OPTIONS_CONTROL_MASTER, + SSH_OPTIONS_CONTROL_PATH, + SSH_OPTIONS_CERTIFICATE, }; enum { @@ -466,6 +479,8 @@ LIBSSH_API int ssh_channel_request_exec(ssh_channel channel, const char *cmd); LIBSSH_API int ssh_channel_request_pty(ssh_channel channel); LIBSSH_API int ssh_channel_request_pty_size(ssh_channel channel, const char *term, int cols, int rows); +LIBSSH_API int ssh_channel_request_pty_size_modes(ssh_channel channel, const char *term, + int cols, int rows, const unsigned char* modes, size_t modes_len); LIBSSH_API int ssh_channel_request_shell(ssh_channel channel); LIBSSH_API int ssh_channel_request_send_signal(ssh_channel channel, const char *signum); LIBSSH_API int ssh_channel_request_send_break(ssh_channel channel, uint32_t length); @@ -475,8 +490,6 @@ LIBSSH_API int ssh_channel_request_x11(ssh_channel channel, int single_connectio const char *cookie, int screen_number); LIBSSH_API int ssh_channel_request_auth_agent(ssh_channel channel); LIBSSH_API int ssh_channel_send_eof(ssh_channel channel); -LIBSSH_API int ssh_channel_select(ssh_channel *readchans, ssh_channel *writechans, ssh_channel *exceptchans, struct - timeval * timeout); LIBSSH_API void ssh_channel_set_blocking(ssh_channel channel, int blocking); LIBSSH_API void ssh_channel_set_counter(ssh_channel channel, ssh_counter counter); @@ -507,7 +520,12 @@ LIBSSH_API char *ssh_dirname (const char *path); LIBSSH_API int ssh_finalize(void); /* REVERSE PORT FORWARDING */ -LIBSSH_API ssh_channel ssh_channel_accept_forward(ssh_session session, +LIBSSH_API ssh_channel ssh_channel_open_forward_port(ssh_session session, + int timeout_ms, + int *destination_port, + char **originator, + int *originator_port); +SSH_DEPRECATED LIBSSH_API ssh_channel ssh_channel_accept_forward(ssh_session session, int timeout_ms, int *destination_port); LIBSSH_API int ssh_channel_cancel_forward(ssh_session session, @@ -526,6 +544,7 @@ LIBSSH_API socket_t ssh_get_fd(ssh_session session); LIBSSH_API char *ssh_get_hexa(const unsigned char *what, size_t len); LIBSSH_API char *ssh_get_issue_banner(ssh_session session); LIBSSH_API int ssh_get_openssh_version(ssh_session session); +LIBSSH_API int ssh_request_no_more_sessions(ssh_session session); LIBSSH_API int ssh_get_server_publickey(ssh_session session, ssh_key *key); @@ -549,7 +568,27 @@ SSH_DEPRECATED LIBSSH_API int ssh_write_knownhost(ssh_session session); SSH_DEPRECATED LIBSSH_API char *ssh_dump_knownhost(ssh_session session); SSH_DEPRECATED LIBSSH_API int ssh_is_server_known(ssh_session session); SSH_DEPRECATED LIBSSH_API void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len); +SSH_DEPRECATED LIBSSH_API int ssh_channel_select(ssh_channel *readchans, ssh_channel *writechans, ssh_channel *exceptchans, struct + timeval * timeout); +SSH_DEPRECATED LIBSSH_API int ssh_scp_accept_request(ssh_scp scp); +SSH_DEPRECATED LIBSSH_API int ssh_scp_close(ssh_scp scp); +SSH_DEPRECATED LIBSSH_API int ssh_scp_deny_request(ssh_scp scp, const char *reason); +SSH_DEPRECATED LIBSSH_API void ssh_scp_free(ssh_scp scp); +SSH_DEPRECATED LIBSSH_API int ssh_scp_init(ssh_scp scp); +SSH_DEPRECATED LIBSSH_API int ssh_scp_leave_directory(ssh_scp scp); +SSH_DEPRECATED LIBSSH_API ssh_scp ssh_scp_new(ssh_session session, int mode, const char *location); +SSH_DEPRECATED LIBSSH_API int ssh_scp_pull_request(ssh_scp scp); +SSH_DEPRECATED LIBSSH_API int ssh_scp_push_directory(ssh_scp scp, const char *dirname, int mode); +SSH_DEPRECATED LIBSSH_API int ssh_scp_push_file(ssh_scp scp, const char *filename, size_t size, int perms); +SSH_DEPRECATED LIBSSH_API int ssh_scp_push_file64(ssh_scp scp, const char *filename, uint64_t size, int perms); +SSH_DEPRECATED LIBSSH_API int ssh_scp_read(ssh_scp scp, void *buffer, size_t size); +SSH_DEPRECATED LIBSSH_API const char *ssh_scp_request_get_filename(ssh_scp scp); +SSH_DEPRECATED LIBSSH_API int ssh_scp_request_get_permissions(ssh_scp scp); +SSH_DEPRECATED LIBSSH_API size_t ssh_scp_request_get_size(ssh_scp scp); +SSH_DEPRECATED LIBSSH_API uint64_t ssh_scp_request_get_size64(ssh_scp scp); +SSH_DEPRECATED LIBSSH_API const char *ssh_scp_request_get_warning(ssh_scp scp); +SSH_DEPRECATED LIBSSH_API int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len); LIBSSH_API int ssh_get_random(void *where,int len,int strong); @@ -587,6 +626,10 @@ LIBSSH_API int ssh_set_log_level(int level); LIBSSH_API int ssh_get_log_level(void); LIBSSH_API void *ssh_get_log_userdata(void); LIBSSH_API int ssh_set_log_userdata(void *data); +LIBSSH_API void ssh_vlog(int verbosity, + const char *function, + const char *format, + va_list *va) PRINTF_ATTRIBUTE(3, 0); LIBSSH_API void _ssh_log(int verbosity, const char *function, const char *format, ...) PRINTF_ATTRIBUTE(3, 4); @@ -645,6 +688,12 @@ typedef int (*ssh_auth_callback) (const char *prompt, char *buf, size_t len, /** @} */ +enum ssh_file_format_e { + SSH_FILE_FORMAT_DEFAULT = 0, + SSH_FILE_FORMAT_OPENSSH, + SSH_FILE_FORMAT_PEM, +}; + LIBSSH_API ssh_key ssh_key_new(void); #define SSH_KEY_FREE(x) \ do { if ((x) != NULL) { ssh_key_free(x); x = NULL; } } while(0) @@ -657,6 +706,7 @@ LIBSSH_API int ssh_key_is_private(const ssh_key k); LIBSSH_API int ssh_key_cmp(const ssh_key k1, const ssh_key k2, enum ssh_keycmp_e what); +LIBSSH_API ssh_key ssh_key_dup(const ssh_key key); LIBSSH_API int ssh_pki_generate(enum ssh_keytypes_e type, int parameter, ssh_key *pkey); @@ -670,6 +720,13 @@ LIBSSH_API int ssh_pki_export_privkey_base64(const ssh_key privkey, ssh_auth_callback auth_fn, void *auth_data, char **b64_key); +LIBSSH_API int +ssh_pki_export_privkey_base64_format(const ssh_key privkey, + const char *passphrase, + ssh_auth_callback auth_fn, + void *auth_data, + char **b64_key, + enum ssh_file_format_e format); LIBSSH_API int ssh_pki_import_privkey_file(const char *filename, const char *passphrase, ssh_auth_callback auth_fn, @@ -680,6 +737,13 @@ LIBSSH_API int ssh_pki_export_privkey_file(const ssh_key privkey, ssh_auth_callback auth_fn, void *auth_data, const char *filename); +LIBSSH_API int +ssh_pki_export_privkey_file_format(const ssh_key privkey, + const char *passphrase, + ssh_auth_callback auth_fn, + void *auth_data, + const char *filename, + enum ssh_file_format_e format); LIBSSH_API int ssh_pki_copy_cert_to_privkey(const ssh_key cert_key, ssh_key privkey); @@ -712,24 +776,6 @@ LIBSSH_API void ssh_print_hash(enum ssh_publickey_hash_type type, unsigned char LIBSSH_API int ssh_send_ignore (ssh_session session, const char *data); LIBSSH_API int ssh_send_debug (ssh_session session, const char *message, int always_display); LIBSSH_API void ssh_gssapi_set_creds(ssh_session session, const ssh_gssapi_creds creds); -LIBSSH_API int ssh_scp_accept_request(ssh_scp scp); -LIBSSH_API int ssh_scp_close(ssh_scp scp); -LIBSSH_API int ssh_scp_deny_request(ssh_scp scp, const char *reason); -LIBSSH_API void ssh_scp_free(ssh_scp scp); -LIBSSH_API int ssh_scp_init(ssh_scp scp); -LIBSSH_API int ssh_scp_leave_directory(ssh_scp scp); -LIBSSH_API ssh_scp ssh_scp_new(ssh_session session, int mode, const char *location); -LIBSSH_API int ssh_scp_pull_request(ssh_scp scp); -LIBSSH_API int ssh_scp_push_directory(ssh_scp scp, const char *dirname, int mode); -LIBSSH_API int ssh_scp_push_file(ssh_scp scp, const char *filename, size_t size, int perms); -LIBSSH_API int ssh_scp_push_file64(ssh_scp scp, const char *filename, uint64_t size, int perms); -LIBSSH_API int ssh_scp_read(ssh_scp scp, void *buffer, size_t size); -LIBSSH_API const char *ssh_scp_request_get_filename(ssh_scp scp); -LIBSSH_API int ssh_scp_request_get_permissions(ssh_scp scp); -LIBSSH_API size_t ssh_scp_request_get_size(ssh_scp scp); -LIBSSH_API uint64_t ssh_scp_request_get_size64(ssh_scp scp); -LIBSSH_API const char *ssh_scp_request_get_warning(ssh_scp scp); -LIBSSH_API int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len); LIBSSH_API int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd, fd_set *readfds, struct timeval *timeout); LIBSSH_API int ssh_service_request(ssh_session session, const char *service); @@ -753,10 +799,8 @@ LIBSSH_API int ssh_userauth_try_publickey(ssh_session session, LIBSSH_API int ssh_userauth_publickey(ssh_session session, const char *username, const ssh_key privkey); -#ifndef _WIN32 LIBSSH_API int ssh_userauth_agent(ssh_session session, const char *username); -#endif LIBSSH_API int ssh_userauth_publickey_auto_get_current_identity(ssh_session session, char** value); LIBSSH_API int ssh_userauth_publickey_auto(ssh_session session, @@ -827,6 +871,7 @@ LIBSSH_API int ssh_buffer_add_data(ssh_buffer buffer, const void *data, uint32_t LIBSSH_API uint32_t ssh_buffer_get_data(ssh_buffer buffer, void *data, uint32_t requestedlen); LIBSSH_API void *ssh_buffer_get(ssh_buffer buffer); LIBSSH_API uint32_t ssh_buffer_get_len(ssh_buffer buffer); +LIBSSH_API int ssh_session_set_disconnect_message(ssh_session session, const char *message); #ifndef LIBSSH_LEGACY_0_4 #include "libssh/legacy.h" diff --git a/include/libssh/libsshpp.hpp b/include/libssh/libsshpp.hpp index 75c9c7a1..e0f21e85 100644 --- a/include/libssh/libsshpp.hpp +++ b/include/libssh/libsshpp.hpp @@ -369,13 +369,11 @@ public: return state; } void log(int priority, const char *format, ...){ - char buffer[1024]; va_list va; va_start(va, format); - vsnprintf(buffer, sizeof(buffer), format, va); + ssh_vlog(priority, "libsshpp", format, &va); va_end(va); - _ssh_log(priority, "libsshpp", "%s", buffer); } /** @brief copies options from a session to another @@ -525,7 +523,7 @@ public: return ssh_channel_is_open(channel) != 0; } int openForward(const char *remotehost, int remoteport, - const char *sourcehost=NULL, int localport=0){ + const char *sourcehost, int localport=0){ int err=ssh_channel_open_forward(channel,remotehost,remoteport, sourcehost, localport); ssh_throw(err); @@ -589,9 +587,12 @@ public: ssh_throw(err); return_throwable; } - void_throwable requestPty(const char *term=NULL, int cols=0, int rows=0){ + void_throwable requestPty(const char *term=NULL, int cols=0, int rows=0, + const unsigned char* modes=NULL, size_t modes_len=0){ int err; - if(term != NULL && cols != 0 && rows != 0) + if(term != NULL && cols != 0 && rows != 0 && modes != NULL) + err=ssh_channel_request_pty_size_modes(channel,term,cols,rows,modes,modes_len); + else if(term != NULL && cols != 0 && rows != 0) err=ssh_channel_request_pty_size(channel,term,cols,rows); else err=ssh_channel_request_pty(channel); @@ -632,8 +633,8 @@ public: * @param is_stderr write should be done on the stderr channel (server only) * @returns number of bytes written * @throws SshException in case of error - * @see channel_write - * @see channel_write_stderr + * @see ssh_channel_write + * @see ssh_channel_write_stderr */ int write(const void *data, size_t len, bool is_stderr=false){ int ret; @@ -671,7 +672,7 @@ private: inline Channel *Session::acceptForward(int timeout_ms){ ssh_channel forward = - ssh_channel_accept_forward(c_session, timeout_ms, NULL); + ssh_channel_open_forward_port(c_session, timeout_ms, NULL, NULL, NULL); ssh_throw_null(c_session,forward); Channel *newchan = new Channel(*this,forward); return newchan; diff --git a/include/libssh/messages.h b/include/libssh/messages.h index 04d041d4..160306cc 100644 --- a/include/libssh/messages.h +++ b/include/libssh/messages.h @@ -28,6 +28,7 @@ struct ssh_auth_request { int method; char *password; struct ssh_key_struct *pubkey; + char *sigtype; enum ssh_publickey_state_e signature_state; char kbdint_response; }; @@ -91,6 +92,10 @@ struct ssh_message_struct { struct ssh_global_request global_request; }; +#ifdef __cplusplus +extern "C" { +#endif + SSH_PACKET_CALLBACK(ssh_packet_channel_open); SSH_PACKET_CALLBACK(ssh_packet_global_request); @@ -103,4 +108,8 @@ int ssh_message_handle_channel_request(ssh_session session, ssh_channel channel, const char *request, uint8_t want_reply); ssh_message ssh_message_pop_head(ssh_session session); +#ifdef __cplusplus +} +#endif + #endif /* MESSAGES_H_ */ diff --git a/include/libssh/misc.h b/include/libssh/misc.h index 5044817a..fc8596f7 100644 --- a/include/libssh/misc.h +++ b/include/libssh/misc.h @@ -21,6 +21,25 @@ #ifndef MISC_H_ #define MISC_H_ +#ifdef _WIN32 + +# ifdef _MSC_VER +# ifndef _SSIZE_T_DEFINED +# undef ssize_t +# include <BaseTsd.h> + typedef _W64 SSIZE_T ssize_t; +# define _SSIZE_T_DEFINED +# endif /* _SSIZE_T_DEFINED */ +# endif /* _MSC_VER */ + +#else +# include <sys/types.h> +#endif /* _WIN32 */ + +#ifdef __cplusplus +extern "C" { +#endif + /* in misc.c */ /* gets the user home dir. */ char *ssh_get_user_home_dir(void); @@ -75,13 +94,13 @@ const void *_ssh_list_pop_head(struct ssh_list *list); /** @brief fetch the head element of a list and remove it from list * @param type type of the element to return - * @param list the ssh_list to use + * @param ssh_list the ssh_list to use * @return the first element of the list, or NULL if the list is empty */ #define ssh_list_pop_head(type, ssh_list)\ ((type)_ssh_list_pop_head(ssh_list)) -int ssh_make_milliseconds(long sec, long usec); +int ssh_make_milliseconds(unsigned long sec, unsigned long usec); void ssh_timestamp_init(struct ssh_timestamp *ts); int ssh_timeout_elapsed(struct ssh_timestamp *ts, int timeout); int ssh_timeout_update(struct ssh_timestamp *ts, int timeout); @@ -96,7 +115,18 @@ int ssh_mkdirs(const char *pathname, mode_t mode); int ssh_quote_file_name(const char *file_name, char *buf, size_t buf_len); int ssh_newline_vis(const char *string, char *buf, size_t buf_len); -int ssh_tmpname(char *template); +int ssh_tmpname(char *name); char *ssh_strreplace(const char *src, const char *pattern, const char *repl); + +ssize_t ssh_readn(int fd, void *buf, size_t nbytes); +ssize_t ssh_writen(int fd, const void *buf, size_t nbytes); + +int ssh_check_hostname_syntax(const char *hostname); +int ssh_check_username_syntax(const char *username); + +#ifdef __cplusplus +} +#endif + #endif /* MISC_H_ */ diff --git a/include/libssh/options.h b/include/libssh/options.h index e8dc6c69..d32e1589 100644 --- a/include/libssh/options.h +++ b/include/libssh/options.h @@ -21,11 +21,22 @@ #ifndef _OPTIONS_H #define _OPTIONS_H +#ifdef __cplusplus +extern "C" { +#endif + int ssh_config_parse_file(ssh_session session, const char *filename); int ssh_config_parse_string(ssh_session session, const char *input); int ssh_options_set_algo(ssh_session session, enum ssh_kex_types_e algo, - const char *list); + const char *list, + char **place); int ssh_options_apply(ssh_session session); +char *ssh_options_get_algo(ssh_session session, enum ssh_kex_types_e algo); + +#ifdef __cplusplus +} +#endif + #endif /* _OPTIONS_H */ diff --git a/include/libssh/packet.h b/include/libssh/packet.h index 8fc7ce42..f0c8cb20 100644 --- a/include/libssh/packet.h +++ b/include/libssh/packet.h @@ -51,6 +51,10 @@ enum ssh_packet_filter_result_e { int ssh_packet_send(ssh_session session); +#ifdef __cplusplus +extern "C" { +#endif + SSH_PACKET_CALLBACK(ssh_packet_unimplemented); SSH_PACKET_CALLBACK(ssh_packet_disconnect_callback); SSH_PACKET_CALLBACK(ssh_packet_ignore_callback); @@ -63,11 +67,12 @@ SSH_PACKET_CALLBACK(ssh_packet_ext_info); SSH_PACKET_CALLBACK(ssh_packet_kexdh_init); #endif +int ssh_packet_send_newkeys(ssh_session session); int ssh_packet_send_unimplemented(ssh_session session, uint32_t seqnum); int ssh_packet_parse_type(ssh_session session); //int packet_flush(ssh_session session, int enforce_blocking); -int ssh_packet_socket_callback(const void *data, size_t len, void *user); +size_t ssh_packet_socket_callback(const void *data, size_t len, void *user); void ssh_packet_register_socket_callback(ssh_session session, struct ssh_socket_struct *s); void ssh_packet_set_callbacks(ssh_session session, ssh_packet_callbacks callbacks); void ssh_packet_remove_callbacks(ssh_session session, ssh_packet_callbacks callbacks); @@ -80,7 +85,7 @@ int ssh_packet_decrypt(ssh_session session, uint8_t *destination, uint8_t *sourc size_t start, size_t encrypted_size); unsigned char *ssh_packet_encrypt(ssh_session session, void *packet, - unsigned int len); + size_t len); int ssh_packet_hmac_verify(ssh_session session, const void *data, size_t len, unsigned char *mac, enum ssh_hmac_e type); int ssh_packet_set_newkeys(ssh_session session, @@ -88,4 +93,8 @@ int ssh_packet_set_newkeys(ssh_session session, struct ssh_crypto_struct *ssh_packet_get_current_crypto(ssh_session session, enum ssh_crypto_direction_e direction); +#ifdef __cplusplus +} +#endif + #endif /* PACKET_H_ */ diff --git a/include/libssh/pcap.h b/include/libssh/pcap.h index 2e43ae87..2a6c3c27 100644 --- a/include/libssh/pcap.h +++ b/include/libssh/pcap.h @@ -27,6 +27,10 @@ #ifdef WITH_PCAP typedef struct ssh_pcap_context_struct* ssh_pcap_context; +#ifdef __cplusplus +extern "C" { +#endif + int ssh_pcap_file_write_packet(ssh_pcap_file pcap, ssh_buffer packet, uint32_t original_len); ssh_pcap_context ssh_pcap_context_new(ssh_session session); @@ -41,5 +45,9 @@ int ssh_pcap_context_write(ssh_pcap_context,enum ssh_pcap_direction direction, v uint32_t len, uint32_t origlen); +#ifdef __cplusplus +} +#endif + #endif /* WITH_PCAP */ #endif /* PCAP_H_ */ diff --git a/include/libssh/pki.h b/include/libssh/pki.h index 6357b0b6..efb9bdbf 100644 --- a/include/libssh/pki.h +++ b/include/libssh/pki.h @@ -33,8 +33,8 @@ #include <openssl/evp.h> #endif #include "libssh/crypto.h" -#ifdef HAVE_OPENSSL_ED25519 -/* If using OpenSSL implementation, define the signature lenght which would be +#ifdef HAVE_LIBCRYPTO +/* If using OpenSSL implementation, define the signature length which would be * defined in libssh/ed25519.h otherwise */ #define ED25519_SIG_LEN 64 #else @@ -57,32 +57,24 @@ struct ssh_key_struct { const char *type_c; /* Don't free it ! it is static */ int ecdsa_nid; #if defined(HAVE_LIBGCRYPT) - gcry_sexp_t dsa; gcry_sexp_t rsa; gcry_sexp_t ecdsa; #elif defined(HAVE_LIBMBEDCRYPTO) mbedtls_pk_context *rsa; mbedtls_ecdsa_context *ecdsa; - void *dsa; #elif defined(HAVE_LIBCRYPTO) - DSA *dsa; - RSA *rsa; - EVP_PKEY *key; /* Saving the OpenSSL context here to save time while converting*/ -# if defined(HAVE_OPENSSL_ECC) - EC_KEY *ecdsa; -# else - void *ecdsa; -# endif /* HAVE_OPENSSL_EC_H */ -#endif /* HAVE_LIBGCRYPT */ -#ifdef HAVE_OPENSSL_ED25519 + /* This holds either ENGINE key for PKCS#11 support or just key in + * high-level format */ + EVP_PKEY *key; uint8_t *ed25519_pubkey; uint8_t *ed25519_privkey; -#else +#endif /* HAVE_LIBGCRYPT */ +#ifndef HAVE_LIBCRYPTO ed25519_pubkey *ed25519_pubkey; ed25519_privkey *ed25519_privkey; -#endif +#endif /* HAVE_LIBCRYPTO */ ssh_string sk_application; - void *cert; + ssh_buffer cert; enum ssh_keytypes_e cert_type; }; @@ -91,16 +83,15 @@ struct ssh_signature_struct { enum ssh_digest_e hash_type; const char *type_c; #if defined(HAVE_LIBGCRYPT) - gcry_sexp_t dsa_sig; gcry_sexp_t rsa_sig; gcry_sexp_t ecdsa_sig; #elif defined(HAVE_LIBMBEDCRYPTO) ssh_string rsa_sig; struct mbedtls_ecdsa_sig ecdsa_sig; #endif /* HAVE_LIBGCRYPT */ -#ifndef HAVE_OPENSSL_ED25519 +#ifndef HAVE_LIBCRYPTO ed25519_signature *ed25519_sig; -#endif +#endif /* HAVE_LIBGCRYPT */ ssh_string raw_sig; /* Security Key specific additions */ @@ -110,8 +101,11 @@ struct ssh_signature_struct { typedef struct ssh_signature_struct *ssh_signature; +#ifdef __cplusplus +extern "C" { +#endif + /* SSH Key Functions */ -ssh_key ssh_key_dup(const ssh_key key); void ssh_key_clean (ssh_key key); const char * @@ -127,10 +121,11 @@ enum ssh_digest_e ssh_key_hash_from_name(const char *name); ((t) >= SSH_KEYTYPE_ECDSA_P256 && (t) <= SSH_KEYTYPE_ECDSA_P521) #define is_cert_type(kt)\ - ((kt) == SSH_KEYTYPE_DSS_CERT01 ||\ - (kt) == SSH_KEYTYPE_RSA_CERT01 ||\ - ((kt) >= SSH_KEYTYPE_ECDSA_P256_CERT01 &&\ - (kt) <= SSH_KEYTYPE_ED25519_CERT01)) + ((kt) == SSH_KEYTYPE_RSA_CERT01 ||\ + (kt) == SSH_KEYTYPE_SK_ECDSA_CERT01 ||\ + (kt) == SSH_KEYTYPE_SK_ED25519_CERT01 ||\ + ((kt) >= SSH_KEYTYPE_ECDSA_P256_CERT01 &&\ + (kt) <= SSH_KEYTYPE_ED25519_CERT01)) /* SSH Signature Functions */ ssh_signature ssh_signature_new(void); @@ -158,6 +153,10 @@ int ssh_pki_import_pubkey_blob(const ssh_string key_blob, int ssh_pki_import_cert_blob(const ssh_string cert_blob, ssh_key *pkey); +/* SSH Private Key Functions */ +int ssh_pki_export_privkey_blob(const ssh_key key, + ssh_string *pblob); + /* SSH Signing Functions */ ssh_string ssh_pki_do_sign(ssh_session session, ssh_buffer sigbuf, @@ -174,9 +173,19 @@ ssh_public_key ssh_pki_convert_key_to_publickey(const ssh_key key); ssh_private_key ssh_pki_convert_key_to_privatekey(const ssh_key key); int ssh_key_algorithm_allowed(ssh_session session, const char *type); +bool ssh_key_size_allowed(ssh_session session, ssh_key key); + +/* Return the key size in bits */ +int ssh_key_size(ssh_key key); /* PKCS11 URI function to check if filename is a path or a PKCS11 URI */ +#ifdef WITH_PKCS11_URI bool ssh_pki_is_uri(const char *filename); char *ssh_pki_export_pub_uri_from_priv_uri(const char *priv_uri); +#endif /* WITH_PKCS11_URI */ + +#ifdef __cplusplus +} +#endif #endif /* PKI_H_ */ diff --git a/include/libssh/pki_priv.h b/include/libssh/pki_priv.h index 71418fdc..2061ebd7 100644 --- a/include/libssh/pki_priv.h +++ b/include/libssh/pki_priv.h @@ -23,6 +23,10 @@ #include "libssh/pki.h" +#ifdef __cplusplus +extern "C" { +#endif + /* defined in bcrypt_pbkdf.c */ int bcrypt_pbkdf(const char *pass, size_t passlen, @@ -34,8 +38,6 @@ int bcrypt_pbkdf(const char *pass, #define RSA_HEADER_BEGIN "-----BEGIN RSA PRIVATE KEY-----" #define RSA_HEADER_END "-----END RSA PRIVATE KEY-----" -#define DSA_HEADER_BEGIN "-----BEGIN DSA PRIVATE KEY-----" -#define DSA_HEADER_END "-----END DSA PRIVATE KEY-----" #define ECDSA_HEADER_BEGIN "-----BEGIN EC PRIVATE KEY-----" #define ECDSA_HEADER_END "-----END EC PRIVATE KEY-----" #define OPENSSH_HEADER_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----" @@ -49,6 +51,8 @@ enum ssh_key_e { SSH_KEY_PRIVATE }; +void pki_key_clean(ssh_key key); + int pki_key_ecdsa_nid_from_name(const char *name); const char *pki_key_ecdsa_nid_to_name(int nid); const char *ssh_key_signature_to_char(enum ssh_keytypes_e type, @@ -59,7 +63,6 @@ enum ssh_digest_e ssh_key_type_to_hash(ssh_session session, /* SSH Key Functions */ ssh_key pki_key_dup(const ssh_key key, int demote); int pki_key_generate_rsa(ssh_key key, int parameter); -int pki_key_generate_dss(ssh_key key, int parameter); int pki_key_generate_ecdsa(ssh_key key, int parameter); int pki_key_generate_ed25519(ssh_key key); @@ -85,24 +88,13 @@ int pki_import_privkey_buffer(enum ssh_keytypes_e type, ssh_key *pkey); /* SSH Public Key Functions */ -int pki_pubkey_build_dss(ssh_key key, - ssh_string p, - ssh_string q, - ssh_string g, - ssh_string pubkey); int pki_pubkey_build_rsa(ssh_key key, ssh_string e, ssh_string n); int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e); -ssh_string pki_publickey_to_blob(const ssh_key key); +ssh_string pki_key_to_blob(const ssh_key key, enum ssh_key_e type); /* SSH Private Key Functions */ -int pki_privkey_build_dss(ssh_key key, - ssh_string p, - ssh_string q, - ssh_string g, - ssh_string pubkey, - ssh_string privkey); int pki_privkey_build_rsa(ssh_key key, ssh_string n, ssh_string e, @@ -114,7 +106,6 @@ int pki_privkey_build_ecdsa(ssh_key key, int nid, ssh_string e, ssh_string exp); -ssh_string pki_publickey_to_blob(const ssh_key key); /* SSH Signature Functions */ ssh_signature pki_sign_data(const ssh_key privkey, @@ -140,15 +131,18 @@ ssh_signature pki_do_sign_hash(const ssh_key privkey, const unsigned char *hash, size_t hlen, enum ssh_digest_e hash_type); +#ifndef HAVE_LIBCRYPTO int pki_ed25519_sign(const ssh_key privkey, ssh_signature sig, const unsigned char *hash, size_t hlen); int pki_ed25519_verify(const ssh_key pubkey, ssh_signature sig, const unsigned char *hash, size_t hlen); +#endif /* HAVE_LIBCRYPTO */ int pki_ed25519_key_cmp(const ssh_key k1, const ssh_key k2, enum ssh_keycmp_e what); -int pki_ed25519_key_dup(ssh_key new, const ssh_key key); +int pki_ed25519_key_dup(ssh_key new_key, const ssh_key key); int pki_ed25519_public_key_to_blob(ssh_buffer buffer, ssh_key key); +int pki_ed25519_private_key_to_blob(ssh_buffer buffer, const ssh_key privkey); ssh_string pki_ed25519_signature_to_blob(ssh_signature sig); int pki_signature_from_ed25519_blob(ssh_signature sig, ssh_string sig_blob); int pki_privkey_build_ed25519(ssh_key key, @@ -162,7 +156,14 @@ ssh_key ssh_pki_openssh_privkey_import(const char *text_key, ssh_string ssh_pki_openssh_privkey_export(const ssh_key privkey, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data); +#ifdef WITH_PKCS11_URI /* URI Function */ int pki_uri_import(const char *uri_name, ssh_key *key, enum ssh_key_e key_type); +#endif /* WITH_PKCS11_URI */ + +bool ssh_key_size_allowed_rsa(int min_size, ssh_key key); +#ifdef __cplusplus +} +#endif #endif /* PKI_PRIV_H_ */ diff --git a/include/libssh/poll.h b/include/libssh/poll.h index 3aa9a49b..8e30676e 100644 --- a/include/libssh/poll.h +++ b/include/libssh/poll.h @@ -114,6 +114,10 @@ typedef unsigned long int nfds_t; #endif /* WIN32 */ #endif /* HAVE_POLL */ +#ifdef __cplusplus +extern "C" { +#endif + void ssh_poll_init(void); void ssh_poll_cleanup(void); int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout); @@ -158,4 +162,8 @@ ssh_poll_ctx ssh_poll_get_default_ctx(ssh_session session); int ssh_event_add_poll(ssh_event event, ssh_poll_handle p); void ssh_event_remove_poll(ssh_event event, ssh_poll_handle p); +#ifdef __cplusplus +} +#endif + #endif /* POLL_H_ */ diff --git a/include/libssh/poly1305.h b/include/libssh/poly1305.h index 513f1b99..a22fea87 100644 --- a/include/libssh/poly1305.h +++ b/include/libssh/poly1305.h @@ -7,6 +7,10 @@ #define POLY1305_H #include "libssh/chacha20-poly1305-common.h" +#ifdef __cplusplus +extern "C" { +#endif + void poly1305_auth(uint8_t out[POLY1305_TAGLEN], const uint8_t *m, size_t inlen, const uint8_t key[POLY1305_KEYLEN]) #ifdef HAVE_GCC_BOUNDED_ATTRIBUTE @@ -16,4 +20,8 @@ void poly1305_auth(uint8_t out[POLY1305_TAGLEN], const uint8_t *m, size_t inlen, #endif ; +#ifdef __cplusplus +} +#endif + #endif /* POLY1305_H */ diff --git a/include/libssh/priv.h b/include/libssh/priv.h index b18ece4c..bfef771d 100644 --- a/include/libssh/priv.h +++ b/include/libssh/priv.h @@ -29,6 +29,7 @@ #ifndef _LIBSSH_PRIV_H #define _LIBSSH_PRIV_H +#include <limits.h> #include <stdint.h> #include <stdlib.h> #include <string.h> @@ -46,6 +47,14 @@ # endif #endif /* !defined(HAVE_STRTOULL) */ +#ifdef HAVE_TERMIOS_H +#include <termios.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + #if !defined(HAVE_STRNDUP) char *strndup(const char *s, size_t n); #endif /* ! HAVE_STRNDUP */ @@ -151,10 +160,26 @@ char *strndup(const char *s, size_t n); # endif /* _MSC_VER */ struct timeval; -int gettimeofday(struct timeval *__p, void *__t); +int ssh_gettimeofday(struct timeval *__p, void *__t); + +#define gettimeofday ssh_gettimeofday #define _XCLOSESOCKET closesocket +# ifdef HAVE_IO_H +# include <io.h> +# undef open +# define open _open +# undef close +# define close _close +# undef read +# define read _read +# undef write +# define write _write +# undef unlink +# define unlink _unlink +# endif /* HAVE_IO_H */ + #else /* _WIN32 */ #include <unistd.h> @@ -167,6 +192,14 @@ int gettimeofday(struct timeval *__p, void *__t); #include "libssh/callbacks.h" /* some constants */ +#ifndef PATH_MAX +#ifdef MAX_PATH +#define PATH_MAX MAX_PATH +#else +#define PATH_MAX 4096 +#endif +#endif + #ifndef MAX_PACKET_LEN #define MAX_PACKET_LEN 262144 #endif @@ -275,6 +308,7 @@ int ssh_auth_reply_success(ssh_session session, int partial); /* client.c */ int ssh_send_banner(ssh_session session, int is_server); +void ssh_session_socket_close(ssh_session session); /* connect.c */ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host, @@ -290,7 +324,7 @@ int decompress_buffer(ssh_session session,ssh_buffer buf, size_t maxlen); /* match.c */ int match_pattern_list(const char *string, const char *pattern, - unsigned int len, int dolower); + size_t len, int dolower); int match_hostname(const char *host, const char *pattern, unsigned int len); /* connector.c */ @@ -420,4 +454,15 @@ void ssh_agent_state_free(void *data); bool is_ssh_initialized(void); +#define SSH_ERRNO_MSG_MAX 1024 +char *ssh_strerror(int err_num, char *buf, size_t buflen); + +/** 55 defined options (5 bytes each) + terminator */ +#define SSH_TTY_MODES_MAX_BUFSIZE (55 * 5 + 1) +int encode_current_tty_opts(unsigned char *buf, size_t buflen); + +#ifdef __cplusplus +} +#endif + #endif /* _LIBSSH_PRIV_H */ diff --git a/include/libssh/sc25519.h b/include/libssh/sc25519.h index 5a2c1b85..43b09a05 100644 --- a/include/libssh/sc25519.h +++ b/include/libssh/sc25519.h @@ -35,6 +35,10 @@ typedef struct { uint32_t v[16]; } shortsc25519; +#ifdef __cplusplus +extern "C" { +#endif + void sc25519_from32bytes(sc25519 *r, const unsigned char x[32]); void shortsc25519_from16bytes(shortsc25519 *r, const unsigned char x[16]); @@ -71,4 +75,8 @@ void sc25519_window5(signed char r[51], const sc25519 *s); void sc25519_2interleave2(unsigned char r[127], const sc25519 *s1, const sc25519 *s2); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/libssh/scp.h b/include/libssh/scp.h index d356d89b..089fcfc9 100644 --- a/include/libssh/scp.h +++ b/include/libssh/scp.h @@ -47,9 +47,17 @@ struct ssh_scp_struct { int request_mode; }; +#ifdef __cplusplus +extern "C" { +#endif + int ssh_scp_read_string(ssh_scp scp, char *buffer, size_t len); int ssh_scp_integer_mode(const char *mode); char *ssh_scp_string_mode(int mode); int ssh_scp_response(ssh_scp scp, char **response); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/libssh/server.h b/include/libssh/server.h index 41f89d5c..e437f292 100644 --- a/include/libssh/server.h +++ b/include/libssh/server.h @@ -36,26 +36,29 @@ extern "C" { #endif enum ssh_bind_options_e { - SSH_BIND_OPTIONS_BINDADDR, - SSH_BIND_OPTIONS_BINDPORT, - SSH_BIND_OPTIONS_BINDPORT_STR, - SSH_BIND_OPTIONS_HOSTKEY, - SSH_BIND_OPTIONS_DSAKEY, - SSH_BIND_OPTIONS_RSAKEY, - SSH_BIND_OPTIONS_BANNER, - SSH_BIND_OPTIONS_LOG_VERBOSITY, - SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, - SSH_BIND_OPTIONS_ECDSAKEY, - SSH_BIND_OPTIONS_IMPORT_KEY, - SSH_BIND_OPTIONS_KEY_EXCHANGE, - SSH_BIND_OPTIONS_CIPHERS_C_S, - SSH_BIND_OPTIONS_CIPHERS_S_C, - SSH_BIND_OPTIONS_HMAC_C_S, - SSH_BIND_OPTIONS_HMAC_S_C, - SSH_BIND_OPTIONS_CONFIG_DIR, - SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES, - SSH_BIND_OPTIONS_HOSTKEY_ALGORITHMS, - SSH_BIND_OPTIONS_PROCESS_CONFIG, + SSH_BIND_OPTIONS_BINDADDR, + SSH_BIND_OPTIONS_BINDPORT, + SSH_BIND_OPTIONS_BINDPORT_STR, + SSH_BIND_OPTIONS_HOSTKEY, + SSH_BIND_OPTIONS_DSAKEY, /* deprecated */ + SSH_BIND_OPTIONS_RSAKEY, /* deprecated */ + SSH_BIND_OPTIONS_BANNER, + SSH_BIND_OPTIONS_LOG_VERBOSITY, + SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, + SSH_BIND_OPTIONS_ECDSAKEY, /* deprecated */ + SSH_BIND_OPTIONS_IMPORT_KEY, + SSH_BIND_OPTIONS_KEY_EXCHANGE, + SSH_BIND_OPTIONS_CIPHERS_C_S, + SSH_BIND_OPTIONS_CIPHERS_S_C, + SSH_BIND_OPTIONS_HMAC_C_S, + SSH_BIND_OPTIONS_HMAC_S_C, + SSH_BIND_OPTIONS_CONFIG_DIR, + SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES, + SSH_BIND_OPTIONS_HOSTKEY_ALGORITHMS, + SSH_BIND_OPTIONS_PROCESS_CONFIG, + SSH_BIND_OPTIONS_MODULI, + SSH_BIND_OPTIONS_RSA_MIN_SIZE, + SSH_BIND_OPTIONS_IMPORT_KEY_STR, }; typedef struct ssh_bind_struct* ssh_bind; @@ -115,7 +118,7 @@ LIBSSH_API int ssh_bind_listen(ssh_bind ssh_bind_o); * * @param[in] userdata A pointer to private data to pass to the callbacks. * - * @return SSH_OK on success, SSH_ERROR if an error occured. + * @return SSH_OK on success, SSH_ERROR if an error occurred. * * @code * struct ssh_callbacks_struct cb = { @@ -220,6 +223,9 @@ LIBSSH_API int ssh_server_init_kex(ssh_session session); /** * @brief Free a ssh servers bind. * + * Note that this will also free options that have been set on the bind, + * including keys set with SSH_BIND_OPTIONS_IMPORT_KEY. + * * @param ssh_bind_o The ssh server bind to free. */ LIBSSH_API void ssh_bind_free(ssh_bind ssh_bind_o); @@ -243,6 +249,18 @@ LIBSSH_API void ssh_bind_free(ssh_bind ssh_bind_o); */ LIBSSH_API void ssh_set_auth_methods(ssh_session session, int auth_methods); +/** + * @brief Send the server's issue-banner to client. + * + * + * @param[in] session The server session. + * + * @param[in] banner The server's banner. + * + * @return SSH_OK on success, SSH_ERROR on error. + */ +LIBSSH_API int ssh_send_issue_banner(ssh_session session, const ssh_string banner); + /********************************************************** * SERVER MESSAGING **********************************************************/ @@ -266,7 +284,7 @@ LIBSSH_API int ssh_message_reply_default(ssh_message msg); * * @param[in] msg The message to get the username from. * - * @return The username or NULL if an error occured. + * @return The username or NULL if an error occurred. * * @see ssh_message_get() * @see ssh_message_type() @@ -278,12 +296,14 @@ LIBSSH_API const char *ssh_message_auth_user(ssh_message msg); * * @param[in] msg The message to get the password from. * - * @return The username or NULL if an error occured. + * @return The password or NULL if an error occurred. * * @see ssh_message_get() * @see ssh_message_type() + * @deprecated This function should not be used anymore as there is a + * callback based server implementation now auth_password_function. */ -LIBSSH_API const char *ssh_message_auth_password(ssh_message msg); +SSH_DEPRECATED LIBSSH_API const char *ssh_message_auth_password(ssh_message msg); /** * @brief Get the publickey of the authenticated user. @@ -298,11 +318,21 @@ LIBSSH_API const char *ssh_message_auth_password(ssh_message msg); * @see ssh_key_cmp() * @see ssh_message_get() * @see ssh_message_type() + * @deprecated This function should not be used anymore as there is a + * callback based server implementation auth_pubkey_function. */ -LIBSSH_API ssh_key ssh_message_auth_pubkey(ssh_message msg); +SSH_DEPRECATED LIBSSH_API ssh_key ssh_message_auth_pubkey(ssh_message msg); LIBSSH_API int ssh_message_auth_kbdint_is_response(ssh_message msg); -LIBSSH_API enum ssh_publickey_state_e ssh_message_auth_publickey_state(ssh_message msg); + +/** + * @param[in] msg The message to get the public key state from. + * + * @deprecated This function should not be used anymore as there is a + * callback based server implementation auth_pubkey_function + */ +SSH_DEPRECATED LIBSSH_API enum ssh_publickey_state_e ssh_message_auth_publickey_state(ssh_message msg); + LIBSSH_API int ssh_message_auth_reply_success(ssh_message msg,int partial); LIBSSH_API int ssh_message_auth_reply_pk_ok(ssh_message msg, ssh_string algo, ssh_string pubkey); LIBSSH_API int ssh_message_auth_reply_pk_ok_simple(ssh_message msg); @@ -331,11 +361,12 @@ LIBSSH_API int ssh_message_channel_request_open_destination_port(ssh_message msg LIBSSH_API ssh_channel ssh_message_channel_request_channel(ssh_message msg); -LIBSSH_API const char *ssh_message_channel_request_pty_term(ssh_message msg); -LIBSSH_API int ssh_message_channel_request_pty_width(ssh_message msg); -LIBSSH_API int ssh_message_channel_request_pty_height(ssh_message msg); -LIBSSH_API int ssh_message_channel_request_pty_pxwidth(ssh_message msg); -LIBSSH_API int ssh_message_channel_request_pty_pxheight(ssh_message msg); +/* Replaced by callback based server implementation function channel_pty_request_function*/ +SSH_DEPRECATED LIBSSH_API const char *ssh_message_channel_request_pty_term(ssh_message msg); +SSH_DEPRECATED LIBSSH_API int ssh_message_channel_request_pty_width(ssh_message msg); +SSH_DEPRECATED LIBSSH_API int ssh_message_channel_request_pty_height(ssh_message msg); +SSH_DEPRECATED LIBSSH_API int ssh_message_channel_request_pty_pxwidth(ssh_message msg); +SSH_DEPRECATED LIBSSH_API int ssh_message_channel_request_pty_pxheight(ssh_message msg); LIBSSH_API const char *ssh_message_channel_request_env_name(ssh_message msg); LIBSSH_API const char *ssh_message_channel_request_env_value(ssh_message msg); @@ -344,17 +375,18 @@ LIBSSH_API const char *ssh_message_channel_request_command(ssh_message msg); LIBSSH_API const char *ssh_message_channel_request_subsystem(ssh_message msg); -LIBSSH_API int ssh_message_channel_request_x11_single_connection(ssh_message msg); -LIBSSH_API const char *ssh_message_channel_request_x11_auth_protocol(ssh_message msg); -LIBSSH_API const char *ssh_message_channel_request_x11_auth_cookie(ssh_message msg); -LIBSSH_API int ssh_message_channel_request_x11_screen_number(ssh_message msg); +/* Replaced by callback based server implementation function channel_open_request_x11_function*/ +SSH_DEPRECATED LIBSSH_API int ssh_message_channel_request_x11_single_connection(ssh_message msg); +SSH_DEPRECATED LIBSSH_API const char *ssh_message_channel_request_x11_auth_protocol(ssh_message msg); +SSH_DEPRECATED LIBSSH_API const char *ssh_message_channel_request_x11_auth_cookie(ssh_message msg); +SSH_DEPRECATED LIBSSH_API int ssh_message_channel_request_x11_screen_number(ssh_message msg); LIBSSH_API const char *ssh_message_global_request_address(ssh_message msg); LIBSSH_API int ssh_message_global_request_port(ssh_message msg); LIBSSH_API int ssh_channel_open_reverse_forward(ssh_channel channel, const char *remotehost, int remoteport, const char *sourcehost, int localport); -LIBSSH_API int ssh_channel_open_x11(ssh_channel channel, +LIBSSH_API int ssh_channel_open_x11(ssh_channel channel, const char *orig_addr, int orig_port); LIBSSH_API int ssh_channel_request_send_exit_status(ssh_channel channel, diff --git a/include/libssh/session.h b/include/libssh/session.h index 22256150..27da7a83 100644 --- a/include/libssh/session.h +++ b/include/libssh/session.h @@ -23,6 +23,7 @@ #include <stdbool.h> #include "libssh/priv.h" +#include "libssh/callbacks.h" #include "libssh/kex.h" #include "libssh/packet.h" #include "libssh/pcap.h" @@ -70,10 +71,24 @@ enum ssh_pending_call_e { }; /* libssh calls may block an undefined amount of time */ -#define SSH_SESSION_FLAG_BLOCKING 1 +#define SSH_SESSION_FLAG_BLOCKING 0x0001 /* Client successfully authenticated */ -#define SSH_SESSION_FLAG_AUTHENTICATED 2 +#define SSH_SESSION_FLAG_AUTHENTICATED 0x0002 + +/* Do not accept new session channels (no-more-sessions@openssh.com) */ +#define SSH_SESSION_FLAG_NO_MORE_SESSIONS 0x0004 + +/* The KEXINIT message can be sent first by either of the parties so this flag + * indicates that the message was already sent to make sure it is sent and avoid + * sending it twice during key exchange to simplify the state machine. */ +#define SSH_SESSION_FLAG_KEXINIT_SENT 0x0008 + +/* The current SSH2 session implements the "strict KEX" feature and should behave + * differently on SSH2_MSG_NEWKEYS. */ +#define SSH_SESSION_FLAG_KEX_STRICT 0x0010 +/* Unexpected packets have been sent while the session was still unencrypted */ +#define SSH_SESSION_FLAG_KEX_TAINTED 0x0020 /* codes to use with ssh_handle_packets*() */ /* Infinite timeout */ @@ -92,6 +107,13 @@ enum ssh_pending_call_e { #define SSH_OPT_FLAG_KBDINT_AUTH 0x4 #define SSH_OPT_FLAG_GSSAPI_AUTH 0x8 +/* Escape expansion of different variables */ +#define SSH_OPT_EXP_FLAG_KNOWNHOSTS 0x1 +#define SSH_OPT_EXP_FLAG_GLOBAL_KNOWNHOSTS 0x2 +#define SSH_OPT_EXP_FLAG_PROXYCOMMAND 0x4 +#define SSH_OPT_EXP_FLAG_IDENTITY 0x8 +#define SSH_OPT_EXP_FLAG_CONTROL_PATH 0x10 + /* extensions flags */ /* negotiation enabled */ #define SSH_EXT_NEGOTIATION 0x01 @@ -131,10 +153,9 @@ struct ssh_session_struct { /* Extensions negotiated using RFC 8308 */ uint32_t extensions; - ssh_string banner; /* that's the issue banner from - the server */ - char *discon_msg; /* disconnect message from - the remote host */ + ssh_string banner; /* that's the issue banner from the server */ + char *peer_discon_msg; /* disconnect message from the remote host */ + char *disconnect_message; /* disconnect message to be set */ ssh_buffer in_buffer; PACKET in_packet; ssh_buffer out_buffer; @@ -158,32 +179,39 @@ struct ssh_session_struct { uint32_t current_method; } auth; + /* Sending this flag before key exchange to save one round trip during the + * key exchange. This might make sense on high-latency connections. + * So far internal only for testing. Usable only on the client side -- + * there is no key exchange method that would start with server message */ + bool send_first_kex_follows; /* * RFC 4253, 7.1: if the first_kex_packet_follows flag was set in * the received SSH_MSG_KEXINIT, but the guess was wrong, this * field will be set such that the following guessed packet will - * be ignored. Once that packet has been received and ignored, - * this field is cleared. + * be ignored on the receiving side. Once that packet has been received and + * ignored, this field is cleared. + * On the sending side, this is set after we got peer KEXINIT message and we + * need to resend the initial message of the negotiated KEX algorithm. */ - int first_kex_follows_guess_wrong; + bool first_kex_follows_guess_wrong; ssh_buffer in_hashbuf; ssh_buffer out_hashbuf; struct ssh_crypto_struct *current_crypto; - struct ssh_crypto_struct *next_crypto; /* next_crypto is going to be used after a SSH2_MSG_NEWKEYS */ + /* next_crypto is going to be used after a SSH2_MSG_NEWKEYS */ + struct ssh_crypto_struct *next_crypto; struct ssh_list *channels; /* linked list of channels */ - int maxchannel; + uint32_t maxchannel; ssh_agent agent; /* ssh agent */ -/* keyb interactive data */ + /* keyboard interactive data */ struct ssh_kbdint_struct *kbdint; struct ssh_gssapi_struct *gssapi; /* server host keys */ struct { ssh_key rsa_key; - ssh_key dsa_key; ssh_key ecdsa_key; ssh_key ed25519_key; /* The type of host key wanted by client */ @@ -193,7 +221,8 @@ struct ssh_session_struct { /* auths accepted by server */ struct ssh_list *ssh_message_list; /* list of delayed SSH messages */ - int (*ssh_message_callback)( struct ssh_session_struct *session, ssh_message msg, void *userdata); + int (*ssh_message_callback)(struct ssh_session_struct *session, + ssh_message msg, void *userdata); void *ssh_message_callback_data; ssh_server_callbacks server_callbacks; void (*ssh_connection_callback)( struct ssh_session_struct *session); @@ -207,6 +236,9 @@ struct ssh_session_struct { #endif struct { struct ssh_list *identity; + struct ssh_list *identity_non_exp; + struct ssh_list *certificate; + struct ssh_list *certificate_non_exp; char *username; char *host; char *bindaddr; /* bind the client to an ip addr */ @@ -217,9 +249,11 @@ struct ssh_session_struct { char *pubkey_accepted_types; char *ProxyCommand; char *custombanner; + char *moduli_file; + char *agent_socket; unsigned long timeout; /* seconds */ unsigned long timeout_usec; - unsigned int port; + uint16_t port; socket_t fd; int StrictHostKeyChecking; char compressionlevel; @@ -227,11 +261,16 @@ struct ssh_session_struct { char *gss_client_identity; int gss_delegate_creds; int flags; + int exp_flags; int nodelay; bool config_processed; uint8_t options_seen[SOC_MAX]; uint64_t rekey_data; uint32_t rekey_time; + int rsa_min_size; + bool identities_only; + int control_master; + char *control_path; } opts; /* counters */ ssh_counter socket_counter; @@ -246,7 +285,7 @@ struct ssh_session_struct { typedef int (*ssh_termination_function)(void *user); int ssh_handle_packets(ssh_session session, int timeout); int ssh_handle_packets_termination(ssh_session session, - long timeout, + int timeout, ssh_termination_function fct, void *user); void ssh_socket_exception_callback(int code, int errno_code, void *user); diff --git a/include/libssh/sftp.h b/include/libssh/sftp.h index c855df8a..754a54c3 100644 --- a/include/libssh/sftp.h +++ b/include/libssh/sftp.h @@ -77,6 +77,8 @@ typedef struct sftp_request_queue_struct* sftp_request_queue; typedef struct sftp_session_struct* sftp_session; typedef struct sftp_status_message_struct* sftp_status_message; typedef struct sftp_statvfs_struct* sftp_statvfs_t; +typedef struct sftp_limits_struct* sftp_limits_t; +typedef struct sftp_aio_struct* sftp_aio; struct sftp_session_struct { ssh_session session; @@ -90,6 +92,7 @@ struct sftp_session_struct { void **handles; sftp_ext ext; sftp_packet read_packet; + sftp_limits_t limits; }; struct sftp_packet_struct { @@ -201,6 +204,16 @@ struct sftp_statvfs_struct { }; /** + * @brief SFTP limits structure. + */ +struct sftp_limits_struct { + uint64_t max_packet_length; /** maximum number of bytes in a single sftp packet */ + uint64_t max_read_length; /** maximum length in a SSH_FXP_READ packet */ + uint64_t max_write_length; /** maximum length in a SSH_FXP_WRITE packet */ + uint64_t max_open_handles; /** maximum number of active handles allowed by server */ +}; + +/** * @brief Creates a new sftp session. * * This function creates a new sftp session and allocates a new sftp channel @@ -476,13 +489,18 @@ LIBSSH_API void sftp_file_set_blocking(sftp_file handle); /** * @brief Read from a file using an opened sftp file handle. * + * This function caps the length a user is allowed to read from an sftp file. + * + * The value used for the cap is same as the value of the max_read_length + * field of the sftp_limits_t returned by sftp_limits(). + * * @param file The opened sftp file handle to be read from. * * @param buf Pointer to buffer to receive read data. * * @param count Size of the buffer in bytes. * - * @return Number of bytes written, < 0 on error with ssh and sftp + * @return Number of bytes read, < 0 on error with ssh and sftp * error set. * * @see sftp_get_error() @@ -520,7 +538,8 @@ LIBSSH_API ssize_t sftp_read(sftp_file file, void *buf, size_t count); * @see sftp_async_read() * @see sftp_open() */ -LIBSSH_API int sftp_async_read_begin(sftp_file file, uint32_t len); +SSH_DEPRECATED LIBSSH_API int sftp_async_read_begin(sftp_file file, + uint32_t len); /** * @brief Wait for an asynchronous read to complete and save the data. @@ -545,11 +564,19 @@ LIBSSH_API int sftp_async_read_begin(sftp_file file, uint32_t len); * * @see sftp_async_read_begin() */ -LIBSSH_API int sftp_async_read(sftp_file file, void *data, uint32_t len, uint32_t id); +SSH_DEPRECATED LIBSSH_API int sftp_async_read(sftp_file file, + void *data, + uint32_t len, + uint32_t id); /** * @brief Write to a file using an opened sftp file handle. * + * This function caps the length a user is allowed to write to an sftp file. + * + * The value used for the cap is same as the value of the max_write_length + * field of the sftp_limits_t returned by sftp_limits(). + * * @param file Open sftp file handle to write to. * * @param buf Pointer to buffer to write data. @@ -566,6 +593,229 @@ LIBSSH_API int sftp_async_read(sftp_file file, void *data, uint32_t len, uint32_ LIBSSH_API ssize_t sftp_write(sftp_file file, const void *buf, size_t count); /** + * @brief Deallocate memory corresponding to a sftp aio handle. + * + * This function deallocates memory corresponding to the aio handle returned + * by the sftp_aio_begin_*() functions. Users can use this function to free + * memory corresponding to an aio handle for an outstanding async i/o request + * on encountering some error. + * + * @param aio sftp aio handle corresponding to which memory has + * to be deallocated. + * + * @see sftp_aio_begin_read() + * @see sftp_aio_wait_read() + * @see sftp_aio_begin_write() + * @see sftp_aio_wait_write() + */ +LIBSSH_API void sftp_aio_free(sftp_aio aio); +#define SFTP_AIO_FREE(x) \ + do { if(x != NULL) {sftp_aio_free(x); x = NULL;} } while(0) + +/** + * @brief Start an asynchronous read from a file using an opened sftp + * file handle. + * + * Its goal is to avoid the slowdowns related to the request/response pattern + * of a synchronous read. To do so, you must call 2 functions : + * + * sftp_aio_begin_read() and sftp_aio_wait_read(). + * + * - The first step is to call sftp_aio_begin_read(). This function sends a + * read request to the sftp server, dynamically allocates memory to store + * information about the sent request and provides the caller an sftp aio + * handle to that memory. + * + * - The second step is to call sftp_aio_wait_read() and pass it the address + * of a location storing the sftp aio handle provided by + * sftp_aio_begin_read(). + * + * These two functions do not close the open sftp file handle passed to + * sftp_aio_begin_read() irrespective of whether they fail or not. + * + * It is the responsibility of the caller to ensure that the open sftp file + * handle passed to sftp_aio_begin_read() must not be closed before the + * corresponding call to sftp_aio_wait_read(). After sftp_aio_wait_read() + * returns, it is caller's decision whether to immediately close the file by + * calling sftp_close() or to keep it open and perform some more operations + * on it. + * + * This function caps the length a user is allowed to read from an sftp file, + * the value of len parameter after capping is returned on success. + * + * The value used for the cap is same as the value of the max_read_length + * field of the sftp_limits_t returned by sftp_limits(). + * + * @param file The opened sftp file handle to be read from. + * + * @param len Number of bytes to read. + * + * @param aio Pointer to a location where the sftp aio handle + * (corresponding to the sent request) should be stored. + * + * @returns On success, the number of bytes the server is + * requested to read (value of len parameter after + * capping). On error, SSH_ERROR with sftp and ssh + * errors set. + * + * @warning When calling this function, the internal file offset is + * updated corresponding to the number of bytes requested + * to read. + * + * @warning A call to sftp_aio_begin_read() sends a request to + * the server. When the server answers, libssh allocates + * memory to store it until sftp_aio_wait_read() is called. + * Not calling sftp_aio_wait_read() will lead to memory + * leaks. + * + * @see sftp_aio_wait_read() + * @see sftp_aio_free() + * @see sftp_open() + * @see sftp_close() + * @see sftp_get_error() + * @see ssh_get_error() + */ +LIBSSH_API ssize_t sftp_aio_begin_read(sftp_file file, + size_t len, + sftp_aio *aio); + +/** + * @brief Wait for an asynchronous read to complete and store the read data + * in the supplied buffer. + * + * A pointer to an sftp aio handle should be passed while calling + * this function. Except when the return value is SSH_AGAIN, + * this function releases the memory corresponding to the supplied + * aio handle and assigns NULL to that aio handle using the passed + * pointer to that handle. + * + * If the file is opened in non-blocking mode and the request hasn't been + * executed yet, this function returns SSH_AGAIN and must be called again + * using the same sftp aio handle. + * + * @param aio Pointer to the sftp aio handle returned by + * sftp_aio_begin_read(). + * + * @param buf Pointer to the buffer in which read data will be stored. + * + * @param buf_size Size of the buffer in bytes. It should be bigger or + * equal to the length parameter of the + * sftp_aio_begin_read() call. + * + * @return Number of bytes read, 0 on EOF, SSH_ERROR if an error + * occurred, SSH_AGAIN if the file is opened in nonblocking + * mode and the request hasn't been executed yet. + * + * @warning A call to this function with an invalid sftp aio handle + * may never return. + * + * @see sftp_aio_begin_read() + * @see sftp_aio_free() + */ +LIBSSH_API ssize_t sftp_aio_wait_read(sftp_aio *aio, + void *buf, + size_t buf_size); + +/** + * @brief Start an asynchronous write to a file using an opened sftp + * file handle. + * + * Its goal is to avoid the slowdowns related to the request/response pattern + * of a synchronous write. To do so, you must call 2 functions : + * + * sftp_aio_begin_write() and sftp_aio_wait_write(). + * + * - The first step is to call sftp_aio_begin_write(). This function sends a + * write request to the sftp server, dynamically allocates memory to store + * information about the sent request and provides the caller an sftp aio + * handle to that memory. + * + * - The second step is to call sftp_aio_wait_write() and pass it the address + * of a location storing the sftp aio handle provided by + * sftp_aio_begin_write(). + * + * These two functions do not close the open sftp file handle passed to + * sftp_aio_begin_write() irrespective of whether they fail or not. + * + * It is the responsibility of the caller to ensure that the open sftp file + * handle passed to sftp_aio_begin_write() must not be closed before the + * corresponding call to sftp_aio_wait_write(). After sftp_aio_wait_write() + * returns, it is caller's decision whether to immediately close the file by + * calling sftp_close() or to keep it open and perform some more operations + * on it. + * + * This function caps the length a user is allowed to write to an sftp file, + * the value of len parameter after capping is returned on success. + * + * The value used for the cap is same as the value of the max_write_length + * field of the sftp_limits_t returned by sftp_limits(). + * + * @param file The opened sftp file handle to write to. + * + * @param buf Pointer to the buffer containing data to write. + * + * @param len Number of bytes to write. + * + * @param aio Pointer to a location where the sftp aio handle + * (corresponding to the sent request) should be stored. + * + * @returns On success, the number of bytes the server is + * requested to write (value of len parameter after + * capping). On error, SSH_ERROR with sftp and ssh errors + * set. + * + * @warning When calling this function, the internal file offset is + * updated corresponding to the number of bytes requested + * to write. + * + * @warning A call to sftp_aio_begin_write() sends a request to + * the server. When the server answers, libssh allocates + * memory to store it until sftp_aio_wait_write() is + * called. Not calling sftp_aio_wait_write() will lead to + * memory leaks. + * + * @see sftp_aio_wait_write() + * @see sftp_aio_free() + * @see sftp_open() + * @see sftp_close() + * @see sftp_get_error() + * @see ssh_get_error() + */ +LIBSSH_API ssize_t sftp_aio_begin_write(sftp_file file, + const void *buf, + size_t len, + sftp_aio *aio); + +/** + * @brief Wait for an asynchronous write to complete. + * + * A pointer to an sftp aio handle should be passed while calling + * this function. Except when the return value is SSH_AGAIN, + * this function releases the memory corresponding to the supplied + * aio handle and assigns NULL to that aio handle using the passed + * pointer to that handle. + * + * If the file is opened in non-blocking mode and the request hasn't + * been executed yet, this function returns SSH_AGAIN and must be called + * again using the same sftp aio handle. + * + * @param aio Pointer to the sftp aio handle returned by + * sftp_aio_begin_write(). + * + * @return Number of bytes written on success, SSH_ERROR + * if an error occurred, SSH_AGAIN if the file is + * opened in nonblocking mode and the request hasn't + * been executed yet. + * + * @warning A call to this function with an invalid sftp aio handle + * may never return. + * + * @see sftp_aio_begin_write() + * @see sftp_aio_free() + */ +LIBSSH_API ssize_t sftp_aio_wait_write(sftp_aio *aio); + +/** * @brief Seek to a specific location in a file. * * @param file Open sftp file handle to seek in. @@ -605,8 +855,7 @@ LIBSSH_API unsigned long sftp_tell(sftp_file file); * @param file Open sftp file handle. * * @return The offset of the current byte relative to the beginning - * of the file associated with the file descriptor. < 0 on - * error. + * of the file associated with the file descriptor. */ LIBSSH_API uint64_t sftp_tell64(sftp_file file); @@ -681,6 +930,11 @@ LIBSSH_API int sftp_rename(sftp_session sftp, const char *original, const char /** * @brief Set file attributes on a file, directory or symbolic link. * + * Note, that this function can only set time values using 32 bit values due to + * the restrictions in the SFTP protocol version 3 implemented by libssh. + * The support for 64 bit time values was introduced in SFTP version 5, which is + * not implemented by libssh nor any major SFTP servers. + * * @param sftp The sftp session handle. * * @param file The file which attributes should be changed. @@ -767,12 +1021,30 @@ LIBSSH_API int sftp_symlink(sftp_session sftp, const char *target, const char *d * @param path Specifies the path name of the symlink to be read. * * @return The target of the link, NULL on error. + * The caller needs to free the memory + * using ssh_string_free_char(). * * @see sftp_get_error() */ LIBSSH_API char *sftp_readlink(sftp_session sftp, const char *path); /** + * @brief Create a hard link. + * + * @param sftp The sftp session handle. + * + * @param oldpath Specifies the pathname of the file for + * which the new hardlink is to be created. + * + * @param newpath Specifies the pathname of the hardlink to be created. + * + * @return 0 on success, -1 on error with ssh and sftp error set. + * + * @see sftp_get_error() + */ +LIBSSH_API int sftp_hardlink(sftp_session sftp, const char *oldpath, const char *newpath); + +/** * @brief Get information about a mounted file system. * * @param sftp The sftp session handle. @@ -820,6 +1092,24 @@ LIBSSH_API void sftp_statvfs_free(sftp_statvfs_t statvfs_o); LIBSSH_API int sftp_fsync(sftp_file file); /** + * @brief Get information about the various limits the server might impose. + * + * @param sftp The sftp session handle. + * + * @return A limits structure or NULL on error. + * + * @see sftp_get_error() + */ +LIBSSH_API sftp_limits_t sftp_limits(sftp_session sftp); + +/** + * @brief Free the memory of an allocated limits. + * + * @param limits The limits to free. + */ +LIBSSH_API void sftp_limits_free(sftp_limits_t limits); + +/** * @brief Canonicalize a sftp path. * * @param sftp The sftp session handle. @@ -841,6 +1131,19 @@ LIBSSH_API char *sftp_canonicalize_path(sftp_session sftp, const char *path); */ LIBSSH_API int sftp_server_version(sftp_session sftp); +/** + * @brief Canonicalize path using expand-path@openssh.com extension + * + * @param sftp The sftp session handle. + * + * @param path The path to be canonicalized. + * + * @return A pointer to the newly allocated canonicalized path, + * NULL on error. The caller needs to free the memory + * using ssh_string_free_char(). + */ +LIBSSH_API char *sftp_expand_path(sftp_session sftp, const char *path); + #ifdef WITH_SERVER /** * @brief Create a new sftp server session. @@ -860,7 +1163,7 @@ LIBSSH_API sftp_session sftp_server_new(ssh_session session, ssh_channel chan); * * @return 0 on success, < 0 on error. */ -LIBSSH_API int sftp_server_init(sftp_session sftp); +SSH_DEPRECATED LIBSSH_API int sftp_server_init(sftp_session sftp); /** * @brief Close and deallocate a sftp server session. diff --git a/include/libssh/sftp_priv.h b/include/libssh/sftp_priv.h index 83925191..8470a8ad 100644 --- a/include/libssh/sftp_priv.h +++ b/include/libssh/sftp_priv.h @@ -21,12 +21,63 @@ #ifndef SFTP_PRIV_H #define SFTP_PRIV_H +#ifdef __cplusplus +extern "C" { +#endif + sftp_packet sftp_packet_read(sftp_session sftp); -ssize_t sftp_packet_write(sftp_session sftp, uint8_t type, ssh_buffer payload); +int sftp_packet_write(sftp_session sftp, uint8_t type, ssh_buffer payload); void sftp_packet_free(sftp_packet packet); int buffer_add_attributes(ssh_buffer buffer, sftp_attributes attr); sftp_attributes sftp_parse_attr(sftp_session session, ssh_buffer buf, int expectname); +/** + * @brief Reply to the SSH_FXP_INIT message with the SSH_FXP_VERSION message + * + * @param client_msg The pointer to client message. + * + * @return 0 on success, < 0 on error with ssh and sftp error set. + * + * @see sftp_get_error() + */ +int sftp_reply_version(sftp_client_message client_msg); +/** + * @brief Decode the data from channel buffer into sftp read_packet. + * + * @param sftp The sftp session handle. + * + * @param data The pointer to the data buffer of channel. + * @param len The data buffer length + * + * @return Length of data decoded. + */ +int sftp_decode_channel_data_to_packet(sftp_session sftp, void *data, uint32_t len); + +void sftp_set_error(sftp_session sftp, int errnum); + +void sftp_message_free(sftp_message msg); + +int sftp_read_and_dispatch(sftp_session sftp); + +sftp_message sftp_dequeue(sftp_session sftp, uint32_t id); + +/* + * Assigns a new SFTP ID for new requests and assures there is no collision + * between them. + * Returns a new ID ready to use in a request + */ +static inline uint32_t sftp_get_new_id(sftp_session session) +{ + return ++session->id_counter; +} + +sftp_status_message parse_status_msg(sftp_message msg); + +void status_msg_free(sftp_status_message status); + +#ifdef __cplusplus +} +#endif #endif /* SFTP_PRIV_H */ diff --git a/include/libssh/sftpserver.h b/include/libssh/sftpserver.h new file mode 100644 index 00000000..d7ed6e49 --- /dev/null +++ b/include/libssh/sftpserver.h @@ -0,0 +1,73 @@ +/* + * This file is part of the SSH Library + * + * Copyright (c) 2022 Zeyu Sheng <shengzeyu19_98@163.com> + * Copyright (c) 2023 Red Hat, Inc. + * + * Authors: Jakub Jelen <jjelen@redhat.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SFTP_SERVER_H +#define SFTP_SERVER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> +/** + * @defgroup libssh_sftp_server The libssh SFTP server API + * + * @brief SFTP server handling functions + * + * TODO + * + * @{ + */ + +#define SSH_SFTP_CALLBACK(name) \ + static int name(sftp_client_message message) + +typedef int (*sftp_server_message_callback)(sftp_client_message message); + +struct sftp_message_handler +{ + const char *name; + const char *extended_name; + uint8_t type; + + sftp_server_message_callback cb; +}; + +LIBSSH_API int sftp_channel_default_subsystem_request(ssh_session session, + ssh_channel channel, + const char *subsystem, + void *userdata); +LIBSSH_API int sftp_channel_default_data_callback(ssh_session session, + ssh_channel channel, + void *data, + uint32_t len, + int is_stderr, + void *userdata); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* SFTP_SERVER_H */ diff --git a/include/libssh/socket.h b/include/libssh/socket.h index 5e345c68..cdd3c837 100644 --- a/include/libssh/socket.h +++ b/include/libssh/socket.h @@ -35,13 +35,14 @@ void ssh_socket_reset(ssh_socket s); void ssh_socket_free(ssh_socket s); void ssh_socket_set_fd(ssh_socket s, socket_t fd); socket_t ssh_socket_get_fd(ssh_socket s); -#ifndef _WIN32 +void ssh_socket_set_connected(ssh_socket s, struct ssh_poll_handle_struct *p); int ssh_socket_unix(ssh_socket s, const char *path); void ssh_execute_command(const char *command, socket_t in, socket_t out); +#ifndef _WIN32 int ssh_socket_connect_proxycommand(ssh_socket s, const char *command); #endif void ssh_socket_close(ssh_socket s); -int ssh_socket_write(ssh_socket s,const void *buffer, int len); +int ssh_socket_write(ssh_socket s,const void *buffer, uint32_t len); int ssh_socket_is_open(ssh_socket s); int ssh_socket_fd_isset(ssh_socket s, fd_set *set); void ssh_socket_fd_set(ssh_socket s, fd_set *set, socket_t *max_fd); diff --git a/include/libssh/string.h b/include/libssh/string.h index 8c7db1df..35b2ea2e 100644 --- a/include/libssh/string.h +++ b/include/libssh/string.h @@ -22,6 +22,10 @@ #define STRING_H_ #include "libssh/priv.h" +#ifdef __cplusplus +extern "C" { +#endif + /* must be 32 bits number + immediately our data */ #ifdef _MSC_VER #pragma pack(1) @@ -38,4 +42,8 @@ __attribute__ ((packed)) #endif ; +#ifdef __cplusplus +} +#endif + #endif /* STRING_H_ */ diff --git a/include/libssh/threads.h b/include/libssh/threads.h index 522f91d5..47340d17 100644 --- a/include/libssh/threads.h +++ b/include/libssh/threads.h @@ -49,6 +49,10 @@ #endif +#ifdef __cplusplus +extern "C" { +#endif + int ssh_threads_init(void); void ssh_threads_finalize(void); const char *ssh_threads_get_type(void); @@ -60,4 +64,8 @@ struct ssh_threads_callbacks_struct *ssh_threads_get_default(void); int crypto_thread_init(struct ssh_threads_callbacks_struct *user_callbacks); void crypto_thread_finalize(void); +#ifdef __cplusplus +} +#endif + #endif /* THREADS_H_ */ diff --git a/include/libssh/token.h b/include/libssh/token.h index 9896fb06..550ad792 100644 --- a/include/libssh/token.h +++ b/include/libssh/token.h @@ -31,6 +31,10 @@ struct ssh_tokens_st { char **tokens; }; +#ifdef __cplusplus +extern "C" { +#endif + struct ssh_tokens_st *ssh_tokenize(const char *chain, char separator); void ssh_tokens_free(struct ssh_tokens_st *tokens); @@ -45,4 +49,13 @@ char *ssh_remove_duplicates(const char *list); char *ssh_append_without_duplicates(const char *list, const char *appended_list); +char *ssh_prefix_without_duplicates(const char *list, + const char *prefixed_list); +char *ssh_remove_all_matching(const char *list, + const char *remove_list); + +#ifdef __cplusplus +} +#endif + #endif /* TOKEN_H_ */ diff --git a/include/libssh/wrapper.h b/include/libssh/wrapper.h index df6544ee..b3e28eac 100644 --- a/include/libssh/wrapper.h +++ b/include/libssh/wrapper.h @@ -29,6 +29,10 @@ #include "libssh/libgcrypt.h" #include "libssh/libmbedcrypto.h" +#ifdef __cplusplus +extern "C" { +#endif + enum ssh_kdf_digest { SSH_KDF_SHA1=1, SSH_KDF_SHA256, @@ -68,42 +72,42 @@ struct ssh_crypto_struct; typedef struct ssh_mac_ctx_struct *ssh_mac_ctx; MD5CTX md5_init(void); -void md5_update(MD5CTX c, const void *data, unsigned long len); -void md5_final(unsigned char *md,MD5CTX c); +void md5_ctx_free(MD5CTX); +int md5_update(MD5CTX c, const void *data, size_t len); +int md5_final(unsigned char *md, MD5CTX c); SHACTX sha1_init(void); -void sha1_update(SHACTX c, const void *data, unsigned long len); -void sha1_final(unsigned char *md,SHACTX c); -void sha1(const unsigned char *digest,int len,unsigned char *hash); +void sha1_ctx_free(SHACTX); +int sha1_update(SHACTX c, const void *data, size_t len); +int sha1_final(unsigned char *md,SHACTX c); +int sha1(const unsigned char *digest,size_t len, unsigned char *hash); SHA256CTX sha256_init(void); -void sha256_update(SHA256CTX c, const void *data, unsigned long len); -void sha256_final(unsigned char *md,SHA256CTX c); -void sha256(const unsigned char *digest, int len, unsigned char *hash); +void sha256_ctx_free(SHA256CTX); +int sha256_update(SHA256CTX c, const void *data, size_t len); +int sha256_final(unsigned char *md,SHA256CTX c); +int sha256(const unsigned char *digest, size_t len, unsigned char *hash); SHA384CTX sha384_init(void); -void sha384_update(SHA384CTX c, const void *data, unsigned long len); -void sha384_final(unsigned char *md,SHA384CTX c); -void sha384(const unsigned char *digest, int len, unsigned char *hash); +void sha384_ctx_free(SHA384CTX); +int sha384_update(SHA384CTX c, const void *data, size_t len); +int sha384_final(unsigned char *md,SHA384CTX c); +int sha384(const unsigned char *digest, size_t len, unsigned char *hash); SHA512CTX sha512_init(void); -void sha512_update(SHA512CTX c, const void *data, unsigned long len); -void sha512_final(unsigned char *md,SHA512CTX c); -void sha512(const unsigned char *digest, int len, unsigned char *hash); - -void evp(int nid, unsigned char *digest, int len, unsigned char *hash, unsigned int *hlen); -EVPCTX evp_init(int nid); -void evp_update(EVPCTX ctx, const void *data, unsigned long len); -void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen); - -HMACCTX hmac_init(const void *key,int len, enum ssh_hmac_e type); -void hmac_update(HMACCTX c, const void *data, unsigned long len); -void hmac_final(HMACCTX ctx,unsigned char *hashmacbuf,unsigned int *len); +void sha512_ctx_free(SHA512CTX); +int sha512_update(SHA512CTX c, const void *data, size_t len); +int sha512_final(unsigned char *md,SHA512CTX c); +int sha512(const unsigned char *digest, size_t len, unsigned char *hash); + +HMACCTX hmac_init(const void *key,size_t len, enum ssh_hmac_e type); +int hmac_update(HMACCTX c, const void *data, size_t len); +int hmac_final(HMACCTX ctx, unsigned char *hashmacbuf, size_t *len); size_t hmac_digest_len(enum ssh_hmac_e type); int ssh_kdf(struct ssh_crypto_struct *crypto, unsigned char *key, size_t key_len, - int key_type, unsigned char *output, + uint8_t key_type, unsigned char *output, size_t requested_len); int crypt_set_algorithms_client(ssh_session session); @@ -120,4 +124,15 @@ struct ssh_hmac_struct *ssh_get_hmactab(void); struct ssh_cipher_struct *ssh_get_ciphertab(void); const char *ssh_hmac_type_to_string(enum ssh_hmac_e hmac_type, bool etm); +#if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L +int evp_build_pkey(const char* name, OSSL_PARAM_BLD *param_bld, EVP_PKEY **pkey, int selection); +int evp_dup_dsa_pkey(const ssh_key key, ssh_key new_key, int demote); +int evp_dup_rsa_pkey(const ssh_key key, ssh_key new_key, int demote); +int evp_dup_ecdsa_pkey(const ssh_key key, ssh_key new_key, int demote); +#endif /* HAVE_LIBCRYPTO && OPENSSL_VERSION_NUMBER */ + +#ifdef __cplusplus +} +#endif + #endif /* WRAPPER_H_ */ |