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