From 0767e55e55336a2e7bb52d28f95a341a63562070 Mon Sep 17 00:00:00 2001 From: TLINDEN Date: Sun, 2 Mar 2014 18:04:54 +0100 Subject: [PATCH] added -L, enhanced -E --- src/keymgmt.c | 63 ++++++++++++++--- src/keyprint.c | 55 ++++++++++++++- src/pcp.c | 42 ++++++++---- tests/decodertest.c | 164 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 301 insertions(+), 23 deletions(-) create mode 100644 tests/decodertest.c diff --git a/src/keymgmt.c b/src/keymgmt.c index 34017e0..ad3d67d 100644 --- a/src/keymgmt.c +++ b/src/keymgmt.c @@ -120,7 +120,7 @@ void pcp_listkeys() { int nkeys = HASH_COUNT(pcpkey_hash) + HASH_COUNT(pcppubkey_hash); if(nkeys > 0) { - printf("Key ID Type Creation Time Owner\n"); + printf("Key ID Type Creation Time Owner\n"); pcphash_iterate(k) { pcpkey_printlineinfo(k); @@ -600,31 +600,76 @@ void pcpdelete_key(char *keyid) { void pcpedit_key(char *keyid) { pcp_key_t *key = pcphash_keyexists(keyid); - + if(key != NULL) { if(key->secret[0] == 0) { char *passphrase; pcp_readpass(&passphrase, "Enter passphrase to decrypt the key", NULL, 1); key = pcpkey_decrypt(key, passphrase); + ucfree(passphrase, strlen(passphrase)); } if(key != NULL) { - char *owner = pcp_getstdin("Enter the name of the key owner"); - memcpy(key->owner, owner, strlen(owner) + 1); + fprintf(stderr, "Current owner: %s\n", key->owner); + char *owner = pcp_getstdin(" enter new name or press enter to keep current"); + if(strlen(owner) > 0) + memcpy(key->owner, owner, strlen(owner) + 1); - char *mail = pcp_getstdin("Enter the email address of the key owner"); - memcpy(key->mail, mail, strlen(mail) + 1); + fprintf(stderr, "Current mail: %s\n", key->mail); + char *mail = pcp_getstdin(" enter new email or press enter to keep current"); + if(strlen(mail) > 0) + memcpy(key->mail, mail, strlen(mail) + 1); + + free(owner); + free(mail); + + if(key->type != PCP_KEY_TYPE_MAINSECRET) { + pcp_key_t *other = NULL; + uint8_t haveprimary = 0; + pcphash_iterate(other) { + if(other->type == PCP_KEY_TYPE_MAINSECRET) { + haveprimary = 1; + break; + } + } + + char *yes = NULL; + if(! haveprimary) { + fprintf(stderr, "There is currently no primary secret in your vault,\n"); + yes = pcp_getstdin("want to make this one the primary [yes|NO]?"); + } + else { + fprintf(stderr, "The key %s is currently the primary secret,\n", other->id); + yes = pcp_getstdin("want to make this one the primary instead [yes|NO]?"); + } + + if(strncmp(yes, "yes", 1024) == 0) { + key->type = PCP_KEY_TYPE_MAINSECRET; + if(haveprimary) { + fprintf(stderr, "other type: %d\n", other->type); + other->type = PCP_KEY_TYPE_SECRET; + fprintf(stderr, " new type: %d\n", other->type); + } + } + free(yes); + } char *passphrase; - pcp_readpass(&passphrase, "Enter passphrase for key encryption", NULL, 1); - key = pcpkey_encrypt(key, passphrase); + pcp_readpass(&passphrase, + "Enter new passphrase for key encryption (press enter to keep current)", + "Enter the passphrase again", 1); + + if(strnlen(passphrase, 1024) > 0) { + key = pcpkey_encrypt(key, passphrase); + ucfree(passphrase, strlen(passphrase)); + } if(key != NULL) { if(debug) pcp_dumpkey(key); vault->unsafed = 1; /* will be safed automatically */ - fprintf(stderr, "Key key changed.\n"); + fprintf(stderr, "Key %s changed.\n", key->id); } } } diff --git a/src/keyprint.c b/src/keyprint.c index 39c8ce2..e9cf2c9 100644 --- a/src/keyprint.c +++ b/src/keyprint.c @@ -123,21 +123,72 @@ void pcpkey_printlineinfo(pcp_key_t *key) { c = localtime(&t); printf("0x%s %s %04d-%02d-%02dT%02d:%02d:%02d %s <%s>\n", key->id, - (key->type == PCP_KEY_TYPE_MAINSECRET) ? "primary" : " secret", + (key->type == PCP_KEY_TYPE_MAINSECRET) ? "primary secret" : "secret ", c->tm_year+1900, c->tm_mon+1, c->tm_mday, c->tm_hour, c->tm_min, c->tm_sec, key->owner, key->mail); + + if(PCPVERBOSE) { + printf(" "); + byte *hash = pcpkey_getchecksum(key); + int i, y; + for(i=0; i<32; i+=4) { + for(y=0; y<4; y++) { + printf("%02x", hash[i+y]); + } + printf(" "); + } + free(hash); + printf("\n encrypted: %s, serial: %08x, version: %d\n", + (key->secret[0] == '\0') ? "yes" : " no", + key->serial, (int)key->version); + printf("\n"); + } } void pcppubkey_printlineinfo(pcp_pubkey_t *key) { struct tm *c; time_t t = (time_t)key->ctime; c = localtime(&t); - printf("0x%s public %04d-%02d-%02dT%02d:%02d:%02d %s <%s>\n", + printf("0x%s %s %04d-%02d-%02dT%02d:%02d:%02d %s <%s>\n", key->id, + (key->valid == 1) ? "valid public " : "public ", c->tm_year+1900, c->tm_mon+1, c->tm_mday, c->tm_hour, c->tm_min, c->tm_sec, key->owner, key->mail); + + if(PCPVERBOSE) { + printf(" "); + byte *hash = pcppubkey_getchecksum(key); + int i, y; + for(i=0; i<32; i+=4) { + for(y=0; y<4; y++) { + printf("%02x", hash[i+y]); + } + printf(" "); + } + free(hash); + printf("\n signed: %s, serial: %08x, version: %d, ", + (key->valid == 1) ? "yes" : " no", + key->serial, (int)key->version); + pcp_keysig_t *sig = pcphash_keysigexists(key->id); + if(sig != NULL) { + printf("signature fingerprint:\n "); + byte *checksum = sig->checksum; + for(i=0; i<32; i+=4) { + for(y=0; y<4; y++) { + printf("%02x", checksum[i+y]); + } + printf(" "); + } + printf("\n"); + } + else { + printf("fail: no signature stored.\n"); + } + + printf("\n"); + } } void pcppubkey_print(pcp_pubkey_t *key, FILE* out) { diff --git a/src/pcp.c b/src/pcp.c index b2819e5..4c11803 100644 --- a/src/pcp.c +++ b/src/pcp.c @@ -71,6 +71,8 @@ int main (int argc, char **argv) { signcrypt = 0; exportformat = EXP_FORMAT_NATIVE; + PCPVERBOSE = 0; + static struct option longopts[] = { /* generics */ { "vault", required_argument, NULL, 'V' }, @@ -84,27 +86,33 @@ int main (int argc, char **argv) { /* key management */ { "keygen", no_argument, NULL, 'k' }, { "listkeys", no_argument, NULL, 'l' }, + { "listkeys-verbose",no_argument, NULL, 'L' }, /* alias for -l -v */ { "export-secret", no_argument, NULL, 's' }, { "export-public", no_argument, NULL, 'p' }, + { "export", no_argument, NULL, 'p' }, /* alias -p */ { "import-secret", no_argument, NULL, 'S' }, { "import-public", no_argument, NULL, 'P' }, + { "import", no_argument, NULL, 'P' }, /* alias -P */ { "remove-key", no_argument, NULL, 'R' }, { "edit-key", no_argument, NULL, 'E' }, { "export-yaml", no_argument, NULL, 'y' }, { "export-format", required_argument, NULL, 'F' }, /* crypto */ - { "encrypt", no_argument, NULL, 'e' }, - { "encrypt-me", no_argument, NULL, 'm' }, - { "decrypt", no_argument, NULL, 'd' }, + { "encrypt", no_argument, NULL, 'e' }, + { "encrypt-me", no_argument, NULL, 'm' }, + { "decrypt", no_argument, NULL, 'd' }, /* encoding */ - { "z85-encode", no_argument, NULL, 'z' }, - { "z85-decode", no_argument, NULL, 'Z' }, + { "z85-encode", no_argument, NULL, 'z' }, + { "armor", no_argument, NULL, 'a' }, /* alias -z */ + { "textmode", no_argument, NULL, 'a' }, /* alias -z */ + { "z85-decode", no_argument, NULL, 'Z' }, /* globals */ { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'v' }, + { "version", no_argument, NULL, '0' }, /* no short opt, FIXME: how to avoid? */ + { "verbose", no_argument, NULL, 'v' }, { "debug", no_argument, NULL, 'D' }, /* signing */ @@ -114,7 +122,7 @@ int main (int argc, char **argv) { { NULL, 0, NULL, 0 } }; - while ((opt = getopt_long(argc, argv, "klV:vdehsO:i:I:pSPRtEx:DzZr:gcymf:b1F:", + while ((opt = getopt_long(argc, argv, "klLV:vdehsO:i:I:pSPRtEx:DzaZr:gcymf:b1F:0", longopts, NULL)) != -1) { switch (opt) { @@ -130,6 +138,8 @@ int main (int argc, char **argv) { mode += PCP_MODE_KEYGEN; usevault = 1; break; + case 'L': + PCPVERBOSE = 1; /* no break by purpose, turn on -l */ case 'l': mode += PCP_MODE_LISTKEYS; usevault = 1; @@ -175,6 +185,7 @@ int main (int argc, char **argv) { usevault = 1; break; case 'z': + case 'a': armor = 1; break; case 'Z': @@ -229,12 +240,16 @@ int main (int argc, char **argv) { strncpy(vaultfile, optarg, 1024); break; case 'O': - outfile = ucmalloc(strlen(optarg)+1); - strncpy(outfile, optarg, strlen(optarg)+1); + if(strncmp(optarg, "-", 2) > 0) { + outfile = ucmalloc(strlen(optarg)+1); + strncpy(outfile, optarg, strlen(optarg)+1); + } break; case 'I': - infile = ucmalloc(strlen(optarg)+1); - strncpy(infile, optarg, strlen(optarg)+1); + if(strncmp(optarg, "-", 2) > 0) { + infile = ucmalloc(strlen(optarg)+1); + strncpy(infile, optarg, strlen(optarg)+1); + } break; case 'i': keyid = ucmalloc(19); @@ -255,8 +270,11 @@ int main (int argc, char **argv) { case 'D': debug = 1; break; - case 'v': + case '0': version(); + case 'v': + PCPVERBOSE = 1; + break; case 'h': usage(0); default: diff --git a/tests/decodertest.c b/tests/decodertest.c new file mode 100644 index 0000000..2fb1f8c --- /dev/null +++ b/tests/decodertest.c @@ -0,0 +1,164 @@ +#include +#include +#include + +#include + +#define TRUE 1 +#define FALSE 0 + +static const char *tell[] = { + NULL, + "Headers: no, Newlines: yes, Compliant: yes", + "Headers: no, Newlines: no, Compliant: yes", + "Headers: no, Newlines: yes, Compliant: yes - no begin header", + "Headers: yes, Newlines: yes, Compliant: no - empty comment", + "Headers: yes, Newlines: yes, Compliant: no - missing z85 char", +}; + +int main(int argc, char **argv) { + int ret; + size_t clearlen = 256; + size_t zlen = (clearlen * 5 / 4); + + if(argc < 2) { + fprintf(stderr, "Usage: decodertest \n"); + return 1; + } + + int mode; + if((mode = strtol(argv[1], NULL, 0)) == 0) { + fprintf(stderr, "Error: decoder sub number %s\n", argv[1]); + return 1; + } + + byte *clear = urmalloc(256); + char *z85 = ucmalloc(zlen+1); + + /* we encode directly */ + z85 = zmq_z85_encode(z85, clear, clearlen); + + if(z85 == NULL) { + ret = FALSE; + if(PCP_ERRSET == 0) { + fatal("failed to encoded data to Z85\n"); + } + goto OUT; + } + + Buffer *Z = buffer_new(384, "z85"); + buffer_add(Z, z85, zlen); + size_t z = buffer_size(Z); + size_t i; + uint8_t c; + + Pcpstream *out = ps_new_outbuffer(); + + /* + modi: expect + 1 = no headers incl newlines ok + 2 = no headers no newlines ok + 3 = no begin header ok + 4 = headers, empty comment fail + 5 = headers, missing z char fail + */ + + /* begin header */ + if(mode > 3) { + ps_print(out, "%s\r\n", PCP_ZFILE_HEADER); + } + + /* empty comment */ + if(mode == 4) { + ps_print(out, "Version:\r\n"); + } + + /* z85 output */ + if(mode == 5) { + z--; + } + int l=0; + for (i=0; i 0) { + ps_print(out, "\r\n"); + l = 0; + } + c = buffer_get8(Z); + ps_write(out, &c, 1); + l++; + } + + /* footer */ + if(mode > 2) { + ps_print(out, "\r\n%s\r\n", PCP_ZFILE_FOOTER); + } + + /* done creating z85 file */ + Buffer *zdone = ps_buffer(out); + byte *back = NULL; + + /* control output */ + + fprintf(stderr, "%s:\n\n%s\n", tell[mode], buffer_get_str(zdone)); + + /* line decoder */ + + char *raw = pcp_readz85string(buffer_get(zdone), buffer_size(zdone)); + + if(raw == NULL) { + /* unexpected */ + ret = FALSE; + } + else { + back = pcp_z85_decode(raw, &zlen); + if(back == NULL) { + if(mode > 3) { + /* expected fail */ + ret = TRUE; + } + else { + /* expected ok */ + ret = FALSE; + } + } + else { + if(mode > 3) { + /* expected fail */ + ret = FALSE; + } + else { + /* expected ok */ + ret = TRUE; + } + } + } + + /* finally see if content matches */ + if(back != NULL) { + if(mode <= 3 && memcmp(back, clear, 256) != 0) { + ret = FALSE; + if(PCP_ERRSET == 0) { + fatal("decoded content doesn't match\n"); + } + } + } + + /* finish */ + ps_close(out); + buffer_free(Z); + if(raw != NULL) + free(raw); + if(z85 != NULL) + free(z85); + + OUT: + if(ret == TRUE) { + fprintf(stdout, "%d - ok\n", mode); + } + else { + fprintf(stdout, "%d - failed\n", mode); + fatals_ifany(); + } + + return ret; +}