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 }