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

Annotation of /trunk/Src/wptPassCache.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 48 - (hide annotations)
Mon Oct 31 21:14:11 2005 UTC (19 years, 4 months ago) by werner
File size: 7461 byte(s)
More changes.  Compiles again but there are at least gettext issues with
w32-gettext.c.  I can't get a gpg-error build with ENABLE_NLS.

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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26