1 /*
2 * server.c - functions for creating a SSH server
3 *
4 * This file is part of the SSH Library
5 *
6 * Copyright (c) 2004-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 <errno.h>
27 #include <fcntl.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31
32 #ifdef _WIN32
33 # include <winsock2.h>
34 # include <ws2tcpip.h>
35
36 /*
37 * <wspiapi.h> is necessary for getaddrinfo before Windows XP, but it isn't
38 * available on some platforms like MinGW.
39 */
40 # ifdef HAVE_WSPIAPI_H
41 # include <wspiapi.h>
42 # endif
43 #else
44 # include <netinet/in.h>
45 #endif
46
47 #include "libssh/priv.h"
48 #include "libssh/libssh.h"
49 #include "libssh/server.h"
50 #include "libssh/ssh2.h"
51 #include "libssh/buffer.h"
52 #include "libssh/packet.h"
53 #include "libssh/socket.h"
54 #include "libssh/session.h"
55 #include "libssh/kex.h"
56 #include "libssh/misc.h"
57 #include "libssh/pki.h"
58 #include "libssh/dh.h"
59 #include "libssh/messages.h"
60 #include "libssh/options.h"
61 #include "libssh/curve25519.h"
62 #include "libssh/token.h"
63
64 #define set_status(session, status) do {\
65 if (session->common.callbacks && session->common.callbacks->connect_status_function) \
66 session->common.callbacks->connect_status_function(session->common.callbacks->userdata, status); \
67 } while (0)
68
69 /**
70 * @addtogroup libssh_server
71 *
72 * @{
73 */
74
75 /** @internal
76 *
77 * @brief initialize the set of key exchange, hostkey, ciphers, MACs, and
78 * compression algorithms for the given ssh_session
79 *
80 * The selection of algorithms and keys used are determined by the
81 * options that are currently set in the given ssh_session structure.
82 */
83
server_set_kex(ssh_session session)84 int server_set_kex(ssh_session session)
85 {
86 struct ssh_kex_struct *server = &session->next_crypto->server_kex;
87 int i, j, rc;
88 const char *wanted, *allowed;
89 char *kept;
90 char hostkeys[128] = {0};
91 enum ssh_keytypes_e keytype;
92 size_t len;
93 int ok;
94
95 ZERO_STRUCTP(server);
96
97 ok = ssh_get_random(server->cookie, 16, 0);
98 if (!ok) {
99 ssh_set_error(session, SSH_FATAL, "PRNG error");
100 return -1;
101 }
102
103 if (session->srv.ed25519_key != NULL) {
104 snprintf(hostkeys,
105 sizeof(hostkeys),
106 "%s",
107 ssh_key_type_to_char(ssh_key_type(session->srv.ed25519_key)));
108 }
109 #ifdef HAVE_ECC
110 if (session->srv.ecdsa_key != NULL) {
111 len = strlen(hostkeys);
112 snprintf(hostkeys + len, sizeof(hostkeys) - len,
113 ",%s", session->srv.ecdsa_key->type_c);
114 }
115 #endif
116 #ifdef HAVE_DSA
117 if (session->srv.dsa_key != NULL) {
118 len = strlen(hostkeys);
119 keytype = ssh_key_type(session->srv.dsa_key);
120
121 snprintf(hostkeys + len, sizeof(hostkeys) - len,
122 ",%s", ssh_key_type_to_char(keytype));
123 }
124 #endif
125 if (session->srv.rsa_key != NULL) {
126 /* We support also the SHA2 variants */
127 len = strlen(hostkeys);
128 snprintf(hostkeys + len, sizeof(hostkeys) - len,
129 ",rsa-sha2-512,rsa-sha2-256");
130
131 len = strlen(hostkeys);
132 keytype = ssh_key_type(session->srv.rsa_key);
133
134 snprintf(hostkeys + len, sizeof(hostkeys) - len,
135 ",%s", ssh_key_type_to_char(keytype));
136 }
137
138 if (strlen(hostkeys) == 0) {
139 return -1;
140 }
141
142 if (session->opts.wanted_methods[SSH_HOSTKEYS]) {
143 allowed = session->opts.wanted_methods[SSH_HOSTKEYS];
144 } else {
145 if (ssh_fips_mode()) {
146 allowed = ssh_kex_get_fips_methods(SSH_HOSTKEYS);
147 } else {
148 allowed = ssh_kex_get_default_methods(SSH_HOSTKEYS);
149 }
150 }
151
152 /* It is expected for the list of allowed hostkeys to be ordered by
153 * preference */
154 kept = ssh_find_all_matching(hostkeys[0] == ',' ? hostkeys + 1 : hostkeys,
155 allowed);
156 if (kept == NULL) {
157 /* Nothing was allowed */
158 return -1;
159 }
160
161 rc = ssh_options_set_algo(session,
162 SSH_HOSTKEYS,
163 kept);
164 SAFE_FREE(kept);
165 if (rc < 0) {
166 return -1;
167 }
168
169 for (i = 0; i < SSH_KEX_METHODS; i++) {
170 wanted = session->opts.wanted_methods[i];
171 if (wanted == NULL) {
172 if (ssh_fips_mode()) {
173 wanted = ssh_kex_get_fips_methods(i);
174 } else {
175 wanted = ssh_kex_get_default_methods(i);
176 }
177 }
178 if (wanted == NULL) {
179 for (j = 0; j < i; j++) {
180 SAFE_FREE(server->methods[j]);
181 }
182 return -1;
183 }
184
185 server->methods[i] = strdup(wanted);
186 if (server->methods[i] == NULL) {
187 for (j = 0; j < i; j++) {
188 SAFE_FREE(server->methods[j]);
189 }
190 return -1;
191 }
192 }
193
194 return 0;
195 }
196
ssh_server_init_kex(ssh_session session)197 int ssh_server_init_kex(ssh_session session) {
198 int i;
199
200 if (session->session_state > SSH_SESSION_STATE_BANNER_RECEIVED) {
201 return SSH_ERROR;
202 }
203
204 /* free any currently-set methods: server_set_kex will allocate new ones */
205 for (i = 0; i < SSH_KEX_METHODS; i++) {
206 SAFE_FREE(session->next_crypto->server_kex.methods[i]);
207 }
208
209 return server_set_kex(session);
210 }
211
ssh_server_send_extensions(ssh_session session)212 static int ssh_server_send_extensions(ssh_session session) {
213 int rc;
214 const char *hostkey_algorithms;
215
216 SSH_LOG(SSH_LOG_PACKET, "Sending SSH_MSG_EXT_INFO");
217
218 if (session->opts.pubkey_accepted_types) {
219 hostkey_algorithms = session->opts.pubkey_accepted_types;
220 } else {
221 if (ssh_fips_mode()) {
222 hostkey_algorithms = ssh_kex_get_fips_methods(SSH_HOSTKEYS);
223 } else {
224 /* There are no restrictions to the accepted public keys */
225 hostkey_algorithms = ssh_kex_get_default_methods(SSH_HOSTKEYS);
226 }
227 }
228
229 rc = ssh_buffer_pack(session->out_buffer,
230 "bdss",
231 SSH2_MSG_EXT_INFO,
232 1, /* nr. of extensions */
233 "server-sig-algs",
234 hostkey_algorithms);
235 if (rc != SSH_OK) {
236 goto error;
237 }
238
239 if (ssh_packet_send(session) == SSH_ERROR) {
240 goto error;
241 }
242
243 return 0;
244 error:
245 ssh_buffer_reinit(session->out_buffer);
246
247 return -1;
248 }
249
SSH_PACKET_CALLBACK(ssh_packet_kexdh_init)250 SSH_PACKET_CALLBACK(ssh_packet_kexdh_init){
251 (void)packet;
252 (void)type;
253 (void)user;
254
255 SSH_LOG(SSH_LOG_PACKET,"Received SSH_MSG_KEXDH_INIT");
256 if(session->dh_handshake_state != DH_STATE_INIT){
257 SSH_LOG(SSH_LOG_RARE,"Invalid state for SSH_MSG_KEXDH_INIT");
258 session->session_state = SSH_SESSION_STATE_ERROR;
259 return SSH_PACKET_USED;
260 }
261
262 /* If first_kex_packet_follows guess was wrong, ignore this message. */
263 if (session->first_kex_follows_guess_wrong != 0) {
264 SSH_LOG(SSH_LOG_RARE, "first_kex_packet_follows guess was wrong, "
265 "ignoring first SSH_MSG_KEXDH_INIT message");
266 session->first_kex_follows_guess_wrong = 0;
267
268 return SSH_PACKET_USED;
269 }
270 SSH_LOG(SSH_LOG_DEBUG, "Calling next KEXDH handler");
271 return SSH_PACKET_NOT_USED;
272 }
273
274 int
ssh_get_key_params(ssh_session session,ssh_key * privkey,enum ssh_digest_e * digest)275 ssh_get_key_params(ssh_session session,
276 ssh_key *privkey,
277 enum ssh_digest_e *digest)
278 {
279 ssh_key pubkey;
280 ssh_string pubkey_blob;
281 int rc;
282
283 switch(session->srv.hostkey) {
284 case SSH_KEYTYPE_DSS:
285 *privkey = session->srv.dsa_key;
286 break;
287 case SSH_KEYTYPE_RSA:
288 *privkey = session->srv.rsa_key;
289 break;
290 case SSH_KEYTYPE_ECDSA_P256:
291 case SSH_KEYTYPE_ECDSA_P384:
292 case SSH_KEYTYPE_ECDSA_P521:
293 *privkey = session->srv.ecdsa_key;
294 break;
295 case SSH_KEYTYPE_ED25519:
296 *privkey = session->srv.ed25519_key;
297 break;
298 case SSH_KEYTYPE_RSA1:
299 case SSH_KEYTYPE_UNKNOWN:
300 default:
301 *privkey = NULL;
302 }
303
304 *digest = session->srv.hostkey_digest;
305 rc = ssh_pki_export_privkey_to_pubkey(*privkey, &pubkey);
306 if (rc < 0) {
307 ssh_set_error(session, SSH_FATAL,
308 "Could not get the public key from the private key");
309
310 return -1;
311 }
312
313 rc = ssh_pki_export_pubkey_blob(pubkey, &pubkey_blob);
314 ssh_key_free(pubkey);
315 if (rc < 0) {
316 ssh_set_error_oom(session);
317 return -1;
318 }
319
320 rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob);
321 SSH_STRING_FREE(pubkey_blob);
322 if (rc != 0) {
323 ssh_set_error(session,
324 SSH_FATAL,
325 "Could not import server public key");
326 return -1;
327 }
328
329 return SSH_OK;
330 }
331
332 /**
333 * @internal
334 *
335 * @brief A function to be called each time a step has been done in the
336 * connection.
337 */
ssh_server_connection_callback(ssh_session session)338 static void ssh_server_connection_callback(ssh_session session){
339 int rc;
340
341 switch(session->session_state){
342 case SSH_SESSION_STATE_NONE:
343 case SSH_SESSION_STATE_CONNECTING:
344 case SSH_SESSION_STATE_SOCKET_CONNECTED:
345 break;
346 case SSH_SESSION_STATE_BANNER_RECEIVED:
347 if (session->clientbanner == NULL) {
348 goto error;
349 }
350 set_status(session, 0.4f);
351 SSH_LOG(SSH_LOG_PROTOCOL,
352 "SSH client banner: %s", session->clientbanner);
353
354 /* Here we analyze the different protocols the server allows. */
355 rc = ssh_analyze_banner(session, 1);
356 if (rc < 0) {
357 ssh_set_error(session, SSH_FATAL,
358 "No version of SSH protocol usable (banner: %s)",
359 session->clientbanner);
360 goto error;
361 }
362
363 /* from now, the packet layer is handling incoming packets */
364 session->socket_callbacks.data=ssh_packet_socket_callback;
365 ssh_packet_register_socket_callback(session, session->socket);
366
367 ssh_packet_set_default_callbacks(session);
368 set_status(session, 0.5f);
369 session->session_state=SSH_SESSION_STATE_INITIAL_KEX;
370 if (ssh_send_kex(session, 1) < 0) {
371 goto error;
372 }
373 break;
374 case SSH_SESSION_STATE_INITIAL_KEX:
375 /* TODO: This state should disappear in favor of get_key handle */
376 break;
377 case SSH_SESSION_STATE_KEXINIT_RECEIVED:
378 set_status(session,0.6f);
379 if(session->next_crypto->server_kex.methods[0]==NULL){
380 if(server_set_kex(session) == SSH_ERROR)
381 goto error;
382 /* We are in a rekeying, so we need to send the server kex */
383 if(ssh_send_kex(session, 1) < 0)
384 goto error;
385 }
386 ssh_list_kex(&session->next_crypto->client_kex); // log client kex
387 if (ssh_kex_select_methods(session) < 0) {
388 goto error;
389 }
390 if (crypt_set_algorithms_server(session) == SSH_ERROR)
391 goto error;
392 set_status(session,0.8f);
393 session->session_state=SSH_SESSION_STATE_DH;
394 break;
395 case SSH_SESSION_STATE_DH:
396 if(session->dh_handshake_state==DH_STATE_FINISHED){
397
398 rc = ssh_packet_set_newkeys(session, SSH_DIRECTION_IN);
399 if (rc != SSH_OK) {
400 goto error;
401 }
402
403 /*
404 * If the client supports extension negotiation, we will send
405 * our supported extensions now. This is the first message after
406 * sending NEWKEYS message and after turning on crypto.
407 */
408 if (session->extensions & SSH_EXT_NEGOTIATION &&
409 session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
410
411 /*
412 * Only send an SSH_MSG_EXT_INFO message the first time the client
413 * undergoes NEWKEYS. It is unexpected for this message to be sent
414 * upon rekey, and may cause clients to log error messages.
415 *
416 * The session_state can not be used for this purpose because it is
417 * re-set to SSH_SESSION_STATE_KEXINIT_RECEIVED during rekey. So,
418 * use the connected flag which transitions from non-zero below.
419 *
420 * See also:
421 * - https://bugzilla.mindrot.org/show_bug.cgi?id=2929
422 */
423 if (session->connected == 0) {
424 ssh_server_send_extensions(session);
425 }
426 }
427
428 set_status(session,1.0f);
429 session->connected = 1;
430 session->session_state=SSH_SESSION_STATE_AUTHENTICATING;
431 if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED)
432 session->session_state = SSH_SESSION_STATE_AUTHENTICATED;
433
434 }
435 break;
436 case SSH_SESSION_STATE_AUTHENTICATING:
437 break;
438 case SSH_SESSION_STATE_ERROR:
439 goto error;
440 default:
441 ssh_set_error(session,SSH_FATAL,"Invalid state %d",session->session_state);
442 }
443
444 return;
445 error:
446 ssh_socket_close(session->socket);
447 session->alive = 0;
448 session->session_state=SSH_SESSION_STATE_ERROR;
449 }
450
451 /**
452 * @internal
453 *
454 * @brief Gets the banner from socket and saves it in session.
455 * Updates the session state
456 *
457 * @param data pointer to the beginning of header
458 * @param len size of the banner
459 * @param user is a pointer to session
460 * @returns Number of bytes processed, or zero if the banner is not complete.
461 */
callback_receive_banner(const void * data,size_t len,void * user)462 static int callback_receive_banner(const void *data, size_t len, void *user) {
463 char *buffer = (char *) data;
464 ssh_session session = (ssh_session) user;
465 char *str = NULL;
466 size_t i;
467 int ret=0;
468
469 for (i = 0; i < len; i++) {
470 #ifdef WITH_PCAP
471 if(session->pcap_ctx && buffer[i] == '\n') {
472 ssh_pcap_context_write(session->pcap_ctx,
473 SSH_PCAP_DIR_IN,
474 buffer,
475 i + 1,
476 i + 1);
477 }
478 #endif
479 if (buffer[i] == '\r') {
480 buffer[i]='\0';
481 }
482
483 if (buffer[i] == '\n') {
484 buffer[i]='\0';
485
486 str = strdup(buffer);
487 /* number of bytes read */
488 ret = i + 1;
489 session->clientbanner = str;
490 session->session_state = SSH_SESSION_STATE_BANNER_RECEIVED;
491 SSH_LOG(SSH_LOG_PACKET, "Received banner: %s", str);
492 session->ssh_connection_callback(session);
493
494 return ret;
495 }
496
497 if(i > 127) {
498 /* Too big banner */
499 session->session_state = SSH_SESSION_STATE_ERROR;
500 ssh_set_error(session, SSH_FATAL, "Receiving banner: too large banner");
501
502 return 0;
503 }
504 }
505
506 return ret;
507 }
508
509 /* returns 0 until the key exchange is not finished */
ssh_server_kex_termination(void * s)510 static int ssh_server_kex_termination(void *s){
511 ssh_session session = s;
512 if (session->session_state != SSH_SESSION_STATE_ERROR &&
513 session->session_state != SSH_SESSION_STATE_AUTHENTICATING &&
514 session->session_state != SSH_SESSION_STATE_DISCONNECTED)
515 return 0;
516 else
517 return 1;
518 }
519
520 /* FIXME: auth_methods should be unsigned */
ssh_set_auth_methods(ssh_session session,int auth_methods)521 void ssh_set_auth_methods(ssh_session session, int auth_methods)
522 {
523 /* accept only methods in range */
524 session->auth.supported_methods = (uint32_t)auth_methods & 0x3fU;
525 }
526
527 /* Do the banner and key exchange */
ssh_handle_key_exchange(ssh_session session)528 int ssh_handle_key_exchange(ssh_session session) {
529 int rc;
530 if (session->session_state != SSH_SESSION_STATE_NONE)
531 goto pending;
532 rc = ssh_send_banner(session, 1);
533 if (rc < 0) {
534 return SSH_ERROR;
535 }
536
537 session->alive = 1;
538
539 session->ssh_connection_callback = ssh_server_connection_callback;
540 session->session_state = SSH_SESSION_STATE_SOCKET_CONNECTED;
541 ssh_socket_set_callbacks(session->socket,&session->socket_callbacks);
542 session->socket_callbacks.data=callback_receive_banner;
543 session->socket_callbacks.exception=ssh_socket_exception_callback;
544 session->socket_callbacks.userdata=session;
545
546 rc = server_set_kex(session);
547 if (rc < 0) {
548 return SSH_ERROR;
549 }
550 pending:
551 rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER,
552 ssh_server_kex_termination,session);
553 SSH_LOG(SSH_LOG_PACKET, "ssh_handle_key_exchange: current state : %d",
554 session->session_state);
555 if (rc != SSH_OK)
556 return rc;
557 if (session->session_state == SSH_SESSION_STATE_ERROR ||
558 session->session_state == SSH_SESSION_STATE_DISCONNECTED) {
559 return SSH_ERROR;
560 }
561
562 return SSH_OK;
563 }
564
565 /* messages */
566
567 /** @internal
568 * replies to an SSH_AUTH packet with a default (denied) response.
569 */
ssh_auth_reply_default(ssh_session session,int partial)570 int ssh_auth_reply_default(ssh_session session,int partial) {
571 char methods_c[128] = {0};
572 int rc = SSH_ERROR;
573
574
575 if (session->auth.supported_methods == 0) {
576 session->auth.supported_methods = SSH_AUTH_METHOD_PUBLICKEY | SSH_AUTH_METHOD_PASSWORD;
577 }
578 if (session->auth.supported_methods & SSH_AUTH_METHOD_PUBLICKEY) {
579 strncat(methods_c, "publickey,",
580 sizeof(methods_c) - strlen(methods_c) - 1);
581 }
582 if (session->auth.supported_methods & SSH_AUTH_METHOD_GSSAPI_MIC){
583 strncat(methods_c,"gssapi-with-mic,",
584 sizeof(methods_c) - strlen(methods_c) - 1);
585 }
586 if (session->auth.supported_methods & SSH_AUTH_METHOD_INTERACTIVE) {
587 strncat(methods_c, "keyboard-interactive,",
588 sizeof(methods_c) - strlen(methods_c) - 1);
589 }
590 if (session->auth.supported_methods & SSH_AUTH_METHOD_PASSWORD) {
591 strncat(methods_c, "password,",
592 sizeof(methods_c) - strlen(methods_c) - 1);
593 }
594 if (session->auth.supported_methods & SSH_AUTH_METHOD_HOSTBASED) {
595 strncat(methods_c, "hostbased,",
596 sizeof(methods_c) - strlen(methods_c) - 1);
597 }
598
599 if (methods_c[0] == '\0' || methods_c[strlen(methods_c)-1] != ',') {
600 return SSH_ERROR;
601 }
602
603 /* Strip the comma. */
604 methods_c[strlen(methods_c) - 1] = '\0'; // strip the comma. We are sure there is at
605
606 SSH_LOG(SSH_LOG_PACKET,
607 "Sending a auth failure. methods that can continue: %s", methods_c);
608
609 rc = ssh_buffer_pack(session->out_buffer,
610 "bsb",
611 SSH2_MSG_USERAUTH_FAILURE,
612 methods_c,
613 partial ? 1 : 0);
614 if (rc != SSH_OK){
615 ssh_set_error_oom(session);
616 return SSH_ERROR;
617 }
618 rc = ssh_packet_send(session);
619 return rc;
620 }
621
ssh_message_channel_request_open_reply_default(ssh_message msg)622 static int ssh_message_channel_request_open_reply_default(ssh_message msg) {
623 int rc;
624
625 SSH_LOG(SSH_LOG_FUNCTIONS, "Refusing a channel");
626
627 rc = ssh_buffer_pack(msg->session->out_buffer,
628 "bdddd",
629 SSH2_MSG_CHANNEL_OPEN_FAILURE,
630 msg->channel_request_open.sender,
631 SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED,
632 0, /* reason is empty string */
633 0); /* language string */
634 if (rc != SSH_OK){
635 ssh_set_error_oom(msg->session);
636 return SSH_ERROR;
637 }
638
639 rc = ssh_packet_send(msg->session);
640 return rc;
641 }
642
ssh_message_channel_request_reply_default(ssh_message msg)643 static int ssh_message_channel_request_reply_default(ssh_message msg) {
644 uint32_t channel;
645 int rc;
646
647 if (msg->channel_request.want_reply) {
648 channel = msg->channel_request.channel->remote_channel;
649
650 SSH_LOG(SSH_LOG_PACKET,
651 "Sending a default channel_request denied to channel %d", channel);
652
653 rc = ssh_buffer_pack(msg->session->out_buffer,
654 "bd",
655 SSH2_MSG_CHANNEL_FAILURE,
656 channel);
657 if (rc != SSH_OK){
658 ssh_set_error_oom(msg->session);
659 return SSH_ERROR;
660 }
661 return ssh_packet_send(msg->session);
662 }
663
664 SSH_LOG(SSH_LOG_PACKET,
665 "The client doesn't want to know the request failed!");
666
667 return SSH_OK;
668 }
669
ssh_message_service_request_reply_default(ssh_message msg)670 static int ssh_message_service_request_reply_default(ssh_message msg) {
671 /* The only return code accepted by specifications are success or disconnect */
672 return ssh_message_service_reply_success(msg);
673 }
674
ssh_message_service_reply_success(ssh_message msg)675 int ssh_message_service_reply_success(ssh_message msg) {
676 ssh_session session;
677 int rc;
678
679 if (msg == NULL) {
680 return SSH_ERROR;
681 }
682 session = msg->session;
683
684 SSH_LOG(SSH_LOG_PACKET,
685 "Sending a SERVICE_ACCEPT for service %s", msg->service_request.service);
686
687 rc = ssh_buffer_pack(session->out_buffer,
688 "bs",
689 SSH2_MSG_SERVICE_ACCEPT,
690 msg->service_request.service);
691 if (rc != SSH_OK){
692 ssh_set_error_oom(session);
693 return SSH_ERROR;
694 }
695 rc = ssh_packet_send(msg->session);
696 return rc;
697 }
698
ssh_message_global_request_reply_success(ssh_message msg,uint16_t bound_port)699 int ssh_message_global_request_reply_success(ssh_message msg, uint16_t bound_port) {
700 int rc;
701
702 SSH_LOG(SSH_LOG_FUNCTIONS, "Accepting a global request");
703
704 if (msg->global_request.want_reply) {
705 if (ssh_buffer_add_u8(msg->session->out_buffer
706 , SSH2_MSG_REQUEST_SUCCESS) < 0) {
707 goto error;
708 }
709
710 if(msg->global_request.type == SSH_GLOBAL_REQUEST_TCPIP_FORWARD
711 && msg->global_request.bind_port == 0) {
712 rc = ssh_buffer_pack(msg->session->out_buffer, "d", bound_port);
713 if (rc != SSH_OK) {
714 ssh_set_error_oom(msg->session);
715 goto error;
716 }
717 }
718
719 return ssh_packet_send(msg->session);
720 }
721
722 if(msg->global_request.type == SSH_GLOBAL_REQUEST_TCPIP_FORWARD
723 && msg->global_request.bind_port == 0) {
724 SSH_LOG(SSH_LOG_PACKET,
725 "The client doesn't want to know the remote port!");
726 }
727
728 return SSH_OK;
729 error:
730 return SSH_ERROR;
731 }
732
ssh_message_global_request_reply_default(ssh_message msg)733 static int ssh_message_global_request_reply_default(ssh_message msg) {
734 SSH_LOG(SSH_LOG_FUNCTIONS, "Refusing a global request");
735
736 if (msg->global_request.want_reply) {
737 if (ssh_buffer_add_u8(msg->session->out_buffer
738 , SSH2_MSG_REQUEST_FAILURE) < 0) {
739 goto error;
740 }
741 return ssh_packet_send(msg->session);
742 }
743 SSH_LOG(SSH_LOG_PACKET,
744 "The client doesn't want to know the request failed!");
745
746 return SSH_OK;
747 error:
748 return SSH_ERROR;
749 }
750
ssh_message_reply_default(ssh_message msg)751 int ssh_message_reply_default(ssh_message msg) {
752 if (msg == NULL) {
753 return -1;
754 }
755
756 switch(msg->type) {
757 case SSH_REQUEST_AUTH:
758 return ssh_auth_reply_default(msg->session, 0);
759 case SSH_REQUEST_CHANNEL_OPEN:
760 return ssh_message_channel_request_open_reply_default(msg);
761 case SSH_REQUEST_CHANNEL:
762 return ssh_message_channel_request_reply_default(msg);
763 case SSH_REQUEST_SERVICE:
764 return ssh_message_service_request_reply_default(msg);
765 case SSH_REQUEST_GLOBAL:
766 return ssh_message_global_request_reply_default(msg);
767 default:
768 SSH_LOG(SSH_LOG_PACKET,
769 "Don't know what to default reply to %d type",
770 msg->type);
771 break;
772 }
773
774 return -1;
775 }
776
ssh_message_service_service(ssh_message msg)777 const char *ssh_message_service_service(ssh_message msg){
778 if (msg == NULL) {
779 return NULL;
780 }
781 return msg->service_request.service;
782 }
783
ssh_message_auth_user(ssh_message msg)784 const char *ssh_message_auth_user(ssh_message msg) {
785 if (msg == NULL) {
786 return NULL;
787 }
788
789 return msg->auth_request.username;
790 }
791
ssh_message_auth_password(ssh_message msg)792 const char *ssh_message_auth_password(ssh_message msg){
793 if (msg == NULL) {
794 return NULL;
795 }
796
797 return msg->auth_request.password;
798 }
799
ssh_message_auth_pubkey(ssh_message msg)800 ssh_key ssh_message_auth_pubkey(ssh_message msg) {
801 if (msg == NULL) {
802 return NULL;
803 }
804
805 return msg->auth_request.pubkey;
806 }
807
808 /* Get the publickey of an auth request */
ssh_message_auth_publickey(ssh_message msg)809 ssh_public_key ssh_message_auth_publickey(ssh_message msg){
810 if (msg == NULL) {
811 return NULL;
812 }
813
814 return ssh_pki_convert_key_to_publickey(msg->auth_request.pubkey);
815 }
816
ssh_message_auth_publickey_state(ssh_message msg)817 enum ssh_publickey_state_e ssh_message_auth_publickey_state(ssh_message msg){
818 if (msg == NULL) {
819 return -1;
820 }
821 return msg->auth_request.signature_state;
822 }
823
ssh_message_auth_kbdint_is_response(ssh_message msg)824 int ssh_message_auth_kbdint_is_response(ssh_message msg) {
825 if (msg == NULL) {
826 return -1;
827 }
828
829 return msg->auth_request.kbdint_response != 0;
830 }
831
832 /* FIXME: methods should be unsigned */
ssh_message_auth_set_methods(ssh_message msg,int methods)833 int ssh_message_auth_set_methods(ssh_message msg, int methods) {
834 if (msg == NULL || msg->session == NULL) {
835 return -1;
836 }
837
838 if (methods < 0) {
839 return -1;
840 }
841
842 msg->session->auth.supported_methods = (uint32_t)methods;
843
844 return 0;
845 }
846
ssh_message_auth_interactive_request(ssh_message msg,const char * name,const char * instruction,unsigned int num_prompts,const char ** prompts,char * echo)847 int ssh_message_auth_interactive_request(ssh_message msg, const char *name,
848 const char *instruction, unsigned int num_prompts,
849 const char **prompts, char *echo) {
850 int rc;
851 unsigned int i = 0;
852
853 if(name == NULL || instruction == NULL) {
854 return SSH_ERROR;
855 }
856 if(num_prompts > 0 && (prompts == NULL || echo == NULL)) {
857 return SSH_ERROR;
858 }
859
860 rc = ssh_buffer_pack(msg->session->out_buffer,
861 "bsssd",
862 SSH2_MSG_USERAUTH_INFO_REQUEST,
863 name,
864 instruction,
865 "", /* language tag */
866 num_prompts);
867 if (rc != SSH_OK){
868 ssh_set_error_oom(msg->session);
869 return SSH_ERROR;
870 }
871
872 for(i = 0; i < num_prompts; i++) {
873 rc = ssh_buffer_pack(msg->session->out_buffer,
874 "sb",
875 prompts[i],
876 echo[i] ? 1 : 0);
877 if (rc != SSH_OK){
878 ssh_set_error_oom(msg->session);
879 return SSH_ERROR;
880 }
881 }
882
883 rc = ssh_packet_send(msg->session);
884
885 /* fill in the kbdint structure */
886 if (msg->session->kbdint == NULL) {
887 SSH_LOG(SSH_LOG_PROTOCOL, "Warning: Got a "
888 "keyboard-interactive response but it "
889 "seems we didn't send the request.");
890
891 msg->session->kbdint = ssh_kbdint_new();
892 if (msg->session->kbdint == NULL) {
893 ssh_set_error_oom(msg->session);
894
895 return SSH_ERROR;
896 }
897 } else {
898 ssh_kbdint_clean(msg->session->kbdint);
899 }
900
901 msg->session->kbdint->name = strdup(name);
902 if(msg->session->kbdint->name == NULL) {
903 ssh_set_error_oom(msg->session);
904 ssh_kbdint_free(msg->session->kbdint);
905 msg->session->kbdint = NULL;
906 return SSH_PACKET_USED;
907 }
908 msg->session->kbdint->instruction = strdup(instruction);
909 if(msg->session->kbdint->instruction == NULL) {
910 ssh_set_error_oom(msg->session);
911 ssh_kbdint_free(msg->session->kbdint);
912 msg->session->kbdint = NULL;
913 return SSH_PACKET_USED;
914 }
915
916 msg->session->kbdint->nprompts = num_prompts;
917 if(num_prompts > 0) {
918 msg->session->kbdint->prompts = calloc(num_prompts, sizeof(char *));
919 if (msg->session->kbdint->prompts == NULL) {
920 msg->session->kbdint->nprompts = 0;
921 ssh_set_error_oom(msg->session);
922 ssh_kbdint_free(msg->session->kbdint);
923 msg->session->kbdint = NULL;
924 return SSH_ERROR;
925 }
926 msg->session->kbdint->echo = calloc(num_prompts, sizeof(unsigned char));
927 if (msg->session->kbdint->echo == NULL) {
928 ssh_set_error_oom(msg->session);
929 ssh_kbdint_free(msg->session->kbdint);
930 msg->session->kbdint = NULL;
931 return SSH_ERROR;
932 }
933 for (i = 0; i < num_prompts; i++) {
934 msg->session->kbdint->echo[i] = echo[i];
935 msg->session->kbdint->prompts[i] = strdup(prompts[i]);
936 if (msg->session->kbdint->prompts[i] == NULL) {
937 ssh_set_error_oom(msg->session);
938 msg->session->kbdint->nprompts = i;
939 ssh_kbdint_free(msg->session->kbdint);
940 msg->session->kbdint = NULL;
941 return SSH_PACKET_USED;
942 }
943 }
944 } else {
945 msg->session->kbdint->prompts = NULL;
946 msg->session->kbdint->echo = NULL;
947 }
948 msg->session->auth.state = SSH_AUTH_STATE_INFO;
949
950 return rc;
951 }
952
ssh_auth_reply_success(ssh_session session,int partial)953 int ssh_auth_reply_success(ssh_session session, int partial)
954 {
955 struct ssh_crypto_struct *crypto = NULL;
956 int r;
957
958 if (session == NULL) {
959 return SSH_ERROR;
960 }
961
962 if (partial) {
963 return ssh_auth_reply_default(session, partial);
964 }
965
966 r = ssh_buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_SUCCESS);
967 if (r < 0) {
968 return SSH_ERROR;
969 }
970
971 r = ssh_packet_send(session);
972
973 /*
974 * Consider the session as having been authenticated only after sending
975 * the USERAUTH_SUCCESS message. Setting these flags after ssh_packet_send
976 * ensures that a rekey is not triggered prematurely, causing the message
977 * to be queued.
978 */
979 session->session_state = SSH_SESSION_STATE_AUTHENTICATED;
980 session->flags |= SSH_SESSION_FLAG_AUTHENTICATED;
981
982 crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_OUT);
983 if (crypto != NULL && crypto->delayed_compress_out) {
984 SSH_LOG(SSH_LOG_PROTOCOL, "Enabling delayed compression OUT");
985 crypto->do_compress_out = 1;
986 }
987
988 crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN);
989 if (crypto != NULL && crypto->delayed_compress_in) {
990 SSH_LOG(SSH_LOG_PROTOCOL, "Enabling delayed compression IN");
991 crypto->do_compress_in = 1;
992 }
993 return r;
994 }
995
ssh_message_auth_reply_success(ssh_message msg,int partial)996 int ssh_message_auth_reply_success(ssh_message msg, int partial) {
997 if(msg == NULL)
998 return SSH_ERROR;
999 return ssh_auth_reply_success(msg->session, partial);
1000 }
1001
1002 /* Answer OK to a pubkey auth request */
ssh_message_auth_reply_pk_ok(ssh_message msg,ssh_string algo,ssh_string pubkey)1003 int ssh_message_auth_reply_pk_ok(ssh_message msg, ssh_string algo, ssh_string pubkey) {
1004 int rc;
1005 if (msg == NULL) {
1006 return SSH_ERROR;
1007 }
1008
1009 rc = ssh_buffer_pack(msg->session->out_buffer,
1010 "bSS",
1011 SSH2_MSG_USERAUTH_PK_OK,
1012 algo,
1013 pubkey);
1014 if(rc != SSH_OK){
1015 ssh_set_error_oom(msg->session);
1016 return SSH_ERROR;
1017 }
1018
1019 rc = ssh_packet_send(msg->session);
1020 return rc;
1021 }
1022
ssh_message_auth_reply_pk_ok_simple(ssh_message msg)1023 int ssh_message_auth_reply_pk_ok_simple(ssh_message msg) {
1024 ssh_string algo;
1025 ssh_string pubkey_blob = NULL;
1026 int ret;
1027
1028 algo = ssh_string_from_char(msg->auth_request.pubkey->type_c);
1029 if (algo == NULL) {
1030 return SSH_ERROR;
1031 }
1032
1033 ret = ssh_pki_export_pubkey_blob(msg->auth_request.pubkey, &pubkey_blob);
1034 if (ret < 0) {
1035 SSH_STRING_FREE(algo);
1036 return SSH_ERROR;
1037 }
1038
1039 ret = ssh_message_auth_reply_pk_ok(msg, algo, pubkey_blob);
1040
1041 SSH_STRING_FREE(algo);
1042 SSH_STRING_FREE(pubkey_blob);
1043
1044 return ret;
1045 }
1046
1047
ssh_message_channel_request_open_originator(ssh_message msg)1048 const char *ssh_message_channel_request_open_originator(ssh_message msg){
1049 return msg->channel_request_open.originator;
1050 }
1051
ssh_message_channel_request_open_originator_port(ssh_message msg)1052 int ssh_message_channel_request_open_originator_port(ssh_message msg){
1053 return msg->channel_request_open.originator_port;
1054 }
1055
ssh_message_channel_request_open_destination(ssh_message msg)1056 const char *ssh_message_channel_request_open_destination(ssh_message msg){
1057 return msg->channel_request_open.destination;
1058 }
1059
ssh_message_channel_request_open_destination_port(ssh_message msg)1060 int ssh_message_channel_request_open_destination_port(ssh_message msg){
1061 return msg->channel_request_open.destination_port;
1062 }
1063
ssh_message_channel_request_channel(ssh_message msg)1064 ssh_channel ssh_message_channel_request_channel(ssh_message msg){
1065 return msg->channel_request.channel;
1066 }
1067
ssh_message_channel_request_pty_term(ssh_message msg)1068 const char *ssh_message_channel_request_pty_term(ssh_message msg){
1069 return msg->channel_request.TERM;
1070 }
1071
ssh_message_channel_request_pty_width(ssh_message msg)1072 int ssh_message_channel_request_pty_width(ssh_message msg){
1073 return msg->channel_request.width;
1074 }
1075
ssh_message_channel_request_pty_height(ssh_message msg)1076 int ssh_message_channel_request_pty_height(ssh_message msg){
1077 return msg->channel_request.height;
1078 }
1079
ssh_message_channel_request_pty_pxwidth(ssh_message msg)1080 int ssh_message_channel_request_pty_pxwidth(ssh_message msg){
1081 return msg->channel_request.pxwidth;
1082 }
1083
ssh_message_channel_request_pty_pxheight(ssh_message msg)1084 int ssh_message_channel_request_pty_pxheight(ssh_message msg){
1085 return msg->channel_request.pxheight;
1086 }
1087
ssh_message_channel_request_env_name(ssh_message msg)1088 const char *ssh_message_channel_request_env_name(ssh_message msg){
1089 return msg->channel_request.var_name;
1090 }
1091
ssh_message_channel_request_env_value(ssh_message msg)1092 const char *ssh_message_channel_request_env_value(ssh_message msg){
1093 return msg->channel_request.var_value;
1094 }
1095
ssh_message_channel_request_command(ssh_message msg)1096 const char *ssh_message_channel_request_command(ssh_message msg){
1097 return msg->channel_request.command;
1098 }
1099
ssh_message_channel_request_subsystem(ssh_message msg)1100 const char *ssh_message_channel_request_subsystem(ssh_message msg){
1101 return msg->channel_request.subsystem;
1102 }
1103
ssh_message_channel_request_x11_single_connection(ssh_message msg)1104 int ssh_message_channel_request_x11_single_connection(ssh_message msg){
1105 return msg->channel_request.x11_single_connection ? 1 : 0;
1106 }
1107
ssh_message_channel_request_x11_auth_protocol(ssh_message msg)1108 const char *ssh_message_channel_request_x11_auth_protocol(ssh_message msg){
1109 return msg->channel_request.x11_auth_protocol;
1110 }
1111
ssh_message_channel_request_x11_auth_cookie(ssh_message msg)1112 const char *ssh_message_channel_request_x11_auth_cookie(ssh_message msg){
1113 return msg->channel_request.x11_auth_cookie;
1114 }
1115
ssh_message_channel_request_x11_screen_number(ssh_message msg)1116 int ssh_message_channel_request_x11_screen_number(ssh_message msg){
1117 return msg->channel_request.x11_screen_number;
1118 }
1119
ssh_message_global_request_address(ssh_message msg)1120 const char *ssh_message_global_request_address(ssh_message msg){
1121 return msg->global_request.bind_address;
1122 }
1123
ssh_message_global_request_port(ssh_message msg)1124 int ssh_message_global_request_port(ssh_message msg){
1125 return msg->global_request.bind_port;
1126 }
1127
1128 /** @brief defines the ssh_message callback
1129 * @param session the current ssh session
1130 * @param[in] ssh_bind_message_callback a function pointer to a callback taking the
1131 * current ssh session and received message as parameters. the function returns
1132 * 0 if the message has been parsed and treated successfully, 1 otherwise (libssh
1133 * must take care of the response).
1134 * @param[in] data void pointer to be passed to callback functions
1135 */
ssh_set_message_callback(ssh_session session,int (* ssh_bind_message_callback)(ssh_session session,ssh_message msg,void * data),void * data)1136 void ssh_set_message_callback(ssh_session session,
1137 int(*ssh_bind_message_callback)(ssh_session session, ssh_message msg, void *data),
1138 void *data) {
1139 session->ssh_message_callback = ssh_bind_message_callback;
1140 session->ssh_message_callback_data = data;
1141 }
1142
ssh_execute_message_callbacks(ssh_session session)1143 int ssh_execute_message_callbacks(ssh_session session){
1144 ssh_message msg=NULL;
1145 int ret;
1146 ssh_handle_packets(session, SSH_TIMEOUT_NONBLOCKING);
1147 if(!session->ssh_message_list)
1148 return SSH_OK;
1149 if(session->ssh_message_callback){
1150 while((msg=ssh_message_pop_head(session)) != NULL) {
1151 ret=session->ssh_message_callback(session,msg,
1152 session->ssh_message_callback_data);
1153 if(ret==1){
1154 ret = ssh_message_reply_default(msg);
1155 ssh_message_free(msg);
1156 if(ret != SSH_OK)
1157 return ret;
1158 } else {
1159 ssh_message_free(msg);
1160 }
1161 }
1162 } else {
1163 while((msg=ssh_message_pop_head(session)) != NULL) {
1164 ret = ssh_message_reply_default(msg);
1165 ssh_message_free(msg);
1166 if(ret != SSH_OK)
1167 return ret;
1168 }
1169 }
1170 return SSH_OK;
1171 }
1172
ssh_send_keepalive(ssh_session session)1173 int ssh_send_keepalive(ssh_session session)
1174 {
1175 /* Client denies the request, so the error code is not meaningful */
1176 (void)ssh_global_request(session, "keepalive@openssh.com", NULL, 1);
1177
1178 return SSH_OK;
1179 }
1180
1181 /** @} */
1182