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

Annotation of /trunk/Src/wptPassCache.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26