Coverage Report

Created: 2025-08-09 07:11

/src/dropbear/src/svr-runopts.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Dropbear - a SSH2 server
3
 * 
4
 * Copyright (c) 2002,2003 Matt Johnston
5
 * All rights reserved.
6
 * 
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated documentation files (the "Software"), to deal
9
 * in the Software without restriction, including without limitation the rights
10
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 * copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 * 
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 * 
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
 * SOFTWARE. */
24
25
#include "includes.h"
26
#include "runopts.h"
27
#include "signkey.h"
28
#include "buffer.h"
29
#include "dbutil.h"
30
#include "algo.h"
31
#include "ecdsa.h"
32
33
#include <grp.h>
34
35
svr_runopts svr_opts; /* GLOBAL */
36
37
static void printhelp(const char * progname);
38
static void addportandaddress(const char* spec);
39
static void loadhostkey(const char *keyfile, int fatal_duplicate);
40
static void addhostkey(const char *keyfile);
41
static void load_banner();
42
43
0
static void printhelp(const char * progname) {
44
45
0
  fprintf(stderr, "Dropbear server v%s https://matt.ucc.asn.au/dropbear/dropbear.html\n"
46
0
          "Usage: %s [options]\n"
47
0
          "-b bannerfile  Display the contents of bannerfile"
48
0
          " before user login\n"
49
0
          "   (default: none)\n"
50
0
          "-r keyfile      Specify hostkeys (repeatable)\n"
51
0
          "   defaults: \n"
52
0
#if DROPBEAR_DSS
53
0
          "   - dss %s\n"
54
0
#endif
55
0
#if DROPBEAR_RSA
56
0
          "   - rsa %s\n"
57
0
#endif
58
0
#if DROPBEAR_ECDSA
59
0
          "   - ecdsa %s\n"
60
0
#endif
61
0
#if DROPBEAR_ED25519
62
0
          "   - ed25519 %s\n"
63
0
#endif
64
0
#if DROPBEAR_SVR_PUBKEY_AUTH
65
0
          "-D   Directory containing authorized_keys file\n"
66
0
#endif
67
0
#if DROPBEAR_DELAY_HOSTKEY
68
0
          "-R   Create hostkeys as required\n" 
69
0
#endif
70
0
          "-F   Don't fork into background\n"
71
0
          "-e   Pass on server process environment to child process\n"
72
#ifdef DISABLE_SYSLOG
73
          "(Syslog support not compiled in, using stderr)\n"
74
#else
75
0
          "-E   Log to stderr rather than syslog\n"
76
0
#endif
77
0
#if DO_MOTD
78
0
          "-m   Don't display the motd on login\n"
79
0
#endif
80
0
          "-w   Disallow root logins\n"
81
0
#ifdef HAVE_GETGROUPLIST
82
0
          "-G   Restrict logins to members of specified group\n"
83
0
#endif
84
0
#if DROPBEAR_SVR_PASSWORD_AUTH || DROPBEAR_SVR_PAM_AUTH
85
0
          "-s   Disable password logins\n"
86
0
          "-g   Disable password logins for root\n"
87
0
          "-B   Allow blank password logins\n"
88
0
          "-t   Enable two-factor authentication (both password and public key required)\n"
89
0
#endif
90
0
          "-T   Maximum authentication tries (default %d)\n"
91
0
#if DROPBEAR_SVR_LOCALANYFWD
92
0
          "-j   Disable local port forwarding\n"
93
0
#endif
94
0
#if DROPBEAR_SVR_REMOTETCPFWD
95
0
          "-k   Disable remote port forwarding\n"
96
0
          "-a   Allow connections to forwarded ports from any host\n"
97
0
          "-c command Force executed command\n"
98
0
#endif
99
0
          "-p [address:]port\n"
100
0
          "   Listen on specified tcp port (and optionally address),\n"
101
0
          "   up to %d can be specified\n"
102
0
          "   (default port is %s if none specified)\n"
103
0
          "-P PidFile Create pid file PidFile\n"
104
0
          "   (default %s)\n"
105
0
#ifdef SO_BINDTODEVICE
106
0
          "-l <interface>\n"
107
0
          "   interface to bind on\n"
108
0
#endif
109
0
#if INETD_MODE
110
0
          "-i   Start for inetd\n"
111
0
#endif
112
0
          "-W <receive_window_buffer> (default %d, larger may be faster, max 10MB)\n"
113
0
          "-K <keepalive>  (0 is never, default %d, in seconds)\n"
114
0
          "-I <idle_timeout>  (0 is never, default %d, in seconds)\n"
115
0
          "-z    disable QoS\n"
116
#if DROPBEAR_PLUGIN
117
                                        "-A <authplugin>[,<options>]\n"
118
                                        "               Enable external public key auth through <authplugin>\n"
119
#endif
120
0
          "-V    Version\n"
121
#if DEBUG_TRACE
122
          "-v    verbose (repeat for more verbose)\n"
123
#endif
124
0
          ,DROPBEAR_VERSION, progname,
125
0
#if DROPBEAR_DSS
126
0
          DSS_PRIV_FILENAME,
127
0
#endif
128
0
#if DROPBEAR_RSA
129
0
          RSA_PRIV_FILENAME,
130
0
#endif
131
0
#if DROPBEAR_ECDSA
132
0
          ECDSA_PRIV_FILENAME,
133
0
#endif
134
0
#if DROPBEAR_ED25519
135
0
          ED25519_PRIV_FILENAME,
136
0
#endif
137
0
          MAX_AUTH_TRIES,
138
0
          DROPBEAR_MAX_PORTS, DROPBEAR_DEFPORT, DROPBEAR_PIDFILE,
139
0
          DEFAULT_RECV_WINDOW, DEFAULT_KEEPALIVE, DEFAULT_IDLE_TIMEOUT);
140
0
}
141
142
2
void svr_getopts(int argc, char ** argv) {
143
144
2
  unsigned int i, j;
145
2
  char ** next = NULL;
146
2
  int nextisport = 0;
147
2
  char* recv_window_arg = NULL;
148
2
  char* keepalive_arg = NULL;
149
2
  char* idle_timeout_arg = NULL;
150
2
  char* maxauthtries_arg = NULL;
151
2
  char* reexec_fd_arg = NULL;
152
2
  char* keyfile = NULL;
153
2
  char c;
154
#if DROPBEAR_PLUGIN
155
        char* pubkey_plugin = NULL;
156
#endif
157
158
159
  /* see printhelp() for options */
160
2
  svr_opts.bannerfile = NULL;
161
2
  svr_opts.banner = NULL;
162
2
  svr_opts.forced_command = NULL;
163
2
  svr_opts.forkbg = 1;
164
2
  svr_opts.norootlogin = 0;
165
2
#ifdef HAVE_GETGROUPLIST
166
2
  svr_opts.restrict_group = NULL;
167
2
  svr_opts.restrict_group_gid = 0;
168
2
#endif
169
2
  svr_opts.noauthpass = 0;
170
2
  svr_opts.norootpass = 0;
171
2
  svr_opts.allowblankpass = 0;
172
2
  svr_opts.multiauthmethod = 0;
173
2
  svr_opts.maxauthtries = MAX_AUTH_TRIES;
174
2
  svr_opts.inetdmode = 0;
175
2
  svr_opts.portcount = 0;
176
2
  svr_opts.hostkey = NULL;
177
2
  svr_opts.delay_hostkey = 0;
178
2
  svr_opts.pidfile = expand_homedir_path(DROPBEAR_PIDFILE);
179
2
  svr_opts.authorized_keys_dir = "~/.ssh";
180
2
#if DROPBEAR_SVR_LOCALANYFWD
181
2
  svr_opts.nolocaltcp = 0;
182
2
#endif
183
2
#if DROPBEAR_SVR_REMOTETCPFWD
184
2
  svr_opts.noremotetcp = 0;
185
2
#endif
186
#if DROPBEAR_PLUGIN
187
        svr_opts.pubkey_plugin = NULL;
188
        svr_opts.pubkey_plugin_options = NULL;
189
#endif
190
2
  svr_opts.pass_on_env = 0;
191
2
  svr_opts.reexec_childpipe = -1;
192
193
#ifndef DISABLE_ZLIB
194
  opts.allow_compress = 1;
195
#endif 
196
197
  /* not yet
198
  opts.ipv4 = 1;
199
  opts.ipv6 = 1;
200
  */
201
2
#if DO_MOTD
202
2
  svr_opts.domotd = 1;
203
2
#endif
204
2
#ifndef DISABLE_SYSLOG
205
2
  opts.usingsyslog = 1;
206
2
#endif
207
2
  opts.recv_window = DEFAULT_RECV_WINDOW;
208
2
  opts.keepalive_secs = DEFAULT_KEEPALIVE;
209
2
  opts.idle_timeout_secs = DEFAULT_IDLE_TIMEOUT;
210
  
211
2
#if DROPBEAR_SVR_REMOTETCPFWD
212
2
  opts.listen_fwd_all = 0;
213
2
#endif
214
2
  opts.disable_ip_tos = 0;
215
216
4
  for (i = 1; i < (unsigned int)argc; i++) {
217
2
    if (argv[i][0] != '-' || argv[i][1] == '\0')
218
0
      dropbear_exit("Invalid argument: %s", argv[i]);
219
220
4
    for (j = 1; (c = argv[i][j]) != '\0' && !next && !nextisport; j++) {
221
2
      switch (c) {
222
0
        case 'b':
223
0
          next = &svr_opts.bannerfile;
224
0
          break;
225
0
        case 'c':
226
0
          next = &svr_opts.forced_command;
227
0
          break;
228
0
        case 'd':
229
0
        case 'r':
230
0
          next = &keyfile;
231
0
          break;
232
0
#if DROPBEAR_SVR_PUBKEY_AUTH
233
0
        case 'D':
234
0
          next = &svr_opts.authorized_keys_dir;
235
0
          break;
236
0
#endif
237
0
        case 'R':
238
0
          svr_opts.delay_hostkey = 1;
239
0
          break;
240
0
        case 'F':
241
0
          svr_opts.forkbg = 0;
242
0
          break;
243
0
#ifndef DISABLE_SYSLOG
244
2
        case 'E':
245
2
          opts.usingsyslog = 0;
246
2
          break;
247
0
#endif
248
0
        case 'e':
249
0
          svr_opts.pass_on_env = 1;
250
0
          break;
251
252
0
#if DROPBEAR_SVR_LOCALANYFWD
253
0
        case 'j':
254
0
          svr_opts.nolocaltcp = 1;
255
0
          break;
256
0
#endif
257
0
#if DROPBEAR_SVR_REMOTETCPFWD
258
0
        case 'k':
259
0
          svr_opts.noremotetcp = 1;
260
0
          break;
261
0
        case 'a':
262
0
          opts.listen_fwd_all = 1;
263
0
          break;
264
0
#endif
265
0
#if INETD_MODE
266
0
        case 'i':
267
0
          svr_opts.inetdmode = 1;
268
0
          break;
269
0
#endif
270
0
#if DROPBEAR_DO_REEXEC && NON_INETD_MODE
271
        /* For internal use by re-exec */
272
0
        case '2':
273
0
          next = &reexec_fd_arg;
274
0
          break;
275
0
#endif
276
0
        case 'p':
277
0
          nextisport = 1;
278
0
          break;
279
0
        case 'P':
280
0
          next = &svr_opts.pidfile;
281
0
          break;
282
0
#ifdef SO_BINDTODEVICE
283
0
        case 'l':
284
0
          next = &svr_opts.interface;
285
0
          break;
286
0
#endif
287
0
#if DO_MOTD
288
        /* motd is displayed by default, -m turns it off */
289
0
        case 'm':
290
0
          svr_opts.domotd = 0;
291
0
          break;
292
0
#endif
293
0
        case 'w':
294
0
          svr_opts.norootlogin = 1;
295
0
          break;
296
0
#ifdef HAVE_GETGROUPLIST
297
0
        case 'G':
298
0
          next = &svr_opts.restrict_group;
299
0
          break;
300
0
#endif
301
0
        case 'W':
302
0
          next = &recv_window_arg;
303
0
          break;
304
0
        case 'K':
305
0
          next = &keepalive_arg;
306
0
          break;
307
0
        case 'I':
308
0
          next = &idle_timeout_arg;
309
0
          break;
310
0
        case 'T':
311
0
          next = &maxauthtries_arg;
312
0
          break;
313
0
#if DROPBEAR_SVR_PASSWORD_AUTH || DROPBEAR_SVR_PAM_AUTH
314
0
        case 's':
315
0
          svr_opts.noauthpass = 1;
316
0
          break;
317
0
        case 'g':
318
0
          svr_opts.norootpass = 1;
319
0
          break;
320
0
        case 'B':
321
0
          svr_opts.allowblankpass = 1;
322
0
          break;
323
0
        case 't':
324
0
          svr_opts.multiauthmethod = 1;
325
0
          break;
326
0
#endif
327
0
        case 'h':
328
0
          printhelp(argv[0]);
329
0
          exit(EXIT_SUCCESS);
330
0
          break;
331
0
        case 'u':
332
          /* backwards compatibility with old urandom option */
333
0
          break;
334
#if DROPBEAR_PLUGIN
335
                                case 'A':
336
                                        next = &pubkey_plugin;
337
                                        break;
338
#endif
339
#if DEBUG_TRACE
340
        case 'v':
341
          debug_trace++;
342
          break;
343
#endif
344
0
        case 'V':
345
0
          print_version();
346
0
          exit(EXIT_SUCCESS);
347
0
          break;
348
0
        case 'z':
349
0
          opts.disable_ip_tos = 1;
350
0
          break;
351
0
        default:
352
0
          fprintf(stderr, "Invalid option -%c\n", c);
353
0
          printhelp(argv[0]);
354
0
          exit(EXIT_FAILURE);
355
0
          break;
356
2
      }
357
2
    }
358
359
2
    if (!next && !nextisport)
360
2
      continue;
361
362
0
    if (c == '\0') {
363
0
      i++;
364
0
      j = 0;
365
0
      if (!argv[i]) {
366
0
        dropbear_exit("Missing argument");
367
0
      }
368
0
    }
369
370
0
    if (nextisport) {
371
0
      addportandaddress(&argv[i][j]);
372
0
      nextisport = 0;
373
0
    } else if (next) {
374
0
      *next = &argv[i][j];
375
0
      if (*next == NULL) {
376
0
        dropbear_exit("Invalid null argument");
377
0
      }
378
0
      next = NULL;
379
380
0
      if (keyfile) {
381
0
        addhostkey(keyfile);
382
0
        keyfile = NULL;
383
0
      }
384
0
    }
385
0
  }
386
387
  /* Set up listening ports */
388
2
  if (svr_opts.portcount == 0) {
389
2
    svr_opts.ports[0] = m_strdup(DROPBEAR_DEFPORT);
390
2
    svr_opts.addresses[0] = m_strdup(DROPBEAR_DEFADDRESS);
391
2
    svr_opts.portcount = 1;
392
2
  }
393
394
2
  if (svr_opts.bannerfile) {
395
0
    load_banner();
396
0
  }
397
398
2
#ifdef HAVE_GETGROUPLIST
399
2
  if (svr_opts.restrict_group) {
400
0
    struct group *restrictedgroup = getgrnam(svr_opts.restrict_group);
401
402
0
    if (restrictedgroup){
403
0
      svr_opts.restrict_group_gid = restrictedgroup->gr_gid;
404
0
    } else {
405
0
      dropbear_exit("Cannot restrict logins to group '%s' as the group does not exist", svr_opts.restrict_group);
406
0
    }
407
0
  }
408
2
#endif
409
410
2
  if (recv_window_arg) {
411
0
    parse_recv_window(recv_window_arg);
412
0
  }
413
414
2
  if (maxauthtries_arg) {
415
0
    unsigned int val = 0;
416
0
    if (m_str_to_uint(maxauthtries_arg, &val) == DROPBEAR_FAILURE 
417
0
      || val == 0) {
418
0
      dropbear_exit("Bad maxauthtries '%s'", maxauthtries_arg);
419
0
    }
420
0
    svr_opts.maxauthtries = val;
421
0
  }
422
423
424
2
  if (keepalive_arg) {
425
0
    unsigned int val;
426
0
    if (m_str_to_uint(keepalive_arg, &val) == DROPBEAR_FAILURE) {
427
0
      dropbear_exit("Bad keepalive '%s'", keepalive_arg);
428
0
    }
429
0
    opts.keepalive_secs = val;
430
0
  }
431
432
2
  if (idle_timeout_arg) {
433
0
    unsigned int val;
434
0
    if (m_str_to_uint(idle_timeout_arg, &val) == DROPBEAR_FAILURE) {
435
0
      dropbear_exit("Bad idle_timeout '%s'", idle_timeout_arg);
436
0
    }
437
0
    opts.idle_timeout_secs = val;
438
0
  }
439
440
2
  if (svr_opts.forced_command) {
441
0
    dropbear_log(LOG_INFO, "Forced command set to '%s'", svr_opts.forced_command);
442
0
  }
443
444
2
  if (svr_opts.interface) {
445
0
    dropbear_log(LOG_INFO, "Binding to interface '%s'", svr_opts.interface);
446
0
  }
447
448
2
  if (reexec_fd_arg) {
449
0
    if (m_str_to_uint(reexec_fd_arg, &svr_opts.reexec_childpipe) == DROPBEAR_FAILURE
450
0
      || svr_opts.reexec_childpipe < 0) {
451
0
      dropbear_exit("Bad -2");
452
0
    }
453
0
  }
454
455
2
  if (svr_opts.multiauthmethod && svr_opts.noauthpass) {
456
0
    dropbear_exit("-t and -s are incompatible");
457
0
  }
458
459
2
  if (strlen(svr_opts.authorized_keys_dir) == 0) {
460
0
    dropbear_exit("Bad -D");
461
0
  }
462
463
#if DROPBEAR_PLUGIN
464
  if (pubkey_plugin) {
465
    svr_opts.pubkey_plugin = m_strdup(pubkey_plugin);
466
    char *args = strchr(svr_opts.pubkey_plugin, ',');
467
    if (args) {
468
      *args='\0';
469
      ++args;
470
    }
471
    svr_opts.pubkey_plugin_options = args;
472
  }
473
#endif
474
2
}
475
476
0
static void addportandaddress(const char* spec) {
477
0
  char *port = NULL, *address = NULL;
478
479
0
  if (svr_opts.portcount >= DROPBEAR_MAX_PORTS) {
480
0
    return;
481
0
  }
482
483
0
  if (split_address_port(spec, &address, &port) == DROPBEAR_FAILURE) {
484
0
    dropbear_exit("Bad -p argument");
485
0
  }
486
487
  /* A bare port */
488
0
  if (!port) {
489
0
    port = address;
490
0
    address = NULL;
491
0
  }
492
493
0
  if (!address) {
494
    /* no address given -> fill in the default address */
495
0
    address = m_strdup(DROPBEAR_DEFADDRESS);
496
0
  }
497
498
0
  if (port[0] == '\0') {
499
    /* empty port -> exit */
500
0
    dropbear_exit("Bad port");
501
0
  }
502
0
  svr_opts.ports[svr_opts.portcount] = port;
503
0
  svr_opts.addresses[svr_opts.portcount] = address;
504
0
  svr_opts.portcount++;
505
0
}
506
507
0
static void disablekey(enum signature_type type) {
508
0
  int i;
509
0
  TRACE(("Disabling key type %d", type))
510
0
  for (i = 0; sigalgs[i].name != NULL; i++) {
511
0
    if ((int)sigalgs[i].val == (int)type) {
512
0
      sigalgs[i].usable = 0;
513
0
      break;
514
0
    }
515
0
  }
516
0
}
517
518
0
static void loadhostkey_helper(const char *name, void** src, void** dst, int fatal_duplicate) {
519
0
  if (*dst) {
520
0
    if (fatal_duplicate) {
521
0
      dropbear_exit("Only one %s key can be specified", name);
522
0
    }
523
0
  } else {
524
0
    *dst = *src;
525
0
    *src = NULL;
526
0
  }
527
528
0
}
529
530
/* Must be called after syslog/etc is working */
531
0
static void loadhostkey(const char *keyfile, int fatal_duplicate) {
532
0
  sign_key * read_key = new_sign_key();
533
0
  char *expand_path = expand_homedir_path(keyfile);
534
0
  enum signkey_type type = DROPBEAR_SIGNKEY_ANY;
535
0
  if (readhostkey(expand_path, read_key, &type) == DROPBEAR_FAILURE) {
536
0
    if (!svr_opts.delay_hostkey) {
537
0
      dropbear_log(LOG_WARNING, "Failed loading %s", expand_path);
538
0
    }
539
0
  }
540
0
  m_free(expand_path);
541
542
0
#if DROPBEAR_RSA
543
0
  if (type == DROPBEAR_SIGNKEY_RSA) {
544
0
    loadhostkey_helper("RSA", (void**)&read_key->rsakey, (void**)&svr_opts.hostkey->rsakey, fatal_duplicate);
545
0
  }
546
0
#endif
547
548
0
#if DROPBEAR_DSS
549
0
  if (type == DROPBEAR_SIGNKEY_DSS) {
550
0
    loadhostkey_helper("DSS", (void**)&read_key->dsskey, (void**)&svr_opts.hostkey->dsskey, fatal_duplicate);
551
0
  }
552
0
#endif
553
554
0
#if DROPBEAR_ECDSA
555
0
#if DROPBEAR_ECC_256
556
0
  if (type == DROPBEAR_SIGNKEY_ECDSA_NISTP256) {
557
0
    loadhostkey_helper("ECDSA256", (void**)&read_key->ecckey256, (void**)&svr_opts.hostkey->ecckey256, fatal_duplicate);
558
0
  }
559
0
#endif
560
0
#if DROPBEAR_ECC_384
561
0
  if (type == DROPBEAR_SIGNKEY_ECDSA_NISTP384) {
562
0
    loadhostkey_helper("ECDSA384", (void**)&read_key->ecckey384, (void**)&svr_opts.hostkey->ecckey384, fatal_duplicate);
563
0
  }
564
0
#endif
565
0
#if DROPBEAR_ECC_521
566
0
  if (type == DROPBEAR_SIGNKEY_ECDSA_NISTP521) {
567
0
    loadhostkey_helper("ECDSA521", (void**)&read_key->ecckey521, (void**)&svr_opts.hostkey->ecckey521, fatal_duplicate);
568
0
  }
569
0
#endif
570
0
#endif /* DROPBEAR_ECDSA */
571
572
0
#if DROPBEAR_ED25519
573
0
  if (type == DROPBEAR_SIGNKEY_ED25519) {
574
0
    loadhostkey_helper("ed25519", (void**)&read_key->ed25519key, (void**)&svr_opts.hostkey->ed25519key, fatal_duplicate);
575
0
  }
576
0
#endif
577
578
0
  sign_key_free(read_key);
579
0
  TRACE(("leave loadhostkey"))
580
0
}
581
582
0
static void addhostkey(const char *keyfile) {
583
0
  if (svr_opts.num_hostkey_files >= MAX_HOSTKEYS) {
584
0
    dropbear_exit("Too many hostkeys");
585
0
  }
586
0
  svr_opts.hostkey_files[svr_opts.num_hostkey_files] = m_strdup(keyfile);
587
0
  svr_opts.num_hostkey_files++;
588
0
}
589
590
591
0
void load_all_hostkeys() {
592
0
  int i;
593
0
  int any_keys = 0;
594
0
#if DROPBEAR_ECDSA
595
0
  int loaded_any_ecdsa = 0;
596
0
#endif
597
598
0
  svr_opts.hostkey = new_sign_key();
599
600
0
  for (i = 0; i < svr_opts.num_hostkey_files; i++) {
601
0
    char *hostkey_file = svr_opts.hostkey_files[i];
602
0
    loadhostkey(hostkey_file, 1);
603
0
    m_free(hostkey_file);
604
0
  }
605
606
  /* Only load default host keys if a host key is not specified by the user */
607
0
  if (svr_opts.num_hostkey_files == 0) {
608
0
#if DROPBEAR_RSA
609
0
    loadhostkey(RSA_PRIV_FILENAME, 0);
610
0
#endif
611
612
0
#if DROPBEAR_DSS
613
0
    loadhostkey(DSS_PRIV_FILENAME, 0);
614
0
#endif
615
616
0
#if DROPBEAR_ECDSA
617
0
    loadhostkey(ECDSA_PRIV_FILENAME, 0);
618
0
#endif
619
0
#if DROPBEAR_ED25519
620
0
    loadhostkey(ED25519_PRIV_FILENAME, 0);
621
0
#endif
622
0
  }
623
624
0
#if DROPBEAR_RSA
625
0
  if (!svr_opts.delay_hostkey && !svr_opts.hostkey->rsakey) {
626
0
#if DROPBEAR_RSA_SHA256
627
0
    disablekey(DROPBEAR_SIGNATURE_RSA_SHA256);
628
0
#endif
629
0
#if DROPBEAR_RSA_SHA1
630
0
    disablekey(DROPBEAR_SIGNATURE_RSA_SHA1);
631
0
#endif
632
0
  } else {
633
0
    any_keys = 1;
634
0
  }
635
0
#endif
636
637
0
#if DROPBEAR_DSS
638
0
  if (!svr_opts.delay_hostkey && !svr_opts.hostkey->dsskey) {
639
0
    disablekey(DROPBEAR_SIGNATURE_DSS);
640
0
  } else {
641
0
    any_keys = 1;
642
0
  }
643
0
#endif
644
645
0
#if DROPBEAR_ECDSA
646
  /* We want to advertise a single ecdsa algorithm size.
647
  - If there is a ecdsa hostkey at startup we choose that that size.
648
  - If we generate at runtime we choose the default ecdsa size.
649
  - Otherwise no ecdsa keys will be advertised */
650
651
  /* check if any keys were loaded at startup */
652
0
  loaded_any_ecdsa = 
653
0
    0
654
0
#if DROPBEAR_ECC_256
655
0
    || svr_opts.hostkey->ecckey256
656
0
#endif
657
0
#if DROPBEAR_ECC_384
658
0
    || svr_opts.hostkey->ecckey384
659
0
#endif
660
0
#if DROPBEAR_ECC_521
661
0
    || svr_opts.hostkey->ecckey521
662
0
#endif
663
0
    ;
664
0
  any_keys |= loaded_any_ecdsa;
665
666
  /* Or an ecdsa key could be generated at runtime */
667
0
  any_keys |= svr_opts.delay_hostkey;
668
669
  /* At most one ecdsa key size will be left enabled */
670
0
#if DROPBEAR_ECC_256
671
0
  if (!svr_opts.hostkey->ecckey256
672
0
    && (!svr_opts.delay_hostkey || loaded_any_ecdsa || ECDSA_DEFAULT_SIZE != 256 )) {
673
0
    disablekey(DROPBEAR_SIGNATURE_ECDSA_NISTP256);
674
0
  }
675
0
#endif
676
0
#if DROPBEAR_ECC_384
677
0
  if (!svr_opts.hostkey->ecckey384
678
0
    && (!svr_opts.delay_hostkey || loaded_any_ecdsa || ECDSA_DEFAULT_SIZE != 384 )) {
679
0
    disablekey(DROPBEAR_SIGNATURE_ECDSA_NISTP384);
680
0
  }
681
0
#endif
682
0
#if DROPBEAR_ECC_521
683
0
  if (!svr_opts.hostkey->ecckey521
684
0
    && (!svr_opts.delay_hostkey || loaded_any_ecdsa || ECDSA_DEFAULT_SIZE != 521 )) {
685
0
    disablekey(DROPBEAR_SIGNATURE_ECDSA_NISTP521);
686
0
  }
687
0
#endif
688
0
#endif /* DROPBEAR_ECDSA */
689
690
0
#if DROPBEAR_ED25519
691
0
  if (!svr_opts.delay_hostkey && !svr_opts.hostkey->ed25519key) {
692
0
    disablekey(DROPBEAR_SIGNATURE_ED25519);
693
0
  } else {
694
0
    any_keys = 1;
695
0
  }
696
0
#endif
697
0
#if DROPBEAR_SK_ECDSA
698
0
  disablekey(DROPBEAR_SIGNATURE_SK_ECDSA_NISTP256);
699
0
#endif 
700
0
#if DROPBEAR_SK_ED25519
701
0
  disablekey(DROPBEAR_SIGNATURE_SK_ED25519);
702
0
#endif
703
704
0
  if (!any_keys) {
705
0
    dropbear_exit("No hostkeys available. 'dropbear -R' may be useful or run dropbearkey.");
706
0
  }
707
0
}
708
709
0
static void load_banner() {
710
0
  struct stat buf;
711
0
  if (stat(svr_opts.bannerfile, &buf) != 0) {
712
0
    dropbear_log(LOG_WARNING, "Error opening banner file '%s'",
713
0
        svr_opts.bannerfile);
714
0
    return;
715
0
  }
716
717
0
  if (buf.st_size > MAX_BANNER_SIZE) {
718
0
    dropbear_log(LOG_WARNING, "Banner file too large, max is %d bytes",
719
0
        MAX_BANNER_SIZE);
720
0
    return;
721
0
  }
722
723
0
  svr_opts.banner = buf_new(buf.st_size);
724
0
  if (buf_readfile(svr_opts.banner, svr_opts.bannerfile) != DROPBEAR_SUCCESS) {
725
0
    dropbear_log(LOG_WARNING, "Error reading banner file '%s'",
726
0
        svr_opts.bannerfile);
727
0
    buf_free(svr_opts.banner);
728
0
    svr_opts.banner = NULL;
729
0
    return;
730
0
  }
731
0
  buf_setpos(svr_opts.banner, 0);
732
733
0
}