#include #include #include #include #include #include #include extern const char *__progname; #include "keygen.h" #include "cmdline.h" #include "stdio-util.h" static void add_dir(const char **vp) { if (!index(*vp,'/')) { const char *d; char *t; d = get_sshdir("key-file directory"); asprintf(&t,"%s/%s",d,*vp); *vp = t; } } static void block_signals(void) { sigset_t mask; sigemptyset(&mask); sigaddset(&mask,SIGHUP); sigaddset(&mask,SIGINT); sigaddset(&mask,SIGQUIT); sigaddset(&mask,SIGTERM); sigaddset(&mask,SIGTSTP); sigaddset(&mask,SIGTTIN); sigaddset(&mask,SIGTTOU); sigprocmask(SIG_BLOCK,&mask,0); } static void writeit(int fd, const char *data, int len, const char *what, const char *fn) { int n; int first; first = 1; while (len > 0) { n = write(fd,data,len); if (n < 0) { fprintf(stderr,"%s: error writing %s %s: %s\n",__progname,what,fn,strerror(errno)); exit(1); } if (n == 0) { fprintf(stderr,"%s: error writing %s %s: zero-length write\n",__progname,what,fn); exit(1); } if (first && (n < len)) { fprintf(stderr,"%s: warning: short write writing %s %s (wanted %d, wrote %d) - retrying remainder\n",__progname,what,fn,len,n); first = 0; } data += n; len -= n; } } void gen_key(void) { HKALG *a; int i; int j; char *pubdata; int publen; FILE *pubf; int pubfd; char *privdata; int privlen; FILE *privf; int privfd; do <"found"> { for (i=0;(a=hkalg_enum(i));i++) if (!strcmp(keytype,a->name)) break <"found">; for (i=0;(a=hkalg_enum(i));i++) for (j=0;a->altnames[j];j++) if (!strcmp(keytype,a->altnames[j])) break <"found">; fprintf(stderr,"%s: unknown key type `%s'\n",__progname,keytype); fprintf(stderr,"Known types:\n"); for (i=0;(a=hkalg_enum(i));i++) { const char *pre; const char *post; fprintf(stderr,"\t%s",a->name); pre = " (aka "; post = ""; for (j=0;a->altnames[j];j++) { fprintf(stderr,"%s%s",pre,a->altnames[j]); pre = ", "; post = ")"; } fprintf(stderr,"%s\n",post); } exit(1); } while (0); if (!keyfile_pub || !keyfile_priv) { char *t; if (! keyfile) keyfile = a->deffile; if (! keyfile_pub) { asprintf(&t,"%s.pub",keyfile); keyfile_pub = t; } if (! keyfile_priv) { asprintf(&t,"%s.priv",keyfile); keyfile_priv = t; } } add_dir(&keyfile_pub); add_dir(&keyfile_priv); printf("Generating %s key\n",a->name); printf("Public portion: %s\n",keyfile_pub); printf("Private portion: %s\n",keyfile_priv); pubf = fopen_alloc(&pubdata,&publen); privf = fopen_alloc(&privdata,&privlen); fprintf(pubf,"%s ",a->name); (*a->genkey)(pubf,privf); { char *user; int n; char *buf; user = getenv("USER"); n = 8; while (1) { buf = malloc(n); buf[n-1] = '\0'; gethostname(buf,n); if (buf[n-1] == '\0') break; free(buf); n *= 2; } fprintf(pubf," %s@%s\n",user?:"unknown",buf); free(buf); } putc('\n',privf); fclose(pubf); fclose(privf); pubfd = open(keyfile_pub,O_WRONLY|O_CREAT,0666); privfd = open(keyfile_priv,O_WRONLY|O_CREAT,0600); block_signals(); writeit(pubfd,pubdata,publen,"public key file",keyfile_pub); writeit(privfd,privdata,privlen,"private key file",keyfile_priv); ftruncate(pubfd,publen); ftruncate(privfd,privlen); }