/src/libssh/include/libssh/session.h
Line | Count | Source |
1 | | /* |
2 | | * This file is part of the SSH Library |
3 | | * |
4 | | * Copyright (c) 2009 by Aris Adamantiadis |
5 | | * |
6 | | * This library is free software; you can redistribute it and/or |
7 | | * modify it under the terms of the GNU Lesser General Public |
8 | | * License as published by the Free Software Foundation; either |
9 | | * version 2.1 of the License, or (at your option) any later version. |
10 | | * |
11 | | * This library is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | | * Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public |
17 | | * License along with this library; if not, write to the Free Software |
18 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | | */ |
20 | | |
21 | | #ifndef SESSION_H_ |
22 | | #define SESSION_H_ |
23 | | #include <stdbool.h> |
24 | | |
25 | | #include "libssh/priv.h" |
26 | | #include "libssh/callbacks.h" |
27 | | #include "libssh/kex.h" |
28 | | #include "libssh/packet.h" |
29 | | #include "libssh/pcap.h" |
30 | | #include "libssh/auth.h" |
31 | | #include "libssh/channels.h" |
32 | | #include "libssh/poll.h" |
33 | | #include "libssh/config.h" |
34 | | #include "libssh/misc.h" |
35 | | |
36 | | /* These are the different states a SSH session can be into its life */ |
37 | | enum ssh_session_state_e { |
38 | | SSH_SESSION_STATE_NONE=0, |
39 | | SSH_SESSION_STATE_CONNECTING, |
40 | | SSH_SESSION_STATE_SOCKET_CONNECTED, |
41 | | SSH_SESSION_STATE_BANNER_RECEIVED, |
42 | | SSH_SESSION_STATE_INITIAL_KEX, |
43 | | SSH_SESSION_STATE_KEXINIT_RECEIVED, |
44 | | SSH_SESSION_STATE_DH, |
45 | | SSH_SESSION_STATE_AUTHENTICATING, |
46 | | SSH_SESSION_STATE_AUTHENTICATED, |
47 | | SSH_SESSION_STATE_ERROR, |
48 | | SSH_SESSION_STATE_DISCONNECTED |
49 | | }; |
50 | | |
51 | | enum ssh_dh_state_e { |
52 | | DH_STATE_INIT=0, |
53 | | DH_STATE_GROUP_SENT, |
54 | | DH_STATE_REQUEST_SENT, |
55 | | DH_STATE_INIT_SENT, |
56 | | DH_STATE_NEWKEYS_SENT, |
57 | | DH_STATE_FINISHED |
58 | | }; |
59 | | |
60 | | enum ssh_pending_call_e { |
61 | | SSH_PENDING_CALL_NONE = 0, |
62 | | SSH_PENDING_CALL_CONNECT, |
63 | | SSH_PENDING_CALL_AUTH_NONE, |
64 | | SSH_PENDING_CALL_AUTH_PASSWORD, |
65 | | SSH_PENDING_CALL_AUTH_OFFER_PUBKEY, |
66 | | SSH_PENDING_CALL_AUTH_PUBKEY, |
67 | | SSH_PENDING_CALL_AUTH_AGENT, |
68 | | SSH_PENDING_CALL_AUTH_KBDINT_INIT, |
69 | | SSH_PENDING_CALL_AUTH_KBDINT_SEND, |
70 | | SSH_PENDING_CALL_AUTH_GSSAPI_MIC, |
71 | | SSH_PENDING_CALL_AUTH_GSSAPI_KEYEX, |
72 | | }; |
73 | | |
74 | | /* libssh calls may block an undefined amount of time */ |
75 | 24.1k | #define SSH_SESSION_FLAG_BLOCKING 0x0001 |
76 | | |
77 | | /* Client successfully authenticated */ |
78 | 645k | #define SSH_SESSION_FLAG_AUTHENTICATED 0x0002 |
79 | | |
80 | | /* Do not accept new session channels (no-more-sessions@openssh.com) */ |
81 | 1.80k | #define SSH_SESSION_FLAG_NO_MORE_SESSIONS 0x0004 |
82 | | |
83 | | /* The KEXINIT message can be sent first by either of the parties so this flag |
84 | | * indicates that the message was already sent to make sure it is sent and avoid |
85 | | * sending it twice during key exchange to simplify the state machine. */ |
86 | 17.8k | #define SSH_SESSION_FLAG_KEXINIT_SENT 0x0008 |
87 | | |
88 | | /* The current SSH2 session implements the "strict KEX" feature and should behave |
89 | | * differently on SSH2_MSG_NEWKEYS. */ |
90 | 15.3k | #define SSH_SESSION_FLAG_KEX_STRICT 0x0010 |
91 | | /* Unexpected packets have been sent while the session was still unencrypted */ |
92 | 157k | #define SSH_SESSION_FLAG_KEX_TAINTED 0x0020 |
93 | | /* The scp on server can not handle quoted paths. Skip the mitigation for |
94 | | * CVE-2019-14889 when using scp */ |
95 | 2 | #define SSH_SESSION_FLAG_SCP_QUOTING_BROKEN 0x0040 |
96 | | |
97 | | /* codes to use with ssh_handle_packets*() */ |
98 | | /* Infinite timeout */ |
99 | 7.72k | #define SSH_TIMEOUT_INFINITE -1 |
100 | | /* Use the timeout defined by user if any. Mostly used with new connections */ |
101 | 33.4k | #define SSH_TIMEOUT_USER -2 |
102 | | /* Use the default timeout, depending on ssh_is_blocking() */ |
103 | 0 | #define SSH_TIMEOUT_DEFAULT -3 |
104 | | /* Don't block at all */ |
105 | 7.72k | #define SSH_TIMEOUT_NONBLOCKING 0 |
106 | | |
107 | | /* options flags */ |
108 | | /* Authentication with *** allowed */ |
109 | 8.20k | #define SSH_OPT_FLAG_PASSWORD_AUTH 0x1 |
110 | 8.20k | #define SSH_OPT_FLAG_PUBKEY_AUTH 0x2 |
111 | 8.20k | #define SSH_OPT_FLAG_KBDINT_AUTH 0x4 |
112 | 8.20k | #define SSH_OPT_FLAG_GSSAPI_AUTH 0x8 |
113 | | |
114 | | /* Escape expansion of different variables */ |
115 | 0 | #define SSH_OPT_EXP_FLAG_KNOWNHOSTS 0x1 |
116 | 0 | #define SSH_OPT_EXP_FLAG_GLOBAL_KNOWNHOSTS 0x2 |
117 | 0 | #define SSH_OPT_EXP_FLAG_PROXYCOMMAND 0x4 |
118 | 0 | #define SSH_OPT_EXP_FLAG_IDENTITY 0x8 |
119 | 0 | #define SSH_OPT_EXP_FLAG_CONTROL_PATH 0x10 |
120 | 0 | #define SSH_OPT_EXP_FLAG_USERNAME 0x20 |
121 | | |
122 | | /* extensions flags */ |
123 | | /* negotiation enabled */ |
124 | 15.2k | #define SSH_EXT_NEGOTIATION 0x01 |
125 | | /* server-sig-algs extension */ |
126 | 2.54k | #define SSH_EXT_SIG_RSA_SHA256 0x02 |
127 | 1.82k | #define SSH_EXT_SIG_RSA_SHA512 0x04 |
128 | | /* Host-bound public key authentication extension */ |
129 | 18 | #define SSH_EXT_PUBLICKEY_HOSTBOUND 0x08 |
130 | | /* ping@openssh.com extension */ |
131 | 52 | #define SSH_EXT_PING 0x10 |
132 | | |
133 | | /* members that are common to ssh_session and ssh_bind */ |
134 | | struct ssh_common_struct { |
135 | | struct error_struct error; |
136 | | ssh_callbacks callbacks; /* Callbacks to user functions */ |
137 | | int log_verbosity; /* verbosity of the log functions */ |
138 | | }; |
139 | | |
140 | | struct ssh_session_struct { |
141 | | struct ssh_common_struct common; |
142 | | struct ssh_socket_struct *socket; |
143 | | char *serverbanner; |
144 | | char *clientbanner; |
145 | | int protoversion; |
146 | | int server; |
147 | | int client; |
148 | | int openssh; |
149 | | uint32_t send_seq; |
150 | | uint32_t recv_seq; |
151 | | struct ssh_timestamp last_rekey_time; |
152 | | bool proxy_root; |
153 | | uint32_t pending_pings; |
154 | | int connected; |
155 | | /* !=0 when the user got a session handle */ |
156 | | int alive; |
157 | | /* two previous are deprecated */ |
158 | | /* int auth_service_asked; */ |
159 | | |
160 | | /* session flags (SSH_SESSION_FLAG_*) */ |
161 | | int flags; |
162 | | |
163 | | /* Extensions negotiated using RFC 8308 */ |
164 | | uint32_t extensions; |
165 | | |
166 | | ssh_string banner; /* that's the issue banner from the server */ |
167 | | char *peer_discon_msg; /* disconnect message from the remote host */ |
168 | | char *disconnect_message; /* disconnect message to be set */ |
169 | | ssh_buffer in_buffer; |
170 | | PACKET in_packet; |
171 | | ssh_buffer out_buffer; |
172 | | struct ssh_list *out_queue; /* This list is used for delaying packets |
173 | | when rekeying is required */ |
174 | | |
175 | | /* the states are used by the nonblocking stuff to remember */ |
176 | | /* where it was before being interrupted */ |
177 | | enum ssh_pending_call_e pending_call_state; |
178 | | enum ssh_session_state_e session_state; |
179 | | enum ssh_packet_state_e packet_state; |
180 | | enum ssh_dh_state_e dh_handshake_state; |
181 | | enum ssh_channel_request_state_e global_req_state; |
182 | | struct ssh_agent_state_struct *agent_state; |
183 | | |
184 | | struct { |
185 | | struct ssh_auth_auto_state_struct *auto_state; |
186 | | enum ssh_auth_service_state_e service_state; |
187 | | enum ssh_auth_state_e state; |
188 | | uint32_t supported_methods; |
189 | | uint32_t current_method; |
190 | | } auth; |
191 | | |
192 | | /* Sending this flag before key exchange to save one round trip during the |
193 | | * key exchange. This might make sense on high-latency connections. |
194 | | * So far internal only for testing. Usable only on the client side -- |
195 | | * there is no key exchange method that would start with server message */ |
196 | | bool send_first_kex_follows; |
197 | | /* |
198 | | * RFC 4253, 7.1: if the first_kex_packet_follows flag was set in |
199 | | * the received SSH_MSG_KEXINIT, but the guess was wrong, this |
200 | | * field will be set such that the following guessed packet will |
201 | | * be ignored on the receiving side. Once that packet has been received and |
202 | | * ignored, this field is cleared. |
203 | | * On the sending side, this is set after we got peer KEXINIT message and we |
204 | | * need to resend the initial message of the negotiated KEX algorithm. |
205 | | */ |
206 | | bool first_kex_follows_guess_wrong; |
207 | | |
208 | | ssh_string gssapi_key_exchange_mic; |
209 | | |
210 | | ssh_buffer in_hashbuf; |
211 | | ssh_buffer out_hashbuf; |
212 | | struct ssh_crypto_struct *current_crypto; |
213 | | /* next_crypto is going to be used after a SSH2_MSG_NEWKEYS */ |
214 | | struct ssh_crypto_struct *next_crypto; |
215 | | |
216 | | struct ssh_list *channels; /* linked list of channels */ |
217 | | uint32_t maxchannel; |
218 | | ssh_agent agent; /* ssh agent */ |
219 | | |
220 | | /* keyboard interactive data */ |
221 | | struct ssh_kbdint_struct *kbdint; |
222 | | struct ssh_gssapi_struct *gssapi; |
223 | | |
224 | | /* server host keys */ |
225 | | struct { |
226 | | ssh_key rsa_key; |
227 | | ssh_key ecdsa_key; |
228 | | ssh_key ed25519_key; |
229 | | /* The type of host key wanted by client */ |
230 | | enum ssh_keytypes_e hostkey; |
231 | | enum ssh_digest_e hostkey_digest; |
232 | | } srv; |
233 | | |
234 | | /* auths accepted by server */ |
235 | | struct ssh_list *ssh_message_list; /* list of delayed SSH messages */ |
236 | | int (*ssh_message_callback)(struct ssh_session_struct *session, |
237 | | ssh_message msg, void *userdata); |
238 | | void *ssh_message_callback_data; |
239 | | ssh_server_callbacks server_callbacks; |
240 | | void (*ssh_connection_callback)( struct ssh_session_struct *session); |
241 | | struct ssh_packet_callbacks_struct default_packet_callbacks; |
242 | | struct ssh_list *packet_callbacks; |
243 | | struct ssh_socket_callbacks_struct socket_callbacks; |
244 | | ssh_poll_ctx default_poll_ctx; |
245 | | /* options */ |
246 | | #ifdef WITH_PCAP |
247 | | ssh_pcap_context pcap_ctx; /* pcap debugging context */ |
248 | | #endif |
249 | | struct { |
250 | | struct ssh_list *identity; |
251 | | struct ssh_list *identity_non_exp; |
252 | | struct ssh_iterator *identity_it; |
253 | | struct ssh_list *certificate; |
254 | | struct ssh_list *certificate_non_exp; |
255 | | struct ssh_list *proxy_jumps; |
256 | | struct ssh_list *proxy_jumps_user_cb; |
257 | | char *proxy_jumps_str; |
258 | | char *username; |
259 | | char *host; |
260 | | char *bindaddr; /* bind the client to an ip addr */ |
261 | | char *homedir; |
262 | | char *sshdir; |
263 | | char *knownhosts; |
264 | | char *global_knownhosts; |
265 | | char *wanted_methods[SSH_KEX_METHODS]; |
266 | | char *pubkey_accepted_types; |
267 | | char *ProxyCommand; |
268 | | char *agent_socket; |
269 | | unsigned long timeout; /* seconds */ |
270 | | unsigned long timeout_usec; |
271 | | uint16_t port; |
272 | | socket_t fd; |
273 | | int StrictHostKeyChecking; |
274 | | char compressionlevel; |
275 | | char *gss_server_identity; |
276 | | char *gss_client_identity; |
277 | | bool gssapi_key_exchange; |
278 | | char *gssapi_key_exchange_algs; |
279 | | int gss_delegate_creds; |
280 | | int flags; |
281 | | int exp_flags; |
282 | | int nodelay; |
283 | | bool config_processed; |
284 | | uint8_t options_seen[SOC_MAX]; |
285 | | uint64_t rekey_data; |
286 | | uint32_t rekey_time; |
287 | | int rsa_min_size; |
288 | | bool identities_only; |
289 | | int control_master; |
290 | | char *control_path; |
291 | | int address_family; |
292 | | int server_alive_interval; |
293 | | int server_alive_count_max; |
294 | | bool batch_mode; |
295 | | char *preferred_authentications; |
296 | | int number_of_password_prompts; |
297 | | int request_tty; |
298 | | int escape_char; |
299 | | struct ssh_list *local_forward; |
300 | | struct ssh_iterator *local_forward_it; |
301 | | struct ssh_list *remote_forward; |
302 | | struct ssh_iterator *remote_forward_it; |
303 | | struct ssh_list *send_env; |
304 | | struct ssh_iterator *send_env_it; |
305 | | char *originalhost; /* user-supplied host for config matching */ |
306 | | char *config_hostname; /* normalized HostName pattern, applied later */ |
307 | | bool config_hostname_only; /* config hostname path: update host only, |
308 | | not originalhost */ |
309 | | char *tag; /* configuration tag for Match tagged */ |
310 | | int pubkey_auth; |
311 | | bool exit_on_forward_failure; |
312 | | bool forward_agent; |
313 | | char *forward_agent_sock_path; |
314 | | bool gateway_ports; |
315 | | } opts; |
316 | | |
317 | | /* server options */ |
318 | | struct { |
319 | | char *custombanner; |
320 | | char *moduli_file; |
321 | | } server_opts; |
322 | | |
323 | | /* counters */ |
324 | | ssh_counter socket_counter; |
325 | | ssh_counter raw_counter; |
326 | | |
327 | | /* PKI context structure containing various parameters to configure PKI |
328 | | * operations */ |
329 | | struct ssh_pki_ctx_struct *pki_context; |
330 | | }; |
331 | | |
332 | | /** |
333 | | * @internal |
334 | | * |
335 | | * @brief Apply the reduced-authentication behavior for an unsafe host key |
336 | | * continuation. |
337 | | * |
338 | | * When `StrictHostKeyChecking` is `off` and host key verification reports a |
339 | | * changed or other key, OpenSSH allows the connection to continue only |
340 | | * "subject to some restrictions"; see `ssh_config(5)` for |
341 | | * `StrictHostKeyChecking` and `check_host_key()` in OpenSSH's `sshconnect.c` |
342 | | * under the `continue_unsafe` label. For libssh's supported client-side auth |
343 | | * methods, this means disabling password and keyboard-interactive |
344 | | * authentication for the rest of the session. |
345 | | */ |
346 | | static inline void ssh_known_hosts_continue_unsafe(ssh_session session) |
347 | 0 | { |
348 | 0 | SSH_LOG(SSH_LOG_WARN, |
349 | 0 | "Continuing despite an unsafe host key with " |
350 | 0 | "StrictHostKeyChecking=off; password and keyboard-interactive " |
351 | 0 | "authentication have been disabled for this session"); |
352 | 0 | session->opts.flags &= |
353 | 0 | ~(SSH_OPT_FLAG_PASSWORD_AUTH | SSH_OPT_FLAG_KBDINT_AUTH); |
354 | 0 | } Unexecuted instantiation: callbacks.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: channels.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: client.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: curve25519.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: sntrup761.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: dh.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: error.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: hybrid_mlkem.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: kex.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: knownhosts.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: log.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: messages.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: misc.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: mlkem.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: options.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: packet.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: packet_cb.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: packet_crypt.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: pcap.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: pki.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: poll.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: session.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: socket.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: wrapper.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: pki_crypto.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: ecdh_crypto.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: curve25519_crypto.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: libcrypto.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: dh_crypto.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: server.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: bind.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: bind_config.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: dh-gex.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: mlkem_native.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: agent.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: auth.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: config.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: connect.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: connector.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: ecdh.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: gzip.c:ssh_known_hosts_continue_unsafe Unexecuted instantiation: kdf.c:ssh_known_hosts_continue_unsafe |
355 | | |
356 | | /** @internal |
357 | | * @brief a termination function evaluates the status of an object |
358 | | * @param user[in] object to evaluate |
359 | | * @returns 1 if the polling routine should terminate, 0 instead |
360 | | */ |
361 | | typedef int (*ssh_termination_function)(void *user); |
362 | | int ssh_handle_packets(ssh_session session, int timeout); |
363 | | int ssh_handle_packets_termination(ssh_session session, |
364 | | int timeout, |
365 | | ssh_termination_function fct, |
366 | | void *user); |
367 | | void ssh_socket_exception_callback(int code, int errno_code, void *user); |
368 | | |
369 | | #endif /* SESSION_H_ */ |