diff --git a/examples/keygen2.c b/examples/keygen2.c index 8cab1077..82aae7e9 100644 --- a/examples/keygen2.c +++ b/examples/keygen2.c @@ -38,6 +38,7 @@ struct arguments_st { unsigned long bits; char *file; char *passphrase; + int action_list; }; static struct argp_option options[] = { @@ -88,6 +89,14 @@ static struct argp_option options[] = { "\"rsa\", \"ecdsa\", \"ed25519\", and \"dsa\".\n", .group = 0 }, + { + .name = "list", + .key = 'l', + .arg = NULL, + .flags = 0, + .doc = "List the Fingerprint of the given key\n", + .group = 0 + }, { /* End of the options */ 0 @@ -160,6 +169,9 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) goto end; } break; + case 'l': + arguments->action_list = 1; + break; case ARGP_KEY_ARG: if (state->arg_num > 0) { /* Too many arguments. */ @@ -185,98 +197,103 @@ static int validate_args(struct arguments_st *args) return EINVAL; } - switch(args->type) { - case SSH_KEYTYPE_RSA: - switch(args->bits) { - case 0: - /* If not provided, use default value */ - args->bits = 3072; - break; - case 1024: - case 2048: - case 3072: - case 4096: - case 8192: - break; - default: - fprintf(stderr, "Error: Invalid bits parameter provided\n"); - rc = EINVAL; - break; - } - - if (args->file == NULL) { - args->file = strdup("id_rsa"); - if (args->file == NULL) { - rc = ENOMEM; - break; - } - } + /* no other arguments needed for listing key fingerprints */ + if (args->action_list) { + return 0; + } + switch (args->type) { + case SSH_KEYTYPE_RSA: + switch (args->bits) { + case 0: + /* If not provided, use default value */ + args->bits = 3072; break; - case SSH_KEYTYPE_ECDSA: - switch(args->bits) { - case 0: - /* If not provided, use default value */ - args->bits = 256; - break; - case 256: - case 384: - case 521: - break; - default: - fprintf(stderr, "Error: Invalid bits parameter provided\n"); - rc = EINVAL; - break; - } - if (args->file == NULL) { - args->file = strdup("id_ecdsa"); - if (args->file == NULL) { - rc = ENOMEM; - break; - } - } - - break; - case SSH_KEYTYPE_DSS: - switch(args->bits) { - case 0: - /* If not provided, use default value */ - args->bits = 1024; - break; - case 1024: - case 2048: - break; - default: - fprintf(stderr, "Error: Invalid bits parameter provided\n"); - rc = EINVAL; - break; - } - if (args->file == NULL) { - args->file = strdup("id_dsa"); - if (args->file == NULL) { - rc = ENOMEM; - break; - } - } - - break; - case SSH_KEYTYPE_ED25519: - /* Ignore value and overwrite with a zero */ - args->bits = 0; - - if (args->file == NULL) { - args->file = strdup("id_ed25519"); - if (args->file == NULL) { - rc = ENOMEM; - break; - } - } - + case 1024: + case 2048: + case 3072: + case 4096: + case 8192: break; default: - fprintf(stderr, "Error: unknown key type\n"); + fprintf(stderr, "Error: Invalid bits parameter provided\n"); rc = EINVAL; break; + } + + if (args->file == NULL) { + args->file = strdup("id_rsa"); + if (args->file == NULL) { + rc = ENOMEM; + break; + } + } + + break; + case SSH_KEYTYPE_ECDSA: + switch (args->bits) { + case 0: + /* If not provided, use default value */ + args->bits = 256; + break; + case 256: + case 384: + case 521: + break; + default: + fprintf(stderr, "Error: Invalid bits parameter provided\n"); + rc = EINVAL; + break; + } + if (args->file == NULL) { + args->file = strdup("id_ecdsa"); + if (args->file == NULL) { + rc = ENOMEM; + break; + } + } + + break; + case SSH_KEYTYPE_DSS: + switch (args->bits) { + case 0: + /* If not provided, use default value */ + args->bits = 1024; + break; + case 1024: + case 2048: + break; + default: + fprintf(stderr, "Error: Invalid bits parameter provided\n"); + rc = EINVAL; + break; + } + if (args->file == NULL) { + args->file = strdup("id_dsa"); + if (args->file == NULL) { + rc = ENOMEM; + break; + } + } + + break; + case SSH_KEYTYPE_ED25519: + /* Ignore value and overwrite with a zero */ + args->bits = 0; + + if (args->file == NULL) { + args->file = strdup("id_ed25519"); + if (args->file == NULL) { + rc = ENOMEM; + break; + } + } + + break; + default: + fprintf(stderr, "Error: unknown key type\n"); + rc = EINVAL; + break; } return rc; @@ -289,6 +306,31 @@ static char doc[] = "Generate an SSH key pair. " /* Our argp parser */ static struct argp argp = {options, parse_opt, NULL, doc, NULL, NULL, NULL}; +static void +list_fingerprint(char *file) +{ + ssh_key key = NULL; + unsigned char *hash = NULL; + size_t hlen = 0; + int rc; + + rc = ssh_pki_import_privkey_file(file, NULL, NULL, NULL, &key); + if (rc != SSH_OK) { + fprintf(stderr, "Failed to import private key %s\n", file); + return; + } + + rc = ssh_get_publickey_hash(key, SSH_PUBLICKEY_HASH_SHA256, &hash, &hlen); + if (rc != SSH_OK) { + fprintf(stderr, "Failed to get key fingerprint\n"); + return; + } + ssh_print_hash(SSH_PUBLICKEY_HASH_SHA256, hash, hlen); + + ssh_clean_pubkey_hash(&hash); + ssh_key_free(key); +} + int main(int argc, char *argv[]) { ssh_key key = NULL; @@ -302,6 +344,7 @@ int main(int argc, char *argv[]) .bits = 0, .file = NULL, .passphrase = NULL, + .action_list = 0, }; if (argc < 2) { @@ -319,6 +362,11 @@ int main(int argc, char *argv[]) goto end; } + if (arguments.action_list && arguments.file) { + list_fingerprint(arguments.file); + goto end; + } + errno = 0; rc = open(arguments.file, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR); if (rc < 0) {