/[winpt]/trunk/Src/wptPassCache.cpp
ViewVC logotype

Annotation of /trunk/Src/wptPassCache.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 22 - (hide annotations)
Wed Aug 10 11:33:35 2005 UTC (19 years, 6 months ago) by twoaday
File size: 7472 byte(s)
2005-08-06  Timo Schulz  <twoaday@freakmail.de>
 
        * wptGPGME.cpp (keycache_update): Reload OpenPGP parts
        of the secret key.
        (keycache_init): cache name of secret keyring.
        * wptKeyList.cpp (keylist_upd_key): Do not add long keyid.
        (get_key_type): Do not assume 'ultimate' means key pair.
        * wptKeyEditDlgs.cpp (diff_time): New.
        (keyedit_addsubkey_dlg_proc): Changed design and use
        diff_time. Drop checks for invalid keylength (< 1024, > 4096)
        because the combo box automatically handles this.
        * wptKeyManager.cpp (km_set_implicit_trust): Return error code.
        * wptGPG.cpp (get_backup_name): New.
        (gnupg_backup_keyrings): Rotate backup names, from 0..3.
        * wptClipImportDialog.cpp (clip_import_dlg_proc): Free memory.
        * wptKeyManagerDlg.cpp (keymanager_dlg_proc): Use 0x short keyid and
        not the long keyid.


1 twoaday 2 /* wptPassCache.c - keep a cache of passphrases
2     * Copyright (C) 2002 Free Software Foundation, Inc.
3     * Copyright (C) 2003 Timo Schulz
4     *
5     * This file is part of WinPT.
6     *
7     * WinPT is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * WinPT is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with WinPT; if not, write to the Free Software Foundation,
19     * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 twoaday 22 */
21 twoaday 2 #include <windows.h>
22     #include <stdio.h>
23     #include <stdlib.h>
24     #include <string.h>
25     #include <time.h>
26     #include <assert.h>
27    
28     #include "wptTypes.h"
29     #include "wptErrors.h"
30     #include "wptAgent.h"
31    
32    
33     struct secret_data_s {
34     int totallen; /* this includes the padding */
35     int datalen; /* actual data length */
36     char data[1];
37     };
38    
39     typedef struct cache_item_s *ITEM;
40     struct cache_item_s {
41     ITEM next;
42     time_t created;
43     time_t accessed;
44     int ttl; /* max. lifetime given in seconds */
45     int lockcount;
46     struct secret_data_s * pw;
47     size_t pwlen;
48     char key[1];
49     };
50    
51    
52     static ITEM thecache;
53    
54    
55     static void
56     release_data( struct secret_data_s * data )
57     {
58     free( data );
59     }
60    
61    
62     static void
63     wipe_data( void * data, size_t dlen )
64     {
65     memset( data, 0xff, dlen );
66     memset( data, 0xaa, dlen );
67     memset( data, 0x55, dlen );
68     memset( data, 0x00, dlen );
69     }
70    
71    
72     static struct secret_data_s *
73     new_data( const void * data, size_t length )
74     {
75     struct secret_data_s * d;
76     int total;
77    
78     /* we pad the data to 32 bytes so that it get more complicated
79     finding something out by watching allocation patterns. This is
80     usally not possible but we better assume nothing about our
81     secure storage provider*/
82     total = length + 32 - (length % 32);
83    
84     d = (secret_data_s *)malloc( sizeof *d + total - 1 );
85     if( d ) {
86     d->totallen = total;
87     d->datalen = length;
88     memcpy( d->data, data, length );
89     }
90     return d;
91     }
92    
93    
94     /* check whether there are items to expire */
95     static void
96     housekeeping( void )
97     {
98     ITEM r, rprev;
99     time_t current = time( NULL );
100    
101     /* first expire the actual data */
102     for( r=thecache; r; r = r->next ) {
103     if( !r->lockcount && r->pw && r->accessed + r->ttl < current ) {
104     wipe_data( r->pw, r->pwlen );
105     release_data( r->pw );
106     r->pw = NULL;
107     r->accessed = current;
108     }
109     }
110    
111     /* second, make sure that we also remove them based on the created stamp so
112     that the user has to enter it from time to time. We do this every hour */
113     for( r=thecache; r; r = r->next ) {
114     if( !r->lockcount && r->pw && r->created + 60*60 < current ) {
115     wipe_data( r->pw, r->pwlen );
116     release_data( r->pw );
117     r->pw = NULL;
118     r->accessed = current;
119     }
120     }
121    
122     /* third, make sure that we don't have too many items in the list.
123     Expire old and unused entries after 30 minutes */
124     for( rprev=NULL, r=thecache; r; ) {
125     if (!r->pw && r->accessed + 60*30 < current) {
126     if (r->lockcount) {
127     BUG( NULL );
128     r->accessed += 60*10; /* next error message in 10 minutes */
129     rprev = r;
130     r = r->next;
131     }
132     else {
133     ITEM r2 = r->next;
134     free (r);
135     if( !rprev )
136     thecache = r2;
137     else
138     rprev->next = r2;
139     r = r2;
140     }
141     }
142     else {
143     rprev = r;
144     r = r->next;
145     }
146     }
147     }
148    
149    
150     void
151     agent_flush_cache( void )
152     {
153     ITEM r;
154    
155     for( r=thecache; r; r = r->next ) {
156     if( !r->lockcount && r->pw ) {
157     wipe_data( r->pw, r->pwlen );
158     release_data( r->pw );
159     r->pw = NULL;
160     r->accessed = 0;
161     }
162     else if( r->lockcount && r->pw ) {
163     r->accessed = 0;
164     r->ttl = 0;
165     }
166     }
167     }
168    
169    
170     /* Try to find the item given by key and set the TTL value to zero.
171     This means the item expires the next time the passphrase cache is used. */
172     int
173     agent_del_cache( const char * key )
174     {
175     void * item;
176     ITEM r;
177    
178     if( agent_get_cache( key, &item ) ) {
179     r = (ITEM)item;
180     if( r )
181     r->ttl = 0;
182     agent_unlock_cache_entry( &item );
183     return 0;
184     }
185     return -1;
186     }
187    
188    
189     /* Store DATA of length DATALEN in the cache under KEY and mark it
190     with a maximum lifetime of TTL seconds. If there is already data
191     under this key, it will be replaced. Using a DATA of NULL deletes
192     the entry */
193     int
194     agent_put_cache( const char * key, const char * data, int ttl )
195     {
196     ITEM r;
197    
198     housekeeping ();
199    
200     if (ttl < 1)
201     ttl = 5*60;
202     if (!ttl)
203     return 0;
204    
205     for (r=thecache; r; r = r->next) {
206     if (!r->lockcount && !strcmp (r->key, key))
207     break;
208     }
209     if( r ) { /* replace */
210     if( r->pw ) {
211     wipe_data( r->pw, r->pwlen );
212     release_data( r->pw );
213     r->pw = NULL;
214     }
215     if (data) {
216     r->created = r->accessed = time( NULL );
217     r->ttl = ttl;
218     r->pwlen = strlen( data );
219     r->pw = new_data( data, r->pwlen+1 );
220     if (!r->pw)
221     BUG( NULL );
222     }
223     }
224     else if (data) { /* simply insert */
225     r = (ITEM)calloc (1, sizeof *r + strlen (key));
226     if (!r)
227     BUG( NULL );
228     else {
229     strcpy (r->key, key);
230     r->created = r->accessed = time( NULL );
231     r->ttl = ttl;
232     r->pwlen = strlen( data );
233     r->pw = new_data( data, r->pwlen+1 );
234     if (!r->pw)
235     BUG( NULL );
236     else {
237     r->next = thecache;
238     thecache = r;
239     }
240     }
241     }
242     return 0;
243     }
244    
245    
246     /* Try to find an item in the cache */
247     const char *
248     agent_get_cache( const char * key, void ** cache_id )
249     {
250     ITEM r;
251    
252     housekeeping ();
253    
254     /* first try to find one with no locks - this is an updated cache
255     entry: We might have entries with a lockcount and without a
256     lockcount. */
257     for (r=thecache; r; r = r->next) {
258     if (!r->lockcount && r->pw && !strcmp (r->key, key)) {
259     /* put_cache does only put strings into the cache, so we
260     don't need the lengths */
261     r->accessed = time (NULL);
262     r->lockcount++;
263     *cache_id = r;
264     return r->pw->data;
265     }
266     }
267     /* again, but this time get even one with a lockcount set */
268     for (r=thecache; r; r = r->next) {
269     if (r->pw && !strcmp (r->key, key)) {
270     r->accessed = time (NULL);
271     r->lockcount++;
272     *cache_id = r;
273     return r->pw->data;
274     }
275     }
276    
277     *cache_id = NULL;
278     return NULL;
279     }
280    
281    
282     void
283     agent_unlock_cache_entry( void ** cache_id )
284     {
285     ITEM r;
286    
287     for( r=thecache; r; r = r->next ) {
288     if( r == *cache_id ) {
289     if( !r->lockcount )
290     BUG( NULL );
291     else
292     r->lockcount--;
293     return;
294     }
295     }
296     }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26