diff options
author | Aaron Ball <nullspoon@oper.io> | 2018-10-29 11:07:13 -0600 |
---|---|---|
committer | Aaron Ball <nullspoon@oper.io> | 2018-10-29 11:16:10 -0600 |
commit | c7b940e9baffca703c9a54aa3b3a2ca42482751c (patch) | |
tree | 147108b043e42ddeab06d2895c7a3dbc2aed06f8 | |
parent | 8213a660ed559679badb1158edb4269618435fe0 (diff) | |
download | gpgedit-c7b940e9baffca703c9a54aa3b3a2ca42482751c.tar.gz gpgedit-c7b940e9baffca703c9a54aa3b3a2ca42482751c.tar.xz |
Support for additional recipients
Added basic support for additional recipients. This required a rewrite
of the recipient memory management. Previously, recipients were stored
in a char array, which was reallocated when a recipient was added. This
was not done globally so the user could add additional recipients at
runtime.
This adds a new gpgedit_config object that handles the file path and the
recipient list. The recipient list is now managed inside of a linked
list (how cool are those?!), allowing for appending without
reallocating. Now the recipient list is loaded from the specified file,
and any additional recipients added via the -r,--recipient switch will
be added to the list when the file is closed and re-encrypted.
Note that this adds support for the -r,--recipient switch.
This deprecates and removes the gpg_keyids.c and .h files, as they are
no longer needed (relevant code was moved to gpg.c). This also adds the
strll.c and strll.h files to handle memory management for linked lists
of char arrays.
-rw-r--r-- | TODO.adoc | 2 | ||||
-rw-r--r-- | src/gpg.c | 38 | ||||
-rw-r--r-- | src/gpg.h | 4 | ||||
-rw-r--r-- | src/gpgedit_config.c (renamed from src/gpg_keyids.c) | 69 | ||||
-rw-r--r-- | src/gpgedit_config.h (renamed from src/strarray.h) | 22 | ||||
-rw-r--r-- | src/main.c | 39 | ||||
-rw-r--r-- | src/strarray.c | 78 | ||||
-rw-r--r-- | src/strll.c | 77 | ||||
-rw-r--r-- | src/strll.h (renamed from src/gpg_keyids.h) | 27 |
9 files changed, 207 insertions, 149 deletions
@@ -10,7 +10,7 @@ Implement * [ ] Read environment variable $EDITOR, default to vim (only parse arg 0 to some avoid security concerns) * [ ] Argument parser (eg: -r,--recipient) -* [ ] Recipient addition beyond the list already in the file +* [x] Recipient addition beyond the list already in the file * [ ] Recipient removal from existing file * [ ] New file creation (at least one recipient required) * [ ] Helptext @@ -101,6 +101,37 @@ int gpg_recip_count(gpgme_recipient_t firstrecip) { } +// gpg_strll_to_key_t: +// Converts a string linked list containing keyids (multiple identifier types +// are supported) into an array of gpgme_key_t objects. +// +// @ctx GPGME context (already initialized) +// @firstrecip First linkedlist recipient item +// +// @return gpgme_key_t* Array of gpgme_key_t objects, one for each keyid string +gpgme_key_t* gpg_strll_to_key_t(gpgme_ctx_t ctx, struct strll* firstrecip) { + gpgme_key_t* out; + gpgme_error_t err; + int i = 0; + struct strll* recip = firstrecip; + + // Initialize the gpgme_key_t pointer array + out = (gpgme_key_t*) malloc(1); + out = NULL; + + // Loop over the keys back to zero + while(recip != NULL) { + out = realloc(out, sizeof(gpgme_key_t) * (i + 1)); + err = gpgme_get_key(ctx, recip->str, &out[i], 0); + gpg_failiferr(err); + recip = recip->next; + i++; + } + out[i] = NULL; + return out; +} + + void gpg_key_dump(gpgme_key_t key) { printf("Recipient: %s\n", key->fpr); printf(" protocol: %d\n", key->protocol); @@ -114,15 +145,13 @@ void gpg_key_dump(gpgme_key_t key) { printf(" can_auth: %d\n", key->can_authenticate); printf(" qualified: %d\n", key->is_qualified); printf(" secret: %d\n", key->secret); - printf(" origin: %d\n", key->origin); printf(" issuer_serial: %s\n", key->issuer_serial); printf(" issuer_name: %s\n", key->issuer_name); printf(" chain_id: %s\n", key->chain_id); - printf(" last_update: %ld\n", key->last_update); } -size_t gpg_encrypt_file(char* infile, char* outfile, char** keyids) { +size_t gpg_encrypt_file(char* infile, char* outfile, struct strll* recipll) { gpgme_ctx_t ctx; gpgme_data_t indata; gpgme_data_t outdata; @@ -141,7 +170,8 @@ size_t gpg_encrypt_file(char* infile, char* outfile, char** keyids) { gpg_failiferr(err); // Get key id objects from keyids char array - keys = gpg_keyids_to_key_t(ctx, keyids); + keys = gpg_strll_to_key_t(ctx, recipll); + // For debugging purposes // int i = 0; // while(keys[i] != NULL) { @@ -24,7 +24,7 @@ #include <gpgme.h> #include <locale.h> -#include "gpg_keyids.h" +#include "strll.h" #define READSIZE 256 @@ -34,7 +34,7 @@ gpgme_error_t init_gpg(gpgme_ctx_t*, gpgme_protocol_t); gpgme_decrypt_result_t gpg_decrypt_file(char*, char*, gpgme_ctx_t); -size_t gpg_encrypt_file(char*, char*, char**); +size_t gpg_encrypt_file(char*, char*, struct strll*); int gpg_failiferr(gpg_error_t); diff --git a/src/gpg_keyids.c b/src/gpgedit_config.c index 5b0edfe..dbf2e6b 100644 --- a/src/gpg_keyids.c +++ b/src/gpgedit_config.c @@ -13,10 +13,36 @@ // // You should have received a copy of the GNU General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. -#include "gpg_keyids.h" +#include "gpgedit_config.h" -// gpg_keyids_load_from_recip: +struct gpgedit_config* gpgedit_config_new() { + struct gpgedit_config* c = NULL; + c = malloc(sizeof(struct gpgedit_config)); + c->file = NULL; + c->recipients = strll_new(); + + return c; +} + + +void gpgedit_config_file_set(struct gpgedit_config* c, char* file) { + c->file = malloc(strlen(file) + 1); + strcpy(c->file, file); +} + + +void gpgedit_config_recipients_add(struct gpgedit_config* c, char* recipient) { + strll_add(c->recipients, recipient); +} + +void gpgedit_config_release(struct gpgedit_config* c) { + free(c->file); + strll_release(c->recipients); + free(c); +} + +// gpgedit_config_recip_from_gpgme_recip: // Converts a gpgme_recipient_t linked list to a string array of key ids. This // is useful when storing a list of recipients for an already-encrypted file to // be used when later re-encrypting that file. @@ -25,44 +51,13 @@ // to this will be updated by the array growth process. // @firstrecip First recipient in the linked list. The list will be traversed // starting here. -void gpg_keyids_load_from_recip(char*** keyids, gpgme_recipient_t firstrecip) { - gpgme_recipient_t recip; // Current recipient object +void gpgedit_config_recip_from_gpgme_recip(struct gpgedit_config* c, gpgme_recipient_t firstrecip) { + gpgme_recipient_t recip = firstrecip; // Current recipient object + // Write each recipient key id to the char array - recip = firstrecip; while(recip != NULL) { - strarray_add(keyids, recip->keyid); + strll_add(c->recipients, recip->keyid); recip = recip->next; } } - -// gpg_keyids_to_key_t: -// Converts a string array containing keyids (multiple identifier types are -// supported) into an array of gpgme_key_t objects. -// -// @ctx GPGME context (already initialized) -// @keyids Pointer to string array of key id strings -// -// @return gpgme_key_t* Array of gpgme_key_t objects, one for each keyid string -gpgme_key_t* gpg_keyids_to_key_t(gpgme_ctx_t ctx, char** keyids) { - gpgme_key_t* out; - gpgme_error_t err; - int count = 0; // Number of recipients - int i = 0; - - // Count the keys - while(keyids[count] != NULL) - count++; - - // Allocate the gpgme_key_t pointer array - out = (gpgme_key_t*) malloc(sizeof(gpgme_key_t) * (count + 1)); - - // Loop over the keys back to zero - while(i < count) { - err = gpgme_get_key(ctx, keyids[i], &out[i], 0); - gpg_failiferr(err); - i++; - } - out[i] = NULL; - return out; -} diff --git a/src/strarray.h b/src/gpgedit_config.h index 69d91a4..1c74a29 100644 --- a/src/strarray.h +++ b/src/gpgedit_config.h @@ -13,15 +13,21 @@ // // You should have received a copy of the GNU General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. -#ifndef GPGEDIT_STRARRAY_H -#define GPGEDIT_STRARRAY_H -#include <stdio.h> -#include <stdlib.h> +#include <gpgme.h> #include <string.h> -char** strarray_new(); -void strarray_add(char***, char*); -void strarray_release(char***); +#include "strll.h" -#endif +struct gpgedit_config { + char* file; // File path to be edited + struct strll* recipients; // Pointer to first item in the linked list + struct gpgme_key_t* keys; +}; + +struct gpgedit_config* gpgedit_config_new(); +void gpgedit_config_file_set(struct gpgedit_config*, char*); +void gpgedit_config_recipients_set(struct gpgedit_config*, char**); +void gpgedit_config_recipients_add(struct gpgedit_config*, char*); +void gpgedit_config_release(struct gpgedit_config*); +void gpgedit_config_recip_from_gpgme_recip(struct gpgedit_config* c, gpgme_recipient_t firstrecip); @@ -21,8 +21,8 @@ #include <gpgme.h> #include "gpg.h" -#include "gpg_keyids.h" -#include "strarray.h" +#include "gpgedit_config.h" +#include "strll.h" void system_edit(char* file) { char cmd[256]; // Buffer for editor command @@ -31,17 +31,36 @@ void system_edit(char* file) { } +void parseargs(int argc, char* argv[], struct gpgedit_config* config) { + int i = 1; + + while(i < argc) { + if(strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "--recipient") == 0) { + i++; + //printf("Adding recipient %s\n", argv[i]); + strll_add(config->recipients, argv[i]); + } else { + gpgedit_config_file_set(config, argv[i]); + } + i++; + } +} + + int main(int argc, char* argv[]) { char tmpfile[32] = "/tmp/gpgedit-XXXXXX"; gpgme_ctx_t decctx; gpgme_error_t err; - char** keyids; + struct gpgedit_config* config; if(argc == 1) { printf("Please specify a gpg encrypted file to edit\n"); return 1; } + config = gpgedit_config_new(); + parseargs(argc, argv, config); + // Initialize decryption context, create tmp file to write decrypted contents // to, and run decryption operation. err = init_gpg(&decctx, GPGME_PROTOCOL_OPENPGP); @@ -51,22 +70,24 @@ int main(int argc, char* argv[]) { } mkstemp(tmpfile); - gpgme_decrypt_result_t res = gpg_decrypt_file(argv[1], tmpfile, decctx); + gpgme_decrypt_result_t res = gpg_decrypt_file(config->file, tmpfile, decctx); // Get keyids array from recipients list - keyids = strarray_new(); - gpg_keyids_load_from_recip(&keyids, res->recipients); + gpgedit_config_recip_from_gpgme_recip(config, res->recipients); // Freedom! gpgme_release(decctx); // Open the system editor system_edit(tmpfile); + printf("Recipients:\n"); + strll_dump(config->recipients); + // Re-encrypt the plaintext tmp file - //printf("Re-encrypting file '%s' -> '%s'\n", tmpfile, argv[1]); - gpg_encrypt_file(tmpfile, argv[1], keyids); + //printf("Re-encrypting file '%s' -> '%s'\n", tmpfile, config->file); + gpg_encrypt_file(tmpfile, config->file, config->recipients); // Clean up tmpfile - strarray_release(&keyids); + gpgedit_config_release(config); unlink(tmpfile); return 0; } diff --git a/src/strarray.c b/src/strarray.c deleted file mode 100644 index 12ddbf8..0000000 --- a/src/strarray.c +++ /dev/null @@ -1,78 +0,0 @@ -// GPGEdit edits GPG encrypted files -// Copyright (C) 2018 Aaron Ball <nullspoon@oper.io> -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. -#include "strarray.h" - - -// strarray_new: -// Pretty much useless constructor. Here mostly for consistency. This can -// easily be replaced with your own malloc statement provided index 0 is set to -// NULL. -// -// NOTE: If not using this, initialized memory *must* be allocated in the heap, -// as growing the string array requires reallocating the memory, which -// can't be done in the stack. -char** strarray_new() { - char** out = malloc(sizeof(char*)); - out[0] = NULL; - return out; -} - - -// strarray_add: -// Dynamically grows a string array (pointer to char array containing pointers -// to char arrays - sorry). Reallocates storage for the original array plus -// room for one additional pointer. Once data is copied in, the source array -// pointer is updated to point to the new storage. -// -// @strorig Source string array pointer -// @newstr New string to add to the string array. -void strarray_add(char*** strorig, char* newstr) { - int i = 0; - char** newstrarr; - - // Count the number of existing strings - while(*strorig[i] != NULL) - i++; - - // Reallocate old array + 1 - newstrarr = (char**) realloc(*strorig, sizeof(char*) * (i + 1)); - - // Append new string to the array - newstrarr[i] = malloc(strlen(newstr) + 1); - strcpy(newstrarr[i], newstr); - // Don't forget the null terminator! - newstrarr[i + 1] = NULL; - - // Repoint strorig to newstrarr memory - *strorig = newstrarr; -} - - -// strarray_release: -// Destructor for a string array. Frees each item in the array before freeing -// the array itself. -// -// @strarray Array to free -void strarray_release(char*** strarray) { - int i = 0; - - while(*strarray[i] != NULL) { - free(*strarray[i]); - i++; - } - free(*strarray); -} - diff --git a/src/strll.c b/src/strll.c new file mode 100644 index 0000000..fd47b5e --- /dev/null +++ b/src/strll.c @@ -0,0 +1,77 @@ +// GPGEdit edits GPG encrypted files +// Copyright (C) 2018 Aaron Ball <nullspoon@oper.io> +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +#include "strll.h" + +struct strll* strll_new() { + struct strll* out; + out = malloc(sizeof(struct strll)); + out->next = NULL; + out->str = NULL; + + return out; +} + + +struct strll* strll_add(struct strll* listitem, char* str) { + struct strll* cur = listitem; + + // If str == null, we're inside the first item of a new list + if(cur->str == NULL) { + cur->str = malloc(sizeof(char) * (strlen(str) + 1)); + strcpy(cur->str, str); + cur->next = NULL; + return cur; + } + + // Traverse to the last item in the list + while(cur->next != NULL) + cur = cur->next; + + // Allocate the next item and update the next pointer + cur->next = malloc(sizeof(struct strll)); + // Repoint cur to the newly allocated struct + cur = cur->next; + + // Allocate string, copy in, and set next to null + cur->str = malloc(sizeof(char) * (strlen(str) + 1)); + strcpy(cur->str, str); + cur->next = NULL; + + return cur; +} + + +void strll_release(struct strll* listitem) { + struct strll* item = listitem; + struct strll* next = NULL; + + while(item != NULL) { + next = item->next; + free(item->str); + free(item); + item = next; + } +} + + +void strll_dump(struct strll* listitem) { + struct strll* cur = listitem; + while(cur != NULL) { + printf("%s\n", cur->str); + cur = cur->next; + } +} diff --git a/src/gpg_keyids.h b/src/strll.h index 70ad9d9..4b473fa 100644 --- a/src/gpg_keyids.h +++ b/src/strll.h @@ -14,22 +14,29 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. -#ifndef GPGEDIT_GPG_KEYIDS_H -#define GPGEDIT_GPG_KEYIDS_H +#ifndef gpgedit_strll_h +#define gpgedit_strll_h #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <gpgme.h> -#include <locale.h> -#include "gpg.h" -#include "strarray.h" +struct strll { + char* str; + struct strll* next; +}; -void gpg_keyids_load_from_recip(char***, gpgme_recipient_t); -gpgme_key_t* gpg_keyids_to_key_t(gpgme_ctx_t, char**); -//void gpg_keyids_release(char**); -//char** gpg_keyids_new(); +// Create new linked list +struct strll* strll_new(); + +// Adds new item to the linked list +struct strll* strll_add(struct strll*, char*); + +// Destructor for strll object +void strll_release(struct strll*); + +// Dump linked list content to stdout +void strll_dump(struct strll*); #endif |