/*
 * Update the visible key list.
 */
void keylist_update(void)
{
    struct RSAKey *rkey;
    struct ssh2_userkey *skey;
    int i;

    if (keylist) {
	SendDlgItemMessage(keylist, 100, LB_RESETCONTENT, 0, 0);
	for (i = 0; NULL != (rkey = pageant_nth_ssh1_key(i)); i++) {
	    char listentry[512], *p;
	    /*
	     * Replace two spaces in the fingerprint with tabs, for
	     * nice alignment in the box.
	     */
	    strcpy(listentry, "ssh1\t");
	    p = listentry + strlen(listentry);
	    rsa_fingerprint(p, sizeof(listentry) - (p - listentry), rkey);
	    p = strchr(listentry, ' ');
	    if (p)
		*p = '\t';
	    p = strchr(listentry, ' ');
	    if (p)
		*p = '\t';
	    SendDlgItemMessage(keylist, 100, LB_ADDSTRING,
			       0, (LPARAM) listentry);
	}
	for (i = 0; NULL != (skey = pageant_nth_ssh2_key(i)); i++) {
	    char *listentry, *p;
	    int pos;
	    /*
	     * Replace spaces with tabs in the fingerprint prefix, for
	     * nice alignment in the list box, until we encounter a :
	     * meaning we're into the fingerprint proper.
	     */
	    p = ssh2_fingerprint(skey->alg, skey->data);
            listentry = dupprintf("%s\t%s", p, skey->comment);
            sfree(p);

            pos = 0;
            while (1) {
                pos += strcspn(listentry + pos, " :");
                if (listentry[pos] == ':' || !listentry[pos])
                    break;
                listentry[pos++] = '\t';
            }

	    SendDlgItemMessage(keylist, 100, LB_ADDSTRING, 0,
			       (LPARAM) listentry);
            sfree(listentry);
	}
	SendDlgItemMessage(keylist, 100, LB_SETCURSEL, (WPARAM) - 1, 0);
    }
}
Example #2
0
int main(int argc, char **argv)
{
    Filename *infilename = NULL;
    int intype = SSH_KEYTYPE_UNOPENABLE;
    int encrypted = 0;
    char* origcomment = 0;
    char* line = 0;
    char* passphrase = 0;
    struct ssh2_userkey *ssh2key = NULL;
    char* fingerprint = 0;

    printf("fzputtygen\n");
    printf("Copyright (C) 2008-2016  Tim Kosse\n");
    printf("Based on PuTTY's puttygen\n");
    printf("Copyright (C) 1997-2015  Simon Tatham and the PuTTY team\n");
    printf("Converts private SSH keys into PuTTY's format.\n");
    printf("This program is used by FileZilla and not intended to be used directly.\n");
    printf("Use the puttygen tool from PuTTY for a human-usable tool.\n");
    printf("\n");
    fflush(stdout);

    while (1) {
	sfree(line);

	line = fgetline(stdin);
	if (!line || !*line || *line == '\n')
	    break;

	line[strlen(line) - 1] = 0;
	char* cmd = line, *args = line;
	
	while (*args) {
	    if (*args == ' ') {
		*(args++) = 0;
		break;
	    }
	    args++;
	}
	if (!*args)
	    args = 0;

	if (!strcmp(cmd, "file")) {
	    char const* ret = NULL;
	    if (ssh2key) {
		ssh2key->alg->freekey(ssh2key->data);
		sfree(ssh2key);
		ssh2key = 0;
	    }
	    sfree(passphrase);
	    passphrase = 0;
	    sfree(fingerprint);
	    fingerprint = 0;
	    
	    if (!args) {
		fzprintf(sftpError, "No argument given");
		continue;
	    }

	    if (infilename) {
		filename_free(infilename);
	    }
	    infilename = filename_from_str(args);

	    intype = key_type(infilename);
	    switch (intype)
	    {
	    case SSH_KEYTYPE_SSH1:
		ret = "incompatible";
		intype = SSH_KEYTYPE_UNOPENABLE;
		break;
	    case SSH_KEYTYPE_SSH2:
		ret = "ok";
		encrypted = ssh2_userkey_encrypted(infilename, &origcomment);
		break;
	    case SSH_KEYTYPE_UNKNOWN:
	    case SSH_KEYTYPE_UNOPENABLE:
	    default:
		ret = "error";
		intype = SSH_KEYTYPE_UNOPENABLE;
		break;
	    case SSH_KEYTYPE_OPENSSH_PEM:
	    case SSH_KEYTYPE_OPENSSH_NEW:
	    case SSH_KEYTYPE_SSHCOM:
		encrypted = import_encrypted(infilename, intype, &origcomment);
		ret = encrypted ? "convertible" : "ok";
		break;
	    }
	    fzprintf(sftpReply, "%s", ret);
	}
	else if (!strcmp(cmd, "encrypted")) {
	    if (intype == SSH_KEYTYPE_UNOPENABLE) {
		fzprintf(sftpError, "No key file opened");
		continue;
	    }
	    
	    fzprintf(sftpReply, "%d", encrypted ? 1 : 0);
	}
	else if (!strcmp(cmd, "comment")) {
	    if (intype == SSH_KEYTYPE_UNOPENABLE) {
		fzprintf(sftpError, "No key file opened");
		continue;
	    }
	    if (ssh2key && ssh2key->comment) {
		fzprintf(sftpReply, "%s", ssh2key->comment);
	    }
	    else if (origcomment)
		fzprintf(sftpReply, "%s", origcomment);
	    else
		fzprintf(sftpReply, "");
	}
	else if (!strcmp(cmd, "password")) {
	    const char* error = NULL;

	    if (!args) {
		fzprintf(sftpError, "No argument given");
		continue;
	    }

	    if (intype == SSH_KEYTYPE_UNOPENABLE) {
		fzprintf(sftpError, "No key file opened");
		continue;
	    }

	    if (!encrypted) {
		fzprintf(sftpError, "File is not encrypted");
		continue;
	    }

	    if (ssh2key) {
		fzprintf(sftpError, "Already opened file");
		continue;
	    }

	    sfree(passphrase);
	    passphrase = strdup(args);

	    switch (intype) {
		case SSH_KEYTYPE_SSH2:
		    ssh2key = ssh2_load_userkey(infilename, passphrase, &error);
		    break;
		case SSH_KEYTYPE_OPENSSH_PEM:
		case SSH_KEYTYPE_OPENSSH_NEW:
		case SSH_KEYTYPE_SSHCOM:
		    ssh2key = import_ssh2(infilename, intype, passphrase, &error);
		    break;
		default:
		    break;
	    }
	    if (ssh2key == SSH2_WRONG_PASSPHRASE) {
		error = "wrong passphrase";
		ssh2key = 0;
	    }
	    if (ssh2key) {
		error = NULL;
	    }
	    else if (!error) {
		error = "unknown error";
	    }

	    if (error)
		fzprintf(sftpError, "Error loading file: %s", error);
	    else
		fzprintf(sftpReply, "");
	}
	else if (!strcmp(cmd, "fingerprint")) {
	    const char* error = 0;

	    if (!fingerprint) {
		if (ssh2key) {
		    fingerprint = ssh2_fingerprint(ssh2key->alg, ssh2key->data);
		}
		else {
		    switch (intype) {
			 case SSH_KEYTYPE_SSH2:
			{
			    void* ssh2blob;
			    int bloblen = 0;
			    char* comment = NULL;

			    ssh2blob = ssh2_userkey_loadpub(infilename, 0, &bloblen, &comment, &error);
			    if (ssh2blob) {
				fingerprint = ssh2_fingerprint_blob(ssh2blob, bloblen);
				sfree(ssh2blob);
			    }
			    else if (!error) {
				error = "unknown error";
			    }

			    if (comment) {
				sfree(origcomment);
				origcomment = comment;
			    }
			    break;
			}
			case SSH_KEYTYPE_OPENSSH_PEM:
			case SSH_KEYTYPE_OPENSSH_NEW:
			case SSH_KEYTYPE_SSHCOM:
			    ssh2key = import_ssh2(infilename, intype, "", &error);
			    if (ssh2key) {
				if (ssh2key != SSH2_WRONG_PASSPHRASE) {
				    error = NULL;
				    fingerprint = ssh2_fingerprint(ssh2key->alg, ssh2key->data);
				}
				else {
				    ssh2key = NULL;
				    error = "wrong passphrase";
				}
			    }
			    else if (!error)
				error = "unknown error";
			    break;
			default:
			    error = "No file loaded";
			    break;
		    }
		}
	    }

	    if (!fingerprint && !error) {
		error = "Could not get fingerprint";
	    }

	    if (error)
		fzprintf(sftpError, "Error loading file: %s", error);
	    else
		fzprintf(sftpReply, "%s", fingerprint);
	}
	else if (!strcmp(cmd, "write")) {
	    Filename* outfilename;

	    int ret;
	    if (!args) {
		fzprintf(sftpError, "No argument given");
		continue;
	    }

	    if (!ssh2key) {
		fzprintf(sftpError, "No key loaded");
		continue;
	    }

	    outfilename = filename_from_str(args);

	    ret = ssh2_save_userkey(outfilename, ssh2key, passphrase);
	     if (!ret) {
		fzprintf(sftpError, "Unable to save SSH-2 private key");
		continue;
	    }

	    filename_free(outfilename);

	    fzprintf(sftpReply, "");
	}
	else
		fzprintf(sftpError, "Unknown command");
    }

    if (infilename) {
	filename_free(infilename);
    }
    sfree(line);
    sfree(passphrase);
    if (ssh2key) {
	ssh2key->alg->freekey(ssh2key->data);
	sfree(ssh2key);
    }
    sfree(fingerprint);
    sfree(origcomment);

    return 0;
}
Example #3
0
void load_key_file(HWND hwnd, struct MainDlgState *state,
		   Filename *filename, int was_import_cmd)
{
    char *passphrase;
    int needs_pass;
    int type, realtype;
    int ret;
    const char *errmsg = NULL;
    char *comment;
    struct RSAKey newkey1;
    struct ssh2_userkey *newkey2 = NULL;

    type = realtype = key_type(filename);
    if (type != SSH_KEYTYPE_SSH1 &&
	type != SSH_KEYTYPE_SSH2 &&
	!import_possible(type)) {
	char *msg = dupprintf("Couldn't load private key (%s)",
			      key_type_to_str(type));
	message_box(msg, "PuTTYgen Error", MB_OK | MB_ICONERROR,
		    HELPCTXID(errors_cantloadkey));
	sfree(msg);
	return;
    }

    if (type != SSH_KEYTYPE_SSH1 &&
	type != SSH_KEYTYPE_SSH2) {
	realtype = type;
	type = import_target_type(type);
    }

    comment = NULL;
    passphrase = NULL;
    if (realtype == SSH_KEYTYPE_SSH1)
	needs_pass = rsakey_encrypted(filename, &comment);
    else if (realtype == SSH_KEYTYPE_SSH2)
	needs_pass = ssh2_userkey_encrypted(filename, &comment);
    else
	needs_pass = import_encrypted(filename, realtype, &comment);
    do {
        burnstr(passphrase);
        passphrase = NULL;

	if (needs_pass) {
	    int dlgret;
            struct PassphraseProcStruct pps;
            pps.passphrase = &passphrase;
            pps.comment = comment;
	    dlgret = DialogBoxParam(hinst,
				    MAKEINTRESOURCE(210),
				    NULL, PassphraseProc,
				    (LPARAM) &pps);
	    if (!dlgret) {
		ret = -2;
		break;
	    }
            assert(passphrase != NULL);
	} else
	    passphrase = dupstr("");
	if (type == SSH_KEYTYPE_SSH1) {
	    if (realtype == type)
		ret = loadrsakey(filename, &newkey1, passphrase, &errmsg);
	    else
		ret = import_ssh1(filename, realtype, &newkey1,
                                  passphrase, &errmsg);
	} else {
	    if (realtype == type)
		newkey2 = ssh2_load_userkey(filename, passphrase, &errmsg);
	    else
		newkey2 = import_ssh2(filename, realtype, passphrase, &errmsg);
	    if (newkey2 == SSH2_WRONG_PASSPHRASE)
		ret = -1;
	    else if (!newkey2)
		ret = 0;
	    else
		ret = 1;
	}
    } while (ret == -1);
    if (comment)
	sfree(comment);
    if (ret == 0) {
	char *msg = dupprintf("Couldn't load private key (%s)", errmsg);
	message_box(msg, "PuTTYgen Error", MB_OK | MB_ICONERROR,
		    HELPCTXID(errors_cantloadkey));
	sfree(msg);
    } else if (ret == 1) {
	/*
	 * Now update the key controls with all the
	 * key data.
	 */
	{
	    SetDlgItemText(hwnd, IDC_PASSPHRASE1EDIT,
			   passphrase);
	    SetDlgItemText(hwnd, IDC_PASSPHRASE2EDIT,
			   passphrase);
	    if (type == SSH_KEYTYPE_SSH1) {
		char buf[128];
		char *savecomment;

		state->ssh2 = FALSE;
		state->commentptr = &state->key.comment;
		state->key = newkey1;

		/*
		 * Set the key fingerprint.
		 */
		savecomment = state->key.comment;
		state->key.comment = NULL;
		rsa_fingerprint(buf, sizeof(buf),
				&state->key);
		state->key.comment = savecomment;

		SetDlgItemText(hwnd, IDC_FINGERPRINT, buf);
		/*
		 * Construct a decimal representation
		 * of the key, for pasting into
		 * .ssh/authorized_keys on a Unix box.
		 */
		setupbigedit1(hwnd, IDC_KEYDISPLAY,
			      IDC_PKSTATIC, &state->key);
	    } else {
		char *fp;
		char *savecomment;

		state->ssh2 = TRUE;
		state->commentptr =
		    &state->ssh2key.comment;
		state->ssh2key = *newkey2;	/* structure copy */
		sfree(newkey2);

		savecomment = state->ssh2key.comment;
		state->ssh2key.comment = NULL;
		fp = ssh2_fingerprint(state->ssh2key.alg, state->ssh2key.data);
		state->ssh2key.comment = savecomment;

		SetDlgItemText(hwnd, IDC_FINGERPRINT, fp);
		sfree(fp);

		setupbigedit2(hwnd, IDC_KEYDISPLAY,
			      IDC_PKSTATIC, &state->ssh2key);
	    }
	    SetDlgItemText(hwnd, IDC_COMMENTEDIT,
			   *state->commentptr);
	}
	/*
	 * Finally, hide the progress bar and show
	 * the key data.
	 */
	ui_set_state(hwnd, state, 2);
	state->key_exists = TRUE;

	/*
	 * If the user has imported a foreign key
	 * using the Load command, let them know.
	 * If they've used the Import command, be
	 * silent.
	 */
	if (realtype != type && !was_import_cmd) {
	    char msg[512];
	    sprintf(msg, "Successfully imported foreign key\n"
		    "(%s).\n"
		    "To use this key with PuTTY, you need to\n"
		    "use the \"Save private key\" command to\n"
		    "save it in PuTTY's own format.",
		    key_type_to_str(realtype));
	    MessageBox(NULL, msg, "PuTTYgen Notice",
		       MB_OK | MB_ICONINFORMATION);
	}
    }
    burnstr(passphrase);
}
Example #4
0
/*
 * Update the visible key list.
 */
void keylist_update(void)
{
  struct RSAKey *rkey;
  struct ssh2_userkey *skey;
  int i;

  if (keylist) {
    SendDlgItemMessage(keylist, 100, LB_RESETCONTENT, 0, 0);
    for (i = 0; NULL != (rkey = pageant_nth_ssh1_key(i)); i++) {
      char listentry[512], *p;
      /*
       * Replace two spaces in the fingerprint with tabs, for
       * nice alignment in the box.
       */
      strcpy(listentry, "ssh1\t");
      p = listentry + strlen(listentry);
      rsa_fingerprint(p, sizeof(listentry) - (p - listentry), rkey);
      p = strchr(listentry, ' ');
      if (p)
        *p = '\t';
      p = strchr(listentry, ' ');
      if (p)
        *p = '\t';
      SendDlgItemMessage(keylist, 100, LB_ADDSTRING, 0, (LPARAM)listentry);
    }
    for (i = 0; NULL != (skey = pageant_nth_ssh2_key(i)); i++) {
      char *listentry, *p;
      int pos;

      /*
       * For nice alignment in the list box, we would ideally
       * want every entry to align to the tab stop settings, and
       * have a column for algorithm name, one for bit count,
       * one for hex fingerprint, and one for key comment.
       *
       * Unfortunately, some of the algorithm names are so long
       * that they overflow into the bit-count field.
       * Fortunately, at the moment, those are _precisely_ the
       * algorithm names that don't need a bit count displayed
       * anyway (because for NIST-style ECDSA the bit count is
       * mentioned in the algorithm name, and for ssh-ed25519
       * there is only one possible value anyway). So we fudge
       * this by simply omitting the bit count field in that
       * situation.
       *
       * This is fragile not only in the face of further key
       * types that don't follow this pattern, but also in the
       * face of font metrics changes - the Windows semantics
       * for list box tab stops is that \t aligns to the next
       * one you haven't already exceeded, so I have to guess
       * when the key type will overflow past the bit-count tab
       * stop and leave out a tab character. Urgh.
       */

      p = ssh2_fingerprint(skey->alg, skey->data);
      listentry = dupprintf("%s\t%s", p, skey->comment);
      sfree(p);

      pos = 0;
      while (1) {
        pos += strcspn(listentry + pos, " :");
        if (listentry[pos] == ':' || !listentry[pos])
          break;
        listentry[pos++] = '\t';
      }
      if (skey->alg != &ssh_dss && skey->alg != &ssh_rsa) {
        /*
         * Remove the bit-count field, which is between the
         * first and second \t.
         */
        int outpos;
        pos = 0;
        while (listentry[pos] && listentry[pos] != '\t')
          pos++;
        outpos = pos;
        pos++;
        while (listentry[pos] && listentry[pos] != '\t')
          pos++;
        while (1) {
          if ((listentry[outpos] = listentry[pos]) == '\0')
            break;
          outpos++;
          pos++;
        }
      }

      SendDlgItemMessage(keylist, 100, LB_ADDSTRING, 0, (LPARAM)listentry);
      sfree(listentry);
    }
    SendDlgItemMessage(keylist, 100, LB_SETCURSEL, (WPARAM)-1, 0);
  }
}