Coverage Report

Created: 2023-09-25 06:08

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