⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cmdgen.c

📁 远程登陆工具软件源码 用于远程登陆unix
💻 C
📖 第 1 页 / 共 3 页
字号:
	     * _public_ key file, thus not needing to trust even
	     * your encrypted private key file to the network. Ooh!
	     */

	  case SSH_KEYTYPE_UNOPENABLE:
	  case SSH_KEYTYPE_UNKNOWN:
	    fprintf(stderr, "puttygen: unable to load file `%s': %s\n",
		    infile, key_type_to_str(intype));
	    return 1;

	  case SSH_KEYTYPE_SSH1:
	    if (sshver == 2) {
		fprintf(stderr, "puttygen: conversion from SSH1 to SSH2 keys"
			" not supported\n");
		return 1;
	    }
	    sshver = 1;
	    break;

	  case SSH_KEYTYPE_SSH2:
	  case SSH_KEYTYPE_OPENSSH:
	  case SSH_KEYTYPE_SSHCOM:
	    if (sshver == 1) {
		fprintf(stderr, "puttygen: conversion from SSH2 to SSH1 keys"
			" not supported\n");
		return 1;
	    }
	    sshver = 2;
	    break;
	}
    }

    /*
     * Determine the default output file, if none is provided.
     * 
     * This will usually be equal to stdout, except that if the
     * input and output file formats are the same then the default
     * output is to overwrite the input.
     * 
     * Also in this code, we bomb out if the input and output file
     * formats are the same and no other action is performed.
     */
    if ((intype == SSH_KEYTYPE_SSH1 && outtype == PRIVATE) ||
	(intype == SSH_KEYTYPE_SSH2 && outtype == PRIVATE) ||
	(intype == SSH_KEYTYPE_OPENSSH && outtype == OPENSSH) ||
	(intype == SSH_KEYTYPE_SSHCOM && outtype == SSHCOM)) {
	if (!outfile) {
	    outfile = infile;
	    outfiletmp = dupcat(outfile, ".tmp", NULL);
	}

	if (!change_passphrase && !comment) {
	    fprintf(stderr, "puttygen: this command would perform no useful"
		    " action\n");
	    return 1;
	}
    } else {
	if (!outfile) {
	    /*
	     * Bomb out rather than automatically choosing to write
	     * a private key file to stdout.
	     */
	    if (outtype==PRIVATE || outtype==OPENSSH || outtype==SSHCOM) {
		fprintf(stderr, "puttygen: need to specify an output file\n");
		return 1;
	    }
	}
    }

    /*
     * Figure out whether we need to load the encrypted part of the
     * key. This will be the case if either (a) we need to write
     * out a private key format, or (b) the entire input key file
     * is encrypted.
     */
    if (outtype == PRIVATE || outtype == OPENSSH || outtype == SSHCOM ||
	intype == SSH_KEYTYPE_OPENSSH || intype == SSH_KEYTYPE_SSHCOM)
	load_encrypted = TRUE;
    else
	load_encrypted = FALSE;

    /* ------------------------------------------------------------------
     * Now we're ready to actually do some stuff.
     */

    /*
     * Either load or generate a key.
     */
    if (keytype != NOKEYGEN) {
	char *entropy;
	char default_comment[80];
	time_t t;
	struct tm *tm;
	struct progress prog;

	prog.phase = -1;
	prog.current = -1;

	time(&t);
	tm = localtime(&t);
	if (keytype == DSA)
	    strftime(default_comment, 30, "dsa-key-%Y%m%d", tm);
	else
	    strftime(default_comment, 30, "rsa-key-%Y%m%d", tm);

	random_init();
	entropy = get_random_data(bits / 8);
	random_add_heavynoise(entropy, bits / 8);
	memset(entropy, 0, bits/8);
	sfree(entropy);

	if (keytype == DSA) {
	    struct dss_key *dsskey = snew(struct dss_key);
	    dsa_generate(dsskey, bits, progressfn, &prog);
	    ssh2key = snew(struct ssh2_userkey);
	    ssh2key->data = dsskey;
	    ssh2key->alg = &ssh_dss;
	    ssh1key = NULL;
	} else {
	    struct RSAKey *rsakey = snew(struct RSAKey);
	    rsa_generate(rsakey, bits, progressfn, &prog);
	    rsakey->comment = NULL;
	    if (keytype == RSA1) {
		ssh1key = rsakey;
	    } else {
		ssh2key = snew(struct ssh2_userkey);
		ssh2key->data = rsakey;
		ssh2key->alg = &ssh_rsa;
	    }
	}
	progressfn(&prog, PROGFN_PROGRESS, INT_MAX, -1);

	if (ssh2key)
	    ssh2key->comment = dupstr(default_comment);
	if (ssh1key)
	    ssh1key->comment = dupstr(default_comment);

    } else {
	const char *error = NULL;
	int encrypted;

	assert(infile != NULL);

	/*
	 * Find out whether the input key is encrypted.
	 */
	if (intype == SSH_KEYTYPE_SSH1)
	    encrypted = rsakey_encrypted(&infilename, &origcomment);
	else if (intype == SSH_KEYTYPE_SSH2)
	    encrypted = ssh2_userkey_encrypted(&infilename, &origcomment);
	else
	    encrypted = import_encrypted(&infilename, intype, &origcomment);

	/*
	 * If so, ask for a passphrase.
	 */
	if (encrypted && load_encrypted) {
	    passphrase = snewn(512, char);
	    if (!console_get_line("Enter passphrase to load key: ",
				  passphrase, 512, TRUE)) {
		perror("puttygen: unable to read passphrase");
		return 1;
	    }
	} else {
	    passphrase = NULL;
	}

	switch (intype) {
	    int ret;

	  case SSH_KEYTYPE_SSH1:
	    ssh1key = snew(struct RSAKey);
	    if (!load_encrypted) {
		void *vblob;
		char *blob;
		int n, l, bloblen;

		ret = rsakey_pubblob(&infilename, &vblob, &bloblen, &error);
		blob = (char *)vblob;

		n = 4;		       /* skip modulus bits */
		
		l = ssh1_read_bignum(blob + n, bloblen - n,
				     &ssh1key->exponent);
		if (l < 0) {
		    error = "SSH1 public key blob was too short";
		} else {
		    n += l;
		    l = ssh1_read_bignum(blob + n, bloblen - n,
					 &ssh1key->modulus);
		    if (l < 0) {
			error = "SSH1 public key blob was too short";
		    } else
			n += l;
		}
		ssh1key->comment = NULL;
		ssh1key->private_exponent = NULL;
	    } else {
		ret = loadrsakey(&infilename, ssh1key, passphrase, &error);
	    }
	    if (ret > 0)
		error = NULL;
	    else if (!error)
		error = "unknown error";
	    break;

	  case SSH_KEYTYPE_SSH2:
	    if (!load_encrypted) {
		ssh2blob = ssh2_userkey_loadpub(&infilename, &ssh2alg,
						&ssh2bloblen, &error);
		ssh2algf = find_pubkey_alg(ssh2alg);
		if (ssh2algf)
		    bits = ssh2algf->pubkey_bits(ssh2blob, ssh2bloblen);
		else
		    bits = -1;
	    } else {
		ssh2key = ssh2_load_userkey(&infilename, passphrase, &error);
	    }
	    if ((ssh2key && ssh2key != SSH2_WRONG_PASSPHRASE) || ssh2blob)
		error = NULL;
	    else if (!error) {
		if (ssh2key == SSH2_WRONG_PASSPHRASE)
		    error = "wrong passphrase";
		else
		    error = "unknown error";
	    }
	    break;

	  case SSH_KEYTYPE_OPENSSH:
	  case SSH_KEYTYPE_SSHCOM:
	    ssh2key = import_ssh2(&infilename, intype, passphrase);
	    if (ssh2key && ssh2key != SSH2_WRONG_PASSPHRASE)
		error = NULL;
	    else if (!error) {
		if (ssh2key == SSH2_WRONG_PASSPHRASE)
		    error = "wrong passphrase";
		else
		    error = "unknown error";
	    }
	    break;

	  default:
	    assert(0);
	}

	if (error) {
	    fprintf(stderr, "puttygen: error loading `%s': %s\n",
		    infile, error);
	    return 1;
	}
    }

    /*
     * Change the comment if asked to.
     */
    if (comment) {
	if (sshver == 1) {
	    assert(ssh1key);
	    sfree(ssh1key->comment);
	    ssh1key->comment = dupstr(comment);
	} else {
	    assert(ssh2key);
	    sfree(ssh2key->comment);
	    ssh2key->comment = dupstr(comment);
	}
    }

    /*
     * Prompt for a new passphrase if we have been asked to, or if
     * we have just generated a key.
     */
    if (change_passphrase || keytype != NOKEYGEN) {
	char *passphrase2;

	if (passphrase) {
	    memset(passphrase, 0, strlen(passphrase));
	    sfree(passphrase);
	}

	passphrase = snewn(512, char);
	passphrase2 = snewn(512, char);
	if (!console_get_line("Enter passphrase to save key: ",
			      passphrase, 512, TRUE) ||
	    !console_get_line("Re-enter passphrase to verify: ",
			      passphrase2, 512, TRUE)) {
	    perror("puttygen: unable to read new passphrase");
	    return 1;
	}
	if (strcmp(passphrase, passphrase2)) {
	    fprintf(stderr, "puttygen: passphrases do not match\n");
	    return 1;
	}
	memset(passphrase2, 0, strlen(passphrase2));
	sfree(passphrase2);
	if (!*passphrase) {
	    sfree(passphrase);
	    passphrase = NULL;
	}
    }

    /*
     * Write output.
     * 
     * (In the case where outfile and outfiletmp are both NULL,
     * there is no semantic reason to initialise outfilename at
     * all; but we have to write _something_ to it or some compiler
     * will probably complain that it might be used uninitialised.)
     */
    if (outfiletmp)
	outfilename = filename_from_str(outfiletmp);
    else
	outfilename = filename_from_str(outfile ? outfile : "");

    switch (outtype) {
	int ret;

      case PRIVATE:
	if (sshver == 1) {
	    assert(ssh1key);
	    ret = saversakey(&outfilename, ssh1key, passphrase);
	    if (!ret) {
		fprintf(stderr, "puttygen: unable to save SSH1 private key\n");
		return 1;
	    }
	} else {
	    assert(ssh2key);
	    ret = ssh2_save_userkey(&outfilename, ssh2key, passphrase);
 	    if (!ret) {
		fprintf(stderr, "puttygen: unable to save SSH2 private key\n");
		return 1;
	    }
	}
	if (outfiletmp) {
	    if (!move(outfiletmp, outfile))
		return 1;	       /* rename failed */
	}
	break;

      case PUBLIC:
      case PUBLICO:
	if (sshver == 1) {
	    FILE *fp;
	    char *dec1, *dec2;

	    assert(ssh1key);

	    if (outfile)
		fp = f_open(outfilename, "w");
	    else
		fp = stdout;
	    dec1 = bignum_decimal(ssh1key->exponent);
	    dec2 = bignum_decimal(ssh1key->modulus);
	    fprintf(fp, "%d %s %s %s\n", bignum_bitcount(ssh1key->modulus),
		    dec1, dec2, ssh1key->comment);
	    sfree(dec1);
	    sfree(dec2);
	    if (outfile)
		fclose(fp);
	} else if (outtype == PUBLIC) {
	    if (!ssh2blob) {
		assert(ssh2key);
		ssh2blob = ssh2key->alg->public_blob(ssh2key->data,
						     &ssh2bloblen);
	    }
	    save_ssh2_pubkey(outfile, ssh2key ? ssh2key->comment : origcomment,
			     ssh2blob, ssh2bloblen);
	} else if (outtype == PUBLICO) {
	    char *buffer, *p;
	    int i;
	    FILE *fp;

	    if (!ssh2blob) {
		assert(ssh2key);
		ssh2blob = ssh2key->alg->public_blob(ssh2key->data,
						     &ssh2bloblen);
	    }
	    if (!ssh2alg) {
		assert(ssh2key);
		ssh2alg = ssh2key->alg->name;
	    }
	    if (ssh2key)
		comment = ssh2key->comment;
	    else
		comment = origcomment;

	    buffer = snewn(strlen(ssh2alg) +
			   4 * ((ssh2bloblen+2) / 3) +
			   strlen(comment) + 3, char);
	    strcpy(buffer, ssh2alg);
	    p = buffer + strlen(buffer);
	    *p++ = ' ';
	    i = 0;
	    while (i < ssh2bloblen) {
		int n = (ssh2bloblen - i < 3 ? ssh2bloblen - i : 3);
		base64_encode_atom(ssh2blob + i, n, p);
		i += n;
		p += 4;
	    }
	    if (*comment) {
		*p++ = ' ';
		strcpy(p, comment);
	    } else
		*p++ = '\0';

	    if (outfile)
		fp = f_open(outfilename, "w");
	    else
		fp = stdout;
	    fprintf(fp, "%s\n", buffer);
	    if (outfile)
		fclose(fp);

	    sfree(buffer);
	}
	break;

      case FP:
	{
	    FILE *fp;
	    char *fingerprint;

	    if (sshver == 1) {
		assert(ssh1key);
		fingerprint = snewn(128, char);
		rsa_fingerprint(fingerprint, 128, ssh1key);
	    } else {
		if (ssh2key) {
		    fingerprint = ssh2key->alg->fingerprint(ssh2key->data);
		} else {
		    assert(ssh2blob);
		    fingerprint = blobfp(ssh2alg, bits, ssh2blob, ssh2bloblen);
		}
	    }

	    if (outfile)
		fp = f_open(outfilename, "w");
	    else
		fp = stdout;
	    fprintf(fp, "%s\n", fingerprint);
	    if (outfile)
		fclose(fp);

	    sfree(fingerprint);
	}
	break;
	
      case OPENSSH:
      case SSHCOM:
	assert(sshver == 2);
	assert(ssh2key);
	ret = export_ssh2(&outfilename, outtype, ssh2key, passphrase);
	if (!ret) {
	    fprintf(stderr, "puttygen: unable to export key\n");
	    return 1;
	}
	if (outfiletmp) {
	    if (!move(outfiletmp, outfile))
		return 1;	       /* rename failed */
	}
	break;
    }

    if (passphrase) {
	memset(passphrase, 0, strlen(passphrase));
	sfree(passphrase);
    }

    if (ssh1key)
	freersakey(ssh1key);
    if (ssh2key) {
	ssh2key->alg->freekey(ssh2key->data);
	sfree(ssh2key);
    }

    return 0;
}

#ifdef TEST_CMDGEN

#undef main

#include <stdarg.h>

int passes, fails;

void setup_passphrases(char *first, ...)
{
    va_list ap;
    char *next;

    nprompts = 0;
    if (first) {
	prompts[nprompts++] = first;
	va_start(ap, first);
	while ((next = va_arg(ap, char *)) != NULL) {
	    assert(nprompts < lenof(prompts));
	    prompts[nprompts++] = next;
	}
	va_end(ap);
    }
}

void test(int retval, ...)
{
    va_list ap;
    int i, argc, ret;
    char **argv;

    argc = 0;
    va_start(ap, retval);
    while (va_arg(ap, char *) != NULL)
	argc++;
    va_end(ap);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -