comparison cli-runopts.c @ 546:568638be7203 agent-client

propagate from branch 'au.asn.ucc.matt.dropbear' (head 899a8851a5edf840b2f7925bcc26ffe99dcac54d) to branch 'au.asn.ucc.matt.dropbear.cli-agent' (head 6bbab8364de17bd9ecb1dee5ffb796e48c0380d2)
author Matt Johnston <matt@ucc.asn.au>
date Wed, 01 Jul 2009 04:16:32 +0000
parents d588e3ea557a 9e51707cd6f2
children c3f2ec71e3d4
comparison
equal deleted inserted replaced
500:d588e3ea557a 546:568638be7203
47 #endif 47 #endif
48 48
49 static void printhelp() { 49 static void printhelp() {
50 50
51 fprintf(stderr, "Dropbear client v%s\n" 51 fprintf(stderr, "Dropbear client v%s\n"
52 #ifdef ENABLE_CLI_MULTIHOP
53 "Usage: %s [options] [user@]host[/port][,[user@]host/port],...] [command]\n"
54 #else
52 "Usage: %s [options] [user@]host[/port] [command]\n" 55 "Usage: %s [options] [user@]host[/port] [command]\n"
56 #endif
53 "Options are:\n" 57 "Options are:\n"
54 "-p <remoteport>\n" 58 "-p <remoteport>\n"
55 "-l <username>\n" 59 "-l <username>\n"
56 "-t Allocate a pty\n" 60 "-t Allocate a pty\n"
57 "-T Don't allocate a pty\n" 61 "-T Don't allocate a pty\n"
72 #ifdef ENABLE_CLI_REMOTETCPFWD 76 #ifdef ENABLE_CLI_REMOTETCPFWD
73 "-R <listenport:remotehost:remoteport> Remote port forwarding\n" 77 "-R <listenport:remotehost:remoteport> Remote port forwarding\n"
74 #endif 78 #endif
75 "-W <receive_window_buffer> (default %d, larger may be faster, max 1MB)\n" 79 "-W <receive_window_buffer> (default %d, larger may be faster, max 1MB)\n"
76 "-K <keepalive> (0 is never, default %d)\n" 80 "-K <keepalive> (0 is never, default %d)\n"
81 "-I <idle_timeout> (0 is never, default %d)\n"
77 #ifdef ENABLE_CLI_NETCAT 82 #ifdef ENABLE_CLI_NETCAT
78 "-B <endhost:endport> Netcat-alike bouncing\n" 83 "-B <endhost:endport> Netcat-alike forwarding\n"
79 #endif 84 #endif
80 #ifdef ENABLE_CLI_PROXYCMD 85 #ifdef ENABLE_CLI_PROXYCMD
81 "-J <proxy_program> Use program rather than tcp connection\n" 86 "-J <proxy_program> Use program pipe rather than TCP connection\n"
82 #endif 87 #endif
83 #ifdef DEBUG_TRACE 88 #ifdef DEBUG_TRACE
84 "-v verbose\n" 89 "-v verbose (compiled with DEBUG_TRACE)\n"
85 #endif 90 #endif
86 ,DROPBEAR_VERSION, cli_opts.progname, 91 ,DROPBEAR_VERSION, cli_opts.progname,
87 DEFAULT_RECV_WINDOW, DEFAULT_KEEPALIVE); 92 DEFAULT_RECV_WINDOW, DEFAULT_KEEPALIVE, DEFAULT_IDLE_TIMEOUT);
88 93
89 } 94 }
90 95
91 void cli_getopts(int argc, char ** argv) { 96 void cli_getopts(int argc, char ** argv) {
92
93 unsigned int i, j; 97 unsigned int i, j;
94 char ** next = 0; 98 char ** next = 0;
95 unsigned int cmdlen; 99 unsigned int cmdlen;
96 #ifdef ENABLE_CLI_PUBKEY_AUTH 100 #ifdef ENABLE_CLI_PUBKEY_AUTH
97 int nextiskey = 0; /* A flag if the next argument is a keyfile */ 101 int nextiskey = 0; /* A flag if the next argument is a keyfile */
107 #endif 111 #endif
108 char* dummy = NULL; /* Not used for anything real */ 112 char* dummy = NULL; /* Not used for anything real */
109 113
110 char* recv_window_arg = NULL; 114 char* recv_window_arg = NULL;
111 char* keepalive_arg = NULL; 115 char* keepalive_arg = NULL;
116 char* idle_timeout_arg = NULL;
117 char *host_arg = NULL;
112 118
113 /* see printhelp() for options */ 119 /* see printhelp() for options */
114 cli_opts.progname = argv[0]; 120 cli_opts.progname = argv[0];
115 cli_opts.remotehost = NULL; 121 cli_opts.remotehost = NULL;
116 cli_opts.remoteport = NULL; 122 cli_opts.remoteport = NULL;
262 next = &recv_window_arg; 268 next = &recv_window_arg;
263 break; 269 break;
264 case 'K': 270 case 'K':
265 next = &keepalive_arg; 271 next = &keepalive_arg;
266 break; 272 break;
273 case 'I':
274 next = &idle_timeout_arg;
275 break;
267 #ifdef ENABLE_CLI_AGENTFWD 276 #ifdef ENABLE_CLI_AGENTFWD
268 case 'A': 277 case 'A':
269 cli_opts.agent_fwd = 1; 278 cli_opts.agent_fwd = 1;
270 break; 279 break;
271 #endif 280 #endif
305 } else { 314 } else {
306 TRACE(("non-flag arg: '%s'", argv[i])) 315 TRACE(("non-flag arg: '%s'", argv[i]))
307 316
308 /* Either the hostname or commands */ 317 /* Either the hostname or commands */
309 318
310 if (cli_opts.remotehost == NULL) { 319 if (host_arg == NULL) {
311 #ifdef ENABLE_CLI_MULTIHOP 320 host_arg = argv[i];
312 parse_multihop_hostname(argv[i], argv[0]);
313 #else
314 parse_hostname(argv[i]);
315 #endif
316 } else { 321 } else {
317 322
318 /* this is part of the commands to send - after this we 323 /* this is part of the commands to send - after this we
319 * don't parse any more options, and flags are sent as the 324 * don't parse any more options, and flags are sent as the
320 * command */ 325 * command */
339 } 344 }
340 } 345 }
341 346
342 /* And now a few sanity checks and setup */ 347 /* And now a few sanity checks and setup */
343 348
344 if (cli_opts.remotehost == NULL) { 349 if (host_arg == NULL) {
345 printhelp(); 350 printhelp();
346 exit(EXIT_FAILURE); 351 exit(EXIT_FAILURE);
347 } 352 }
348 353
349 if (cli_opts.remoteport == NULL) { 354 if (cli_opts.remoteport == NULL) {
375 if (m_str_to_uint(keepalive_arg, &opts.keepalive_secs) == DROPBEAR_FAILURE) { 380 if (m_str_to_uint(keepalive_arg, &opts.keepalive_secs) == DROPBEAR_FAILURE) {
376 dropbear_exit("Bad keepalive '%s'", keepalive_arg); 381 dropbear_exit("Bad keepalive '%s'", keepalive_arg);
377 } 382 }
378 } 383 }
379 384
385 if (idle_timeout_arg) {
386 if (m_str_to_uint(idle_timeout_arg, &opts.idle_timeout_secs) == DROPBEAR_FAILURE) {
387 dropbear_exit("Bad idle_timeout '%s'", idle_timeout_arg);
388 }
389 }
390
380 #ifdef ENABLE_CLI_NETCAT 391 #ifdef ENABLE_CLI_NETCAT
381 if (cli_opts.cmd && cli_opts.netcat_host) { 392 if (cli_opts.cmd && cli_opts.netcat_host) {
382 dropbear_log(LOG_INFO, "Ignoring command '%s' in netcat mode", cli_opts.cmd); 393 dropbear_log(LOG_INFO, "Ignoring command '%s' in netcat mode", cli_opts.cmd);
383 } 394 }
384 #endif 395 #endif
385 396
397 /* The hostname gets set up last, since
398 * in multi-hop mode it will require knowledge
399 * of other flags such as -i */
400 #ifdef ENABLE_CLI_MULTIHOP
401 parse_multihop_hostname(host_arg, argv[0]);
402 #else
403 parse_hostname(host_arg);
404 #endif
386 } 405 }
387 406
388 #ifdef ENABLE_CLI_PUBKEY_AUTH 407 #ifdef ENABLE_CLI_PUBKEY_AUTH
389 static void loadidentityfile(const char* filename) { 408 static void loadidentityfile(const char* filename) {
390 409
393 int keytype; 412 int keytype;
394 413
395 key = new_sign_key(); 414 key = new_sign_key();
396 keytype = DROPBEAR_SIGNKEY_ANY; 415 keytype = DROPBEAR_SIGNKEY_ANY;
397 if ( readhostkey(filename, key, &keytype) != DROPBEAR_SUCCESS ) { 416 if ( readhostkey(filename, key, &keytype) != DROPBEAR_SUCCESS ) {
398
399 fprintf(stderr, "Failed loading keyfile '%s'\n", filename); 417 fprintf(stderr, "Failed loading keyfile '%s'\n", filename);
400 sign_key_free(key); 418 sign_key_free(key);
401
402 } else { 419 } else {
403
404 nextkey = (struct SignKeyList*)m_malloc(sizeof(struct SignKeyList)); 420 nextkey = (struct SignKeyList*)m_malloc(sizeof(struct SignKeyList));
405 nextkey->key = key; 421 nextkey->key = key;
422 nextkey->filename = m_strdup(filename);
406 nextkey->next = cli_opts.privkeys; 423 nextkey->next = cli_opts.privkeys;
407 nextkey->type = keytype; 424 nextkey->type = keytype;
408 nextkey->source = SIGNKEY_SOURCE_RAW_FILE; 425 nextkey->source = SIGNKEY_SOURCE_RAW_FILE;
409 cli_opts.privkeys = nextkey; 426 cli_opts.privkeys = nextkey;
410 } 427 }
411 } 428 }
412 #endif 429 #endif
413 430
414 #ifdef ENABLE_CLI_MULTIHOP 431 #ifdef ENABLE_CLI_MULTIHOP
432
433 static char*
434 multihop_passthrough_args() {
435 char *ret;
436 int total;
437 unsigned int len = 0;
438 struct SignKeyList *nextkey;
439 /* Fill out -i and -W options that make sense for all
440 * the intermediate processes */
441 for (nextkey = cli_opts.privkeys; nextkey; nextkey = nextkey->next)
442 {
443 len += 3 + strlen(nextkey->filename);
444 }
445 len += 20; // space for -W <size>, terminator.
446 ret = m_malloc(len);
447 total = 0;
448
449 if (opts.recv_window != DEFAULT_RECV_WINDOW)
450 {
451 int written = snprintf(ret+total, len-total, "-W %d", opts.recv_window);
452 total += written;
453 }
454
455 for (nextkey = cli_opts.privkeys; nextkey; nextkey = nextkey->next)
456 {
457 const size_t size = len - total;
458 int written = snprintf(ret+total, size, "-i %s", nextkey->filename);
459 dropbear_assert(written < size);
460 total += written;
461 }
462
463 return ret;
464 }
415 465
416 /* Sets up 'onion-forwarding' connections. This will spawn 466 /* Sets up 'onion-forwarding' connections. This will spawn
417 * a separate dbclient process for each hop. 467 * a separate dbclient process for each hop.
418 * As an example, if the cmdline is 468 * As an example, if the cmdline is
419 * dbclient wrt,madako,canyons 469 * dbclient wrt,madako,canyons
425 * 475 *
426 * Ports for hosts can be specified as host/port. 476 * Ports for hosts can be specified as host/port.
427 */ 477 */
428 static void parse_multihop_hostname(const char* orighostarg, const char* argv0) { 478 static void parse_multihop_hostname(const char* orighostarg, const char* argv0) {
429 char *userhostarg = NULL; 479 char *userhostarg = NULL;
480 char *hostbuf = NULL;
430 char *last_hop = NULL;; 481 char *last_hop = NULL;;
431 char *remainder = NULL; 482 char *remainder = NULL;
432 483
433 /* both scp and rsync parse a user@host argument 484 /* both scp and rsync parse a user@host argument
434 * and turn it into "-l user host". This breaks 485 * and turn it into "-l user host". This breaks
437 * though that should be fairly uncommon. */ 488 * though that should be fairly uncommon. */
438 if (cli_opts.username 489 if (cli_opts.username
439 && strchr(cli_opts.username, ',') 490 && strchr(cli_opts.username, ',')
440 && strchr(cli_opts.username, '@')) { 491 && strchr(cli_opts.username, '@')) {
441 unsigned int len = strlen(orighostarg) + strlen(cli_opts.username) + 2; 492 unsigned int len = strlen(orighostarg) + strlen(cli_opts.username) + 2;
442 userhostarg = m_malloc(len); 493 hostbuf = m_malloc(len);
443 snprintf(userhostarg, len, "%s@%s", cli_opts.username, orighostarg); 494 snprintf(hostbuf, len, "%s@%s", cli_opts.username, orighostarg);
444 } else { 495 } else {
445 userhostarg = m_strdup(orighostarg); 496 hostbuf = m_strdup(orighostarg);
446 } 497 }
498 userhostarg = hostbuf;
447 499
448 last_hop = strrchr(userhostarg, ','); 500 last_hop = strrchr(userhostarg, ',');
449 if (last_hop) { 501 if (last_hop) {
450 if (last_hop == userhostarg) { 502 if (last_hop == userhostarg) {
451 dropbear_exit("Bad multi-hop hostnames"); 503 dropbear_exit("Bad multi-hop hostnames");
459 parse_hostname(userhostarg); 511 parse_hostname(userhostarg);
460 512
461 if (last_hop) { 513 if (last_hop) {
462 /* Set up the proxycmd */ 514 /* Set up the proxycmd */
463 unsigned int cmd_len = 0; 515 unsigned int cmd_len = 0;
516 char *passthrough_args = multihop_passthrough_args();
464 if (cli_opts.proxycmd) { 517 if (cli_opts.proxycmd) {
465 dropbear_exit("-J can't be used with multihop mode"); 518 dropbear_exit("-J can't be used with multihop mode");
466 } 519 }
467 if (cli_opts.remoteport == NULL) { 520 if (cli_opts.remoteport == NULL) {
468 cli_opts.remoteport = "22"; 521 cli_opts.remoteport = "22";
469 } 522 }
470 cmd_len = strlen(remainder) 523 cmd_len = strlen(argv0) + strlen(remainder)
471 + strlen(cli_opts.remotehost) + strlen(cli_opts.remoteport) 524 + strlen(cli_opts.remotehost) + strlen(cli_opts.remoteport)
472 + strlen(argv0) + 30; 525 + strlen(passthrough_args)
526 + 30;
473 cli_opts.proxycmd = m_malloc(cmd_len); 527 cli_opts.proxycmd = m_malloc(cmd_len);
474 snprintf(cli_opts.proxycmd, cmd_len, "%s -B %s:%s %s", 528 snprintf(cli_opts.proxycmd, cmd_len, "%s -B %s:%s %s %s",
475 argv0, cli_opts.remotehost, cli_opts.remoteport, remainder); 529 argv0, cli_opts.remotehost, cli_opts.remoteport,
476 } 530 passthrough_args, remainder);
531 m_free(passthrough_args);
532 }
533 m_free(hostbuf);
477 } 534 }
478 #endif /* !ENABLE_CLI_MULTIHOP */ 535 #endif /* !ENABLE_CLI_MULTIHOP */
479 536
480 /* Parses a [user@]hostname[/port] argument. */ 537 /* Parses a [user@]hostname[/port] argument. */
481 static void parse_hostname(const char* orighostarg) { 538 static void parse_hostname(const char* orighostarg) {
620 if (newfwd->connectport > 65535) { 677 if (newfwd->connectport > 65535) {
621 TRACE(("connectport > 65535")) 678 TRACE(("connectport > 65535"))
622 goto badport; 679 goto badport;
623 } 680 }
624 681
682 newfwd->have_reply = 0;
625 newfwd->next = *fwdlist; 683 newfwd->next = *fwdlist;
626 *fwdlist = newfwd; 684 *fwdlist = newfwd;
627 685
628 TRACE(("leave addforward: done")) 686 TRACE(("leave addforward: done"))
629 return; 687 return;