Coverage Report

Created: 2025-07-12 06:56

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