~ubuntu-branches/ubuntu/precise/dropbear/precise

« back to all changes in this revision

Viewing changes to cli-runopts.c

  • Committer: Bazaar Package Importer
  • Author(s): Gerrit Pape, Matt Johnston, Gerrit Pape
  • Date: 2008-11-19 20:58:59 UTC
  • mfrom: (1.3.5 upstream) (6.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20081119205859-mzv0m0ew1ynjpl6g
Tags: 0.52-1
[ Matt Johnston ]
* New upstream release.
  * dbclient.1: mention optional 'command' argument (closes: #495823).

[ Gerrit Pape ]
* debian/diff/0001-dbclient.1-dbclient-uses-compression-if...diff:
  new; dbclient.1: dbclient uses compression if compiled with zlib
  support (thx Luca Capello, closes: #495825).
* debian/initramfs/*: new; cryptroot remote unlocking on boot feature
  (thx debian@x.ray.net).
* debian/rules: install debian/initramfs/* (thx debian@x.ray.net).
* debian/control: Suggests: udev (for cryptroot support, thx
  debian@x.ray.net).
* debian/dropbear.postinst: conditionally run update-initramfs -u
  (for cryptroot support, thx debian@x.ray.net. closes: #465903).
* debian/diff/0002-dropbearkey.8-mention-y-option-add-example.diff:
  new; mention -y option, add example (thx debian@x.ray.net).

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
cli_runopts cli_opts; /* GLOBAL */
34
34
 
35
35
static void printhelp();
36
 
static void parsehostname(char* userhostarg);
 
36
static void parse_hostname(const char* orighostarg);
 
37
static void parse_multihop_hostname(const char* orighostarg, const char* argv0);
 
38
static void fill_own_user();
37
39
#ifdef ENABLE_CLI_PUBKEY_AUTH
38
40
static void loadidentityfile(const char* filename);
39
41
#endif
40
42
#ifdef ENABLE_CLI_ANYTCPFWD
41
 
static void addforward(char* str, struct TCPFwdList** fwdlist);
 
43
static void addforward(const char* str, struct TCPFwdList** fwdlist);
 
44
#endif
 
45
#ifdef ENABLE_CLI_NETCAT
 
46
static void add_netcat(const char *str);
42
47
#endif
43
48
 
44
49
static void printhelp() {
45
50
 
46
51
        fprintf(stderr, "Dropbear client v%s\n"
47
 
                                        "Usage: %s [options] [user@]host [command]\n"
 
52
#ifdef ENABLE_CLI_MULTIHOP
 
53
                                        "Usage: %s [options] [user@]host[/port][,[user@]host/port],...] [command]\n"
 
54
#else
 
55
                                        "Usage: %s [options] [user@]host[/port] [command]\n"
 
56
#endif
48
57
                                        "Options are:\n"
49
58
                                        "-p <remoteport>\n"
50
59
                                        "-l <username>\n"
53
62
                                        "-N    Don't run a remote command\n"
54
63
                                        "-f    Run in background after auth\n"
55
64
                                        "-y    Always accept remote host key if unknown\n"
 
65
                                        "-s    Request a subsystem (use for sftp)\n"
56
66
#ifdef ENABLE_CLI_PUBKEY_AUTH
57
67
                                        "-i <identityfile>   (multiple allowed)\n"
58
68
#endif
65
75
#endif
66
76
                                        "-W <receive_window_buffer> (default %d, larger may be faster, max 1MB)\n"
67
77
                                        "-K <keepalive>  (0 is never, default %d)\n"
 
78
                                        "-I <idle_timeout>  (0 is never, default %d)\n"
 
79
#ifdef ENABLE_CLI_NETCAT
 
80
                                        "-B <endhost:endport> Netcat-alike forwarding\n"
 
81
#endif                          
 
82
#ifdef ENABLE_CLI_PROXYCMD
 
83
                                        "-J <proxy_program> Use program pipe rather than TCP connection\n"
 
84
#endif
68
85
#ifdef DEBUG_TRACE
69
 
                                        "-v    verbose\n"
 
86
                                        "-v    verbose (compiled with DEBUG_TRACE)\n"
70
87
#endif
71
88
                                        ,DROPBEAR_VERSION, cli_opts.progname,
72
 
                                        DEFAULT_RECV_WINDOW, DEFAULT_KEEPALIVE);
 
89
                                        DEFAULT_RECV_WINDOW, DEFAULT_KEEPALIVE, DEFAULT_IDLE_TIMEOUT);
73
90
                                        
74
91
}
75
92
 
87
104
#ifdef ENABLE_CLI_REMOTETCPFWD
88
105
        int nextisremote = 0;
89
106
#endif
 
107
#ifdef ENABLE_CLI_NETCAT
 
108
        int nextisnetcat = 0;
 
109
#endif
90
110
        char* dummy = NULL; /* Not used for anything real */
91
111
 
92
112
        char* recv_window_arg = NULL;
93
113
        char* keepalive_arg = NULL;
 
114
        char* idle_timeout_arg = NULL;
94
115
 
95
116
        /* see printhelp() for options */
96
117
        cli_opts.progname = argv[0];
102
123
        cli_opts.backgrounded = 0;
103
124
        cli_opts.wantpty = 9; /* 9 means "it hasn't been touched", gets set later */
104
125
        cli_opts.always_accept_key = 0;
 
126
        cli_opts.is_subsystem = 0;
105
127
#ifdef ENABLE_CLI_PUBKEY_AUTH
106
128
        cli_opts.privkeys = NULL;
107
129
#endif
112
134
#ifdef ENABLE_CLI_REMOTETCPFWD
113
135
        cli_opts.remotefwds = NULL;
114
136
#endif
 
137
#ifdef ENABLE_CLI_PROXYCMD
 
138
        cli_opts.proxycmd = NULL;
 
139
#endif
115
140
        /* not yet
116
141
        opts.ipv4 = 1;
117
142
        opts.ipv6 = 1;
118
143
        */
119
144
        opts.recv_window = DEFAULT_RECV_WINDOW;
120
145
 
 
146
        fill_own_user();
 
147
 
121
148
        /* Iterate all the arguments */
122
149
        for (i = 1; i < (unsigned int)argc; i++) {
123
150
#ifdef ENABLE_CLI_PUBKEY_AUTH
144
171
                        continue;
145
172
                }
146
173
#endif
 
174
#ifdef ENABLE_CLI_NETCAT
 
175
                if (nextisnetcat) {
 
176
                        TRACE(("nextisnetcat true"))
 
177
                        add_netcat(argv[i]);
 
178
                        nextisnetcat = 0;
 
179
                        continue;
 
180
                }
 
181
#endif
147
182
                if (next) {
148
183
                        /* The previous flag set a value to assign */
149
184
                        *next = argv[i];
186
221
                                case 'f':
187
222
                                        cli_opts.backgrounded = 1;
188
223
                                        break;
 
224
                                case 's':
 
225
                                        cli_opts.is_subsystem = 1;
 
226
                                        break;
189
227
#ifdef ENABLE_CLI_LOCALTCPFWD
190
228
                                case 'L':
191
229
                                        nextislocal = 1;
199
237
                                        nextisremote = 1;
200
238
                                        break;
201
239
#endif
 
240
#ifdef ENABLE_CLI_NETCAT
 
241
                                case 'B':
 
242
                                        nextisnetcat = 1;
 
243
                                        break;
 
244
#endif
 
245
#ifdef ENABLE_CLI_PROXYCMD
 
246
                                case 'J':
 
247
                                        next = &cli_opts.proxycmd;
 
248
                                        break;
 
249
#endif
202
250
                                case 'l':
203
251
                                        next = &cli_opts.username;
204
252
                                        break;
215
263
                                case 'K':
216
264
                                        next = &keepalive_arg;
217
265
                                        break;
 
266
                                case 'I':
 
267
                                        next = &idle_timeout_arg;
 
268
                                        break;
218
269
#ifdef DEBUG_TRACE
219
270
                                case 'v':
220
271
                                        debug_trace = 1;
254
305
                        /* Either the hostname or commands */
255
306
 
256
307
                        if (cli_opts.remotehost == NULL) {
257
 
 
258
 
                                parsehostname(argv[i]);
259
 
 
 
308
#ifdef ENABLE_CLI_MULTIHOP
 
309
                                parse_multihop_hostname(argv[i], argv[0]);
 
310
#else
 
311
                                parse_hostname(argv[i]);
 
312
#endif
260
313
                        } else {
261
314
 
262
315
                                /* this is part of the commands to send - after this we
283
336
                }
284
337
        }
285
338
 
 
339
        /* And now a few sanity checks and setup */
 
340
 
286
341
        if (cli_opts.remotehost == NULL) {
287
342
                printhelp();
288
343
                exit(EXIT_FAILURE);
307
362
                dropbear_exit("command required for -f");
308
363
        }
309
364
        
310
 
        if (recv_window_arg)
311
 
        {
 
365
        if (recv_window_arg) {
312
366
                opts.recv_window = atol(recv_window_arg);
313
 
                if (opts.recv_window == 0 || opts.recv_window > MAX_RECV_WINDOW)
314
 
                {
 
367
                if (opts.recv_window == 0 || opts.recv_window > MAX_RECV_WINDOW) {
315
368
                        dropbear_exit("Bad recv window '%s'", recv_window_arg);
316
369
                }
317
370
        }
318
371
        if (keepalive_arg) {
319
 
                opts.keepalive_secs = strtoul(keepalive_arg, NULL, 10);
320
 
                if (opts.keepalive_secs == 0 && errno == EINVAL)
321
 
                {
 
372
                if (m_str_to_uint(keepalive_arg, &opts.keepalive_secs) == DROPBEAR_FAILURE) {
322
373
                        dropbear_exit("Bad keepalive '%s'", keepalive_arg);
323
374
                }
324
375
        }
 
376
 
 
377
        if (idle_timeout_arg) {
 
378
                if (m_str_to_uint(idle_timeout_arg, &opts.idle_timeout_secs) == DROPBEAR_FAILURE) {
 
379
                        dropbear_exit("Bad idle_timeout '%s'", idle_timeout_arg);
 
380
                }
 
381
        }
 
382
 
 
383
#ifdef ENABLE_CLI_NETCAT
 
384
        if (cli_opts.cmd && cli_opts.netcat_host) {
 
385
                dropbear_log(LOG_INFO, "Ignoring command '%s' in netcat mode", cli_opts.cmd);
 
386
        }
 
387
#endif
325
388
        
326
389
}
327
390
 
350
413
}
351
414
#endif
352
415
 
353
 
 
354
 
/* Parses a [user@]hostname argument. userhostarg is the argv[i] corresponding
355
 
 * - note that it will be modified */
356
 
static void parsehostname(char* orighostarg) {
357
 
 
358
 
        uid_t uid;
359
 
        struct passwd *pw = NULL; 
360
 
        char *userhostarg = NULL;
361
 
 
362
 
        /* We probably don't want to be editing argvs */
 
416
#ifdef ENABLE_CLI_MULTIHOP
 
417
 
 
418
/* Sets up 'onion-forwarding' connections. This will spawn
 
419
 * a separate dbclient process for each hop.
 
420
 * As an example, if the cmdline is
 
421
 *   dbclient wrt,madako,canyons
 
422
 * then we want to run:
 
423
 *   dbclient -J "dbclient -B canyons:22 wrt,madako" canyons
 
424
 * and then the inner dbclient will recursively run:
 
425
 *   dbclient -J "dbclient -B madako:22 wrt" madako
 
426
 * etc for as many hosts as we want.
 
427
 *
 
428
 * Ports for hosts can be specified as host/port.
 
429
 */
 
430
static void parse_multihop_hostname(const char* orighostarg, const char* argv0) {
 
431
        char *userhostarg = NULL;
 
432
        char *last_hop = NULL;;
 
433
        char *remainder = NULL;
 
434
 
 
435
        /* both scp and rsync parse a user@host argument
 
436
         * and turn it into "-l user host". This breaks
 
437
         * for our multihop syntax, so we suture it back together.
 
438
         * This will break usernames that have both '@' and ',' in them,
 
439
         * though that should be fairly uncommon. */
 
440
        if (cli_opts.username 
 
441
                        && strchr(cli_opts.username, ',') 
 
442
                        && strchr(cli_opts.username, '@')) {
 
443
                unsigned int len = strlen(orighostarg) + strlen(cli_opts.username) + 2;
 
444
                userhostarg = m_malloc(len);
 
445
                snprintf(userhostarg, len, "%s@%s", cli_opts.username, orighostarg);
 
446
        } else {
 
447
                userhostarg = m_strdup(orighostarg);
 
448
        }
 
449
 
 
450
        last_hop = strrchr(userhostarg, ',');
 
451
        if (last_hop) {
 
452
                if (last_hop == userhostarg) {
 
453
                        dropbear_exit("Bad multi-hop hostnames");
 
454
                }
 
455
                *last_hop = '\0';
 
456
                last_hop++;
 
457
                remainder = userhostarg;
 
458
                userhostarg = last_hop;
 
459
        }
 
460
 
 
461
        parse_hostname(userhostarg);
 
462
 
 
463
        if (last_hop) {
 
464
                /* Set up the proxycmd */
 
465
                unsigned int cmd_len = 0;
 
466
                if (cli_opts.proxycmd) {
 
467
                        dropbear_exit("-J can't be used with multihop mode");
 
468
                }
 
469
                if (cli_opts.remoteport == NULL) {
 
470
                        cli_opts.remoteport = "22";
 
471
                }
 
472
                cmd_len = strlen(remainder) 
 
473
                        + strlen(cli_opts.remotehost) + strlen(cli_opts.remoteport)
 
474
                        + strlen(argv0) + 30;
 
475
                cli_opts.proxycmd = m_malloc(cmd_len);
 
476
                snprintf(cli_opts.proxycmd, cmd_len, "%s -B %s:%s %s", 
 
477
                                argv0, cli_opts.remotehost, cli_opts.remoteport, remainder);
 
478
        }
 
479
}
 
480
#endif /* !ENABLE_CLI_MULTIHOP */
 
481
 
 
482
/* Parses a [user@]hostname[/port] argument. */
 
483
static void parse_hostname(const char* orighostarg) {
 
484
        char *userhostarg = NULL;
 
485
        char *port = NULL;
 
486
 
363
487
        userhostarg = m_strdup(orighostarg);
364
488
 
365
489
        cli_opts.remotehost = strchr(userhostarg, '@');
374
498
        }
375
499
 
376
500
        if (cli_opts.username == NULL) {
377
 
                uid = getuid();
378
 
                
379
 
                pw = getpwuid(uid);
380
 
                if (pw == NULL || pw->pw_name == NULL) {
381
 
                        dropbear_exit("Unknown own user");
382
 
                }
 
501
                cli_opts.username = m_strdup(cli_opts.own_user);
 
502
        }
383
503
 
384
 
                cli_opts.username = m_strdup(pw->pw_name);
 
504
        port = strchr(cli_opts.remotehost, '/');
 
505
        if (port) {
 
506
                *port = '\0';
 
507
                cli_opts.remoteport = port+1;
385
508
        }
386
509
 
387
510
        if (cli_opts.remotehost[0] == '\0') {
389
512
        }
390
513
}
391
514
 
 
515
#ifdef ENABLE_CLI_NETCAT
 
516
static void add_netcat(const char* origstr) {
 
517
        char *portstr = NULL;
 
518
        
 
519
        char * str = m_strdup(origstr);
 
520
        
 
521
        portstr = strchr(str, ':');
 
522
        if (portstr == NULL) {
 
523
                TRACE(("No netcat port"))
 
524
                goto fail;
 
525
        }
 
526
        *portstr = '\0';
 
527
        portstr++;
 
528
        
 
529
        if (strchr(portstr, ':')) {
 
530
                TRACE(("Multiple netcat colons"))
 
531
                goto fail;
 
532
        }
 
533
        
 
534
        if (m_str_to_uint(portstr, &cli_opts.netcat_port) == DROPBEAR_FAILURE) {
 
535
                TRACE(("bad netcat port"))
 
536
                goto fail;
 
537
        }
 
538
        
 
539
        if (cli_opts.netcat_port > 65535) {
 
540
                TRACE(("too large netcat port"))
 
541
                goto fail;
 
542
        }
 
543
        
 
544
        cli_opts.netcat_host = str;
 
545
        return;
 
546
        
 
547
fail:
 
548
        dropbear_exit("Bad netcat endpoint '%s'", origstr);
 
549
}
 
550
#endif
 
551
 
 
552
static void fill_own_user() {
 
553
        uid_t uid;
 
554
        struct passwd *pw = NULL; 
 
555
 
 
556
        uid = getuid();
 
557
 
 
558
        pw = getpwuid(uid);
 
559
        if (pw == NULL || pw->pw_name == NULL) {
 
560
                dropbear_exit("Unknown own user");
 
561
        }
 
562
 
 
563
        cli_opts.own_user = m_strdup(pw->pw_name);
 
564
}
 
565
 
392
566
#ifdef ENABLE_CLI_ANYTCPFWD
393
567
/* Turn a "listenport:remoteaddr:remoteport" string into into a forwarding
394
568
 * set, and add it to the forwarding list */
395
 
static void addforward(char* origstr, struct TCPFwdList** fwdlist) {
 
569
static void addforward(const char* origstr, struct TCPFwdList** fwdlist) {
396
570
 
397
571
        char * listenport = NULL;
398
572
        char * connectport = NULL;
428
602
 
429
603
        /* Now we check the ports - note that the port ints are unsigned,
430
604
         * the check later only checks for >= MAX_PORT */
431
 
        newfwd->listenport = strtol(listenport, NULL, 10);
432
 
        if (errno != 0) {
433
 
                TRACE(("bad listenport strtol"))
 
605
        if (m_str_to_uint(listenport, &newfwd->listenport) == DROPBEAR_FAILURE) {
 
606
                TRACE(("bad listenport strtoul"))
434
607
                goto fail;
435
608
        }
436
609
 
437
 
        newfwd->connectport = strtol(connectport, NULL, 10);
438
 
        if (errno != 0) {
439
 
                TRACE(("bad connectport strtol"))
 
610
        if (m_str_to_uint(connectport, &newfwd->connectport) == DROPBEAR_FAILURE) {
 
611
                TRACE(("bad connectport strtoul"))
440
612
                goto fail;
441
613
        }
442
614
 
452
624
                goto badport;
453
625
        }
454
626
 
 
627
        newfwd->have_reply = 0;
455
628
        newfwd->next = *fwdlist;
456
629
        *fwdlist = newfwd;
457
630