/* This file is in the public domain. */ #include #include #include extern const char *__progname; #include "b64.h" #include "md5.h" #include "algs.h" #include "panic.h" #include "config.h" #include "nested.h" #include "stdio-util.h" #include "keyutils.h" #define BEGIN_MAGIC "---- BEGIN SSH2 PUBLIC KEY ----" #define END_MAGIC "---- END SSH2 PUBLIC KEY ----" #define MAXHDRTAG 64 #define MAXHDRBODY 1024 static char *getline(void) { static char *b = 0; static int a = 0; int l; int c; NESTED void savec(int ch) { if (l >= a) b = realloc(b,a=l+8); b[l++] = ch; } l = 0; while (1) { c = getchar(); switch (c) { case EOF: if (l == 0) return(0); savec('\0'); return(b); break; case '\n': savec('\0'); return(b); break; case '\r': c = getchar(); if ((c != '\n') && (c != EOF)) ungetc(c,stdin); savec('\0'); return(b); break; } savec(c); } } void do_import(void) { int inkey; int inhdr; int contd; char *line; char hdrline[MAXHDRTAG+2+MAXHDRBODY+1]; int hdrlen; int lineno; int ll; char *key64b; int key64l; char *keybinb; int keybinl; char *comment; inkey = 0; lineno = 0; while (1) { line = getline(); if (! line) break; lineno ++; ll = strlen(line); if (! inkey) { if (!strcmp(line,BEGIN_MAGIC)) { inkey = 1; inhdr = 1; contd = 0; hdrlen = 0; key64b = 0; key64l = 0; comment = 0; } continue; } if (inhdr && !contd && !index(line,':')) inhdr = 0; if (! inhdr) { if (!strcmp(line,END_MAGIC)) { FILE *r; FILE *w; void *b64; int c; int i; void *av; HKALG *a; r = fopen_rstr(key64b,key64l); w = fopen_alloc(&keybinb,&keybinl); b64 = b64r_init(&b64_stdio_get,r); do <"done"> { do <"err"> { while <"data"> (1) { c = b64r_get(b64); switch (c) { case B64R_EOF: break <"data">; break; case B64R_ERR: fprintf(stderr,"%s: line %d: invalid encoded data\n",__progname,lineno); break <"err">; break; } putc(c,w); } b64r_done(b64); fclose(r); fclose(w); do <"done"> { do <"found"> { for (i=0;(av=(*at_hk.list)(i));i++) { a = av; if ((*a->checkpub)(keybinb,keybinl)) break <"found">; } fprintf(stderr,"%s: line %d: unrecognized key format\n",__progname,lineno); break <"done">; } while (0); printf("%s ",a->name); b64 = b64w_init(&b64_stdio_put,stdout); for (i=0;i; } while (0); b64r_done(b64); fclose(r); fclose(w); free(keybinb); } while (0); inkey = 0; } else { key64b = realloc(key64b,key64l+ll); bcopy(line,key64b+key64l,ll); key64l += ll; } continue; } if (! contd) hdrlen = 0; if (hdrlen >= 0) { if (ll+hdrlen > sizeof(hdrline)-1) { fprintf(stderr,"%s: line %d: header line too long\n",__progname,lineno); hdrlen = -1; } else { bcopy(line,&hdrline[hdrlen],ll); hdrlen += ll; } } contd = (ll > 0) && (line[ll-1] == '\\'); if (contd) { hdrlen --; } else { if (hdrlen >= 0) { char *colon; hdrline[hdrlen] = '\0'; colon = index(&hdrline[0],':'); if (! colon) panic("no : in header"); if (colon-&hdrline[0] > MAXHDRTAG) { fprintf(stderr,"%s: line %d: header tag too long\n",__progname,lineno); } else if (colon[1] != ' ') { fprintf(stderr,"%s: line %d: header is missing space after colon\n",__progname,lineno); } else if (&hdrline[hdrlen]-(colon+2) > MAXHDRBODY) { fprintf(stderr,"%s: line %d: header body too long\n",__progname,lineno); } else { if ( (colon-&hdrline[0] == 7) && !strncasecmp(&hdrline[0],"comment",7) ) { free(comment); if ( (hdrlen >= 11) && (hdrline[9] == '"') && (hdrline[hdrlen-1] == '"') ) { hdrline[--hdrlen] = '\0'; comment = strdup(&hdrline[10]); } else { comment = strdup(&hdrline[9]); } } } } contd = 0; hdrlen = 0; } } } void do_export(void) { char *line; int lineno; char *space; int i; void *av; HKALG *a; FILE *r; int c; FILE *w; void *b64; FILE *w64; char *keyb; int keyl; char *commb; int comml; const char *u; int outcol; const char *wrapsuff; NESTED int wrap72_w(void *cookie __attribute__((__unused__)), const char *buf, int len) { int i; for (i=0;i= 70) { printf("%s\n",wrapsuff); outcol = 0; } putchar(buf[i]); outcol ++; } } return(len); } lineno = 0; while <"nextline"> (1) { line = getline(); if (! line) break; lineno ++; space = index(line,' '); if (! space) { fprintf(stderr,"%s: line %d: malformatted line (no space)\n",__progname,lineno); continue; } *space++ = '\0'; do <"found"> { for (i=0;(av=(*at_hk.list)(i));i++) { a = av; if (!strcmp(line,a->name)) break <"found">; } fprintf(stderr,"%s: line %d: unrecognized algorithm name `%s'\n",__progname,lineno,line); continue <"nextline">; } while (0); r = fopen_rstr(space,-1); b64 = b64r_init(&b64_stdio_get,r); w = fopen_alloc(&keyb,&keyl); while <"keydata"> (1) { c = b64r_get(b64); switch (c) { case B64R_EOF: break <"keydata">; break; case B64R_ERR: fprintf(stderr,"%s: line %d: malformatted line (bad base-64 data)\n",__progname,lineno); b64r_done(b64); fclose(r); fclose(w); free(keyb); continue <"nextline">; break; } putc(c,w); } fclose(w); b64r_done(b64); c = getc(r); if (c == ' ') { w = fopen_alloc(&commb,&comml); while (1) { c = getc(r); if (c == EOF) break; putc(c,w); } fclose(w); } else if (c == EOF) { commb = 0; comml = 0; } else { fprintf(stderr,"%s: line %d: malformatted line (botched comment delimiter)\n",__progname,lineno); fclose(r); free(keyb); continue <"nextline">; } fclose(r); outcol = 0; wrapsuff = "\\"; w = fwopen(0,&wrap72_w); fprintf(w,"%s\n",BEGIN_MAGIC); u = config_str("user"); if (u) fprintf(w,"Subject: %s\n",u); if (comml > 0) { fprintf(w,"Comment: "); fwrite(commb,1,comml,w); fprintf(w,"\n"); } fflush(w); wrapsuff = ""; w64 = b64w_wrap(w); for (i=0;i (1) { line = getline(); if (! line) break; lineno ++; space = index(line,' '); if (! space) { fprintf(stderr,"%s: line %d: malformatted line (no space)\n",__progname,lineno); continue; } *space++ = '\0'; do <"found"> { for (i=0;(av=(*at_hk.list)(i));i++) { a = av; if (!strcmp(line,a->name)) break <"found">; } fprintf(stderr,"%s: line %d: unrecognized algorithm name `%s'\n",__progname,lineno,line); continue <"nextline">; } while (0); r = fopen_rstr(space,-1); b64 = b64r_init(&b64_stdio_get,r); hh = md5_init(); while <"keydata"> (1) { c = b64r_get(b64); switch (c) { case B64R_EOF: break <"keydata">; break; case B64R_ERR: fprintf(stderr,"%s: line %d: malformatted line (bad base-64 data)\n",__progname,lineno); b64r_done(b64); fclose(r); fclose(w); continue <"nextline">; break; } ch = c; md5_process_bytes(hh,&ch,1); } b64r_done(b64); md5_result(hh,&hr[0]); c = getc(r); switch (c) { case ' ': case EOF: break; default: fprintf(stderr,"%s: line %d: malformatted line (botched comment delimiter)\n",__progname,lineno); fclose(r); continue <"nextline">; break; } fclose(r); printf("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:" "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", hr[0],hr[1],hr[2],hr[3],hr[4],hr[5],hr[6],hr[7], hr[8],hr[9],hr[10],hr[11],hr[12],hr[13],hr[14],hr[15]); } }