/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 1997 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <fcntl.h>
#include <unistd.h>
#include <thread.h>
#include <synch.h>
#include <stdlib.h>
#include <syslog.h>
#include <rpc/des_crypt.h>
#include "keyserv_cache.h"
struct cachekey {
};
struct skck {
};
struct cachekey_disklist {
/*
* Storage for encrypted skck structure here. The length will be
* 8 * ( ( ( sizeof(struct skck) - 1 + secret.length ) - 1 ) / 8 + 1 )
*/
};
/* Length of skck structure for given key length (in bits) */
/* Length of a cachekey_disklist record for given key length (in bits) */
#define CACHEKEY_HEADER_VERSION 0
};
int sizespec);
static void release_cache_header(struct cachekey *);
static int cache_remap_addresses_ch(
struct cachekey_header *);
static void list_remove(struct cachekey_disklist *,
struct cachekey_disklist **,
struct cachekey_disklist **,
u_int *);
static void list_remove_hash(struct cachekey_disklist *,
struct cachekey_disklist **,
struct cachekey_disklist **,
u_int *);
static void list_insert(struct cachekey_disklist *,
struct cachekey_disklist **,
struct cachekey_disklist **,
u_int *);
static void list_insert_hash(struct cachekey_disklist *,
struct cachekey_disklist **,
struct cachekey_disklist **,
u_int *);
struct cachekey_disklist *cd,
/*
* The folowing set of macros implement address validity checking. A valid
* address is defined to be either 0, or to fall on a record boundary. In
* the latter case, the the difference between the address and the start of
* the record array is divisible by the record length.
*/
/* Add offset to old address */
/* Number of records in use or on free list */
(ck_header)->free_count)
/* Max number of records the mapped file could hold */
sizeof (struct cachekey_header)) / \
/* Max number of records the file will hold if extended to the maxsize */
sizeof (struct cachekey_header)) / \
struct cachekey_header *
{
/* Construct cache file name */
return (0);
}
return (0);
}
/* We want exclusive use of the file */
return (0);
}
/* Zero size means a new file */
return (0);
}
if (sizespec < 0) {
/* specifies the number of records in file */
} else {
/* specifies size of file in MB */
}
/*
* First record resides partly in the header, so the length
* cannot be allowed to be less than header plus one record.
*/
else {
}
}
/* Extend the file if we just created it */
"cache file ftruncate error for mech %d-%d: %m",
return (0);
}
newfile = 1;
} else {
/*
* Temporarily mmap the header, to sanity check and obtain
* the address where it was mapped the last time.
*/
MAP_FAILED) {
"cache file mmap1 error for mech %d-%d: %m",
return (0);
}
"cache file consistency error for mech %d-%d",
return (0);
}
"cache file munmap error for mech %d-%d: %m",
return (0);
}
}
/* Map the file */
"cache file mmap2 error for mech %d-%d: %m",
return (0);
}
if (newfile) {
ch->inuse_count = 0;
ch->free_count = 0;
for (i = 0; i < NUMHASHBUCKETS; i++) {
}
}
/*
* Last record next pointer, and first record prev pointer,
* are both NULL.
*/
/* File should shrink */
return (0);
}
checkvalid = 0;
}
/*
* cache_remap_addresses() also checks address consistency, so call
* it even if the remap is a no-op. However, if we've called
* remap_cache_file_ch(), it will have invoked cache_remap_addresses()
* already, so we don't have to do that again.
*/
if (checkvalid &&
cache_remap_addresses_ch(ch) == 0) {
return (0);
}
return (ch);
}
static int
{
int i;
return (0);
}
return (0);
}
}
for (i = 0; i < NUMHASHBUCKETS; i++) {
return (0);
}
}
/*
* To prevent disaster if this function is invoked again, we
* update ch->address, so that offset will be zero if we do
* get called once more, and the mapped file hasn't moved.
*/
return (1);
}
/*
* Remap cache file with space for 'newrecs' records. The mmap:ed address
* may have to move; the new address is returned.
*/
static struct cachekey_header *
{
int i, fd;
if (ch == 0)
return (0);
/*
* Since the first record partly resides in the cachekey_header,
* newrecs cannot be less than 1.
*/
if (newrecs < 1)
newrecs = 1;
/* Would exceed maximum allowed */
}
/* Save stuff we need while the file is unmapped */
/* Extending the file */
/* Already OK */
return (ch);
} else {
/*
* Shrink the file by removing records from the end.
* First, we have to make sure the file contains valid
* addresses.
*/
if (cache_remap_addresses_ch(ch) == 0) {
return (0);
}
&(ch->free_count));
} else {
&(ch->inuse_count));
}
}
}
/* Unmap the file */
return (0);
}
ch = 0;
return (0);
}
/* Map it again */
MAP_FAILED) {
return (0);
}
/* Update with new values */
if (cache_remap_addresses_ch(newch) == 0) {
return (0);
}
/* If extending the file, add new records to the free list */
if (cd != 0) {
&(newch->free_count));
}
}
return (newch);
}
#ifdef DEBUG
void
{
int pb;
"\nkeylen = %d, algtype = %d, version = %d, headerlen = %d, reclen = %d\n",
printf("fd = %d, address = 0x%x, mapped length = %d, maxsize = %d\n",
printf("Active hash buckets:\n");
pb = -1;
if (cd != 0) {
pb = 0;
printf("\t%d: ", i);
}
while (cd != 0) {
pb++;
inuse++;
} else {
inuse_err++;
}
}
if (pb >= 0)
}
while (cd != 0) {
inuse++;
} else {
inuse_err++;
}
}
while (cd != 0) {
free++;
} else {
free_err++;
}
}
}
void
{
struct cachekey *c;
return;
if (c->ch == 0) {
return;
}
print_cache_ch(c->ch);
}
#endif
static u_int
{
return (uid % NUMHASHBUCKETS);
}
static void
struct cachekey_disklist *item,
struct cachekey_disklist **head,
struct cachekey_disklist **tail,
{
/* Handle previous item, if any */
else
/* Take care of the next item, if any */
/* Handle tail pointer, if supplied */
if (count != 0)
(*count)--;
}
static void
struct cachekey_disklist *item,
struct cachekey_disklist **head,
struct cachekey_disklist **tail,
{
/* Handle previous item, if any */
else
/* Take care of the next item, if any */
/* Handle tail pointer, if supplied */
if (count != 0)
(*count)--;
}
static void
struct cachekey_disklist *item,
struct cachekey_disklist **head,
struct cachekey_disklist **tail,
{
/* Insert at tail, if supplied */
if (tail != 0) {
if (*head == 0)
} else {
}
if (count != 0)
(*count)++;
}
static void
struct cachekey_disklist *item,
struct cachekey_disklist **head,
struct cachekey_disklist **tail,
{
/* Insert at tail, if supplied */
if (tail != 0) {
if (*head == 0)
} else {
}
if (count != 0)
(*count)++;
}
/*
* Find the cache item specified by the header, uid, and public key. If
* In either case, the item returned has been removed from any and all
* lists.
*/
static struct cachekey_disklist *
{
return (0);
}
&((*ch)->inuse_count));
return (cd);
}
}
return (cd);
}
/* Try to extend the file by CHUNK_NUMREC records */
return (0);
/* If the extend worked, there should now be at least one free record */
return (cd);
}
/* Sacrifice the LRU item, if there is one */
return (0);
/* Extract from hash list */
/* Extract from LRU list */
&((*ch)->inuse_count));
return (cd);
}
static struct cachekey_header *
struct cachekey_header *ch,
{
int i, err;
return (0);
}
return (0);
}
return (newch);
}
/*
* The item may have been free, or may have been the LRU sacrificial
* lamb, so reset all fields.
*/
for (i = 0; i < common.deskeyarray_len; i++) {
}
if (DES_FAILED(err)) {
/* Re-insert on free list */
return (newch);
}
/* Re-insert on hash list */
/* Insert at end of LRU list */
&(newch->inuse_count));
return (newch);
}
static struct cachekey3_list *
int i, err;
/* Allocate the cachekey3_list structure */
return (0);
}
/* Allocate skck structure for decryption */
return (0);
}
/* Decrypt and check verifier */
if (DES_FAILED(err)) {
return (0);
}
return (0);
}
/* Everything OK; copy values */
}
return (cl);
}
static struct cachekey3_list *
return (0);
}
/* Match on public key as well ? */
if (pk != 0) {
/* Keep looking... */
continue;
}
/* Match on public key => nothing more to do */
break;
}
if (*cltmp == 0) {
/* Return what we've got */
break;
}
/* On to the next item */
}
}
if (pk != 0)
return (cl);
}
/*
* Remove specified item. 'public' == 0 => remove all items for uid.
* Return number of items removed.
*/
static int
int match = 0;
return (0);
}
/* Match on public key as well ? */
if (pk != 0) {
/* Keep looking... */
continue;
}
match++;
&(ch->inuse_count));
&(ch->free_count));
/* Match on public key => nothing more to do */
break;
}
match++;
/*
* XXX: Assume that the order of the hash list remains
* the same after removal of an item. If this isn't
* true, we really should start over from the start
* of the hash bucket.
*/
&(ch->inuse_count));
&(ch->free_count));
/* On to the next item */
} else {
}
}
return (match);
}
cache_refcnt++; \
if (cache_refcnt > 0) \
#else
#endif
/*
* Return the cachekey structure for the specified keylen and algtype.
* When returned, the lock in the structure has been activated. It's the
* responsibility of the caller to unlock it by calling release_cache_header().
*/
static struct cachekey *
struct cachekey *c;
mutex_lock(&c->mp);
return (c);
}
}
/* Spin until there are no cache readers */
if (cache_refcnt > 0)
#endif
cache_refcnt--;
while (cache_refcnt != 0) {
}
c->ch = 0;
mutex_init(&c->mp, 0, 0);
cache = c;
mutex_lock(&c->mp);
cache_refcnt++;
return (c);
}
return (0);
}
static void
struct cachekey *c;
if (ck == 0)
return;
if (c == ck) {
mutex_unlock(&c->mp);
break;
}
}
}
int
{
struct cachekey *c;
int ret;
return (0);
if (c->ch != 0) {
/* Already created and opened */
return (1);
}
return (ret);
}
int
{
struct cachekey *c;
int ret;
return (0);
if (c->ch == 0) {
return (0);
}
return (ret);
}
struct cachekey3_list *
{
struct cachekey *c;
return (0);
if (c->ch == 0) {
return (0);
}
return (cl);
}
int
{
struct cachekey *c;
int ret;
return (0);
if (c->ch == 0) {
return (0);
}
return (ret);
}
static struct dhkey *
{
/* hexkey->keybuf3_len*4 is the key length in bits */
return (0);
/* Set to zero to keep dbx and Purify access checking happy */
return (binkey);
}