#include #include #include #include extern const char *__progname; #include "hkdb.h" #include "cmdline.h" const char *host = 0; const char *port = 0; const char *remuser = 0; int showoffer = 0; ALGLIST *algs_kex = 0; ALGLIST *algs_hk = 0; ALGLIST *algs_enc_c2s = 0; ALGLIST *algs_enc_s2c = 0; ALGLIST *algs_mac_c2s = 0; ALGLIST *algs_mac_s2c = 0; ALGLIST *algs_comp_c2s = 0; ALGLIST *algs_comp_s2c = 0; const char *lang_c2s = 0; const char *lang_s2c = 0; const char *hostkeydb = 0; int savehostkey = 0; const char *randpoolfile = 0; const char *authkey = 0; const char *authkeydir = 0; int noauthkey = 0; const char *sshdir = 0; char **cmdbegin = 0; int cmdcount = 0; const char *keytype = 0; const char *keysize = 0; const char *keyfile = 0; const char *keyfile_pub = 0; const char *keyfile_priv = 0; int opmode = OPMODE_UNSPEC; const char *escchar = 0; char *passphrase; const char *comment = 0; static char *local_user_name(void) { char *s; s = getenv("USER"); if (s == 0) { fprintf(stderr,"%s: no $USER and no remote username specified\n",__progname); exit(1); } return(strdup(s)); } static int algset(ALGLIST **listp, void *(*find)(const char *), const char *name, const char *what) { void *alg; ALGLIST *l; ALGLIST **lp; alg = (*find)(name); if (alg == 0) { if (what) fprintf(stderr,"%s: %s: unknown %s algorithm name\n",__progname,name,what); return(1); } for (lp=listp;(l=*lp);) { if (l->alg == alg) { *lp = l->link; l->link = *listp; *listp = l; return(0); } } l = malloc(sizeof(ALGLIST)); l->alg = alg; l->link = *listp; *listp = l; return(0); } static ALGLIST *default_algs(void *(*enumfn)(int)) { ALGLIST *l; ALGLIST **lp; ALGLIST *a; int i; void *alg; lp = &l; for (i=0;(alg=(*enumfn)(i));i++) { a = malloc(sizeof(ALGLIST)); a->alg = alg; *lp = a; lp = &a->link; } *lp =0; return(l); } static const char *default_sshdir(void) { const char *home; char *s; home = getenv("HOME"); if (home) { asprintf(&s,"%s/.ssh",home); return(s); } return(0); } void handleargs(int ac, char **av) { int skip; int errs; skip = 0; errs = 0; for (ac--,av++;ac;ac--,av++) { if (skip > 0) { skip --; continue; } if (**av != '-') { if (! host) { host = *av; } else { cmdbegin = av; cmdcount = ac; break; } continue; } if (0) { needarg:; fprintf(stderr,"%s: %s needs a following argument\n",__progname,*av); errs ++; continue; } #define WANTARG() do { if (++skip >= ac) goto needarg; } while (0) if (!strcmp(*av,"-host")) { WANTARG(); if (host) fprintf(stderr,"%s: %s %s: warning: host already specified, using later value\n",__progname,av[0],av[skip]); host = av[skip]; continue; } if (!strcmp(*av,"-port")) { WANTARG(); if (port) fprintf(stderr,"%s: %s %s: warning: port already specified, using later value\n",__progname,av[0],av[skip]); port = av[skip]; continue; } if (!strcmp(*av,"-kex")) { WANTARG(); errs += algset(&algs_kex,&kexalg_vfind_c,av[skip],"key exchange"); continue; } if (!strcmp(*av,"-hk")) { WANTARG(); errs += algset(&algs_hk,&hkalg_vfind_c,av[skip],"host key verification"); continue; } if (!strcmp(*av,"-enc")) { WANTARG(); errs += algset(&algs_enc_c2s,&encalg_vfind_c,av[skip],"encryption"); errs += algset(&algs_enc_s2c,&encalg_vfind_c,av[skip],0); continue; } if (!strcmp(*av,"-enc-c2s")) { WANTARG(); errs += algset(&algs_enc_c2s,&encalg_vfind_c,av[skip],"encryption"); continue; } if (!strcmp(*av,"-enc-s2c")) { WANTARG(); errs += algset(&algs_enc_s2c,&encalg_vfind_c,av[skip],"encryption"); continue; } if (!strcmp(*av,"-mac")) { WANTARG(); errs += algset(&algs_mac_c2s,&macalg_vfind_c,av[skip],"MAC"); errs += algset(&algs_mac_s2c,&macalg_vfind_c,av[skip],0); continue; } if (!strcmp(*av,"-mac-c2s")) { WANTARG(); errs += algset(&algs_mac_c2s,&macalg_vfind_c,av[skip],"MAC"); continue; } if (!strcmp(*av,"-mac-s2c")) { WANTARG(); errs += algset(&algs_mac_s2c,&macalg_vfind_c,av[skip],"MAC"); continue; } if (!strcmp(*av,"-comp")) { WANTARG(); errs += algset(&algs_comp_c2s,&compalg_vfind_c,av[skip],"compression"); errs += algset(&algs_comp_s2c,&compalg_vfind_c,av[skip],0); continue; } if (!strcmp(*av,"-comp-c2s")) { WANTARG(); errs += algset(&algs_comp_c2s,&compalg_vfind_c,av[skip],"compression"); continue; } if (!strcmp(*av,"-comp-s2c")) { WANTARG(); errs += algset(&algs_comp_s2c,&compalg_vfind_c,av[skip],"compression"); continue; } if (!strcmp(*av,"-lang-c2s")) { WANTARG(); if (lang_c2s) fprintf(stderr,"%s: %s %s: warning: c2s language already specified, using later value\n",__progname,av[0],av[skip]); lang_c2s = av[skip]; continue; } if (!strcmp(*av,"-lang-s2c")) { WANTARG(); if (lang_s2c) fprintf(stderr,"%s: %s %s: warning: s2c language already specified, using later value\n",__progname,av[0],av[skip]); lang_s2c = av[skip]; continue; } if (!strcmp(*av,"-l") || !strcmp(*av,"-remuser")) { WANTARG(); if (remuser) fprintf(stderr,"%s: %s %s: warning: remote user already specified, using later value\n",__progname,av[0],av[skip]); remuser = av[skip]; continue; } if (!strcmp(*av,"-sshdir")) { WANTARG(); if (sshdir) fprintf(stderr,"%s: %s %s: warning: .ssh directory path already specified, using later value\n",__progname,av[0],av[skip]); sshdir = av[skip]; continue; } if (!strcmp(*av,"-hkdb")) { WANTARG(); if (hostkeydb) fprintf(stderr,"%s: %s %s: warning: host-key database already specified, using later value\n",__progname,av[0],av[skip]); hostkeydb = av[skip]; continue; } if (!strcmp(*av,"-savehostkey")) { savehostkey = 1; continue; } if (!strcmp(*av,"-randfile")) { WANTARG(); if (randpoolfile) fprintf(stderr,"%s: %s %s: warning: random pool file already specified, using later value\n",__progname,av[0],av[skip]); randpoolfile = av[skip]; continue; } if (!strcmp(*av,"-authkey")) { WANTARG(); if (authkey) fprintf(stderr,"%s: %s %s: warning: authentication key file already specified, using later value\n",__progname,av[0],av[skip]); if (authkeydir) fprintf(stderr,"%s: %s %s: warning: overriding -authkeydir %s\n",__progname,av[0],av[skip],authkeydir); if (noauthkey) fprintf(stderr,"%s: %s %s: warning: overriding -noauthkeydir\n",__progname,av[0],av[skip]); authkey = av[skip]; noauthkey = 0; continue; } if (!strcmp(*av,"-authkeydir")) { WANTARG(); if (authkeydir) fprintf(stderr,"%s: %s %s: warning: authentication key directory already specified, using later value\n",__progname,av[0],av[skip]); if (authkey) fprintf(stderr,"%s: %s %s: warning: -authkey %s overrides %s\n",__progname,av[0],av[skip],authkey,av[0]); if (noauthkey) fprintf(stderr,"%s: %s %s: warning: overriding -noauthkeydir\n",__progname,av[0],av[skip]); authkeydir = av[skip]; noauthkey = 0; continue; } if (!strcmp(*av,"-noauthkey")) { if (authkeydir) fprintf(stderr,"%s: %s: warning: overriding -authkeydir %s\n",__progname,av[0],authkeydir); if (authkey) fprintf(stderr,"%s: %s: warning: overriding -authkey %s\n",__progname,av[0],authkey); noauthkey = 1; continue; } if (!strcmp(*av,"-showoffer")) { showoffer = 1; continue; } if (!strcmp(*av,"-keygen")) { opmode = OPMODE_KEYGEN; continue; } if (!strcmp(*av,"-keytype")) { WANTARG(); if (keytype) fprintf(stderr,"%s: %s %s: warning: key type already specified, using later value\n",__progname,av[0],av[skip]); keytype = av[skip]; continue; } if (!strcmp(*av,"-keysize")) { WANTARG(); if (keysize) fprintf(stderr,"%s: %s %s: warning: key size already specified, using later value\n",__progname,av[0],av[skip]); keysize = av[skip]; continue; } if (!strcmp(*av,"-keyfile")) { WANTARG(); if (keyfile) fprintf(stderr,"%s: %s %s: warning: key filename already specified, using later value\n",__progname,av[0],av[skip]); keyfile = av[skip]; continue; } if (!strcmp(*av,"-keyfile-pub")) { WANTARG(); if (keyfile_pub) fprintf(stderr,"%s: %s %s: warning: public-key filename already specified, using later value\n",__progname,av[0],av[skip]); keyfile_pub = av[skip]; continue; } if (!strcmp(*av,"-keyfile-priv")) { WANTARG(); if (keyfile_priv) fprintf(stderr,"%s: %s %s: warning: private-key filename already specified, using later value\n",__progname,av[0],av[skip]); keyfile_priv = av[skip]; continue; } if (!strcmp(*av,"-passphrase")) { WANTARG(); if (passphrase) { fprintf(stderr,"%s: %s %s: warning: passphrase already specified, using later value\n",__progname,av[0],av[skip]); bzero(passphrase,strlen(passphrase)); free(passphrase); } passphrase = strdup(av[skip]); bzero(av[skip],strlen(passphrase)); continue; } if (!strcmp(*av,"-comment")) { WANTARG(); if (comment) fprintf(stderr,"%s: %s %s: warning: key comment already specified, using later value\n",__progname,av[0],av[skip]); comment = av[skip]; continue; } if (!strcmp(*av,"-e") || !strcmp(*av,"-esc")) { WANTARG(); if (escchar) fprintf(stderr,"%s: %s %s: warning: escape character already specified, using later value\n",__progname,av[0],av[skip]); escchar = av[skip]; continue; } #undef WANTARG fprintf(stderr,"%s: unrecognized option `%s'\n",__progname,*av); errs ++; } if (errs) exit(1); if (opmode == OPMODE_UNSPEC) opmode = OPMODE_RUN; if (! sshdir) sshdir = default_sshdir(); switch (opmode) { case OPMODE_RUN: if (! algs_kex) algs_kex = default_algs(kexalg_enum); if (! algs_hk) algs_hk = default_algs(hkalg_enum); if (! algs_enc_c2s) algs_enc_c2s = default_algs(encalg_enum); if (! algs_enc_s2c) algs_enc_s2c = default_algs(encalg_enum); if (! algs_mac_c2s) algs_mac_c2s = default_algs(macalg_enum); if (! algs_mac_s2c) algs_mac_s2c = default_algs(macalg_enum); if (! algs_comp_c2s) algs_comp_c2s = default_algs(compalg_enum); if (! algs_comp_s2c) algs_comp_s2c = default_algs(compalg_enum); if (! remuser) remuser = local_user_name(); if (! hostkeydb) hostkeydb = default_hkdb_path(); break; case OPMODE_KEYGEN: if (! keytype) { fprintf(stderr,"%s: need to specify -keytype\n",__progname); exit(1); } break; default: abort(); break; } } const char *get_sshdir(const char *fmt, ...) { va_list ap; if (sshdir) return(sshdir); fprintf(stderr,"%s: no $HOME, can't default ",__progname); va_start(ap,fmt); vfprintf(stderr,fmt,ap); va_end(ap); fprintf(stderr,"\n"); exit(1); }