pinentry-dmenu

a pinentry program based on dmenu
git clone anongit@rnpnr.xyz:pinentry-dmenu.git
Log | Files | Refs | Feed | README | LICENSE

password-cache.c (3812B)


      1 /* password-cache.c - Password cache support.
      2    Copyright (C) 2015 g10 Code GmbH
      3 
      4    This file is part of PINENTRY.
      5 
      6    PINENTRY is free software; you can redistribute it and/or modify it
      7    under the terms of the GNU General Public License as published by
      8    the Free Software Foundation; either version 2 of the License, or
      9    (at your option) any later version.
     10 
     11    PINENTRY is distributed in the hope that it will be useful, but
     12    WITHOUT ANY WARRANTY; without even the implied warranty of
     13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14    General Public License for more details.
     15 
     16    You should have received a copy of the GNU General Public License
     17    along with this program; if not, see <http://www.gnu.org/licenses/>.
     18  */
     19 
     20 #ifdef HAVE_CONFIG_H
     21 # include <config.h>
     22 #endif
     23 
     24 #include <stdlib.h>
     25 #include <stdio.h>
     26 #include <string.h>
     27 
     28 #ifdef HAVE_LIBSECRET
     29 # include <libsecret/secret.h>
     30 #endif
     31 
     32 #include "password-cache.h"
     33 #include "memory.h"
     34 
     35 #ifdef HAVE_LIBSECRET
     36 static const SecretSchema *
     37 gpg_schema (void)
     38 {
     39     static const SecretSchema the_schema = {
     40         "org.gnupg.Passphrase", SECRET_SCHEMA_NONE,
     41         {
     42 	  { "stored-by", SECRET_SCHEMA_ATTRIBUTE_STRING },
     43 	  { "keygrip", SECRET_SCHEMA_ATTRIBUTE_STRING },
     44 	  { "NULL", 0 },
     45 	}
     46     };
     47     return &the_schema;
     48 }
     49 
     50 static char *
     51 keygrip_to_label (const char *keygrip)
     52 {
     53   char const prefix[] = "GnuPG: ";
     54   char *label;
     55 
     56   label = malloc (sizeof (prefix) + strlen (keygrip));
     57   if (label)
     58     {
     59       memcpy (label, prefix, sizeof (prefix) - 1);
     60       strcpy (&label[sizeof (prefix) - 1], keygrip);
     61     }
     62   return label;
     63 }
     64 #endif
     65 
     66 void
     67 password_cache_save (const char *keygrip, const char *password)
     68 {
     69 #ifdef HAVE_LIBSECRET
     70   char *label;
     71   GError *error = NULL;
     72 
     73   if (! *keygrip)
     74     return;
     75 
     76   label = keygrip_to_label (keygrip);
     77   if (! label)
     78     return;
     79 
     80   if (! secret_password_store_sync (gpg_schema (),
     81 				    SECRET_COLLECTION_DEFAULT,
     82 				    label, password, NULL, &error,
     83 				    "stored-by", "GnuPG Pinentry",
     84 				    "keygrip", keygrip, NULL))
     85     {
     86       printf("Failed to cache password for key %s with secret service: %s\n",
     87 	     keygrip, error->message);
     88 
     89       g_error_free (error);
     90     }
     91 
     92   free (label);
     93 #else
     94   return;
     95 #endif
     96 }
     97 
     98 char *
     99 password_cache_lookup (const char *keygrip)
    100 {
    101 #ifdef HAVE_LIBSECRET
    102   GError *error = NULL;
    103   char *password;
    104   char *password2;
    105 
    106   if (! *keygrip)
    107     return NULL;
    108 
    109   password = secret_password_lookup_nonpageable_sync
    110     (gpg_schema (), NULL, &error,
    111      "keygrip", keygrip, NULL);
    112 
    113   if (error != NULL)
    114     {
    115       printf("Failed to lookup password for key %s with secret service: %s\n",
    116 	     keygrip, error->message);
    117       g_error_free (error);
    118       return NULL;
    119     }
    120   if (! password)
    121     /* The password for this key is not cached.  Just return NULL.  */
    122     return NULL;
    123 
    124   /* The password needs to be returned in secmem allocated memory.  */
    125   password2 = secmem_malloc (strlen (password) + 1);
    126   if (password2)
    127     strcpy(password2, password);
    128   else
    129     printf("secmem_malloc failed: can't copy password!\n");
    130 
    131   secret_password_free (password);
    132 
    133   return password2;
    134 #else
    135   return NULL;
    136 #endif
    137 }
    138 
    139 /* Try and remove the cached password for key grip.  Returns -1 on
    140    error, 0 if the key is not found and 1 if the password was
    141    removed.  */
    142 int
    143 password_cache_clear (const char *keygrip)
    144 {
    145 #ifdef HAVE_LIBSECRET
    146   GError *error = NULL;
    147   int removed = secret_password_clear_sync (gpg_schema (), NULL, &error,
    148 					    "keygrip", keygrip, NULL);
    149   if (error != NULL)
    150     {
    151       printf("Failed to clear password for key %s with secret service: %s\n",
    152 	     keygrip, error->message);
    153       g_debug("%s", error->message);
    154       g_error_free (error);
    155       return -1;
    156     }
    157   if (removed)
    158     return 1;
    159   return 0;
    160 #else
    161   return -1;
    162 #endif
    163 }