1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate *
4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate * with the License.
8*7c478bd9Sstevel@tonic-gate *
9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate *
14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate *
20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate * Copyright 1997 Sun Microsystems, Inc. All rights reserved.
24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate */
26*7c478bd9Sstevel@tonic-gate
27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
28*7c478bd9Sstevel@tonic-gate
29*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
31*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
32*7c478bd9Sstevel@tonic-gate #include <unistd.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/mman.h>
34*7c478bd9Sstevel@tonic-gate #include <thread.h>
35*7c478bd9Sstevel@tonic-gate #include <synch.h>
36*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
37*7c478bd9Sstevel@tonic-gate #include <syslog.h>
38*7c478bd9Sstevel@tonic-gate #include <rpc/des_crypt.h>
39*7c478bd9Sstevel@tonic-gate
40*7c478bd9Sstevel@tonic-gate #include "keyserv_cache.h"
41*7c478bd9Sstevel@tonic-gate
42*7c478bd9Sstevel@tonic-gate struct cachekey {
43*7c478bd9Sstevel@tonic-gate struct cachekey_header *ch;
44*7c478bd9Sstevel@tonic-gate keylen_t keylen;
45*7c478bd9Sstevel@tonic-gate algtype_t algtype;
46*7c478bd9Sstevel@tonic-gate mutex_t mp;
47*7c478bd9Sstevel@tonic-gate struct cachekey *next;
48*7c478bd9Sstevel@tonic-gate };
49*7c478bd9Sstevel@tonic-gate
50*7c478bd9Sstevel@tonic-gate static struct cachekey *cache = 0;
51*7c478bd9Sstevel@tonic-gate static mutex_t cache_lock = DEFAULTMUTEX;
52*7c478bd9Sstevel@tonic-gate static cond_t cache_cv = DEFAULTCV;
53*7c478bd9Sstevel@tonic-gate static u_long cache_refcnt = 0;
54*7c478bd9Sstevel@tonic-gate
55*7c478bd9Sstevel@tonic-gate struct skck {
56*7c478bd9Sstevel@tonic-gate des_block common[3];
57*7c478bd9Sstevel@tonic-gate des_block verifier; /* Checksum */
58*7c478bd9Sstevel@tonic-gate struct dhkey secret;
59*7c478bd9Sstevel@tonic-gate };
60*7c478bd9Sstevel@tonic-gate
61*7c478bd9Sstevel@tonic-gate struct cachekey_disklist {
62*7c478bd9Sstevel@tonic-gate uid_t uid;
63*7c478bd9Sstevel@tonic-gate struct cachekey_disklist *prev; /* LRU order */
64*7c478bd9Sstevel@tonic-gate struct cachekey_disklist *next;
65*7c478bd9Sstevel@tonic-gate struct cachekey_disklist *prevhash; /* Hash chain */
66*7c478bd9Sstevel@tonic-gate struct cachekey_disklist *nexthash;
67*7c478bd9Sstevel@tonic-gate struct dhkey public;
68*7c478bd9Sstevel@tonic-gate /*
69*7c478bd9Sstevel@tonic-gate * Storage for encrypted skck structure here. The length will be
70*7c478bd9Sstevel@tonic-gate * 8 * ( ( ( sizeof(struct skck) - 1 + secret.length ) - 1 ) / 8 + 1 )
71*7c478bd9Sstevel@tonic-gate */
72*7c478bd9Sstevel@tonic-gate };
73*7c478bd9Sstevel@tonic-gate
74*7c478bd9Sstevel@tonic-gate /* Length of skck structure for given key length (in bits) */
75*7c478bd9Sstevel@tonic-gate #define SKCK_LEN(keylen) ALIGN8(sizeof (struct skck) + KEYLEN(keylen))
76*7c478bd9Sstevel@tonic-gate /* Length of a cachekey_disklist record for given key length (in bits) */
77*7c478bd9Sstevel@tonic-gate #define CACHEKEY_RECLEN(keylen) ALIGN8(sizeof (struct cachekey_disklist) - 1 + \
78*7c478bd9Sstevel@tonic-gate KEYLEN(keylen) + SKCK_LEN(keylen))
79*7c478bd9Sstevel@tonic-gate #define NUMHASHBUCKETS 253
80*7c478bd9Sstevel@tonic-gate #define CHUNK_NUMREC 64
81*7c478bd9Sstevel@tonic-gate
82*7c478bd9Sstevel@tonic-gate #define CACHEKEY_HEADER_VERSION 0
83*7c478bd9Sstevel@tonic-gate
84*7c478bd9Sstevel@tonic-gate struct cachekey_header { /* First in each key cache file */
85*7c478bd9Sstevel@tonic-gate u_int version; /* version number of interface */
86*7c478bd9Sstevel@tonic-gate u_int headerlength; /* size of this header */
87*7c478bd9Sstevel@tonic-gate keylen_t keylen; /* in bits */
88*7c478bd9Sstevel@tonic-gate algtype_t algtype; /* algorithm type */
89*7c478bd9Sstevel@tonic-gate size_t reclength; /* cache file record size in bytes */
90*7c478bd9Sstevel@tonic-gate int fd; /* file descriptor */
91*7c478bd9Sstevel@tonic-gate caddr_t address; /* mmap()ed here */
92*7c478bd9Sstevel@tonic-gate size_t length; /* bytes mapped */
93*7c478bd9Sstevel@tonic-gate size_t maxsize; /* don't grow beyond this */
94*7c478bd9Sstevel@tonic-gate u_int inuse_count;
95*7c478bd9Sstevel@tonic-gate struct cachekey_disklist *inuse; /* LRU order */
96*7c478bd9Sstevel@tonic-gate struct cachekey_disklist *inuse_end;
97*7c478bd9Sstevel@tonic-gate u_int free_count;
98*7c478bd9Sstevel@tonic-gate struct cachekey_disklist *free;
99*7c478bd9Sstevel@tonic-gate struct cachekey_disklist *bucket[NUMHASHBUCKETS];
100*7c478bd9Sstevel@tonic-gate struct cachekey_disklist array[1]; /* Start of array */
101*7c478bd9Sstevel@tonic-gate };
102*7c478bd9Sstevel@tonic-gate
103*7c478bd9Sstevel@tonic-gate
104*7c478bd9Sstevel@tonic-gate static struct cachekey_header *create_cache_file_ch(keylen_t keylen,
105*7c478bd9Sstevel@tonic-gate algtype_t algtype,
106*7c478bd9Sstevel@tonic-gate int sizespec);
107*7c478bd9Sstevel@tonic-gate
108*7c478bd9Sstevel@tonic-gate static struct cachekey_header *remap_cache_file_ch(struct cachekey_header *ch,
109*7c478bd9Sstevel@tonic-gate u_int newrecs);
110*7c478bd9Sstevel@tonic-gate
111*7c478bd9Sstevel@tonic-gate static struct cachekey_header *cache_insert_ch(struct cachekey_header *ch,
112*7c478bd9Sstevel@tonic-gate uid_t uid, deskeyarray common,
113*7c478bd9Sstevel@tonic-gate des_block key,
114*7c478bd9Sstevel@tonic-gate keybuf3 *public,
115*7c478bd9Sstevel@tonic-gate keybuf3 *secret);
116*7c478bd9Sstevel@tonic-gate
117*7c478bd9Sstevel@tonic-gate static struct cachekey3_list *cache_retrieve_ch(struct cachekey_header *ch,
118*7c478bd9Sstevel@tonic-gate uid_t uid,
119*7c478bd9Sstevel@tonic-gate keybuf3 *public,
120*7c478bd9Sstevel@tonic-gate des_block key);
121*7c478bd9Sstevel@tonic-gate
122*7c478bd9Sstevel@tonic-gate static int cache_remove_ch(struct cachekey_header *ch,
123*7c478bd9Sstevel@tonic-gate uid_t uid,
124*7c478bd9Sstevel@tonic-gate keybuf3 *public);
125*7c478bd9Sstevel@tonic-gate
126*7c478bd9Sstevel@tonic-gate static struct cachekey *get_cache_header(keylen_t keylen,
127*7c478bd9Sstevel@tonic-gate algtype_t algtype);
128*7c478bd9Sstevel@tonic-gate
129*7c478bd9Sstevel@tonic-gate static void release_cache_header(struct cachekey *);
130*7c478bd9Sstevel@tonic-gate
131*7c478bd9Sstevel@tonic-gate static int cache_remap_addresses_ch(
132*7c478bd9Sstevel@tonic-gate struct cachekey_header *);
133*7c478bd9Sstevel@tonic-gate
134*7c478bd9Sstevel@tonic-gate static struct cachekey_disklist *find_cache_item(struct cachekey_header **,
135*7c478bd9Sstevel@tonic-gate uid_t, struct dhkey *);
136*7c478bd9Sstevel@tonic-gate
137*7c478bd9Sstevel@tonic-gate static struct dhkey *keybuf3_2_dhkey(keybuf3 *);
138*7c478bd9Sstevel@tonic-gate
139*7c478bd9Sstevel@tonic-gate static u_int hashval(uid_t);
140*7c478bd9Sstevel@tonic-gate
141*7c478bd9Sstevel@tonic-gate static void list_remove(struct cachekey_disklist *,
142*7c478bd9Sstevel@tonic-gate struct cachekey_disklist **,
143*7c478bd9Sstevel@tonic-gate struct cachekey_disklist **,
144*7c478bd9Sstevel@tonic-gate u_int *);
145*7c478bd9Sstevel@tonic-gate
146*7c478bd9Sstevel@tonic-gate static void list_remove_hash(struct cachekey_disklist *,
147*7c478bd9Sstevel@tonic-gate struct cachekey_disklist **,
148*7c478bd9Sstevel@tonic-gate struct cachekey_disklist **,
149*7c478bd9Sstevel@tonic-gate u_int *);
150*7c478bd9Sstevel@tonic-gate
151*7c478bd9Sstevel@tonic-gate static void list_insert(struct cachekey_disklist *,
152*7c478bd9Sstevel@tonic-gate struct cachekey_disklist **,
153*7c478bd9Sstevel@tonic-gate struct cachekey_disklist **,
154*7c478bd9Sstevel@tonic-gate u_int *);
155*7c478bd9Sstevel@tonic-gate
156*7c478bd9Sstevel@tonic-gate static void list_insert_hash(struct cachekey_disklist *,
157*7c478bd9Sstevel@tonic-gate struct cachekey_disklist **,
158*7c478bd9Sstevel@tonic-gate struct cachekey_disklist **,
159*7c478bd9Sstevel@tonic-gate u_int *);
160*7c478bd9Sstevel@tonic-gate
161*7c478bd9Sstevel@tonic-gate static struct cachekey3_list * copy_cl_item(struct cachekey_header *ch,
162*7c478bd9Sstevel@tonic-gate struct cachekey_disklist *cd,
163*7c478bd9Sstevel@tonic-gate des_block key);
164*7c478bd9Sstevel@tonic-gate
165*7c478bd9Sstevel@tonic-gate extern int hex2bin(u_char *, u_char *, int);
166*7c478bd9Sstevel@tonic-gate extern int bin2hex(u_char *, u_char *, int);
167*7c478bd9Sstevel@tonic-gate
168*7c478bd9Sstevel@tonic-gate /*
169*7c478bd9Sstevel@tonic-gate * The folowing set of macros implement address validity checking. A valid
170*7c478bd9Sstevel@tonic-gate * address is defined to be either 0, or to fall on a record boundary. In
171*7c478bd9Sstevel@tonic-gate * the latter case, the the difference between the address and the start of
172*7c478bd9Sstevel@tonic-gate * the record array is divisible by the record length.
173*7c478bd9Sstevel@tonic-gate */
174*7c478bd9Sstevel@tonic-gate #define FILEOFFSET(ckh) ((u_long)(ckh) - \
175*7c478bd9Sstevel@tonic-gate (u_long)((ckh)->address))
176*7c478bd9Sstevel@tonic-gate #define ADJUSTEDADDR(addr, ckh) ((u_long)(addr) + FILEOFFSET(ckh))
177*7c478bd9Sstevel@tonic-gate #define ARRAYOFFSET(addr, ckh) (ADJUSTEDADDR(addr, ckh) - \
178*7c478bd9Sstevel@tonic-gate (u_long)&((ckh)->array[0]))
179*7c478bd9Sstevel@tonic-gate #define INVALID_ADDRESS(addr, ckh) ((addr == 0) ? 0 : \
180*7c478bd9Sstevel@tonic-gate (ARRAYOFFSET(addr, ckh) % (ckh)->reclength) != 0)
181*7c478bd9Sstevel@tonic-gate
182*7c478bd9Sstevel@tonic-gate /* Add offset to old address */
183*7c478bd9Sstevel@tonic-gate #define MOVE_ADDR(old, offset) ((old) == 0) ? 0 : \
184*7c478bd9Sstevel@tonic-gate (void *)((u_long)(old) + (offset))
185*7c478bd9Sstevel@tonic-gate
186*7c478bd9Sstevel@tonic-gate /* Number of records in use or on free list */
187*7c478bd9Sstevel@tonic-gate #define NUMRECS(ck_header) ((ck_header)->inuse_count + \
188*7c478bd9Sstevel@tonic-gate (ck_header)->free_count)
189*7c478bd9Sstevel@tonic-gate
190*7c478bd9Sstevel@tonic-gate /* Max number of records the mapped file could hold */
191*7c478bd9Sstevel@tonic-gate #define MAPRECS(ck_header) (((ck_header)->length - \
192*7c478bd9Sstevel@tonic-gate sizeof (struct cachekey_header)) / \
193*7c478bd9Sstevel@tonic-gate (ck_header)->reclength)
194*7c478bd9Sstevel@tonic-gate /* Max number of records the file will hold if extended to the maxsize */
195*7c478bd9Sstevel@tonic-gate #define MAXRECS(ck_header) (((ck_header)->maxsize - \
196*7c478bd9Sstevel@tonic-gate sizeof (struct cachekey_header)) / \
197*7c478bd9Sstevel@tonic-gate (ck_header)->reclength)
198*7c478bd9Sstevel@tonic-gate
199*7c478bd9Sstevel@tonic-gate
200*7c478bd9Sstevel@tonic-gate struct cachekey_header *
create_cache_file_ch(keylen_t keylen,algtype_t algtype,int sizespec)201*7c478bd9Sstevel@tonic-gate create_cache_file_ch(keylen_t keylen, algtype_t algtype, int sizespec)
202*7c478bd9Sstevel@tonic-gate {
203*7c478bd9Sstevel@tonic-gate char filename[MAXPATHLEN];
204*7c478bd9Sstevel@tonic-gate struct cachekey_header *ch;
205*7c478bd9Sstevel@tonic-gate int fd, newfile = 0, i, checkvalid = 1;
206*7c478bd9Sstevel@tonic-gate struct stat statbuf;
207*7c478bd9Sstevel@tonic-gate size_t reclength, length;
208*7c478bd9Sstevel@tonic-gate struct cachekey_header *oldbase = 0;
209*7c478bd9Sstevel@tonic-gate struct cachekey_disklist *cd;
210*7c478bd9Sstevel@tonic-gate size_t maxsize;
211*7c478bd9Sstevel@tonic-gate
212*7c478bd9Sstevel@tonic-gate /* Construct cache file name */
213*7c478bd9Sstevel@tonic-gate if (snprintf(filename, sizeof (filename), "/var/nis/.keyserv_%d-%d",
214*7c478bd9Sstevel@tonic-gate keylen, algtype) > sizeof (filename)) {
215*7c478bd9Sstevel@tonic-gate syslog(LOG_WARNING,
216*7c478bd9Sstevel@tonic-gate "error constructing file name for mech %d-%d", keylen, algtype);
217*7c478bd9Sstevel@tonic-gate return (0);
218*7c478bd9Sstevel@tonic-gate }
219*7c478bd9Sstevel@tonic-gate
220*7c478bd9Sstevel@tonic-gate /* Open/create the file */
221*7c478bd9Sstevel@tonic-gate if ((fd = open(filename, O_RDWR|O_CREAT, 0600)) < 0) {
222*7c478bd9Sstevel@tonic-gate syslog(LOG_WARNING, "cache file open error for mech %d-%d: %m",
223*7c478bd9Sstevel@tonic-gate keylen, algtype);
224*7c478bd9Sstevel@tonic-gate return (0);
225*7c478bd9Sstevel@tonic-gate }
226*7c478bd9Sstevel@tonic-gate
227*7c478bd9Sstevel@tonic-gate /* We want exclusive use of the file */
228*7c478bd9Sstevel@tonic-gate if (lockf(fd, F_LOCK, 0) < 0) {
229*7c478bd9Sstevel@tonic-gate syslog(LOG_WARNING, "cache file lock error for mech %d-%d: %m",
230*7c478bd9Sstevel@tonic-gate keylen, algtype);
231*7c478bd9Sstevel@tonic-gate close(fd);
232*7c478bd9Sstevel@tonic-gate return (0);
233*7c478bd9Sstevel@tonic-gate }
234*7c478bd9Sstevel@tonic-gate
235*7c478bd9Sstevel@tonic-gate /* Zero size means a new file */
236*7c478bd9Sstevel@tonic-gate if (fstat(fd, &statbuf) < 0) {
237*7c478bd9Sstevel@tonic-gate syslog(LOG_WARNING, "cache file fstat error for mech %d-%d: %m",
238*7c478bd9Sstevel@tonic-gate keylen, algtype);
239*7c478bd9Sstevel@tonic-gate close(fd);
240*7c478bd9Sstevel@tonic-gate return (0);
241*7c478bd9Sstevel@tonic-gate }
242*7c478bd9Sstevel@tonic-gate
243*7c478bd9Sstevel@tonic-gate reclength = CACHEKEY_RECLEN(keylen);
244*7c478bd9Sstevel@tonic-gate if (sizespec < 0) {
245*7c478bd9Sstevel@tonic-gate /* specifies the number of records in file */
246*7c478bd9Sstevel@tonic-gate maxsize = ALIGN8(sizeof (struct cachekey_header)) +
247*7c478bd9Sstevel@tonic-gate -sizespec*reclength;
248*7c478bd9Sstevel@tonic-gate } else {
249*7c478bd9Sstevel@tonic-gate /* specifies size of file in MB */
250*7c478bd9Sstevel@tonic-gate maxsize = sizespec*1024*1024;
251*7c478bd9Sstevel@tonic-gate }
252*7c478bd9Sstevel@tonic-gate length = ALIGN8(sizeof (struct cachekey_header)) +
253*7c478bd9Sstevel@tonic-gate reclength*CHUNK_NUMREC;
254*7c478bd9Sstevel@tonic-gate if (length > maxsize) {
255*7c478bd9Sstevel@tonic-gate /*
256*7c478bd9Sstevel@tonic-gate * First record resides partly in the header, so the length
257*7c478bd9Sstevel@tonic-gate * cannot be allowed to be less than header plus one record.
258*7c478bd9Sstevel@tonic-gate */
259*7c478bd9Sstevel@tonic-gate if (maxsize > ALIGN8(sizeof (struct cachekey_header)+reclength))
260*7c478bd9Sstevel@tonic-gate length = maxsize;
261*7c478bd9Sstevel@tonic-gate else {
262*7c478bd9Sstevel@tonic-gate length = ALIGN8(sizeof (struct cachekey_header)+
263*7c478bd9Sstevel@tonic-gate reclength);
264*7c478bd9Sstevel@tonic-gate maxsize = length;
265*7c478bd9Sstevel@tonic-gate }
266*7c478bd9Sstevel@tonic-gate }
267*7c478bd9Sstevel@tonic-gate
268*7c478bd9Sstevel@tonic-gate if (statbuf.st_size == 0) {
269*7c478bd9Sstevel@tonic-gate /* Extend the file if we just created it */
270*7c478bd9Sstevel@tonic-gate if (ftruncate(fd, length) < 0) {
271*7c478bd9Sstevel@tonic-gate syslog(LOG_WARNING,
272*7c478bd9Sstevel@tonic-gate "cache file ftruncate error for mech %d-%d: %m",
273*7c478bd9Sstevel@tonic-gate keylen, algtype);
274*7c478bd9Sstevel@tonic-gate close(fd);
275*7c478bd9Sstevel@tonic-gate return (0);
276*7c478bd9Sstevel@tonic-gate }
277*7c478bd9Sstevel@tonic-gate newfile = 1;
278*7c478bd9Sstevel@tonic-gate } else {
279*7c478bd9Sstevel@tonic-gate /*
280*7c478bd9Sstevel@tonic-gate * Temporarily mmap the header, to sanity check and obtain
281*7c478bd9Sstevel@tonic-gate * the address where it was mapped the last time.
282*7c478bd9Sstevel@tonic-gate */
283*7c478bd9Sstevel@tonic-gate if ((ch = (void *)mmap(0, sizeof (struct cachekey_header),
284*7c478bd9Sstevel@tonic-gate PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) ==
285*7c478bd9Sstevel@tonic-gate MAP_FAILED) {
286*7c478bd9Sstevel@tonic-gate syslog(LOG_WARNING,
287*7c478bd9Sstevel@tonic-gate "cache file mmap1 error for mech %d-%d: %m",
288*7c478bd9Sstevel@tonic-gate keylen, algtype);
289*7c478bd9Sstevel@tonic-gate close(fd);
290*7c478bd9Sstevel@tonic-gate return (0);
291*7c478bd9Sstevel@tonic-gate }
292*7c478bd9Sstevel@tonic-gate if (ch->version != CACHEKEY_HEADER_VERSION ||
293*7c478bd9Sstevel@tonic-gate ch->headerlength != sizeof (struct cachekey_header) ||
294*7c478bd9Sstevel@tonic-gate ch->keylen != keylen ||
295*7c478bd9Sstevel@tonic-gate ch->algtype != algtype ||
296*7c478bd9Sstevel@tonic-gate ch->reclength != reclength ||
297*7c478bd9Sstevel@tonic-gate ch->length < sizeof (struct cachekey_header) ||
298*7c478bd9Sstevel@tonic-gate ch->maxsize < ch->length ||
299*7c478bd9Sstevel@tonic-gate INVALID_ADDRESS(ch->inuse, ch) ||
300*7c478bd9Sstevel@tonic-gate INVALID_ADDRESS(ch->free, ch)) {
301*7c478bd9Sstevel@tonic-gate syslog(LOG_WARNING,
302*7c478bd9Sstevel@tonic-gate "cache file consistency error for mech %d-%d",
303*7c478bd9Sstevel@tonic-gate keylen, algtype);
304*7c478bd9Sstevel@tonic-gate munmap((caddr_t)ch, sizeof (struct cachekey_header));
305*7c478bd9Sstevel@tonic-gate close(fd);
306*7c478bd9Sstevel@tonic-gate return (0);
307*7c478bd9Sstevel@tonic-gate }
308*7c478bd9Sstevel@tonic-gate oldbase = (void *)ch->address;
309*7c478bd9Sstevel@tonic-gate length = ch->length;
310*7c478bd9Sstevel@tonic-gate if (munmap((caddr_t)ch, sizeof (struct cachekey_header)) < 0) {
311*7c478bd9Sstevel@tonic-gate syslog(LOG_WARNING,
312*7c478bd9Sstevel@tonic-gate "cache file munmap error for mech %d-%d: %m",
313*7c478bd9Sstevel@tonic-gate keylen, algtype);
314*7c478bd9Sstevel@tonic-gate close(fd);
315*7c478bd9Sstevel@tonic-gate return (0);
316*7c478bd9Sstevel@tonic-gate }
317*7c478bd9Sstevel@tonic-gate }
318*7c478bd9Sstevel@tonic-gate
319*7c478bd9Sstevel@tonic-gate /* Map the file */
320*7c478bd9Sstevel@tonic-gate if ((ch = (void *)mmap((caddr_t)oldbase, length,
321*7c478bd9Sstevel@tonic-gate PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) {
322*7c478bd9Sstevel@tonic-gate syslog(LOG_WARNING,
323*7c478bd9Sstevel@tonic-gate "cache file mmap2 error for mech %d-%d: %m",
324*7c478bd9Sstevel@tonic-gate keylen, algtype);
325*7c478bd9Sstevel@tonic-gate close(fd);
326*7c478bd9Sstevel@tonic-gate return (0);
327*7c478bd9Sstevel@tonic-gate }
328*7c478bd9Sstevel@tonic-gate
329*7c478bd9Sstevel@tonic-gate ch->fd = fd;
330*7c478bd9Sstevel@tonic-gate ch->maxsize = maxsize;
331*7c478bd9Sstevel@tonic-gate
332*7c478bd9Sstevel@tonic-gate if (newfile) {
333*7c478bd9Sstevel@tonic-gate ch->version = CACHEKEY_HEADER_VERSION;
334*7c478bd9Sstevel@tonic-gate ch->headerlength = sizeof (struct cachekey_header);
335*7c478bd9Sstevel@tonic-gate ch->keylen = keylen;
336*7c478bd9Sstevel@tonic-gate ch->algtype = algtype;
337*7c478bd9Sstevel@tonic-gate ch->reclength = reclength;
338*7c478bd9Sstevel@tonic-gate ch->length = length;
339*7c478bd9Sstevel@tonic-gate ch->address = (caddr_t)ch;
340*7c478bd9Sstevel@tonic-gate ch->inuse_count = 0;
341*7c478bd9Sstevel@tonic-gate ch->inuse = 0;
342*7c478bd9Sstevel@tonic-gate ch->inuse_end = 0;
343*7c478bd9Sstevel@tonic-gate ch->free = 0;
344*7c478bd9Sstevel@tonic-gate ch->free_count = 0;
345*7c478bd9Sstevel@tonic-gate for (i = 0; i < NUMHASHBUCKETS; i++) {
346*7c478bd9Sstevel@tonic-gate ch->bucket[i] = 0;
347*7c478bd9Sstevel@tonic-gate }
348*7c478bd9Sstevel@tonic-gate
349*7c478bd9Sstevel@tonic-gate cd = &(ch->array[0]);
350*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAPRECS(ch);
351*7c478bd9Sstevel@tonic-gate i++, cd = MOVE_ADDR(cd, ch->reclength)) {
352*7c478bd9Sstevel@tonic-gate cd->uid = (uid_t)-1;
353*7c478bd9Sstevel@tonic-gate cd->prev = MOVE_ADDR(cd, -(ch->reclength));
354*7c478bd9Sstevel@tonic-gate cd->next = MOVE_ADDR(cd, +(ch->reclength));
355*7c478bd9Sstevel@tonic-gate cd->prevhash = 0;
356*7c478bd9Sstevel@tonic-gate cd->nexthash = 0;
357*7c478bd9Sstevel@tonic-gate }
358*7c478bd9Sstevel@tonic-gate /*
359*7c478bd9Sstevel@tonic-gate * Last record next pointer, and first record prev pointer,
360*7c478bd9Sstevel@tonic-gate * are both NULL.
361*7c478bd9Sstevel@tonic-gate */
362*7c478bd9Sstevel@tonic-gate cd = MOVE_ADDR(cd, -(ch->reclength));
363*7c478bd9Sstevel@tonic-gate cd->next = 0;
364*7c478bd9Sstevel@tonic-gate cd = &(ch->array[0]);
365*7c478bd9Sstevel@tonic-gate cd->prev = 0;
366*7c478bd9Sstevel@tonic-gate
367*7c478bd9Sstevel@tonic-gate ch->free_count = MAPRECS(ch);
368*7c478bd9Sstevel@tonic-gate ch->free = &(ch->array[0]);
369*7c478bd9Sstevel@tonic-gate
370*7c478bd9Sstevel@tonic-gate (void) msync((caddr_t)ch, ch->length, MS_SYNC);
371*7c478bd9Sstevel@tonic-gate
372*7c478bd9Sstevel@tonic-gate } else if (ch->length > maxsize) {
373*7c478bd9Sstevel@tonic-gate /* File should shrink */
374*7c478bd9Sstevel@tonic-gate if ((ch = remap_cache_file_ch(ch, MAXRECS(ch))) == 0) {
375*7c478bd9Sstevel@tonic-gate return (0);
376*7c478bd9Sstevel@tonic-gate }
377*7c478bd9Sstevel@tonic-gate checkvalid = 0;
378*7c478bd9Sstevel@tonic-gate }
379*7c478bd9Sstevel@tonic-gate
380*7c478bd9Sstevel@tonic-gate /*
381*7c478bd9Sstevel@tonic-gate * cache_remap_addresses() also checks address consistency, so call
382*7c478bd9Sstevel@tonic-gate * it even if the remap is a no-op. However, if we've called
383*7c478bd9Sstevel@tonic-gate * remap_cache_file_ch(), it will have invoked cache_remap_addresses()
384*7c478bd9Sstevel@tonic-gate * already, so we don't have to do that again.
385*7c478bd9Sstevel@tonic-gate */
386*7c478bd9Sstevel@tonic-gate if (checkvalid &&
387*7c478bd9Sstevel@tonic-gate cache_remap_addresses_ch(ch) == 0) {
388*7c478bd9Sstevel@tonic-gate syslog(LOG_WARNING, "cache file invalid for mech %d-%d",
389*7c478bd9Sstevel@tonic-gate keylen, algtype);
390*7c478bd9Sstevel@tonic-gate (void) munmap((caddr_t)ch, ch->length);
391*7c478bd9Sstevel@tonic-gate close(fd);
392*7c478bd9Sstevel@tonic-gate return (0);
393*7c478bd9Sstevel@tonic-gate }
394*7c478bd9Sstevel@tonic-gate
395*7c478bd9Sstevel@tonic-gate (void) msync((caddr_t)ch, ch->length, MS_SYNC);
396*7c478bd9Sstevel@tonic-gate
397*7c478bd9Sstevel@tonic-gate return (ch);
398*7c478bd9Sstevel@tonic-gate }
399*7c478bd9Sstevel@tonic-gate
400*7c478bd9Sstevel@tonic-gate
401*7c478bd9Sstevel@tonic-gate static int
cache_remap_addresses_ch(struct cachekey_header * ch)402*7c478bd9Sstevel@tonic-gate cache_remap_addresses_ch(struct cachekey_header *ch)
403*7c478bd9Sstevel@tonic-gate {
404*7c478bd9Sstevel@tonic-gate int i;
405*7c478bd9Sstevel@tonic-gate u_long offset;
406*7c478bd9Sstevel@tonic-gate struct cachekey_disklist *cd;
407*7c478bd9Sstevel@tonic-gate
408*7c478bd9Sstevel@tonic-gate offset = (u_long)ch - (u_long)ch->address;
409*7c478bd9Sstevel@tonic-gate
410*7c478bd9Sstevel@tonic-gate if (INVALID_ADDRESS(ch->inuse, ch) ||
411*7c478bd9Sstevel@tonic-gate INVALID_ADDRESS(ch->inuse_end, ch) ||
412*7c478bd9Sstevel@tonic-gate INVALID_ADDRESS(ch->free, ch)) {
413*7c478bd9Sstevel@tonic-gate return (0);
414*7c478bd9Sstevel@tonic-gate }
415*7c478bd9Sstevel@tonic-gate
416*7c478bd9Sstevel@tonic-gate ch->inuse = MOVE_ADDR(ch->inuse, offset);
417*7c478bd9Sstevel@tonic-gate ch->inuse_end = MOVE_ADDR(ch->inuse_end, offset);
418*7c478bd9Sstevel@tonic-gate ch->free = MOVE_ADDR(ch->free, offset);
419*7c478bd9Sstevel@tonic-gate
420*7c478bd9Sstevel@tonic-gate cd = &(ch->array[0]);
421*7c478bd9Sstevel@tonic-gate for (i = 0; i < NUMRECS(ch); i++) {
422*7c478bd9Sstevel@tonic-gate if (INVALID_ADDRESS(cd->prev, ch) ||
423*7c478bd9Sstevel@tonic-gate INVALID_ADDRESS(cd->next, ch) ||
424*7c478bd9Sstevel@tonic-gate INVALID_ADDRESS(cd->prevhash, ch) ||
425*7c478bd9Sstevel@tonic-gate INVALID_ADDRESS(cd->nexthash, ch)) {
426*7c478bd9Sstevel@tonic-gate return (0);
427*7c478bd9Sstevel@tonic-gate }
428*7c478bd9Sstevel@tonic-gate cd->prev = MOVE_ADDR(cd->prev, offset);
429*7c478bd9Sstevel@tonic-gate cd->next = MOVE_ADDR(cd->next, offset);
430*7c478bd9Sstevel@tonic-gate cd->prevhash = MOVE_ADDR(cd->prevhash, offset);
431*7c478bd9Sstevel@tonic-gate cd->nexthash = MOVE_ADDR(cd->nexthash, offset);
432*7c478bd9Sstevel@tonic-gate cd = MOVE_ADDR(cd, ch->reclength);
433*7c478bd9Sstevel@tonic-gate }
434*7c478bd9Sstevel@tonic-gate
435*7c478bd9Sstevel@tonic-gate for (i = 0; i < NUMHASHBUCKETS; i++) {
436*7c478bd9Sstevel@tonic-gate if (INVALID_ADDRESS(ch->bucket[i], ch)) {
437*7c478bd9Sstevel@tonic-gate return (0);
438*7c478bd9Sstevel@tonic-gate }
439*7c478bd9Sstevel@tonic-gate ch->bucket[i] = MOVE_ADDR(ch->bucket[i], offset);
440*7c478bd9Sstevel@tonic-gate }
441*7c478bd9Sstevel@tonic-gate
442*7c478bd9Sstevel@tonic-gate /*
443*7c478bd9Sstevel@tonic-gate * To prevent disaster if this function is invoked again, we
444*7c478bd9Sstevel@tonic-gate * update ch->address, so that offset will be zero if we do
445*7c478bd9Sstevel@tonic-gate * get called once more, and the mapped file hasn't moved.
446*7c478bd9Sstevel@tonic-gate */
447*7c478bd9Sstevel@tonic-gate ch->address = (caddr_t)ch;
448*7c478bd9Sstevel@tonic-gate
449*7c478bd9Sstevel@tonic-gate return (1);
450*7c478bd9Sstevel@tonic-gate }
451*7c478bd9Sstevel@tonic-gate
452*7c478bd9Sstevel@tonic-gate
453*7c478bd9Sstevel@tonic-gate /*
454*7c478bd9Sstevel@tonic-gate * Remap cache file with space for 'newrecs' records. The mmap:ed address
455*7c478bd9Sstevel@tonic-gate * may have to move; the new address is returned.
456*7c478bd9Sstevel@tonic-gate */
457*7c478bd9Sstevel@tonic-gate static struct cachekey_header *
remap_cache_file_ch(struct cachekey_header * ch,u_int newrecs)458*7c478bd9Sstevel@tonic-gate remap_cache_file_ch(struct cachekey_header *ch, u_int newrecs)
459*7c478bd9Sstevel@tonic-gate {
460*7c478bd9Sstevel@tonic-gate size_t newsize, oldsize;
461*7c478bd9Sstevel@tonic-gate u_int currecs;
462*7c478bd9Sstevel@tonic-gate int i, fd;
463*7c478bd9Sstevel@tonic-gate struct cachekey_header *newch;
464*7c478bd9Sstevel@tonic-gate caddr_t oldaddr;
465*7c478bd9Sstevel@tonic-gate struct cachekey_disklist *cd = 0;
466*7c478bd9Sstevel@tonic-gate
467*7c478bd9Sstevel@tonic-gate if (ch == 0)
468*7c478bd9Sstevel@tonic-gate return (0);
469*7c478bd9Sstevel@tonic-gate
470*7c478bd9Sstevel@tonic-gate
471*7c478bd9Sstevel@tonic-gate /*
472*7c478bd9Sstevel@tonic-gate * Since the first record partly resides in the cachekey_header,
473*7c478bd9Sstevel@tonic-gate * newrecs cannot be less than 1.
474*7c478bd9Sstevel@tonic-gate */
475*7c478bd9Sstevel@tonic-gate if (newrecs < 1)
476*7c478bd9Sstevel@tonic-gate newrecs = 1;
477*7c478bd9Sstevel@tonic-gate
478*7c478bd9Sstevel@tonic-gate newsize = ALIGN8(sizeof (struct cachekey_header)) +
479*7c478bd9Sstevel@tonic-gate (ch->reclength)*newrecs;
480*7c478bd9Sstevel@tonic-gate currecs = NUMRECS(ch);
481*7c478bd9Sstevel@tonic-gate
482*7c478bd9Sstevel@tonic-gate if (newsize > ch->maxsize) {
483*7c478bd9Sstevel@tonic-gate /* Would exceed maximum allowed */
484*7c478bd9Sstevel@tonic-gate newsize = ch->maxsize;
485*7c478bd9Sstevel@tonic-gate }
486*7c478bd9Sstevel@tonic-gate
487*7c478bd9Sstevel@tonic-gate /* Save stuff we need while the file is unmapped */
488*7c478bd9Sstevel@tonic-gate oldsize = ch->length;
489*7c478bd9Sstevel@tonic-gate oldaddr = (caddr_t)ch;
490*7c478bd9Sstevel@tonic-gate fd = ch->fd;
491*7c478bd9Sstevel@tonic-gate
492*7c478bd9Sstevel@tonic-gate if (newsize > ch->length) {
493*7c478bd9Sstevel@tonic-gate /* Extending the file */
494*7c478bd9Sstevel@tonic-gate cd = &(ch->array[0]);
495*7c478bd9Sstevel@tonic-gate } else if (newsize == ch->length) {
496*7c478bd9Sstevel@tonic-gate /* Already OK */
497*7c478bd9Sstevel@tonic-gate return (ch);
498*7c478bd9Sstevel@tonic-gate } else {
499*7c478bd9Sstevel@tonic-gate size_t tmpsize;
500*7c478bd9Sstevel@tonic-gate struct cachekey_disklist *fcd;
501*7c478bd9Sstevel@tonic-gate /*
502*7c478bd9Sstevel@tonic-gate * Shrink the file by removing records from the end.
503*7c478bd9Sstevel@tonic-gate * First, we have to make sure the file contains valid
504*7c478bd9Sstevel@tonic-gate * addresses.
505*7c478bd9Sstevel@tonic-gate */
506*7c478bd9Sstevel@tonic-gate if (cache_remap_addresses_ch(ch) == 0) {
507*7c478bd9Sstevel@tonic-gate syslog(LOG_WARNING, "cache file invalid for mech %d-%d",
508*7c478bd9Sstevel@tonic-gate ch->keylen, ch->algtype);
509*7c478bd9Sstevel@tonic-gate close(ch->fd);
510*7c478bd9Sstevel@tonic-gate munmap((caddr_t)ch, ch->length);
511*7c478bd9Sstevel@tonic-gate return (0);
512*7c478bd9Sstevel@tonic-gate }
513*7c478bd9Sstevel@tonic-gate fcd = MOVE_ADDR(&(ch->array[0]),
514*7c478bd9Sstevel@tonic-gate ch->reclength*(MAPRECS(ch)-1));
515*7c478bd9Sstevel@tonic-gate tmpsize = (u_long)fcd - (u_long)ch + ch->reclength;
516*7c478bd9Sstevel@tonic-gate while (tmpsize > newsize && fcd > &(ch->array[0])) {
517*7c478bd9Sstevel@tonic-gate if (fcd->uid == (uid_t)-1) {
518*7c478bd9Sstevel@tonic-gate list_remove(fcd, &(ch->free), 0,
519*7c478bd9Sstevel@tonic-gate &(ch->free_count));
520*7c478bd9Sstevel@tonic-gate } else {
521*7c478bd9Sstevel@tonic-gate list_remove_hash(fcd,
522*7c478bd9Sstevel@tonic-gate &(ch->bucket[hashval(fcd->uid)]), 0, 0);
523*7c478bd9Sstevel@tonic-gate list_remove(fcd, &(ch->inuse), &(ch->inuse_end),
524*7c478bd9Sstevel@tonic-gate &(ch->inuse_count));
525*7c478bd9Sstevel@tonic-gate }
526*7c478bd9Sstevel@tonic-gate tmpsize -= ch->reclength;
527*7c478bd9Sstevel@tonic-gate fcd = MOVE_ADDR(fcd, -(ch->reclength));
528*7c478bd9Sstevel@tonic-gate }
529*7c478bd9Sstevel@tonic-gate ch->length = newsize;
530*7c478bd9Sstevel@tonic-gate (void) msync((caddr_t)ch, ch->length, MS_SYNC);
531*7c478bd9Sstevel@tonic-gate }
532*7c478bd9Sstevel@tonic-gate
533*7c478bd9Sstevel@tonic-gate /* Unmap the file */
534*7c478bd9Sstevel@tonic-gate if (munmap((caddr_t)oldaddr, oldsize) < 0) {
535*7c478bd9Sstevel@tonic-gate return (0);
536*7c478bd9Sstevel@tonic-gate }
537*7c478bd9Sstevel@tonic-gate ch = 0;
538*7c478bd9Sstevel@tonic-gate
539*7c478bd9Sstevel@tonic-gate /* Truncate/extend it */
540*7c478bd9Sstevel@tonic-gate if (ftruncate(fd, newsize) < 0) {
541*7c478bd9Sstevel@tonic-gate return (0);
542*7c478bd9Sstevel@tonic-gate }
543*7c478bd9Sstevel@tonic-gate
544*7c478bd9Sstevel@tonic-gate /* Map it again */
545*7c478bd9Sstevel@tonic-gate if ((newch = (void *)mmap(oldaddr, newsize,
546*7c478bd9Sstevel@tonic-gate PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) ==
547*7c478bd9Sstevel@tonic-gate MAP_FAILED) {
548*7c478bd9Sstevel@tonic-gate return (0);
549*7c478bd9Sstevel@tonic-gate }
550*7c478bd9Sstevel@tonic-gate
551*7c478bd9Sstevel@tonic-gate /* Update with new values */
552*7c478bd9Sstevel@tonic-gate newch->length = newsize;
553*7c478bd9Sstevel@tonic-gate
554*7c478bd9Sstevel@tonic-gate if (cache_remap_addresses_ch(newch) == 0) {
555*7c478bd9Sstevel@tonic-gate syslog(LOG_WARNING, "cache file invalid for mech %d-%d",
556*7c478bd9Sstevel@tonic-gate newch->keylen, newch->algtype);
557*7c478bd9Sstevel@tonic-gate newch->length = oldsize;
558*7c478bd9Sstevel@tonic-gate close(newch->fd);
559*7c478bd9Sstevel@tonic-gate munmap((caddr_t)newch, newsize);
560*7c478bd9Sstevel@tonic-gate return (0);
561*7c478bd9Sstevel@tonic-gate }
562*7c478bd9Sstevel@tonic-gate
563*7c478bd9Sstevel@tonic-gate /* If extending the file, add new records to the free list */
564*7c478bd9Sstevel@tonic-gate if (cd != 0) {
565*7c478bd9Sstevel@tonic-gate cd = MOVE_ADDR(&(newch->array[0]), currecs*newch->reclength);
566*7c478bd9Sstevel@tonic-gate for (i = currecs; i < MAPRECS(newch); i++) {
567*7c478bd9Sstevel@tonic-gate cd->uid = (uid_t)-1;
568*7c478bd9Sstevel@tonic-gate list_insert(cd, &(newch->free), 0,
569*7c478bd9Sstevel@tonic-gate &(newch->free_count));
570*7c478bd9Sstevel@tonic-gate cd = MOVE_ADDR(cd, newch->reclength);
571*7c478bd9Sstevel@tonic-gate }
572*7c478bd9Sstevel@tonic-gate }
573*7c478bd9Sstevel@tonic-gate
574*7c478bd9Sstevel@tonic-gate (void) msync(newch->address, newch->length, MS_SYNC);
575*7c478bd9Sstevel@tonic-gate
576*7c478bd9Sstevel@tonic-gate return (newch);
577*7c478bd9Sstevel@tonic-gate }
578*7c478bd9Sstevel@tonic-gate
579*7c478bd9Sstevel@tonic-gate
580*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
581*7c478bd9Sstevel@tonic-gate void
print_cache_ch(struct cachekey_header * ch)582*7c478bd9Sstevel@tonic-gate print_cache_ch(struct cachekey_header *ch)
583*7c478bd9Sstevel@tonic-gate {
584*7c478bd9Sstevel@tonic-gate int i, inuse, inuse_err, free, free_err;
585*7c478bd9Sstevel@tonic-gate int pb;
586*7c478bd9Sstevel@tonic-gate struct cachekey_disklist *cd;
587*7c478bd9Sstevel@tonic-gate
588*7c478bd9Sstevel@tonic-gate printf(
589*7c478bd9Sstevel@tonic-gate "\nkeylen = %d, algtype = %d, version = %d, headerlen = %d, reclen = %d\n",
590*7c478bd9Sstevel@tonic-gate ch->keylen, ch->algtype, ch->version, ch->headerlength,
591*7c478bd9Sstevel@tonic-gate ch->reclength);
592*7c478bd9Sstevel@tonic-gate printf("fd = %d, address = 0x%x, mapped length = %d, maxsize = %d\n",
593*7c478bd9Sstevel@tonic-gate ch->fd, ch->address, ch->length, ch->maxsize);
594*7c478bd9Sstevel@tonic-gate printf("inuse = %d, free = %d\n", ch->inuse_count, ch->free_count);
595*7c478bd9Sstevel@tonic-gate
596*7c478bd9Sstevel@tonic-gate printf("Active hash buckets:\n");
597*7c478bd9Sstevel@tonic-gate
598*7c478bd9Sstevel@tonic-gate for (i = 0, inuse = 0, inuse_err = 0; i < NUMHASHBUCKETS; i++) {
599*7c478bd9Sstevel@tonic-gate cd = ch->bucket[i];
600*7c478bd9Sstevel@tonic-gate pb = -1;
601*7c478bd9Sstevel@tonic-gate if (cd != 0) {
602*7c478bd9Sstevel@tonic-gate pb = 0;
603*7c478bd9Sstevel@tonic-gate printf("\t%d: ", i);
604*7c478bd9Sstevel@tonic-gate }
605*7c478bd9Sstevel@tonic-gate while (cd != 0) {
606*7c478bd9Sstevel@tonic-gate pb++;
607*7c478bd9Sstevel@tonic-gate printf("%d ", cd->uid);
608*7c478bd9Sstevel@tonic-gate if (cd->uid != (uid_t)-1) {
609*7c478bd9Sstevel@tonic-gate inuse++;
610*7c478bd9Sstevel@tonic-gate } else {
611*7c478bd9Sstevel@tonic-gate inuse_err++;
612*7c478bd9Sstevel@tonic-gate }
613*7c478bd9Sstevel@tonic-gate cd = cd->nexthash;
614*7c478bd9Sstevel@tonic-gate }
615*7c478bd9Sstevel@tonic-gate if (pb >= 0)
616*7c478bd9Sstevel@tonic-gate printf(" (%d)\n", pb);
617*7c478bd9Sstevel@tonic-gate }
618*7c478bd9Sstevel@tonic-gate
619*7c478bd9Sstevel@tonic-gate printf("\ncounted hash inuse = %d, errors = %d\n", inuse, inuse_err);
620*7c478bd9Sstevel@tonic-gate
621*7c478bd9Sstevel@tonic-gate cd = ch->inuse;
622*7c478bd9Sstevel@tonic-gate inuse = inuse_err = 0;
623*7c478bd9Sstevel@tonic-gate while (cd != 0) {
624*7c478bd9Sstevel@tonic-gate if (cd->uid != (uid_t)-1) {
625*7c478bd9Sstevel@tonic-gate inuse++;
626*7c478bd9Sstevel@tonic-gate } else {
627*7c478bd9Sstevel@tonic-gate inuse_err++;
628*7c478bd9Sstevel@tonic-gate }
629*7c478bd9Sstevel@tonic-gate cd = cd->next;
630*7c478bd9Sstevel@tonic-gate }
631*7c478bd9Sstevel@tonic-gate printf("counted LRU inuse = %d, errors = %d\n", inuse, inuse_err);
632*7c478bd9Sstevel@tonic-gate
633*7c478bd9Sstevel@tonic-gate cd = ch->free;
634*7c478bd9Sstevel@tonic-gate free = free_err = 0;
635*7c478bd9Sstevel@tonic-gate while (cd != 0) {
636*7c478bd9Sstevel@tonic-gate if (cd->uid == (uid_t)-1) {
637*7c478bd9Sstevel@tonic-gate free++;
638*7c478bd9Sstevel@tonic-gate } else {
639*7c478bd9Sstevel@tonic-gate free_err++;
640*7c478bd9Sstevel@tonic-gate fprintf(stderr, "free = %d, err = %d, cd->uid = %d\n",
641*7c478bd9Sstevel@tonic-gate free, free_err, cd->uid);
642*7c478bd9Sstevel@tonic-gate }
643*7c478bd9Sstevel@tonic-gate cd = cd->next;
644*7c478bd9Sstevel@tonic-gate }
645*7c478bd9Sstevel@tonic-gate printf("counted free = %d, errors = %d\n", free, free_err);
646*7c478bd9Sstevel@tonic-gate }
647*7c478bd9Sstevel@tonic-gate
648*7c478bd9Sstevel@tonic-gate void
print_cache(keylen_t keylen,algtype_t algtype)649*7c478bd9Sstevel@tonic-gate print_cache(keylen_t keylen, algtype_t algtype)
650*7c478bd9Sstevel@tonic-gate {
651*7c478bd9Sstevel@tonic-gate struct cachekey *c;
652*7c478bd9Sstevel@tonic-gate
653*7c478bd9Sstevel@tonic-gate if ((c = get_cache_header(keylen, algtype)) == 0)
654*7c478bd9Sstevel@tonic-gate return;
655*7c478bd9Sstevel@tonic-gate
656*7c478bd9Sstevel@tonic-gate if (c->ch == 0) {
657*7c478bd9Sstevel@tonic-gate release_cache_header(c);
658*7c478bd9Sstevel@tonic-gate return;
659*7c478bd9Sstevel@tonic-gate }
660*7c478bd9Sstevel@tonic-gate
661*7c478bd9Sstevel@tonic-gate print_cache_ch(c->ch);
662*7c478bd9Sstevel@tonic-gate
663*7c478bd9Sstevel@tonic-gate release_cache_header(c);
664*7c478bd9Sstevel@tonic-gate }
665*7c478bd9Sstevel@tonic-gate #endif
666*7c478bd9Sstevel@tonic-gate
667*7c478bd9Sstevel@tonic-gate
668*7c478bd9Sstevel@tonic-gate
669*7c478bd9Sstevel@tonic-gate static u_int
hashval(uid_t uid)670*7c478bd9Sstevel@tonic-gate hashval(uid_t uid)
671*7c478bd9Sstevel@tonic-gate {
672*7c478bd9Sstevel@tonic-gate return (uid % NUMHASHBUCKETS);
673*7c478bd9Sstevel@tonic-gate }
674*7c478bd9Sstevel@tonic-gate
675*7c478bd9Sstevel@tonic-gate
676*7c478bd9Sstevel@tonic-gate static void
list_remove(struct cachekey_disklist * item,struct cachekey_disklist ** head,struct cachekey_disklist ** tail,u_int * count)677*7c478bd9Sstevel@tonic-gate list_remove(
678*7c478bd9Sstevel@tonic-gate struct cachekey_disklist *item,
679*7c478bd9Sstevel@tonic-gate struct cachekey_disklist **head,
680*7c478bd9Sstevel@tonic-gate struct cachekey_disklist **tail,
681*7c478bd9Sstevel@tonic-gate u_int *count)
682*7c478bd9Sstevel@tonic-gate {
683*7c478bd9Sstevel@tonic-gate if (item == NULL) return;
684*7c478bd9Sstevel@tonic-gate
685*7c478bd9Sstevel@tonic-gate /* Handle previous item, if any */
686*7c478bd9Sstevel@tonic-gate if (item->prev == 0)
687*7c478bd9Sstevel@tonic-gate *head = item->next;
688*7c478bd9Sstevel@tonic-gate else
689*7c478bd9Sstevel@tonic-gate item->prev->next = item->next;
690*7c478bd9Sstevel@tonic-gate
691*7c478bd9Sstevel@tonic-gate /* Take care of the next item, if any */
692*7c478bd9Sstevel@tonic-gate if (item->next != 0)
693*7c478bd9Sstevel@tonic-gate item->next->prev = item->prev;
694*7c478bd9Sstevel@tonic-gate
695*7c478bd9Sstevel@tonic-gate /* Handle tail pointer, if supplied */
696*7c478bd9Sstevel@tonic-gate if (tail != 0 && *tail == item)
697*7c478bd9Sstevel@tonic-gate *tail = item->prev;
698*7c478bd9Sstevel@tonic-gate
699*7c478bd9Sstevel@tonic-gate item->prev = item->next = 0;
700*7c478bd9Sstevel@tonic-gate if (count != 0)
701*7c478bd9Sstevel@tonic-gate (*count)--;
702*7c478bd9Sstevel@tonic-gate }
703*7c478bd9Sstevel@tonic-gate
704*7c478bd9Sstevel@tonic-gate
705*7c478bd9Sstevel@tonic-gate static void
list_remove_hash(struct cachekey_disklist * item,struct cachekey_disklist ** head,struct cachekey_disklist ** tail,u_int * count)706*7c478bd9Sstevel@tonic-gate list_remove_hash(
707*7c478bd9Sstevel@tonic-gate struct cachekey_disklist *item,
708*7c478bd9Sstevel@tonic-gate struct cachekey_disklist **head,
709*7c478bd9Sstevel@tonic-gate struct cachekey_disklist **tail,
710*7c478bd9Sstevel@tonic-gate u_int *count)
711*7c478bd9Sstevel@tonic-gate {
712*7c478bd9Sstevel@tonic-gate if (item == NULL) return;
713*7c478bd9Sstevel@tonic-gate
714*7c478bd9Sstevel@tonic-gate /* Handle previous item, if any */
715*7c478bd9Sstevel@tonic-gate if (item->prevhash == 0)
716*7c478bd9Sstevel@tonic-gate *head = item->nexthash;
717*7c478bd9Sstevel@tonic-gate else
718*7c478bd9Sstevel@tonic-gate item->prevhash->nexthash = item->nexthash;
719*7c478bd9Sstevel@tonic-gate
720*7c478bd9Sstevel@tonic-gate /* Take care of the next item, if any */
721*7c478bd9Sstevel@tonic-gate if (item->nexthash != 0)
722*7c478bd9Sstevel@tonic-gate item->nexthash->prevhash = item->prevhash;
723*7c478bd9Sstevel@tonic-gate
724*7c478bd9Sstevel@tonic-gate /* Handle tail pointer, if supplied */
725*7c478bd9Sstevel@tonic-gate if (tail != 0 && *tail == item)
726*7c478bd9Sstevel@tonic-gate *tail = item->prevhash;
727*7c478bd9Sstevel@tonic-gate
728*7c478bd9Sstevel@tonic-gate item->prevhash = item->nexthash = 0;
729*7c478bd9Sstevel@tonic-gate if (count != 0)
730*7c478bd9Sstevel@tonic-gate (*count)--;
731*7c478bd9Sstevel@tonic-gate }
732*7c478bd9Sstevel@tonic-gate
733*7c478bd9Sstevel@tonic-gate
734*7c478bd9Sstevel@tonic-gate static void
list_insert(struct cachekey_disklist * item,struct cachekey_disklist ** head,struct cachekey_disklist ** tail,u_int * count)735*7c478bd9Sstevel@tonic-gate list_insert(
736*7c478bd9Sstevel@tonic-gate struct cachekey_disklist *item,
737*7c478bd9Sstevel@tonic-gate struct cachekey_disklist **head,
738*7c478bd9Sstevel@tonic-gate struct cachekey_disklist **tail,
739*7c478bd9Sstevel@tonic-gate u_int *count)
740*7c478bd9Sstevel@tonic-gate {
741*7c478bd9Sstevel@tonic-gate if (item == NULL) return;
742*7c478bd9Sstevel@tonic-gate
743*7c478bd9Sstevel@tonic-gate /* Insert at tail, if supplied */
744*7c478bd9Sstevel@tonic-gate if (tail != 0) {
745*7c478bd9Sstevel@tonic-gate item->prev = *tail;
746*7c478bd9Sstevel@tonic-gate if (item->prev != 0)
747*7c478bd9Sstevel@tonic-gate item->prev->next = item;
748*7c478bd9Sstevel@tonic-gate item->next = 0;
749*7c478bd9Sstevel@tonic-gate *tail = item;
750*7c478bd9Sstevel@tonic-gate if (*head == 0)
751*7c478bd9Sstevel@tonic-gate *head = item;
752*7c478bd9Sstevel@tonic-gate } else {
753*7c478bd9Sstevel@tonic-gate item->next = *head;
754*7c478bd9Sstevel@tonic-gate if (item->next != 0)
755*7c478bd9Sstevel@tonic-gate item->next->prev = item;
756*7c478bd9Sstevel@tonic-gate item->prev = 0;
757*7c478bd9Sstevel@tonic-gate *head = item;
758*7c478bd9Sstevel@tonic-gate }
759*7c478bd9Sstevel@tonic-gate if (count != 0)
760*7c478bd9Sstevel@tonic-gate (*count)++;
761*7c478bd9Sstevel@tonic-gate }
762*7c478bd9Sstevel@tonic-gate
763*7c478bd9Sstevel@tonic-gate static void
list_insert_hash(struct cachekey_disklist * item,struct cachekey_disklist ** head,struct cachekey_disklist ** tail,u_int * count)764*7c478bd9Sstevel@tonic-gate list_insert_hash(
765*7c478bd9Sstevel@tonic-gate struct cachekey_disklist *item,
766*7c478bd9Sstevel@tonic-gate struct cachekey_disklist **head,
767*7c478bd9Sstevel@tonic-gate struct cachekey_disklist **tail,
768*7c478bd9Sstevel@tonic-gate u_int *count)
769*7c478bd9Sstevel@tonic-gate {
770*7c478bd9Sstevel@tonic-gate if (item == NULL) return;
771*7c478bd9Sstevel@tonic-gate
772*7c478bd9Sstevel@tonic-gate /* Insert at tail, if supplied */
773*7c478bd9Sstevel@tonic-gate if (tail != 0) {
774*7c478bd9Sstevel@tonic-gate item->prevhash = *tail;
775*7c478bd9Sstevel@tonic-gate if (item->prevhash != 0)
776*7c478bd9Sstevel@tonic-gate item->prevhash->nexthash = item;
777*7c478bd9Sstevel@tonic-gate item->nexthash = 0;
778*7c478bd9Sstevel@tonic-gate *tail = item;
779*7c478bd9Sstevel@tonic-gate if (*head == 0)
780*7c478bd9Sstevel@tonic-gate *head = item;
781*7c478bd9Sstevel@tonic-gate } else {
782*7c478bd9Sstevel@tonic-gate item->nexthash = *head;
783*7c478bd9Sstevel@tonic-gate if (item->nexthash != 0)
784*7c478bd9Sstevel@tonic-gate item->nexthash->prevhash = item;
785*7c478bd9Sstevel@tonic-gate item->prevhash = 0;
786*7c478bd9Sstevel@tonic-gate *head = item;
787*7c478bd9Sstevel@tonic-gate }
788*7c478bd9Sstevel@tonic-gate if (count != 0)
789*7c478bd9Sstevel@tonic-gate (*count)++;
790*7c478bd9Sstevel@tonic-gate }
791*7c478bd9Sstevel@tonic-gate
792*7c478bd9Sstevel@tonic-gate
793*7c478bd9Sstevel@tonic-gate /*
794*7c478bd9Sstevel@tonic-gate * Find the cache item specified by the header, uid, and public key. If
795*7c478bd9Sstevel@tonic-gate * no such uid/public item exists, return a pointer to an empty record.
796*7c478bd9Sstevel@tonic-gate * In either case, the item returned has been removed from any and all
797*7c478bd9Sstevel@tonic-gate * lists.
798*7c478bd9Sstevel@tonic-gate */
799*7c478bd9Sstevel@tonic-gate static struct cachekey_disklist *
find_cache_item(struct cachekey_header ** ch,uid_t uid,struct dhkey * public)800*7c478bd9Sstevel@tonic-gate find_cache_item(struct cachekey_header **ch, uid_t uid, struct dhkey *public)
801*7c478bd9Sstevel@tonic-gate {
802*7c478bd9Sstevel@tonic-gate u_int hash;
803*7c478bd9Sstevel@tonic-gate struct cachekey_disklist *cd;
804*7c478bd9Sstevel@tonic-gate
805*7c478bd9Sstevel@tonic-gate hash = hashval(uid);
806*7c478bd9Sstevel@tonic-gate
807*7c478bd9Sstevel@tonic-gate if ((ch == NULL) || ((*ch) == NULL)) {
808*7c478bd9Sstevel@tonic-gate return (0);
809*7c478bd9Sstevel@tonic-gate }
810*7c478bd9Sstevel@tonic-gate for (cd = (*ch)->bucket[hash]; cd != 0; cd = cd->nexthash) {
811*7c478bd9Sstevel@tonic-gate if (uid == cd->uid &&
812*7c478bd9Sstevel@tonic-gate public->length == cd->public.length &&
813*7c478bd9Sstevel@tonic-gate memcmp(public->key, cd->public.key,
814*7c478bd9Sstevel@tonic-gate cd->public.length) == 0) {
815*7c478bd9Sstevel@tonic-gate list_remove_hash(cd, &((*ch)->bucket[hash]), 0, 0);
816*7c478bd9Sstevel@tonic-gate list_remove(cd, &((*ch)->inuse), &((*ch)->inuse_end),
817*7c478bd9Sstevel@tonic-gate &((*ch)->inuse_count));
818*7c478bd9Sstevel@tonic-gate return (cd);
819*7c478bd9Sstevel@tonic-gate }
820*7c478bd9Sstevel@tonic-gate }
821*7c478bd9Sstevel@tonic-gate
822*7c478bd9Sstevel@tonic-gate if ((cd = (*ch)->free) != 0) {
823*7c478bd9Sstevel@tonic-gate list_remove(cd, &((*ch)->free), 0, &((*ch)->free_count));
824*7c478bd9Sstevel@tonic-gate return (cd);
825*7c478bd9Sstevel@tonic-gate }
826*7c478bd9Sstevel@tonic-gate
827*7c478bd9Sstevel@tonic-gate /* Try to extend the file by CHUNK_NUMREC records */
828*7c478bd9Sstevel@tonic-gate if (((*ch) = remap_cache_file_ch(*ch, NUMRECS(*ch)+CHUNK_NUMREC)) == 0)
829*7c478bd9Sstevel@tonic-gate return (0);
830*7c478bd9Sstevel@tonic-gate
831*7c478bd9Sstevel@tonic-gate /* If the extend worked, there should now be at least one free record */
832*7c478bd9Sstevel@tonic-gate if ((cd = (*ch)->free) != 0) {
833*7c478bd9Sstevel@tonic-gate list_remove(cd, &((*ch)->free), 0, &((*ch)->free_count));
834*7c478bd9Sstevel@tonic-gate return (cd);
835*7c478bd9Sstevel@tonic-gate }
836*7c478bd9Sstevel@tonic-gate
837*7c478bd9Sstevel@tonic-gate /* Sacrifice the LRU item, if there is one */
838*7c478bd9Sstevel@tonic-gate if ((cd = (*ch)->inuse) == 0)
839*7c478bd9Sstevel@tonic-gate return (0);
840*7c478bd9Sstevel@tonic-gate
841*7c478bd9Sstevel@tonic-gate /* Extract from hash list */
842*7c478bd9Sstevel@tonic-gate list_remove_hash(cd, &((*ch)->bucket[hashval(cd->uid)]), 0, 0);
843*7c478bd9Sstevel@tonic-gate /* Extract from LRU list */
844*7c478bd9Sstevel@tonic-gate list_remove(cd, &((*ch)->inuse), &((*ch)->inuse_end),
845*7c478bd9Sstevel@tonic-gate &((*ch)->inuse_count));
846*7c478bd9Sstevel@tonic-gate
847*7c478bd9Sstevel@tonic-gate return (cd);
848*7c478bd9Sstevel@tonic-gate }
849*7c478bd9Sstevel@tonic-gate
850*7c478bd9Sstevel@tonic-gate
851*7c478bd9Sstevel@tonic-gate static struct cachekey_header *
cache_insert_ch(struct cachekey_header * ch,uid_t uid,deskeyarray common,des_block key,keybuf3 * public,keybuf3 * secret)852*7c478bd9Sstevel@tonic-gate cache_insert_ch(
853*7c478bd9Sstevel@tonic-gate struct cachekey_header *ch,
854*7c478bd9Sstevel@tonic-gate uid_t uid,
855*7c478bd9Sstevel@tonic-gate deskeyarray common,
856*7c478bd9Sstevel@tonic-gate des_block key,
857*7c478bd9Sstevel@tonic-gate keybuf3 *public,
858*7c478bd9Sstevel@tonic-gate keybuf3 *secret)
859*7c478bd9Sstevel@tonic-gate {
860*7c478bd9Sstevel@tonic-gate struct cachekey_disklist *cd;
861*7c478bd9Sstevel@tonic-gate struct cachekey_header *newch;
862*7c478bd9Sstevel@tonic-gate int i, err;
863*7c478bd9Sstevel@tonic-gate struct skck *skck;
864*7c478bd9Sstevel@tonic-gate des_block ivec;
865*7c478bd9Sstevel@tonic-gate struct dhkey *pk;
866*7c478bd9Sstevel@tonic-gate struct dhkey *sk;
867*7c478bd9Sstevel@tonic-gate
868*7c478bd9Sstevel@tonic-gate
869*7c478bd9Sstevel@tonic-gate if (ch == 0 || uid == (uid_t)-1) {
870*7c478bd9Sstevel@tonic-gate return (0);
871*7c478bd9Sstevel@tonic-gate }
872*7c478bd9Sstevel@tonic-gate
873*7c478bd9Sstevel@tonic-gate if (common.deskeyarray_len > sizeof (skck->common)/sizeof (des_block) ||
874*7c478bd9Sstevel@tonic-gate (pk = keybuf3_2_dhkey(public)) == 0 ||
875*7c478bd9Sstevel@tonic-gate (sk = keybuf3_2_dhkey(secret)) == 0) {
876*7c478bd9Sstevel@tonic-gate return (0);
877*7c478bd9Sstevel@tonic-gate }
878*7c478bd9Sstevel@tonic-gate
879*7c478bd9Sstevel@tonic-gate newch = ch;
880*7c478bd9Sstevel@tonic-gate if ((cd = find_cache_item(&newch, uid, pk)) == 0) {
881*7c478bd9Sstevel@tonic-gate free(pk);
882*7c478bd9Sstevel@tonic-gate free(sk);
883*7c478bd9Sstevel@tonic-gate return (newch);
884*7c478bd9Sstevel@tonic-gate }
885*7c478bd9Sstevel@tonic-gate
886*7c478bd9Sstevel@tonic-gate /*
887*7c478bd9Sstevel@tonic-gate * The item may have been free, or may have been the LRU sacrificial
888*7c478bd9Sstevel@tonic-gate * lamb, so reset all fields.
889*7c478bd9Sstevel@tonic-gate */
890*7c478bd9Sstevel@tonic-gate cd->uid = uid;
891*7c478bd9Sstevel@tonic-gate memcpy(&(cd->public), pk, DHKEYSIZE(pk));
892*7c478bd9Sstevel@tonic-gate
893*7c478bd9Sstevel@tonic-gate skck = MOVE_ADDR(&(cd->public), DHKEYSIZE(pk));
894*7c478bd9Sstevel@tonic-gate for (i = 0; i < common.deskeyarray_len; i++) {
895*7c478bd9Sstevel@tonic-gate skck->common[i] = common.deskeyarray_val[i];
896*7c478bd9Sstevel@tonic-gate }
897*7c478bd9Sstevel@tonic-gate skck->verifier = key;
898*7c478bd9Sstevel@tonic-gate memcpy(&(skck->secret), sk, DHKEYSIZE(sk));
899*7c478bd9Sstevel@tonic-gate free(pk);
900*7c478bd9Sstevel@tonic-gate free(sk);
901*7c478bd9Sstevel@tonic-gate memcpy(ivec.c, key.c, sizeof (key.c));
902*7c478bd9Sstevel@tonic-gate err = cbc_crypt(key.c, (char *)skck, SKCK_LEN(newch->keylen),
903*7c478bd9Sstevel@tonic-gate DES_ENCRYPT|DES_HW, ivec.c);
904*7c478bd9Sstevel@tonic-gate if (DES_FAILED(err)) {
905*7c478bd9Sstevel@tonic-gate /* Re-insert on free list */
906*7c478bd9Sstevel@tonic-gate list_insert(cd, &(newch->free), 0, &(newch->free_count));
907*7c478bd9Sstevel@tonic-gate return (newch);
908*7c478bd9Sstevel@tonic-gate }
909*7c478bd9Sstevel@tonic-gate
910*7c478bd9Sstevel@tonic-gate /* Re-insert on hash list */
911*7c478bd9Sstevel@tonic-gate list_insert_hash(cd, &(newch->bucket[hashval(cd->uid)]), 0, 0);
912*7c478bd9Sstevel@tonic-gate /* Insert at end of LRU list */
913*7c478bd9Sstevel@tonic-gate list_insert(cd, &(newch->inuse), &(newch->inuse_end),
914*7c478bd9Sstevel@tonic-gate &(newch->inuse_count));
915*7c478bd9Sstevel@tonic-gate
916*7c478bd9Sstevel@tonic-gate (void) msync((caddr_t)newch, newch->length, MS_SYNC);
917*7c478bd9Sstevel@tonic-gate
918*7c478bd9Sstevel@tonic-gate return (newch);
919*7c478bd9Sstevel@tonic-gate }
920*7c478bd9Sstevel@tonic-gate
921*7c478bd9Sstevel@tonic-gate
922*7c478bd9Sstevel@tonic-gate static struct cachekey3_list *
copy_cl_item(struct cachekey_header * ch,struct cachekey_disklist * cd,des_block key)923*7c478bd9Sstevel@tonic-gate copy_cl_item(struct cachekey_header *ch, struct cachekey_disklist *cd,
924*7c478bd9Sstevel@tonic-gate des_block key) {
925*7c478bd9Sstevel@tonic-gate
926*7c478bd9Sstevel@tonic-gate struct cachekey3_list *cl;
927*7c478bd9Sstevel@tonic-gate struct skck *skck, *skck_cd;
928*7c478bd9Sstevel@tonic-gate int i, err;
929*7c478bd9Sstevel@tonic-gate des_block ivec;
930*7c478bd9Sstevel@tonic-gate
931*7c478bd9Sstevel@tonic-gate /* Allocate the cachekey3_list structure */
932*7c478bd9Sstevel@tonic-gate if ((cl = malloc(CACHEKEY3_LIST_SIZE(ch->keylen))) == 0) {
933*7c478bd9Sstevel@tonic-gate return (0);
934*7c478bd9Sstevel@tonic-gate }
935*7c478bd9Sstevel@tonic-gate
936*7c478bd9Sstevel@tonic-gate /* Allocate skck structure for decryption */
937*7c478bd9Sstevel@tonic-gate if ((skck = malloc(SKCK_LEN(ch->keylen))) == 0) {
938*7c478bd9Sstevel@tonic-gate free(cl);
939*7c478bd9Sstevel@tonic-gate return (0);
940*7c478bd9Sstevel@tonic-gate }
941*7c478bd9Sstevel@tonic-gate
942*7c478bd9Sstevel@tonic-gate /* Decrypt and check verifier */
943*7c478bd9Sstevel@tonic-gate skck_cd = MOVE_ADDR(&(cd->public), DHKEYSIZE(&(cd->public)));
944*7c478bd9Sstevel@tonic-gate memcpy(skck, skck_cd, SKCK_LEN(ch->keylen));
945*7c478bd9Sstevel@tonic-gate memcpy(ivec.c, key.c, sizeof (ivec.c));
946*7c478bd9Sstevel@tonic-gate err = cbc_crypt(key.c, (char *)skck, SKCK_LEN(ch->keylen),
947*7c478bd9Sstevel@tonic-gate DES_DECRYPT|DES_HW, ivec.c);
948*7c478bd9Sstevel@tonic-gate if (DES_FAILED(err)) {
949*7c478bd9Sstevel@tonic-gate free(cl);
950*7c478bd9Sstevel@tonic-gate free(skck);
951*7c478bd9Sstevel@tonic-gate return (0);
952*7c478bd9Sstevel@tonic-gate }
953*7c478bd9Sstevel@tonic-gate if (memcmp(key.c, skck->verifier.c, sizeof (skck->verifier.c)) != 0) {
954*7c478bd9Sstevel@tonic-gate free(cl);
955*7c478bd9Sstevel@tonic-gate free(skck);
956*7c478bd9Sstevel@tonic-gate return (0);
957*7c478bd9Sstevel@tonic-gate }
958*7c478bd9Sstevel@tonic-gate
959*7c478bd9Sstevel@tonic-gate /* Everything OK; copy values */
960*7c478bd9Sstevel@tonic-gate cl->public = MOVE_ADDR(cl, sizeof (struct cachekey3_list));
961*7c478bd9Sstevel@tonic-gate cl->public->keybuf3_val = MOVE_ADDR(cl->public, sizeof (keybuf3));
962*7c478bd9Sstevel@tonic-gate cl->secret = MOVE_ADDR(cl->public->keybuf3_val,
963*7c478bd9Sstevel@tonic-gate ALIGN4(2*KEYLEN(ch->keylen)+1));
964*7c478bd9Sstevel@tonic-gate cl->secret->keybuf3_val = MOVE_ADDR(cl->secret, sizeof (keybuf3));
965*7c478bd9Sstevel@tonic-gate cl->deskey.deskeyarray_val =
966*7c478bd9Sstevel@tonic-gate MOVE_ADDR(cl->secret->keybuf3_val,
967*7c478bd9Sstevel@tonic-gate ALIGN4(2*KEYLEN(ch->keylen)+1));
968*7c478bd9Sstevel@tonic-gate bin2hex(cd->public.key, (u_char *)cl->public->keybuf3_val,
969*7c478bd9Sstevel@tonic-gate cd->public.length);
970*7c478bd9Sstevel@tonic-gate cl->public->keybuf3_len = cd->public.length*2+1;
971*7c478bd9Sstevel@tonic-gate
972*7c478bd9Sstevel@tonic-gate bin2hex(skck->secret.key, (u_char *)cl->secret->keybuf3_val,
973*7c478bd9Sstevel@tonic-gate skck->secret.length);
974*7c478bd9Sstevel@tonic-gate cl->secret->keybuf3_len = skck->secret.length*2+1;
975*7c478bd9Sstevel@tonic-gate cl->deskey.deskeyarray_len = sizeof (skck->common)/sizeof (des_block);
976*7c478bd9Sstevel@tonic-gate for (i = 0; i < cl->deskey.deskeyarray_len; i++) {
977*7c478bd9Sstevel@tonic-gate cl->deskey.deskeyarray_val[i] = skck->common[i];
978*7c478bd9Sstevel@tonic-gate }
979*7c478bd9Sstevel@tonic-gate
980*7c478bd9Sstevel@tonic-gate cl->refcnt = 0;
981*7c478bd9Sstevel@tonic-gate cl->next = 0;
982*7c478bd9Sstevel@tonic-gate
983*7c478bd9Sstevel@tonic-gate free(skck);
984*7c478bd9Sstevel@tonic-gate
985*7c478bd9Sstevel@tonic-gate return (cl);
986*7c478bd9Sstevel@tonic-gate
987*7c478bd9Sstevel@tonic-gate }
988*7c478bd9Sstevel@tonic-gate
989*7c478bd9Sstevel@tonic-gate
990*7c478bd9Sstevel@tonic-gate static struct cachekey3_list *
cache_retrieve_ch(struct cachekey_header * ch,uid_t uid,keybuf3 * public,des_block key)991*7c478bd9Sstevel@tonic-gate cache_retrieve_ch(struct cachekey_header *ch, uid_t uid, keybuf3 *public,
992*7c478bd9Sstevel@tonic-gate des_block key) {
993*7c478bd9Sstevel@tonic-gate
994*7c478bd9Sstevel@tonic-gate struct cachekey_disklist *cd;
995*7c478bd9Sstevel@tonic-gate struct cachekey3_list *cl = 0, **cltmp = &cl;
996*7c478bd9Sstevel@tonic-gate u_int hash;
997*7c478bd9Sstevel@tonic-gate struct dhkey *pk = 0;
998*7c478bd9Sstevel@tonic-gate
999*7c478bd9Sstevel@tonic-gate if (uid == (uid_t)-1 ||
1000*7c478bd9Sstevel@tonic-gate (public != 0 && (pk = keybuf3_2_dhkey(public)) == 0)) {
1001*7c478bd9Sstevel@tonic-gate return (0);
1002*7c478bd9Sstevel@tonic-gate }
1003*7c478bd9Sstevel@tonic-gate
1004*7c478bd9Sstevel@tonic-gate hash = hashval(uid);
1005*7c478bd9Sstevel@tonic-gate
1006*7c478bd9Sstevel@tonic-gate for (cd = ch->bucket[hash]; cd != 0; cd = cd->nexthash) {
1007*7c478bd9Sstevel@tonic-gate if (uid == cd->uid) {
1008*7c478bd9Sstevel@tonic-gate /* Match on public key as well ? */
1009*7c478bd9Sstevel@tonic-gate if (pk != 0) {
1010*7c478bd9Sstevel@tonic-gate if (memcmp(cd->public.key, pk->key,
1011*7c478bd9Sstevel@tonic-gate cd->public.length) != 0) {
1012*7c478bd9Sstevel@tonic-gate /* Keep looking... */
1013*7c478bd9Sstevel@tonic-gate continue;
1014*7c478bd9Sstevel@tonic-gate }
1015*7c478bd9Sstevel@tonic-gate cl = copy_cl_item(ch, cd, key);
1016*7c478bd9Sstevel@tonic-gate /* Match on public key => nothing more to do */
1017*7c478bd9Sstevel@tonic-gate break;
1018*7c478bd9Sstevel@tonic-gate }
1019*7c478bd9Sstevel@tonic-gate *cltmp = copy_cl_item(ch, cd, key);
1020*7c478bd9Sstevel@tonic-gate if (*cltmp == 0) {
1021*7c478bd9Sstevel@tonic-gate /* Return what we've got */
1022*7c478bd9Sstevel@tonic-gate break;
1023*7c478bd9Sstevel@tonic-gate }
1024*7c478bd9Sstevel@tonic-gate cltmp = &((*cltmp)->next);
1025*7c478bd9Sstevel@tonic-gate /* On to the next item */
1026*7c478bd9Sstevel@tonic-gate }
1027*7c478bd9Sstevel@tonic-gate }
1028*7c478bd9Sstevel@tonic-gate
1029*7c478bd9Sstevel@tonic-gate if (pk != 0)
1030*7c478bd9Sstevel@tonic-gate free(pk);
1031*7c478bd9Sstevel@tonic-gate
1032*7c478bd9Sstevel@tonic-gate return (cl);
1033*7c478bd9Sstevel@tonic-gate }
1034*7c478bd9Sstevel@tonic-gate
1035*7c478bd9Sstevel@tonic-gate
1036*7c478bd9Sstevel@tonic-gate /*
1037*7c478bd9Sstevel@tonic-gate * Remove specified item. 'public' == 0 => remove all items for uid.
1038*7c478bd9Sstevel@tonic-gate * Return number of items removed.
1039*7c478bd9Sstevel@tonic-gate */
1040*7c478bd9Sstevel@tonic-gate static int
cache_remove_ch(struct cachekey_header * ch,uid_t uid,keybuf3 * public)1041*7c478bd9Sstevel@tonic-gate cache_remove_ch(struct cachekey_header *ch, uid_t uid, keybuf3 *public) {
1042*7c478bd9Sstevel@tonic-gate
1043*7c478bd9Sstevel@tonic-gate struct cachekey_disklist *cd, *cdtmp;
1044*7c478bd9Sstevel@tonic-gate u_int hash;
1045*7c478bd9Sstevel@tonic-gate int match = 0;
1046*7c478bd9Sstevel@tonic-gate struct dhkey *pk = 0;
1047*7c478bd9Sstevel@tonic-gate
1048*7c478bd9Sstevel@tonic-gate if (uid == (uid_t)-1 ||
1049*7c478bd9Sstevel@tonic-gate (public != 0 && (pk = keybuf3_2_dhkey(public)) == 0)) {
1050*7c478bd9Sstevel@tonic-gate return (0);
1051*7c478bd9Sstevel@tonic-gate }
1052*7c478bd9Sstevel@tonic-gate
1053*7c478bd9Sstevel@tonic-gate hash = hashval(uid);
1054*7c478bd9Sstevel@tonic-gate
1055*7c478bd9Sstevel@tonic-gate for (cd = ch->bucket[hash]; cd != 0; ) {
1056*7c478bd9Sstevel@tonic-gate if (uid == cd->uid) {
1057*7c478bd9Sstevel@tonic-gate /* Match on public key as well ? */
1058*7c478bd9Sstevel@tonic-gate if (pk != 0) {
1059*7c478bd9Sstevel@tonic-gate if (memcmp(cd->public.key, pk->key,
1060*7c478bd9Sstevel@tonic-gate cd->public.length) != 0) {
1061*7c478bd9Sstevel@tonic-gate /* Keep looking... */
1062*7c478bd9Sstevel@tonic-gate continue;
1063*7c478bd9Sstevel@tonic-gate }
1064*7c478bd9Sstevel@tonic-gate match++;
1065*7c478bd9Sstevel@tonic-gate list_remove_hash(cd, &(ch->bucket[hash]), 0, 0);
1066*7c478bd9Sstevel@tonic-gate list_remove(cd, &(ch->inuse), &(ch->inuse_end),
1067*7c478bd9Sstevel@tonic-gate &(ch->inuse_count));
1068*7c478bd9Sstevel@tonic-gate cd->uid = (uid_t)-1;
1069*7c478bd9Sstevel@tonic-gate list_insert(cd, &(ch->free), 0,
1070*7c478bd9Sstevel@tonic-gate &(ch->free_count));
1071*7c478bd9Sstevel@tonic-gate /* Match on public key => nothing more to do */
1072*7c478bd9Sstevel@tonic-gate break;
1073*7c478bd9Sstevel@tonic-gate }
1074*7c478bd9Sstevel@tonic-gate match++;
1075*7c478bd9Sstevel@tonic-gate /*
1076*7c478bd9Sstevel@tonic-gate * XXX: Assume that the order of the hash list remains
1077*7c478bd9Sstevel@tonic-gate * the same after removal of an item. If this isn't
1078*7c478bd9Sstevel@tonic-gate * true, we really should start over from the start
1079*7c478bd9Sstevel@tonic-gate * of the hash bucket.
1080*7c478bd9Sstevel@tonic-gate */
1081*7c478bd9Sstevel@tonic-gate cdtmp = cd->nexthash;
1082*7c478bd9Sstevel@tonic-gate list_remove_hash(cd, &(ch->bucket[hash]), 0, 0);
1083*7c478bd9Sstevel@tonic-gate list_remove(cd, &(ch->inuse), &(ch->inuse_end),
1084*7c478bd9Sstevel@tonic-gate &(ch->inuse_count));
1085*7c478bd9Sstevel@tonic-gate cd->uid = (uid_t)-1;
1086*7c478bd9Sstevel@tonic-gate list_insert(cd, &(ch->free), 0,
1087*7c478bd9Sstevel@tonic-gate &(ch->free_count));
1088*7c478bd9Sstevel@tonic-gate /* On to the next item */
1089*7c478bd9Sstevel@tonic-gate cd = cdtmp;
1090*7c478bd9Sstevel@tonic-gate } else {
1091*7c478bd9Sstevel@tonic-gate cd = cd->nexthash;
1092*7c478bd9Sstevel@tonic-gate }
1093*7c478bd9Sstevel@tonic-gate }
1094*7c478bd9Sstevel@tonic-gate
1095*7c478bd9Sstevel@tonic-gate free(pk);
1096*7c478bd9Sstevel@tonic-gate return (match);
1097*7c478bd9Sstevel@tonic-gate }
1098*7c478bd9Sstevel@tonic-gate
1099*7c478bd9Sstevel@tonic-gate
1100*7c478bd9Sstevel@tonic-gate #define INCCACHEREFCNT mutex_lock(&cache_lock); \
1101*7c478bd9Sstevel@tonic-gate cache_refcnt++; \
1102*7c478bd9Sstevel@tonic-gate mutex_unlock(&cache_lock)
1103*7c478bd9Sstevel@tonic-gate
1104*7c478bd9Sstevel@tonic-gate #if !defined(lint) && !defined(__lint)
1105*7c478bd9Sstevel@tonic-gate #define DECCACHEREFCNT mutex_lock(&cache_lock); \
1106*7c478bd9Sstevel@tonic-gate if (cache_refcnt > 0) \
1107*7c478bd9Sstevel@tonic-gate if (cache_refcnt-- == 0) (void) cond_broadcast(&cache_cv); \
1108*7c478bd9Sstevel@tonic-gate mutex_unlock(&cache_lock)
1109*7c478bd9Sstevel@tonic-gate #else
1110*7c478bd9Sstevel@tonic-gate #define DECCACHEREFCNT mutex_lock(&cache_lock); \
1111*7c478bd9Sstevel@tonic-gate if (cache_refcnt-- == 0) (void) cond_broadcast(&cache_cv); \
1112*7c478bd9Sstevel@tonic-gate mutex_unlock(&cache_lock)
1113*7c478bd9Sstevel@tonic-gate #endif
1114*7c478bd9Sstevel@tonic-gate
1115*7c478bd9Sstevel@tonic-gate /*
1116*7c478bd9Sstevel@tonic-gate * Return the cachekey structure for the specified keylen and algtype.
1117*7c478bd9Sstevel@tonic-gate * When returned, the lock in the structure has been activated. It's the
1118*7c478bd9Sstevel@tonic-gate * responsibility of the caller to unlock it by calling release_cache_header().
1119*7c478bd9Sstevel@tonic-gate */
1120*7c478bd9Sstevel@tonic-gate static struct cachekey *
get_cache_header(keylen_t keylen,algtype_t algtype)1121*7c478bd9Sstevel@tonic-gate get_cache_header(keylen_t keylen, algtype_t algtype) {
1122*7c478bd9Sstevel@tonic-gate
1123*7c478bd9Sstevel@tonic-gate struct cachekey *c;
1124*7c478bd9Sstevel@tonic-gate
1125*7c478bd9Sstevel@tonic-gate INCCACHEREFCNT;
1126*7c478bd9Sstevel@tonic-gate
1127*7c478bd9Sstevel@tonic-gate for (c = cache; c != 0; c = c->next) {
1128*7c478bd9Sstevel@tonic-gate if (c->keylen == keylen && c->algtype == algtype) {
1129*7c478bd9Sstevel@tonic-gate mutex_lock(&c->mp);
1130*7c478bd9Sstevel@tonic-gate return (c);
1131*7c478bd9Sstevel@tonic-gate }
1132*7c478bd9Sstevel@tonic-gate }
1133*7c478bd9Sstevel@tonic-gate
1134*7c478bd9Sstevel@tonic-gate /* Spin until there are no cache readers */
1135*7c478bd9Sstevel@tonic-gate mutex_lock(&cache_lock);
1136*7c478bd9Sstevel@tonic-gate #if !defined(lint) && !defined(__lint)
1137*7c478bd9Sstevel@tonic-gate if (cache_refcnt > 0)
1138*7c478bd9Sstevel@tonic-gate #endif
1139*7c478bd9Sstevel@tonic-gate cache_refcnt--;
1140*7c478bd9Sstevel@tonic-gate while (cache_refcnt != 0) {
1141*7c478bd9Sstevel@tonic-gate (void) cond_wait(&cache_cv, &cache_lock);
1142*7c478bd9Sstevel@tonic-gate }
1143*7c478bd9Sstevel@tonic-gate
1144*7c478bd9Sstevel@tonic-gate if ((c = malloc(sizeof (struct cachekey))) != 0) {
1145*7c478bd9Sstevel@tonic-gate c->ch = 0;
1146*7c478bd9Sstevel@tonic-gate c->keylen = keylen;
1147*7c478bd9Sstevel@tonic-gate c->algtype = algtype;
1148*7c478bd9Sstevel@tonic-gate mutex_init(&c->mp, 0, 0);
1149*7c478bd9Sstevel@tonic-gate c->next = cache;
1150*7c478bd9Sstevel@tonic-gate cache = c;
1151*7c478bd9Sstevel@tonic-gate mutex_lock(&c->mp);
1152*7c478bd9Sstevel@tonic-gate cache_refcnt++;
1153*7c478bd9Sstevel@tonic-gate mutex_unlock(&cache_lock);
1154*7c478bd9Sstevel@tonic-gate return (c);
1155*7c478bd9Sstevel@tonic-gate }
1156*7c478bd9Sstevel@tonic-gate
1157*7c478bd9Sstevel@tonic-gate mutex_unlock(&cache_lock);
1158*7c478bd9Sstevel@tonic-gate return (0);
1159*7c478bd9Sstevel@tonic-gate }
1160*7c478bd9Sstevel@tonic-gate
1161*7c478bd9Sstevel@tonic-gate
1162*7c478bd9Sstevel@tonic-gate static void
release_cache_header(struct cachekey * ck)1163*7c478bd9Sstevel@tonic-gate release_cache_header(struct cachekey *ck) {
1164*7c478bd9Sstevel@tonic-gate
1165*7c478bd9Sstevel@tonic-gate struct cachekey *c;
1166*7c478bd9Sstevel@tonic-gate
1167*7c478bd9Sstevel@tonic-gate if (ck == 0)
1168*7c478bd9Sstevel@tonic-gate return;
1169*7c478bd9Sstevel@tonic-gate
1170*7c478bd9Sstevel@tonic-gate for (c = cache; c != 0; c = c->next) {
1171*7c478bd9Sstevel@tonic-gate if (c == ck) {
1172*7c478bd9Sstevel@tonic-gate mutex_unlock(&c->mp);
1173*7c478bd9Sstevel@tonic-gate DECCACHEREFCNT;
1174*7c478bd9Sstevel@tonic-gate break;
1175*7c478bd9Sstevel@tonic-gate }
1176*7c478bd9Sstevel@tonic-gate }
1177*7c478bd9Sstevel@tonic-gate }
1178*7c478bd9Sstevel@tonic-gate
1179*7c478bd9Sstevel@tonic-gate
1180*7c478bd9Sstevel@tonic-gate int
create_cache_file(keylen_t keylen,algtype_t algtype,int sizespec)1181*7c478bd9Sstevel@tonic-gate create_cache_file(keylen_t keylen, algtype_t algtype, int sizespec)
1182*7c478bd9Sstevel@tonic-gate {
1183*7c478bd9Sstevel@tonic-gate struct cachekey *c;
1184*7c478bd9Sstevel@tonic-gate int ret;
1185*7c478bd9Sstevel@tonic-gate
1186*7c478bd9Sstevel@tonic-gate if ((c = get_cache_header(keylen, algtype)) == 0)
1187*7c478bd9Sstevel@tonic-gate return (0);
1188*7c478bd9Sstevel@tonic-gate
1189*7c478bd9Sstevel@tonic-gate if (c->ch != 0) {
1190*7c478bd9Sstevel@tonic-gate /* Already created and opened */
1191*7c478bd9Sstevel@tonic-gate release_cache_header(c);
1192*7c478bd9Sstevel@tonic-gate return (1);
1193*7c478bd9Sstevel@tonic-gate }
1194*7c478bd9Sstevel@tonic-gate
1195*7c478bd9Sstevel@tonic-gate ret = (c->ch = create_cache_file_ch(keylen, algtype, sizespec)) != 0;
1196*7c478bd9Sstevel@tonic-gate release_cache_header(c);
1197*7c478bd9Sstevel@tonic-gate
1198*7c478bd9Sstevel@tonic-gate return (ret);
1199*7c478bd9Sstevel@tonic-gate }
1200*7c478bd9Sstevel@tonic-gate
1201*7c478bd9Sstevel@tonic-gate
1202*7c478bd9Sstevel@tonic-gate int
cache_insert(keylen_t keylen,algtype_t algtype,uid_t uid,deskeyarray common,des_block key,keybuf3 * public,keybuf3 * secret)1203*7c478bd9Sstevel@tonic-gate cache_insert(
1204*7c478bd9Sstevel@tonic-gate keylen_t keylen,
1205*7c478bd9Sstevel@tonic-gate algtype_t algtype,
1206*7c478bd9Sstevel@tonic-gate uid_t uid,
1207*7c478bd9Sstevel@tonic-gate deskeyarray common,
1208*7c478bd9Sstevel@tonic-gate des_block key,
1209*7c478bd9Sstevel@tonic-gate keybuf3 *public,
1210*7c478bd9Sstevel@tonic-gate keybuf3 *secret)
1211*7c478bd9Sstevel@tonic-gate {
1212*7c478bd9Sstevel@tonic-gate struct cachekey *c;
1213*7c478bd9Sstevel@tonic-gate int ret;
1214*7c478bd9Sstevel@tonic-gate
1215*7c478bd9Sstevel@tonic-gate if ((c = get_cache_header(keylen, algtype)) == 0)
1216*7c478bd9Sstevel@tonic-gate return (0);
1217*7c478bd9Sstevel@tonic-gate
1218*7c478bd9Sstevel@tonic-gate if (c->ch == 0) {
1219*7c478bd9Sstevel@tonic-gate release_cache_header(c);
1220*7c478bd9Sstevel@tonic-gate return (0);
1221*7c478bd9Sstevel@tonic-gate }
1222*7c478bd9Sstevel@tonic-gate
1223*7c478bd9Sstevel@tonic-gate ret = (c->ch =
1224*7c478bd9Sstevel@tonic-gate cache_insert_ch(c->ch, uid, common, key, public, secret)) != 0;
1225*7c478bd9Sstevel@tonic-gate
1226*7c478bd9Sstevel@tonic-gate release_cache_header(c);
1227*7c478bd9Sstevel@tonic-gate
1228*7c478bd9Sstevel@tonic-gate return (ret);
1229*7c478bd9Sstevel@tonic-gate }
1230*7c478bd9Sstevel@tonic-gate
1231*7c478bd9Sstevel@tonic-gate
1232*7c478bd9Sstevel@tonic-gate struct cachekey3_list *
cache_retrieve(keylen_t keylen,algtype_t algtype,uid_t uid,keybuf3 * public,des_block key)1233*7c478bd9Sstevel@tonic-gate cache_retrieve(
1234*7c478bd9Sstevel@tonic-gate keylen_t keylen,
1235*7c478bd9Sstevel@tonic-gate algtype_t algtype,
1236*7c478bd9Sstevel@tonic-gate uid_t uid,
1237*7c478bd9Sstevel@tonic-gate keybuf3 *public,
1238*7c478bd9Sstevel@tonic-gate des_block key)
1239*7c478bd9Sstevel@tonic-gate {
1240*7c478bd9Sstevel@tonic-gate struct cachekey *c;
1241*7c478bd9Sstevel@tonic-gate struct cachekey3_list *cl;
1242*7c478bd9Sstevel@tonic-gate
1243*7c478bd9Sstevel@tonic-gate if ((c = get_cache_header(keylen, algtype)) == 0)
1244*7c478bd9Sstevel@tonic-gate return (0);
1245*7c478bd9Sstevel@tonic-gate
1246*7c478bd9Sstevel@tonic-gate if (c->ch == 0) {
1247*7c478bd9Sstevel@tonic-gate release_cache_header(c);
1248*7c478bd9Sstevel@tonic-gate return (0);
1249*7c478bd9Sstevel@tonic-gate }
1250*7c478bd9Sstevel@tonic-gate
1251*7c478bd9Sstevel@tonic-gate cl = cache_retrieve_ch(c->ch, uid, public, key);
1252*7c478bd9Sstevel@tonic-gate
1253*7c478bd9Sstevel@tonic-gate release_cache_header(c);
1254*7c478bd9Sstevel@tonic-gate
1255*7c478bd9Sstevel@tonic-gate return (cl);
1256*7c478bd9Sstevel@tonic-gate }
1257*7c478bd9Sstevel@tonic-gate
1258*7c478bd9Sstevel@tonic-gate int
cache_remove(keylen_t keylen,algtype_t algtype,uid_t uid,keybuf3 * public)1259*7c478bd9Sstevel@tonic-gate cache_remove(keylen_t keylen, algtype_t algtype, uid_t uid, keybuf3 *public)
1260*7c478bd9Sstevel@tonic-gate {
1261*7c478bd9Sstevel@tonic-gate struct cachekey *c;
1262*7c478bd9Sstevel@tonic-gate int ret;
1263*7c478bd9Sstevel@tonic-gate
1264*7c478bd9Sstevel@tonic-gate if ((c = get_cache_header(keylen, algtype)) == 0)
1265*7c478bd9Sstevel@tonic-gate return (0);
1266*7c478bd9Sstevel@tonic-gate
1267*7c478bd9Sstevel@tonic-gate if (c->ch == 0) {
1268*7c478bd9Sstevel@tonic-gate release_cache_header(c);
1269*7c478bd9Sstevel@tonic-gate return (0);
1270*7c478bd9Sstevel@tonic-gate }
1271*7c478bd9Sstevel@tonic-gate
1272*7c478bd9Sstevel@tonic-gate ret = cache_remove_ch(c->ch, uid, public);
1273*7c478bd9Sstevel@tonic-gate
1274*7c478bd9Sstevel@tonic-gate release_cache_header(c);
1275*7c478bd9Sstevel@tonic-gate
1276*7c478bd9Sstevel@tonic-gate return (ret);
1277*7c478bd9Sstevel@tonic-gate }
1278*7c478bd9Sstevel@tonic-gate
1279*7c478bd9Sstevel@tonic-gate
1280*7c478bd9Sstevel@tonic-gate static struct dhkey *
keybuf3_2_dhkey(keybuf3 * hexkey)1281*7c478bd9Sstevel@tonic-gate keybuf3_2_dhkey(keybuf3 *hexkey)
1282*7c478bd9Sstevel@tonic-gate {
1283*7c478bd9Sstevel@tonic-gate struct dhkey *binkey;
1284*7c478bd9Sstevel@tonic-gate
1285*7c478bd9Sstevel@tonic-gate /* hexkey->keybuf3_len*4 is the key length in bits */
1286*7c478bd9Sstevel@tonic-gate if ((binkey = malloc(DHKEYALLOC(hexkey->keybuf3_len*4))) == 0)
1287*7c478bd9Sstevel@tonic-gate return (0);
1288*7c478bd9Sstevel@tonic-gate
1289*7c478bd9Sstevel@tonic-gate /* Set to zero to keep dbx and Purify access checking happy */
1290*7c478bd9Sstevel@tonic-gate memset(binkey, 0, DHKEYALLOC(hexkey->keybuf3_len*4));
1291*7c478bd9Sstevel@tonic-gate
1292*7c478bd9Sstevel@tonic-gate binkey->length = hexkey->keybuf3_len/2;
1293*7c478bd9Sstevel@tonic-gate hex2bin((u_char *)hexkey->keybuf3_val, binkey->key,
1294*7c478bd9Sstevel@tonic-gate (int)binkey->length);
1295*7c478bd9Sstevel@tonic-gate
1296*7c478bd9Sstevel@tonic-gate return (binkey);
1297*7c478bd9Sstevel@tonic-gate }
1298