summaryrefslogtreecommitdiff
path: root/src/main.c
blob: 03f43817b4f0b1dd15c6c17c1abaac99849381d8 (plain)
    1 // GPGEdit edits GPG encrypted files
    2 // Copyright (C) 2018  Aaron Ball <nullspoon@oper.io>
    3 //
    4 // This program is free software: you can redistribute it and/or modify
    5 // it under the terms of the GNU General Public License as published by
    6 // the Free Software Foundation, either version 3 of the License, or
    7 // (at your option) any later version.
    8 //
    9 // This program is distributed in the hope that it will be useful,
   10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
   11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12 // GNU General Public License for more details.
   13 //
   14 // You should have received a copy of the GNU General Public License
   15 // along with this program.  If not, see <https://www.gnu.org/licenses/>.
   16 
   17 #include <stdio.h>
   18 #include <stdlib.h>
   19 #include <string.h>
   20 #include <unistd.h>
   21 #include <gpgme.h>
   22 
   23 #include "gpg.h"
   24 #include "gpgedit_config.h"
   25 #include "strll.h"
   26 
   27 void system_edit(char* file) {
   28   char cmd[256]; // Buffer for editor command
   29   char* editor;  // Editor to use when editing the file
   30 
   31   // Read the environment variable for "EDITOR". If null, default to vim.
   32   editor = getenv("EDITOR");
   33   if(editor == NULL)
   34     editor = "vim";
   35 
   36   sprintf(cmd, "%s %s\n", editor, file);
   37   system(cmd);
   38 }
   39 
   40 
   41 void usage() {
   42   const char* helptext = 
   43   "GPGEdit is an editor wrapper for GPG encrypted files. It will decrypt the\n"
   44   "specified text file to a secure location in memory, and open the specified\n"
   45   "editor. Upon closing the editor, the unencrypted copy in memory is\n"
   46   "re-encrypted, written back to the original encrypted location, and the\n"
   47   "decrypted copy is deleted from memory.\n\n"
   48   "NOTE: If power is lost while editing a file, all changes will be lost as\n"
   49   "they are stored exclusively in memory.\n"
   50   "\nUsage:\n\n"
   51   "  gpgedit [-r user@host] <file.gpg>\n"
   52   "\nArguments:\n"
   53   "  -r,--recipient   Adds a recipient key to the encrypted output\n"
   54   "  -h,--help        Print this help text\n";
   55 
   56   printf("%s\n", helptext);
   57 }
   58 
   59 
   60 void parseargs(int argc, char* argv[], struct gpgedit_config* config) {
   61   int i = 1;
   62 
   63   while(i < argc) {
   64     if(strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "--recipient") == 0) {
   65       i++;
   66       //printf("Adding recipient %s\n", argv[i]);
   67       strll_add(config->recipients, argv[i]);
   68     } else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
   69       usage();
   70       exit(0);
   71     } else {
   72       gpgedit_config_file_set(config, argv[i]);
   73     }
   74     i++;
   75   }
   76 }
   77 
   78 
   79 int main(int argc, char* argv[]) {
   80   char  tmpfile[32] = "/tmp/gpgedit-XXXXXX";
   81   gpgme_ctx_t decctx;
   82   gpgme_error_t err;
   83   struct gpgedit_config* config;
   84 
   85   config = gpgedit_config_new();
   86   parseargs(argc, argv, config);
   87 
   88   if(config->file == NULL) {
   89     printf("Please specify a gpg encrypted file to edit\n");
   90     return 1;
   91   }
   92 
   93 
   94   // Check if fd opened. If not, the specified file doesn't exist, so we need
   95   // to create it.
   96   FILE* fd = fopen(config->file, "r");
   97   if(!fd) {
   98     printf("File '%s' does not exist. Creating.\n", config->file);
   99     mkstemp(tmpfile);
  100   } else {
  101     // File exists, close the fd for testing existance
  102     fclose(fd);
  103 
  104     // Initialize decryption context, create tmp file to write decrypted contents
  105     // to, and run decryption operation.
  106     err = init_gpg(&decctx, GPGME_PROTOCOL_OPENPGP);
  107     if(err != GPG_ERR_NO_ERROR) {
  108       printf("Error: %s\n", gpgme_strerror(err));
  109       return 1;
  110     }
  111 
  112     mkstemp(tmpfile);
  113     gpgme_decrypt_result_t res = gpg_decrypt_file(config->file, tmpfile, decctx);
  114     // Get keyids array from recipients list
  115     gpgedit_config_recip_from_gpgme_recip(config, res->recipients);
  116     // Freedom!
  117     gpgme_release(decctx);
  118   }
  119 
  120   // We can't do anything if the recipient list is empty (eg: new file but no
  121   // recipients specified).
  122   if(config->recipients->str == NULL) {
  123     printf("Recipient list empty. Cannot proceed.\n");
  124   } else {
  125     // Open the system editor
  126     system_edit(tmpfile);
  127 
  128     printf("Recipients:\n");
  129     strll_dump(config->recipients);
  130 
  131     // Re-encrypt the plaintext tmp file
  132     //printf("Re-encrypting file '%s' -> '%s'\n", tmpfile, config->file);
  133     gpg_encrypt_file(tmpfile, config->file, config->recipients);
  134   }
  135 
  136   // Clean up tmpfile
  137   gpgedit_config_release(config);
  138   unlink(tmpfile);
  139   return 0;
  140 }

Generated by cgit