1 /*
2 * session.c - non-networking functions
3 *
4 * This file is part of the SSH Library
5 *
6 * Copyright (c) 2005-2013 by Aris Adamantiadis
7 *
8 * The SSH Library is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or (at your
11 * option) any later version.
12 *
13 * The SSH Library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 * License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with the SSH Library; see the file COPYING. If not, write to
20 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
21 * MA 02111-1307, USA.
22 */
23
24 #include "config.h"
25
26 #include <string.h>
27 #include <stdlib.h>
28
29 #include "libssh/priv.h"
30 #include "libssh/libssh.h"
31 #include "libssh/crypto.h"
32 #include "libssh/server.h"
33 #include "libssh/socket.h"
34 #include "libssh/ssh2.h"
35 #include "libssh/agent.h"
36 #include "libssh/packet.h"
37 #include "libssh/session.h"
38 #include "libssh/misc.h"
39 #include "libssh/buffer.h"
40 #include "libssh/poll.h"
41 #include "libssh/pki.h"
42
43 #define FIRST_CHANNEL 42 // why not ? it helps to find bugs.
44
45 /**
46 * @defgroup libssh_session The SSH session functions.
47 * @ingroup libssh
48 *
49 * Functions that manage a session.
50 *
51 * @{
52 */
53
54 /**
55 * @brief Create a new ssh session.
56 *
57 * @returns A new ssh_session pointer, NULL on error.
58 */
ssh_new(void)59 ssh_session ssh_new(void)
60 {
61 ssh_session session;
62 char *id = NULL;
63 int rc;
64
65 session = calloc(1, sizeof (struct ssh_session_struct));
66 if (session == NULL) {
67 return NULL;
68 }
69
70 session->next_crypto = crypto_new();
71 if (session->next_crypto == NULL) {
72 goto err;
73 }
74
75 session->socket = ssh_socket_new(session);
76 if (session->socket == NULL) {
77 goto err;
78 }
79
80 session->out_buffer = ssh_buffer_new();
81 if (session->out_buffer == NULL) {
82 goto err;
83 }
84
85 session->in_buffer = ssh_buffer_new();
86 if (session->in_buffer == NULL) {
87 goto err;
88 }
89
90 session->out_queue = ssh_list_new();
91 if (session->out_queue == NULL) {
92 goto err;
93 }
94
95 session->alive = 0;
96 session->auth.supported_methods = 0;
97 ssh_set_blocking(session, 1);
98 session->maxchannel = FIRST_CHANNEL;
99
100 #ifndef _WIN32
101 session->agent = ssh_agent_new(session);
102 if (session->agent == NULL) {
103 goto err;
104 }
105 #endif /* _WIN32 */
106
107 /* OPTIONS */
108 session->opts.StrictHostKeyChecking = 1;
109 session->opts.port = 0;
110 session->opts.fd = -1;
111 session->opts.compressionlevel = 7;
112 session->opts.nodelay = 0;
113
114 session->opts.flags = SSH_OPT_FLAG_PASSWORD_AUTH |
115 SSH_OPT_FLAG_PUBKEY_AUTH |
116 SSH_OPT_FLAG_KBDINT_AUTH |
117 SSH_OPT_FLAG_GSSAPI_AUTH;
118
119 session->opts.identity = ssh_list_new();
120 if (session->opts.identity == NULL) {
121 goto err;
122 }
123
124 id = strdup("%d/id_ed25519");
125 if (id == NULL) {
126 goto err;
127 }
128
129 rc = ssh_list_append(session->opts.identity, id);
130 if (rc == SSH_ERROR) {
131 goto err;
132 }
133
134 #ifdef HAVE_ECC
135 id = strdup("%d/id_ecdsa");
136 if (id == NULL) {
137 goto err;
138 }
139 rc = ssh_list_append(session->opts.identity, id);
140 if (rc == SSH_ERROR) {
141 goto err;
142 }
143 #endif
144
145 id = strdup("%d/id_rsa");
146 if (id == NULL) {
147 goto err;
148 }
149 rc = ssh_list_append(session->opts.identity, id);
150 if (rc == SSH_ERROR) {
151 goto err;
152 }
153
154 #ifdef HAVE_DSA
155 id = strdup("%d/id_dsa");
156 if (id == NULL) {
157 goto err;
158 }
159 rc = ssh_list_append(session->opts.identity, id);
160 if (rc == SSH_ERROR) {
161 goto err;
162 }
163 #endif
164
165 /* Explicitly initialize states */
166 session->session_state = SSH_SESSION_STATE_NONE;
167 session->pending_call_state = SSH_PENDING_CALL_NONE;
168 session->packet_state = PACKET_STATE_INIT;
169 session->dh_handshake_state = DH_STATE_INIT;
170 session->global_req_state = SSH_CHANNEL_REQ_STATE_NONE;
171
172 session->auth.state = SSH_AUTH_STATE_NONE;
173 session->auth.service_state = SSH_AUTH_SERVICE_NONE;
174
175 return session;
176
177 err:
178 free(id);
179 ssh_free(session);
180 return NULL;
181 }
182
183 /**
184 * @brief Deallocate a SSH session handle.
185 *
186 * @param[in] session The SSH session to free.
187 *
188 * @see ssh_disconnect()
189 * @see ssh_new()
190 */
ssh_free(ssh_session session)191 void ssh_free(ssh_session session)
192 {
193 int i;
194 struct ssh_iterator *it = NULL;
195 struct ssh_buffer_struct *b = NULL;
196
197 if (session == NULL) {
198 return;
199 }
200
201 /*
202 * Delete all channels
203 *
204 * This needs the first thing we clean up cause if there is still an open
205 * channel we call ssh_channel_close() first. So we need a working socket
206 * and poll context for it.
207 */
208 for (it = ssh_list_get_iterator(session->channels);
209 it != NULL;
210 it = ssh_list_get_iterator(session->channels)) {
211 ssh_channel_do_free(ssh_iterator_value(ssh_channel,it));
212 ssh_list_remove(session->channels, it);
213 }
214 ssh_list_free(session->channels);
215 session->channels = NULL;
216
217 #ifdef WITH_PCAP
218 if (session->pcap_ctx) {
219 ssh_pcap_context_free(session->pcap_ctx);
220 session->pcap_ctx = NULL;
221 }
222 #endif
223
224 ssh_socket_free(session->socket);
225 session->socket = NULL;
226
227 if (session->default_poll_ctx) {
228 ssh_poll_ctx_free(session->default_poll_ctx);
229 }
230
231 SSH_BUFFER_FREE(session->in_buffer);
232 SSH_BUFFER_FREE(session->out_buffer);
233 session->in_buffer = session->out_buffer = NULL;
234
235 if (session->in_hashbuf != NULL) {
236 SSH_BUFFER_FREE(session->in_hashbuf);
237 }
238 if (session->out_hashbuf != NULL) {
239 SSH_BUFFER_FREE(session->out_hashbuf);
240 }
241
242 crypto_free(session->current_crypto);
243 crypto_free(session->next_crypto);
244
245 #ifndef _WIN32
246 ssh_agent_free(session->agent);
247 #endif /* _WIN32 */
248
249 ssh_key_free(session->srv.dsa_key);
250 session->srv.dsa_key = NULL;
251 ssh_key_free(session->srv.rsa_key);
252 session->srv.rsa_key = NULL;
253 ssh_key_free(session->srv.ecdsa_key);
254 session->srv.ecdsa_key = NULL;
255 ssh_key_free(session->srv.ed25519_key);
256 session->srv.ed25519_key = NULL;
257
258 if (session->ssh_message_list) {
259 ssh_message msg;
260
261 for (msg = ssh_list_pop_head(ssh_message, session->ssh_message_list);
262 msg != NULL;
263 msg = ssh_list_pop_head(ssh_message, session->ssh_message_list)) {
264 ssh_message_free(msg);
265 }
266 ssh_list_free(session->ssh_message_list);
267 }
268
269 if (session->kbdint != NULL) {
270 ssh_kbdint_free(session->kbdint);
271 }
272
273 if (session->packet_callbacks) {
274 ssh_list_free(session->packet_callbacks);
275 }
276
277 /* options */
278 if (session->opts.identity) {
279 char *id;
280
281 for (id = ssh_list_pop_head(char *, session->opts.identity);
282 id != NULL;
283 id = ssh_list_pop_head(char *, session->opts.identity)) {
284 SAFE_FREE(id);
285 }
286 ssh_list_free(session->opts.identity);
287 }
288
289 while ((b = ssh_list_pop_head(struct ssh_buffer_struct *,
290 session->out_queue)) != NULL) {
291 SSH_BUFFER_FREE(b);
292 }
293 ssh_list_free(session->out_queue);
294
295 #ifndef _WIN32
296 ssh_agent_state_free (session->agent_state);
297 #endif
298 session->agent_state = NULL;
299
300 SAFE_FREE(session->auth.auto_state);
301 SAFE_FREE(session->serverbanner);
302 SAFE_FREE(session->clientbanner);
303 SAFE_FREE(session->banner);
304
305 SAFE_FREE(session->opts.bindaddr);
306 SAFE_FREE(session->opts.custombanner);
307 SAFE_FREE(session->opts.username);
308 SAFE_FREE(session->opts.host);
309 SAFE_FREE(session->opts.sshdir);
310 SAFE_FREE(session->opts.knownhosts);
311 SAFE_FREE(session->opts.global_knownhosts);
312 SAFE_FREE(session->opts.ProxyCommand);
313 SAFE_FREE(session->opts.gss_server_identity);
314 SAFE_FREE(session->opts.gss_client_identity);
315 SAFE_FREE(session->opts.pubkey_accepted_types);
316
317 for (i = 0; i < SSH_KEX_METHODS; i++) {
318 if (session->opts.wanted_methods[i]) {
319 SAFE_FREE(session->opts.wanted_methods[i]);
320 }
321 }
322
323 /* burn connection, it could contain sensitive data */
324 explicit_bzero(session, sizeof(struct ssh_session_struct));
325 SAFE_FREE(session);
326 }
327
328 /**
329 * @brief get the client banner
330 *
331 * @param[in] session The SSH session
332 *
333 * @return Returns the client banner string or NULL.
334 */
ssh_get_clientbanner(ssh_session session)335 const char* ssh_get_clientbanner(ssh_session session) {
336 if (session == NULL) {
337 return NULL;
338 }
339
340 return session->clientbanner;
341 }
342
343 /**
344 * @brief get the server banner
345 *
346 * @param[in] session The SSH session
347 *
348 * @return Returns the server banner string or NULL.
349 */
ssh_get_serverbanner(ssh_session session)350 const char* ssh_get_serverbanner(ssh_session session) {
351 if(!session) {
352 return NULL;
353 }
354 return session->serverbanner;
355 }
356
357 /**
358 * @brief get the name of the current key exchange algorithm.
359 *
360 * @param[in] session The SSH session
361 *
362 * @return Returns the key exchange algorithm string or NULL.
363 */
ssh_get_kex_algo(ssh_session session)364 const char* ssh_get_kex_algo(ssh_session session) {
365 if ((session == NULL) ||
366 (session->current_crypto == NULL)) {
367 return NULL;
368 }
369
370 switch (session->current_crypto->kex_type) {
371 case SSH_KEX_DH_GROUP1_SHA1:
372 return "diffie-hellman-group1-sha1";
373 case SSH_KEX_DH_GROUP14_SHA1:
374 return "diffie-hellman-group14-sha1";
375 case SSH_KEX_DH_GROUP14_SHA256:
376 return "diffie-hellman-group14-sha256";
377 case SSH_KEX_DH_GROUP16_SHA512:
378 return "diffie-hellman-group16-sha512";
379 case SSH_KEX_DH_GROUP18_SHA512:
380 return "diffie-hellman-group18-sha512";
381 case SSH_KEX_ECDH_SHA2_NISTP256:
382 return "ecdh-sha2-nistp256";
383 case SSH_KEX_ECDH_SHA2_NISTP384:
384 return "ecdh-sha2-nistp384";
385 case SSH_KEX_ECDH_SHA2_NISTP521:
386 return "ecdh-sha2-nistp521";
387 case SSH_KEX_CURVE25519_SHA256:
388 return "curve25519-sha256";
389 case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
390 return "curve25519-sha256@libssh.org";
391 default:
392 break;
393 }
394
395 return NULL;
396 }
397
398 /**
399 * @brief get the name of the input cipher for the given session.
400 *
401 * @param[in] session The SSH session.
402 *
403 * @return Returns cipher name or NULL.
404 */
ssh_get_cipher_in(ssh_session session)405 const char* ssh_get_cipher_in(ssh_session session) {
406 if ((session != NULL) &&
407 (session->current_crypto != NULL) &&
408 (session->current_crypto->in_cipher != NULL)) {
409 return session->current_crypto->in_cipher->name;
410 }
411 return NULL;
412 }
413
414 /**
415 * @brief get the name of the output cipher for the given session.
416 *
417 * @param[in] session The SSH session.
418 *
419 * @return Returns cipher name or NULL.
420 */
ssh_get_cipher_out(ssh_session session)421 const char* ssh_get_cipher_out(ssh_session session) {
422 if ((session != NULL) &&
423 (session->current_crypto != NULL) &&
424 (session->current_crypto->out_cipher != NULL)) {
425 return session->current_crypto->out_cipher->name;
426 }
427 return NULL;
428 }
429
430 /**
431 * @brief get the name of the input HMAC algorithm for the given session.
432 *
433 * @param[in] session The SSH session.
434 *
435 * @return Returns HMAC algorithm name or NULL if unknown.
436 */
ssh_get_hmac_in(ssh_session session)437 const char* ssh_get_hmac_in(ssh_session session) {
438 if ((session != NULL) &&
439 (session->current_crypto != NULL)) {
440 return ssh_hmac_type_to_string(session->current_crypto->in_hmac, session->current_crypto->in_hmac_etm);
441 }
442 return NULL;
443 }
444
445 /**
446 * @brief get the name of the output HMAC algorithm for the given session.
447 *
448 * @param[in] session The SSH session.
449 *
450 * @return Returns HMAC algorithm name or NULL if unknown.
451 */
ssh_get_hmac_out(ssh_session session)452 const char* ssh_get_hmac_out(ssh_session session) {
453 if ((session != NULL) &&
454 (session->current_crypto != NULL)) {
455 return ssh_hmac_type_to_string(session->current_crypto->out_hmac, session->current_crypto->out_hmac_etm);
456 }
457 return NULL;
458 }
459
460 /**
461 * @brief Disconnect impolitely from a remote host by closing the socket.
462 *
463 * Suitable if you forked and want to destroy this session.
464 *
465 * @param[in] session The SSH session to disconnect.
466 */
ssh_silent_disconnect(ssh_session session)467 void ssh_silent_disconnect(ssh_session session) {
468 if (session == NULL) {
469 return;
470 }
471
472 ssh_socket_close(session->socket);
473 session->alive = 0;
474 ssh_disconnect(session);
475 }
476
477 /**
478 * @brief Set the session in blocking/nonblocking mode.
479 *
480 * @param[in] session The ssh session to change.
481 *
482 * @param[in] blocking Zero for nonblocking mode.
483 */
ssh_set_blocking(ssh_session session,int blocking)484 void ssh_set_blocking(ssh_session session, int blocking)
485 {
486 if (session == NULL) {
487 return;
488 }
489 session->flags &= ~SSH_SESSION_FLAG_BLOCKING;
490 session->flags |= blocking ? SSH_SESSION_FLAG_BLOCKING : 0;
491 }
492
493 /**
494 * @brief Return the blocking mode of libssh
495 * @param[in] session The SSH session
496 * @returns 0 if the session is nonblocking,
497 * @returns 1 if the functions may block.
498 */
ssh_is_blocking(ssh_session session)499 int ssh_is_blocking(ssh_session session)
500 {
501 return (session->flags & SSH_SESSION_FLAG_BLOCKING) ? 1 : 0;
502 }
503
504 /* Waits until the output socket is empty */
ssh_flush_termination(void * c)505 static int ssh_flush_termination(void *c){
506 ssh_session session = c;
507 if (ssh_socket_buffered_write_bytes(session->socket) == 0 ||
508 session->session_state == SSH_SESSION_STATE_ERROR)
509 return 1;
510 else
511 return 0;
512 }
513
514 /**
515 * @brief Blocking flush of the outgoing buffer
516 * @param[in] session The SSH session
517 * @param[in] timeout Set an upper limit on the time for which this function
518 * will block, in milliseconds. Specifying -1
519 * means an infinite timeout. This parameter is passed to
520 * the poll() function.
521 * @returns SSH_OK on success, SSH_AGAIN if timeout occurred,
522 * SSH_ERROR otherwise.
523 */
524
ssh_blocking_flush(ssh_session session,int timeout)525 int ssh_blocking_flush(ssh_session session, int timeout){
526 int rc;
527 if (session == NULL) {
528 return SSH_ERROR;
529 }
530
531 rc = ssh_handle_packets_termination(session, timeout,
532 ssh_flush_termination, session);
533 if (rc == SSH_ERROR) {
534 return rc;
535 }
536 if (!ssh_flush_termination(session)) {
537 rc = SSH_AGAIN;
538 }
539
540 return rc;
541 }
542
543 /**
544 * @brief Check if we are connected.
545 *
546 * @param[in] session The session to check if it is connected.
547 *
548 * @return 1 if we are connected, 0 if not.
549 */
ssh_is_connected(ssh_session session)550 int ssh_is_connected(ssh_session session) {
551 if (session == NULL) {
552 return 0;
553 }
554
555 return session->alive;
556 }
557
558 /**
559 * @brief Get the fd of a connection.
560 *
561 * In case you'd need the file descriptor of the connection to the server/client.
562 *
563 * @param[in] session The ssh session to use.
564 *
565 * @return The file descriptor of the connection, or -1 if it is
566 * not connected
567 */
ssh_get_fd(ssh_session session)568 socket_t ssh_get_fd(ssh_session session) {
569 if (session == NULL) {
570 return -1;
571 }
572
573 return ssh_socket_get_fd(session->socket);
574 }
575
576 /**
577 * @brief Tell the session it has data to read on the file descriptor without
578 * blocking.
579 *
580 * @param[in] session The ssh session to use.
581 */
ssh_set_fd_toread(ssh_session session)582 void ssh_set_fd_toread(ssh_session session) {
583 if (session == NULL) {
584 return;
585 }
586
587 ssh_socket_set_read_wontblock(session->socket);
588 }
589
590 /**
591 * @brief Tell the session it may write to the file descriptor without blocking.
592 *
593 * @param[in] session The ssh session to use.
594 */
ssh_set_fd_towrite(ssh_session session)595 void ssh_set_fd_towrite(ssh_session session) {
596 if (session == NULL) {
597 return;
598 }
599
600 ssh_socket_set_write_wontblock(session->socket);
601 }
602
603 /**
604 * @brief Tell the session it has an exception to catch on the file descriptor.
605 *
606 * \param[in] session The ssh session to use.
607 */
ssh_set_fd_except(ssh_session session)608 void ssh_set_fd_except(ssh_session session) {
609 if (session == NULL) {
610 return;
611 }
612
613 ssh_socket_set_except(session->socket);
614 }
615
616 /**
617 * @internal
618 *
619 * @brief Poll the current session for an event and call the appropriate
620 * callbacks. This function will not loop until the timeout is expired.
621 *
622 * This will block until one event happens.
623 *
624 * @param[in] session The session handle to use.
625 *
626 * @param[in] timeout Set an upper limit on the time for which this function
627 * will block, in milliseconds. Specifying SSH_TIMEOUT_INFINITE
628 * (-1) means an infinite timeout.
629 * Specifying SSH_TIMEOUT_USER means to use the timeout
630 * specified in options. 0 means poll will return immediately.
631 * This parameter is passed to the poll() function.
632 *
633 * @return SSH_OK on success, SSH_ERROR otherwise.
634 */
ssh_handle_packets(ssh_session session,int timeout)635 int ssh_handle_packets(ssh_session session, int timeout) {
636 ssh_poll_handle spoll;
637 ssh_poll_ctx ctx;
638 int tm = timeout;
639 int rc;
640
641 if (session == NULL || session->socket == NULL) {
642 return SSH_ERROR;
643 }
644
645 spoll = ssh_socket_get_poll_handle(session->socket);
646 ssh_poll_add_events(spoll, POLLIN);
647 ctx = ssh_poll_get_ctx(spoll);
648
649 if (!ctx) {
650 ctx = ssh_poll_get_default_ctx(session);
651 ssh_poll_ctx_add(ctx, spoll);
652 }
653
654 if (timeout == SSH_TIMEOUT_USER) {
655 if (ssh_is_blocking(session))
656 tm = ssh_make_milliseconds(session->opts.timeout,
657 session->opts.timeout_usec);
658 else
659 tm = 0;
660 }
661 rc = ssh_poll_ctx_dopoll(ctx, tm);
662 if (rc == SSH_ERROR) {
663 session->session_state = SSH_SESSION_STATE_ERROR;
664 }
665
666 return rc;
667 }
668
669 /**
670 * @internal
671 *
672 * @brief Poll the current session for an event and call the appropriate
673 * callbacks.
674 *
675 * This will block until termination function returns true, or timeout expired.
676 *
677 * @param[in] session The session handle to use.
678 *
679 * @param[in] timeout Set an upper limit on the time for which this function
680 * will block, in milliseconds. Specifying
681 * SSH_TIMEOUT_INFINITE (-1) means an infinite timeout.
682 * Specifying SSH_TIMEOUT_USER means to use the timeout
683 * specified in options. 0 means poll will return
684 * immediately.
685 * SSH_TIMEOUT_DEFAULT uses the session timeout if set or
686 * uses blocking parameters of the session.
687 * This parameter is passed to the poll() function.
688 *
689 * @param[in] fct Termination function to be used to determine if it is
690 * possible to stop polling.
691 * @param[in] user User parameter to be passed to fct termination function.
692 * @returns SSH_OK on success, SSH_AGAIN if timeout occurred,
693 * SSH_ERROR otherwise.
694 */
ssh_handle_packets_termination(ssh_session session,long timeout,ssh_termination_function fct,void * user)695 int ssh_handle_packets_termination(ssh_session session,
696 long timeout,
697 ssh_termination_function fct,
698 void *user)
699 {
700 struct ssh_timestamp ts;
701 long timeout_ms = SSH_TIMEOUT_INFINITE;
702 long tm;
703 int ret = SSH_OK;
704
705 /* If a timeout has been provided, use it */
706 if (timeout >= 0) {
707 timeout_ms = timeout;
708 } else {
709 if (ssh_is_blocking(session)) {
710 if (timeout == SSH_TIMEOUT_USER || timeout == SSH_TIMEOUT_DEFAULT) {
711 if (session->opts.timeout > 0 ||
712 session->opts.timeout_usec > 0) {
713 timeout_ms =
714 ssh_make_milliseconds(session->opts.timeout,
715 session->opts.timeout_usec);
716 }
717 }
718 } else {
719 timeout_ms = SSH_TIMEOUT_NONBLOCKING;
720 }
721 }
722
723 /* avoid unnecessary syscall for the SSH_TIMEOUT_NONBLOCKING case */
724 if (timeout_ms != SSH_TIMEOUT_NONBLOCKING) {
725 ssh_timestamp_init(&ts);
726 }
727
728 tm = timeout_ms;
729 while(!fct(user)) {
730 ret = ssh_handle_packets(session, tm);
731 if (ret == SSH_ERROR) {
732 break;
733 }
734 if (ssh_timeout_elapsed(&ts, timeout_ms)) {
735 ret = fct(user) ? SSH_OK : SSH_AGAIN;
736 break;
737 }
738
739 tm = ssh_timeout_update(&ts, timeout_ms);
740 }
741
742 return ret;
743 }
744
745 /**
746 * @brief Get session status
747 *
748 * @param session The ssh session to use.
749 *
750 * @returns A bitmask including SSH_CLOSED, SSH_READ_PENDING, SSH_WRITE_PENDING
751 * or SSH_CLOSED_ERROR which respectively means the session is closed,
752 * has data to read on the connection socket and session was closed
753 * due to an error.
754 */
ssh_get_status(ssh_session session)755 int ssh_get_status(ssh_session session) {
756 int socketstate;
757 int r = 0;
758
759 if (session == NULL) {
760 return 0;
761 }
762
763 socketstate = ssh_socket_get_status(session->socket);
764
765 if (session->session_state == SSH_SESSION_STATE_DISCONNECTED) {
766 r |= SSH_CLOSED;
767 }
768 if (socketstate & SSH_READ_PENDING) {
769 r |= SSH_READ_PENDING;
770 }
771 if (socketstate & SSH_WRITE_PENDING) {
772 r |= SSH_WRITE_PENDING;
773 }
774 if ((session->session_state == SSH_SESSION_STATE_DISCONNECTED &&
775 (socketstate & SSH_CLOSED_ERROR)) ||
776 session->session_state == SSH_SESSION_STATE_ERROR) {
777 r |= SSH_CLOSED_ERROR;
778 }
779
780 return r;
781 }
782
783 /**
784 * @brief Get poll flags for an external mainloop
785 *
786 * @param session The ssh session to use.
787 *
788 * @returns A bitmask including SSH_READ_PENDING or SSH_WRITE_PENDING.
789 * For SSH_READ_PENDING, your invocation of poll() should include
790 * POLLIN. For SSH_WRITE_PENDING, your invocation of poll() should
791 * include POLLOUT.
792 */
ssh_get_poll_flags(ssh_session session)793 int ssh_get_poll_flags(ssh_session session)
794 {
795 if (session == NULL) {
796 return 0;
797 }
798
799 return ssh_socket_get_poll_flags (session->socket);
800 }
801
802 /**
803 * @brief Get the disconnect message from the server.
804 *
805 * @param[in] session The ssh session to use.
806 *
807 * @return The message sent by the server along with the
808 * disconnect, or NULL in which case the reason of the
809 * disconnect may be found with ssh_get_error.
810 *
811 * @see ssh_get_error()
812 */
ssh_get_disconnect_message(ssh_session session)813 const char *ssh_get_disconnect_message(ssh_session session) {
814 if (session == NULL) {
815 return NULL;
816 }
817
818 if (session->session_state != SSH_SESSION_STATE_DISCONNECTED) {
819 ssh_set_error(session, SSH_REQUEST_DENIED,
820 "Connection not closed yet");
821 } else if(!session->discon_msg) {
822 ssh_set_error(session, SSH_FATAL,
823 "Connection correctly closed but no disconnect message");
824 } else {
825 return session->discon_msg;
826 }
827
828 return NULL;
829 }
830
831 /**
832 * @brief Get the protocol version of the session.
833 *
834 * @param session The ssh session to use.
835 *
836 * @return The SSH version as integer, < 0 on error.
837 */
ssh_get_version(ssh_session session)838 int ssh_get_version(ssh_session session) {
839 if (session == NULL) {
840 return -1;
841 }
842
843 return 2;
844 }
845
846 /**
847 * @internal
848 * @brief Callback to be called when the socket received an exception code.
849 * @param user is a pointer to session
850 */
ssh_socket_exception_callback(int code,int errno_code,void * user)851 void ssh_socket_exception_callback(int code, int errno_code, void *user){
852 ssh_session session=(ssh_session)user;
853
854 SSH_LOG(SSH_LOG_RARE,"Socket exception callback: %d (%d)",code, errno_code);
855 session->session_state = SSH_SESSION_STATE_ERROR;
856 if (errno_code == 0 && code == SSH_SOCKET_EXCEPTION_EOF) {
857 ssh_set_error(session, SSH_FATAL, "Socket error: disconnected");
858 } else {
859 ssh_set_error(session, SSH_FATAL, "Socket error: %s", strerror(errno_code));
860 }
861
862 session->ssh_connection_callback(session);
863 }
864
865 /**
866 * @brief Send a message that should be ignored
867 *
868 * @param[in] session The SSH session
869 * @param[in] data Data to be sent
870 *
871 * @return SSH_OK on success, SSH_ERROR otherwise.
872 */
ssh_send_ignore(ssh_session session,const char * data)873 int ssh_send_ignore (ssh_session session, const char *data) {
874 const int type = SSH2_MSG_IGNORE;
875 int rc;
876
877 if (ssh_socket_is_open(session->socket)) {
878 rc = ssh_buffer_pack(session->out_buffer,
879 "bs",
880 type,
881 data);
882 if (rc != SSH_OK){
883 ssh_set_error_oom(session);
884 goto error;
885 }
886 ssh_packet_send(session);
887 ssh_handle_packets(session, 0);
888 }
889
890 return SSH_OK;
891
892 error:
893 ssh_buffer_reinit(session->out_buffer);
894 return SSH_ERROR;
895 }
896
897 /**
898 * @brief Send a debug message
899 *
900 * @param[in] session The SSH session
901 * @param[in] message Data to be sent
902 * @param[in] always_display Message SHOULD be displayed by the server. It
903 * SHOULD NOT be displayed unless debugging
904 * information has been explicitly requested.
905 *
906 * @return SSH_OK on success, SSH_ERROR otherwise.
907 */
ssh_send_debug(ssh_session session,const char * message,int always_display)908 int ssh_send_debug (ssh_session session, const char *message, int always_display) {
909 int rc;
910
911 if (ssh_socket_is_open(session->socket)) {
912 rc = ssh_buffer_pack(session->out_buffer,
913 "bbsd",
914 SSH2_MSG_DEBUG,
915 always_display != 0 ? 1 : 0,
916 message,
917 0); /* empty language tag */
918 if (rc != SSH_OK) {
919 ssh_set_error_oom(session);
920 goto error;
921 }
922 ssh_packet_send(session);
923 ssh_handle_packets(session, 0);
924 }
925
926 return SSH_OK;
927
928 error:
929 ssh_buffer_reinit(session->out_buffer);
930 return SSH_ERROR;
931 }
932
933 /**
934 * @brief Set the session data counters.
935 *
936 * This functions sets the counter structures to be used to calculate data
937 * which comes in and goes out through the session at different levels.
938 *
939 * @code
940 * struct ssh_counter_struct scounter = {
941 * .in_bytes = 0,
942 * .out_bytes = 0,
943 * .in_packets = 0,
944 * .out_packets = 0
945 * };
946 *
947 * struct ssh_counter_struct rcounter = {
948 * .in_bytes = 0,
949 * .out_bytes = 0,
950 * .in_packets = 0,
951 * .out_packets = 0
952 * };
953 *
954 * ssh_set_counters(session, &scounter, &rcounter);
955 * @endcode
956 *
957 * @param[in] session The SSH session.
958 *
959 * @param[in] scounter Counter for byte data handled by the session sockets.
960 *
961 * @param[in] rcounter Counter for byte and packet data handled by the session,
962 * prior compression and SSH overhead.
963 */
ssh_set_counters(ssh_session session,ssh_counter scounter,ssh_counter rcounter)964 void ssh_set_counters(ssh_session session, ssh_counter scounter,
965 ssh_counter rcounter) {
966 if (session != NULL) {
967 session->socket_counter = scounter;
968 session->raw_counter = rcounter;
969 }
970 }
971
972 /**
973 * @deprecated Use ssh_get_publickey_hash()
974 */
ssh_get_pubkey_hash(ssh_session session,unsigned char ** hash)975 int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash)
976 {
977 ssh_key pubkey = NULL;
978 ssh_string pubkey_blob = NULL;
979 MD5CTX ctx;
980 unsigned char *h;
981 int rc;
982
983 if (session == NULL || hash == NULL) {
984 return SSH_ERROR;
985 }
986
987 /* In FIPS mode, we cannot use MD5 */
988 if (ssh_fips_mode()) {
989 ssh_set_error(session,
990 SSH_FATAL,
991 "In FIPS mode MD5 is not allowed."
992 "Try ssh_get_publickey_hash() with"
993 "SSH_PUBLICKEY_HASH_SHA256");
994 return SSH_ERROR;
995 }
996
997 *hash = NULL;
998 if (session->current_crypto == NULL ||
999 session->current_crypto->server_pubkey == NULL) {
1000 ssh_set_error(session,SSH_FATAL,"No current cryptographic context");
1001 return SSH_ERROR;
1002 }
1003
1004 h = calloc(MD5_DIGEST_LEN, sizeof(unsigned char));
1005 if (h == NULL) {
1006 return SSH_ERROR;
1007 }
1008
1009 ctx = md5_init();
1010 if (ctx == NULL) {
1011 SAFE_FREE(h);
1012 return SSH_ERROR;
1013 }
1014
1015 rc = ssh_get_server_publickey(session, &pubkey);
1016 if (rc != SSH_OK) {
1017 md5_final(h, ctx);
1018 SAFE_FREE(h);
1019 return SSH_ERROR;
1020 }
1021
1022 rc = ssh_pki_export_pubkey_blob(pubkey, &pubkey_blob);
1023 ssh_key_free(pubkey);
1024 if (rc != SSH_OK) {
1025 md5_final(h, ctx);
1026 SAFE_FREE(h);
1027 return SSH_ERROR;
1028 }
1029
1030 md5_update(ctx, ssh_string_data(pubkey_blob), ssh_string_len(pubkey_blob));
1031 SSH_STRING_FREE(pubkey_blob);
1032 md5_final(h, ctx);
1033
1034 *hash = h;
1035
1036 return MD5_DIGEST_LEN;
1037 }
1038
1039 /**
1040 * @brief Deallocate the hash obtained by ssh_get_pubkey_hash.
1041 *
1042 * This is required under Microsoft platform as this library might use a
1043 * different C library than your software, hence a different heap.
1044 *
1045 * @param[in] hash The buffer to deallocate.
1046 *
1047 * @see ssh_get_pubkey_hash()
1048 */
ssh_clean_pubkey_hash(unsigned char ** hash)1049 void ssh_clean_pubkey_hash(unsigned char **hash) {
1050 SAFE_FREE(*hash);
1051 }
1052
1053 /**
1054 * @brief Get the server public key from a session.
1055 *
1056 * @param[in] session The session to get the key from.
1057 *
1058 * @param[out] key A pointer to store the allocated key. You need to free
1059 * the key.
1060 *
1061 * @return SSH_OK on success, SSH_ERROR on errror.
1062 *
1063 * @see ssh_key_free()
1064 */
ssh_get_server_publickey(ssh_session session,ssh_key * key)1065 int ssh_get_server_publickey(ssh_session session, ssh_key *key)
1066 {
1067 ssh_key pubkey = NULL;
1068
1069 if (session == NULL ||
1070 session->current_crypto == NULL ||
1071 session->current_crypto->server_pubkey == NULL) {
1072 return SSH_ERROR;
1073 }
1074
1075 pubkey = ssh_key_dup(session->current_crypto->server_pubkey);
1076 if (pubkey == NULL) {
1077 return SSH_ERROR;
1078 }
1079
1080 *key = pubkey;
1081 return SSH_OK;
1082 }
1083
1084 /**
1085 * @deprecated Use ssh_get_server_publickey()
1086 */
ssh_get_publickey(ssh_session session,ssh_key * key)1087 int ssh_get_publickey(ssh_session session, ssh_key *key)
1088 {
1089 return ssh_get_server_publickey(session, key);
1090 }
1091
1092 /**
1093 * @brief Allocates a buffer with the hash of the public key.
1094 *
1095 * This function allows you to get a hash of the public key. You can then
1096 * print this hash in a human-readable form to the user so that he is able to
1097 * verify it. Use ssh_get_hexa() or ssh_print_hash() to display it.
1098 *
1099 * @param[in] key The public key to create the hash for.
1100 *
1101 * @param[in] type The type of the hash you want.
1102 *
1103 * @param[in] hash A pointer to store the allocated buffer. It can be
1104 * freed using ssh_clean_pubkey_hash().
1105 *
1106 * @param[in] hlen The length of the hash.
1107 *
1108 * @return 0 on success, -1 if an error occured.
1109 *
1110 * @warning It is very important that you verify at some moment that the hash
1111 * matches a known server. If you don't do it, cryptography wont help
1112 * you at making things secure.
1113 * OpenSSH uses SHA256 to print public key digests.
1114 *
1115 * @see ssh_session_update_known_hosts()
1116 * @see ssh_get_hexa()
1117 * @see ssh_print_hash()
1118 * @see ssh_clean_pubkey_hash()
1119 */
ssh_get_publickey_hash(const ssh_key key,enum ssh_publickey_hash_type type,unsigned char ** hash,size_t * hlen)1120 int ssh_get_publickey_hash(const ssh_key key,
1121 enum ssh_publickey_hash_type type,
1122 unsigned char **hash,
1123 size_t *hlen)
1124 {
1125 ssh_string blob;
1126 unsigned char *h;
1127 int rc;
1128
1129 rc = ssh_pki_export_pubkey_blob(key, &blob);
1130 if (rc < 0) {
1131 return rc;
1132 }
1133
1134 switch (type) {
1135 case SSH_PUBLICKEY_HASH_SHA1:
1136 {
1137 SHACTX ctx;
1138
1139 h = calloc(1, SHA_DIGEST_LEN);
1140 if (h == NULL) {
1141 rc = -1;
1142 goto out;
1143 }
1144
1145 ctx = sha1_init();
1146 if (ctx == NULL) {
1147 free(h);
1148 rc = -1;
1149 goto out;
1150 }
1151
1152 sha1_update(ctx, ssh_string_data(blob), ssh_string_len(blob));
1153 sha1_final(h, ctx);
1154
1155 *hlen = SHA_DIGEST_LEN;
1156 }
1157 break;
1158 case SSH_PUBLICKEY_HASH_SHA256:
1159 {
1160 SHA256CTX ctx;
1161
1162 h = calloc(1, SHA256_DIGEST_LEN);
1163 if (h == NULL) {
1164 rc = -1;
1165 goto out;
1166 }
1167
1168 ctx = sha256_init();
1169 if (ctx == NULL) {
1170 free(h);
1171 rc = -1;
1172 goto out;
1173 }
1174
1175 sha256_update(ctx, ssh_string_data(blob), ssh_string_len(blob));
1176 sha256_final(h, ctx);
1177
1178 *hlen = SHA256_DIGEST_LEN;
1179 }
1180 break;
1181 case SSH_PUBLICKEY_HASH_MD5:
1182 {
1183 MD5CTX ctx;
1184
1185 /* In FIPS mode, we cannot use MD5 */
1186 if (ssh_fips_mode()) {
1187 SSH_LOG(SSH_LOG_WARN, "In FIPS mode MD5 is not allowed."
1188 "Try using SSH_PUBLICKEY_HASH_SHA256");
1189 rc = SSH_ERROR;
1190 goto out;
1191 }
1192
1193 h = calloc(1, MD5_DIGEST_LEN);
1194 if (h == NULL) {
1195 rc = -1;
1196 goto out;
1197 }
1198
1199 ctx = md5_init();
1200 if (ctx == NULL) {
1201 free(h);
1202 rc = -1;
1203 goto out;
1204 }
1205
1206 md5_update(ctx, ssh_string_data(blob), ssh_string_len(blob));
1207 md5_final(h, ctx);
1208
1209 *hlen = MD5_DIGEST_LEN;
1210 }
1211 break;
1212 default:
1213 rc = -1;
1214 goto out;
1215 }
1216
1217 *hash = h;
1218 rc = 0;
1219 out:
1220 SSH_STRING_FREE(blob);
1221 return rc;
1222 }
1223
1224 /** @} */
1225