[196] in Kerberos-V5-bugs

home help back first fref pref prev next nref lref last post

shar file for support of deletion in keytab/file

daemon@ATHENA.MIT.EDU (Joe Pato)
Tue Sep 10 14:07:07 1991

From: pato@apollo.com (Joe Pato)
Date: Tue, 10 Sep 91 14:03:19 EDT
To: krb5-bugs@MIT.EDU
Cc: tytso@athena.mit.edu

This shar file contains the modifications to the beta1 keytab code to support
deletion from the keytab file.  This involves a change in format to the keytab
file (defined in ktf_util.c).  We have also added a timestamp field to the 
krb5_keytab_entry data type (which is used by garbage collectors).  Included is
also lib/os/krbfileio.c which supports a function to create "secure" files and
another to sync a file to disk.

This shar file does not contain changes to the keytab API reflecting the use of
multiple keytypes (i.e., the get function should take a keytype as an
input argument so that it yields a key of the proper form) (this will follow
shortly).

                    -- Joe Pato
                       Cooperative Computing Division
                       Hewlett-Packard Company
                       pato@apollo.hp.com


#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 09/10/1991 17:57 UTC by pato@chelm
# Source directory //chelm/pato/sandbox/pe2/source
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#   3555 -rw-rw-r-- krb5.src/include/krb5/keytab.h
#   2887 -rw-rw-r-- krb5.src/lib/keytab/file/ktf_remove.c
#  15979 -rw-rw-r-- krb5.src/lib/keytab/file/ktf_util.c
#   4072 -rw-rw-r-- krb5.src/lib/keytab/file/ktfile.h
#   2131 -rw-rw-r-- krb5.src/lib/os/Imakefile
#   2543 -rw-rw-r-- krb5.src/lib/os/krbfileio.c
#
# ============= krb5.src/include/krb5/keytab.h ==============
if test ! -d 'krb5.src'; then
    echo 'x - creating directory krb5.src'
    mkdir 'krb5.src'
fi
if test ! -d 'krb5.src/include'; then
    echo 'x - creating directory krb5.src/include'
    mkdir 'krb5.src/include'
fi
if test ! -d 'krb5.src/include/krb5'; then
    echo 'x - creating directory krb5.src/include/krb5'
    mkdir 'krb5.src/include/krb5'
fi
if test -f 'krb5.src/include/krb5/keytab.h' -a X"$1" != X"-c"; then
	echo 'x - skipping krb5.src/include/krb5/keytab.h (File already exists)'
else
echo 'x - extracting krb5.src/include/krb5/keytab.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'krb5.src/include/krb5/keytab.h' &&
/*
X * $Source: /afs/athena.mit.edu/astaff/project/krb5/src/include/krb5/RCS/keytab.h,v $
X * $Author: jtkohl $
X * $Id: keytab.h,v 5.12 91/06/06 09:33:36 jtkohl Exp $
X *
X * Copyright 1990 by the Massachusetts Institute of Technology.
X * All Rights Reserved.
X *
X * Export of this software from the United States of America is assumed
X *   to require a specific license from the United States Government.
X *   It is the responsibility of any person or organization contemplating
X *   export to obtain such a license before exporting.
X * 
X * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
X * distribute this software and its documentation for any purpose and
X * without fee is hereby granted, provided that the above copyright
X * notice appear in all copies and that both that copyright notice and
X * this permission notice appear in supporting documentation, and that
X * the name of M.I.T. not be used in advertising or publicity pertaining
X * to distribution of the software without specific, written prior
X * permission.  M.I.T. makes no representations about the suitability of
X * this software for any purpose.  It is provided "as is" without express
X * or implied warranty.
X * 
X *
X * Keytab definitions.
X */
X
X
#ifndef KRB5_KEYTAB__
#define KRB5_KEYTAB__
X
X
/* XXX */
#define MAX_KEYTAB_NAME_LEN 1100 /* Long enough for MAXPATHLEN + some extra */
X
typedef krb5_pointer krb5_kt_cursor;	/* XXX */
X
typedef struct krb5_keytab_entry_st {
X    krb5_principal principal;	/* principal of this key */
X    krb5_timestamp timestamp;   /* time entry written to keytable */
X    krb5_kvno vno;		/* key version number */
X    krb5_keyblock key;		/* the secret key */
} krb5_keytab_entry;
X
X
typedef struct _krb5_kt {
X	struct _krb5_kt_ops *ops;
X	krb5_pointer data;
} *krb5_keytab;
X
X
/* widen prototypes, if needed */
#include <krb5/widen.h>
X
typedef struct _krb5_kt_ops {
X	char *prefix;
X        /* routines always present */
X	krb5_error_code (*resolve) PROTOTYPE((char *,
X					      krb5_keytab *));
X	krb5_error_code (*get_name) PROTOTYPE((krb5_keytab,
X					       char *,
X					       int));
X	krb5_error_code (*close) PROTOTYPE((krb5_keytab));
X	krb5_error_code (*get) PROTOTYPE((krb5_keytab,
X					  krb5_principal,
X					  krb5_kvno,
X					  krb5_keytab_entry *));
X	krb5_error_code (*start_seq_get) PROTOTYPE((krb5_keytab,
X						    krb5_kt_cursor *));	
X	krb5_error_code (*get_next) PROTOTYPE((krb5_keytab,
X					       krb5_keytab_entry *,
X					       krb5_kt_cursor *));
X	krb5_error_code (*end_get) PROTOTYPE((krb5_keytab,
X					      krb5_kt_cursor *));
X	/* routines to be included on extended version (write routines) */
X	krb5_error_code (*add) PROTOTYPE((krb5_keytab,
X					  krb5_keytab_entry *));
X	krb5_error_code (*remove) PROTOTYPE((krb5_keytab,
X					     krb5_keytab_entry *));
} krb5_kt_ops;
X
/* and back to narrow */
#include <krb5/narrow.h>
X
#define krb5_kt_get_name(keytab, name, namelen) (*(keytab)->ops->get_name)(keytab,name,namelen)
#define krb5_kt_close(keytab) (*(keytab)->ops->close)(keytab)
#define krb5_kt_get_entry(keytab, principal, vno, entry) (*(keytab)->ops->get)(keytab, principal, vno, entry)
#define krb5_kt_start_seq_get(keytab, cursor) (*(keytab)->ops->start_seq_get)(keytab, cursor)
#define krb5_kt_next_entry(keytab, entry, cursor) (*(keytab)->ops->get_next)(keytab, entry, cursor)
#define krb5_kt_end_seq_get(keytab, cursor) (*(keytab)->ops->end_get)(keytab, cursor)
/* remove and add are functions, so that they can return NOWRITE
X   if not a writable keytab */
X
X
extern krb5_kt_ops krb5_kt_dfl_ops;
X
#endif /* KRB5_KEYTAB__ */
SHAR_EOF
chmod 0664 krb5.src/include/krb5/keytab.h ||
echo 'restore of krb5.src/include/krb5/keytab.h failed'
Wc_c="`wc -c < 'krb5.src/include/krb5/keytab.h'`"
test 3555 -eq "$Wc_c" ||
	echo 'krb5.src/include/krb5/keytab.h: original size 3555, current size' "$Wc_c"
fi
# ============= krb5.src/lib/keytab/file/ktf_remove.c ==============
if test ! -d 'krb5.src/lib'; then
    echo 'x - creating directory krb5.src/lib'
    mkdir 'krb5.src/lib'
fi
if test ! -d 'krb5.src/lib/keytab'; then
    echo 'x - creating directory krb5.src/lib/keytab'
    mkdir 'krb5.src/lib/keytab'
fi
if test ! -d 'krb5.src/lib/keytab/file'; then
    echo 'x - creating directory krb5.src/lib/keytab/file'
    mkdir 'krb5.src/lib/keytab/file'
fi
if test -f 'krb5.src/lib/keytab/file/ktf_remove.c' -a X"$1" != X"-c"; then
	echo 'x - skipping krb5.src/lib/keytab/file/ktf_remove.c (File already exists)'
else
echo 'x - extracting krb5.src/lib/keytab/file/ktf_remove.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'krb5.src/lib/keytab/file/ktf_remove.c' &&
/*
X * $Source: /afs/athena.mit.edu/astaff/project/krb5/src/lib/keytab/file/RCS/ktf_remove.c,v $
X * $Author: pato $
X *
X * Copyright (c) Hewlett-Packard Company 1991
X * Released to the Massachusetts Institute of Technology for inclusion
X * in the Kerberos source code distribution.
X *
X * Copyright 1990, 1991 by the Massachusetts Institute of Technology.
X * All Rights Reserved.
X *
X * Export of this software from the United States of America is assumed
X *   to require a specific license from the United States Government.
X *   It is the responsibility of any person or organization contemplating
X *   export to obtain such a license before exporting.
X * 
X * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
X * distribute this software and its documentation for any purpose and
X * without fee is hereby granted, provided that the above copyright
X * notice appear in all copies and that both that copyright notice and
X * this permission notice appear in supporting documentation, and that
X * the name of M.I.T. not be used in advertising or publicity pertaining
X * to distribution of the software without specific, written prior
X * permission.  M.I.T. makes no representations about the suitability of
X * this software for any purpose.  It is provided "as is" without express
X * or implied warranty.
X * 
X *
X * krb5_ktfile_remove()
X */
X
#if !defined(lint) && !defined(SABER)
static char rcsid_ktf_add_c[] =
"$Id: ktf_remove.c,v 5.3 91/06/06 09:45:34 jtkohl Exp $";
#endif	/* !lint & !SABER */
X
#include <krb5/krb5.h>
#include <krb5/ext-proto.h>
X
#include "ktfile.h"
X
krb5_error_code
krb5_ktfile_remove(id, entry)
krb5_keytab id;
krb5_keytab_entry *entry;
{
X    krb5_keytab_entry   *cur_entry;
X    krb5_error_code     kerror;
X    krb5_int32          delete_point;
X    krb5_boolean        found = FALSE;
X
X    if (kerror = krb5_ktfileint_openw(id)) {
X	return kerror;
X    }
X
X    /* 
X     * For efficiency and simplicity, we'll use a while true that 
X     * is exited with a break statement.
X     */
X    while (TRUE) {
X	cur_entry = 0;
X	if (kerror = krb5_ktfileint_internal_read_entry(id, &cur_entry,
X                                                            &delete_point))
X  	    break;
X
X	if ((entry->vno == cur_entry->vno) &&
X            (entry->key.keytype == cur_entry->key.keytype) &&
X	    krb5_principal_compare(entry->principal, cur_entry->principal)) {
X	    /* found a match */
X            found = TRUE;
X            krb5_kt_free_entry(cur_entry);
X	    break;
X	}
X	krb5_kt_free_entry(cur_entry);
X    }
X
X    if (kerror && kerror != KRB5_KT_END) {
X	(void) krb5_ktfileint_close(id);
X	return kerror;
X    }
X
X    if (found) {
X        kerror = krb5_ktfileint_delete_entry(id, delete_point);
X    } else {
X        kerror = KRB5_KT_NOTFOUND;
X    }
X
X    if (kerror) {
X	(void) krb5_ktfileint_close(id);
X    } else {
X        kerror = krb5_ktfileint_close(id);
X    }
X
X    return kerror;
}
SHAR_EOF
chmod 0664 krb5.src/lib/keytab/file/ktf_remove.c ||
echo 'restore of krb5.src/lib/keytab/file/ktf_remove.c failed'
Wc_c="`wc -c < 'krb5.src/lib/keytab/file/ktf_remove.c'`"
test 2887 -eq "$Wc_c" ||
	echo 'krb5.src/lib/keytab/file/ktf_remove.c: original size 2887, current size' "$Wc_c"
fi
# ============= krb5.src/lib/keytab/file/ktf_util.c ==============
if test -f 'krb5.src/lib/keytab/file/ktf_util.c' -a X"$1" != X"-c"; then
	echo 'x - skipping krb5.src/lib/keytab/file/ktf_util.c (File already exists)'
else
echo 'x - extracting krb5.src/lib/keytab/file/ktf_util.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'krb5.src/lib/keytab/file/ktf_util.c' &&
/*
X * $Source: /afs/athena.mit.edu/astaff/project/krb5/src/lib/keytab/file/RCS/ktf_util.c,v $
X * $Author: jtkohl, pato $
X *
X * Copyright (c) Hewlett-Packard Company 1991
X * Released to the Massachusetts Institute of Technology for inclusion
X * in the Kerberos source code distribution.
X *
X * Copyright 1990,1991 by the Massachusetts Institute of Technology.
X * All Rights Reserved.
X *
X * Export of this software from the United States of America is assumed
X *   to require a specific license from the United States Government.
X *   It is the responsibility of any person or organization contemplating
X *   export to obtain such a license before exporting.
X * 
X * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
X * distribute this software and its documentation for any purpose and
X * without fee is hereby granted, provided that the above copyright
X * notice appear in all copies and that both that copyright notice and
X * this permission notice appear in supporting documentation, and that
X * the name of M.I.T. not be used in advertising or publicity pertaining
X * to distribution of the software without specific, written prior
X * permission.  M.I.T. makes no representations about the suitability of
X * this software for any purpose.  It is provided "as is" without express
X * or implied warranty.
X * 
X *
X * This function contains utilities for the file based implementation of 
X * the keytab.  There are no public functions in this file.
X *
X * This file is the only one that has knowledge of the format of a
X * keytab file.
X *
X * The format is as follows:
X * 
X * <file format vno>
X * <record length>
X * principal timestamp vno key
X * <record length>
X * principal timestamp vno key
X * ....
X *
X * A length field (sizeof(krb5_int32)) exists between entries.  When this
X * length is positive it indicates an active entry, when negative a hole.
X * The length indicates the size of the block in the file (this may be 
X * larger than the size of the next record, since we are using a first
X * fit algorithm for re-using holes and the first fit may be larger than
X * the entry we are writing).  Another (compatible) implementation could
X * break up holes when allocating them to smaller entries to minimize 
X * wasted space.  (Such an implementation should also coalesce adjacent
X * holes to reduce fragmentation).  This implementation does neither.
X *
X * There are no separators between fields of an entry.  
X * A principal is a length-encoded array of length-encoded strings.  The
X * length is a krb5_int16 in each case.  The specific format, then, is 
X * multiple entries concatinated with no separators.  An entry has this 
X * exact format:
X *
X * sizeof(krb5_int16) bytes for number of components in the principal; 
X * then, each component listed in ordser.
X * For each component, sizeof(krb5_int16) bytes for the number of bytes
X * in the component, followed by the component.
X * sizeof(krb5_timestamp) bytes for the timestamp
X * sizeof(krb5_kvno) bytes for the key version number
X * sizeof(krb5_keytype) bytes for the keytype
X * sizeof(krb5_int32) bytes for the key length, followed by the key
X *
X */
X
#if !defined(lint) && !defined(SABER)
static char rcsid_ktf_util_c[] =
"$Id: ktf_util.c,v 5.12 91/06/06 09:44:54 jtkohl Exp $";
#endif	/* !lint & !SABER */
X
#include <krb5/krb5.h>
#include <krb5/ext-proto.h>
#include <krb5/libos.h>
#include <krb5/los-proto.h>
X
#include "ktfile.h"
#include <krb5/osconf.h>
X
#ifdef KRB5_USE_INET
#include <netinet/in.h>
#else
X #error find some way to use net-byte-order file version numbers.
#endif
X
#define KRB5_KT_VNO	0x0501		/* krb5, keytab v 1 */
typedef krb5_int16  krb5_kt_vno;
X
#define xfwrite(a, b, c, d) fwrite((char *)a, b, c, d)
#define xfread(a, b, c, d) fread((char *)a, b, c, d)
X
extern int errno;
X
static krb5_error_code
krb5_ktfileint_open(id, mode)
krb5_keytab id;
int mode;
{
X    krb5_error_code kerror;
X    krb5_kt_vno kt_vno = htons(KRB5_KT_VNO);
X    int writevno = 0;
X
#if defined(__STDC__)
X    KTFILEP(id) = fopen(KTFILENAME(id),
X			(mode == KRB5_LOCKMODE_EXCLUSIVE) ? "rb+" : "rb");
#else
X    KTFILEP(id) = fopen(KTFILENAME(id),
X			(mode == KRB5_LOCKMODE_EXCLUSIVE) ? "r+" : "r");
#endif
X    if (!KTFILEP(id)) {
X	if ((mode == KRB5_LOCKMODE_EXCLUSIVE) && (errno == ENOENT)) {
X	    /* try making it first time around */
X            krb5_create_secure_file(KTFILENAME(id));
#if defined(__STDC__)
X	    KTFILEP(id) = fopen(KTFILENAME(id), "rb+");
#else
X	    KTFILEP(id) = fopen(KTFILENAME(id), "r+");
#endif
X	    if (!KTFILEP(id))
X		return errno;
X	    writevno = 1;
X	} else				/* some other error */
X	    return errno;
X    }
X    if (kerror = krb5_lock_file(KTFILEP(id), KTFILENAME(id),
X				mode)) {
X	(void) fclose(KTFILEP(id));
X	KTFILEP(id) = 0;
X	return kerror;
X    }
X    /* assume ANSI or BSD-style stdio */
X    setbuf(KTFILEP(id), NULL);
X
X    /* get the vno and verify it */
X    if (writevno) {
X	if (!xfwrite(&kt_vno, sizeof(kt_vno), 1, KTFILEP(id))) {
X	    kerror = errno;
X	    (void) krb5_unlock_file(KTFILEP(id), KTFILENAME(id));
X	    (void) fclose(KTFILEP(id));
X	    return kerror;
X	}
X    } else {
X	/* gotta verify it instead... */
X	if (!xfread(&kt_vno, sizeof(kt_vno), 1, KTFILEP(id))) {
X	    kerror = errno;
X	    (void) krb5_unlock_file(KTFILEP(id), KTFILENAME(id));
X	    (void) fclose(KTFILEP(id));
X	    return kerror;
X	}
X	if (kt_vno != ntohs(KRB5_KT_VNO)) {
X	    (void) krb5_unlock_file(KTFILEP(id), KTFILENAME(id));
X	    (void) fclose(KTFILEP(id));
X	    return -1 /* KRB5_KEYTAB_BADVNO */;
X	}
X    }
X    return 0;
}
X
krb5_error_code
krb5_ktfileint_openr(id)
krb5_keytab id;
{
X    return krb5_ktfileint_open(id, KRB5_LOCKMODE_SHARED);
}
X
krb5_error_code
krb5_ktfileint_openw(id)
krb5_keytab id;
{
X    return krb5_ktfileint_open(id, KRB5_LOCKMODE_EXCLUSIVE);
}
X
krb5_error_code
krb5_ktfileint_close(id)
krb5_keytab id;
{
X    krb5_error_code kerror;
X
X    if (!KTFILEP(id))
X	return 0;
X    kerror = krb5_unlock_file(KTFILEP(id), KTFILENAME(id));
X    (void) fclose(KTFILEP(id));
X    KTFILEP(id) = 0;
X    return kerror;
}
X
krb5_error_code
krb5_ktfileint_delete_entry(id, delete_point)
krb5_keytab id;
krb5_int32 delete_point;
{
X    krb5_int32  size;
X    krb5_int32  len;
X    char        iobuf[BUFSIZ];
X
X    if (fseek(KTFILEP(id), delete_point, SEEK_SET)) {
X        return errno;
X    }
X    if (!xfread(&size, sizeof(size), 1, KTFILEP(id))) {
X        return KRB5_KT_END;
X    }
X    if (size > 0) {
X        size = -size;
X        if (fseek(KTFILEP(id), delete_point, SEEK_SET)) {
X            return errno;
X        }
X        if (!xfwrite(&size, sizeof(size), 1, KTFILEP(id))) {
X            return KRB5_KT_IOERR;
X        }
X
X        size = -size;
X        if (size < BUFSIZ) {
X            len = size;
X        } else {
X            len = BUFSIZ;
X        }
X
X        memset(iobuf, 0, len);
X        while (size > 0) {
X            xfwrite(iobuf, 1, len, KTFILEP(id));
X            size -= len;
X            if (size < len) {
X                len = size;
X            }
X        }
X
X        return krb5_sync_disk_file(KTFILEP(id));
X    }
X
X    return 0;
}
X
krb5_error_code
krb5_ktfileint_internal_read_entry(id, entrypp, delete_point)
krb5_keytab id;
krb5_keytab_entry **entrypp;
krb5_int32 *delete_point;
{
X    register krb5_keytab_entry *ret_entry;
X    krb5_int16 count;
X    krb5_int16 princ_size;
X    register int i;
X    krb5_int32 size;
X    krb5_int32 start_pos;
X
X    if (!(ret_entry = (krb5_keytab_entry *)calloc(1, sizeof(*ret_entry))))
X	return ENOMEM;
X
X    do {
X        *delete_point = ftell(KTFILEP(id));
X        if (!xfread(&size, sizeof(size), 1, KTFILEP(id))) {
X            return KRB5_KT_END;
X        }
X
X        if (size < 0) {
X            if (fseek(KTFILEP(id), -size, SEEK_CUR)) {
X                return errno;
X            }
X        }
X    } while (size < 0);
X
X    if (size == 0) {
X        return KRB5_KT_END;
X    }
X
X    start_pos = ftell(KTFILEP(id));
X
X    /* deal with guts of parsing... */
X
X    /* first, int16 with #princ components */
X    if (!xfread(&count, sizeof(count), 1, KTFILEP(id)))
X	return KRB5_KT_END;
X    if (!count || (count < 0))
X	return KRB5_KT_END;
X    if (!(ret_entry->principal = (krb5_data **)calloc(count+1, sizeof(krb5_data *))))
X	return ENOMEM;
X    for (i = 0; i < count; i++) {
X	if (!xfread(&princ_size, sizeof(princ_size), 1, KTFILEP(id)))
X	    return KRB5_KT_END;
X	if (!princ_size || (princ_size < 0))
X	    return KRB5_KT_END;
X
X	if (!(ret_entry->principal[i] = (krb5_data *)malloc(sizeof(krb5_data))))
X	    return ENOMEM;
X	ret_entry->principal[i]->length = princ_size;
X	ret_entry->principal[i]->data = malloc(princ_size);
X	if (!ret_entry->principal[i]->data)
X	    return ENOMEM;
X	if (!xfread(ret_entry->principal[i]->data, sizeof(char), princ_size,
X		    KTFILEP(id)))
X	    return KRB5_KT_END;
X    }
X    if (!xfread(&ret_entry->timestamp, sizeof(ret_entry->timestamp), 1, KTFILEP(id)))
X	return KRB5_KT_END;
X    if (!xfread(&ret_entry->vno, sizeof(ret_entry->vno), 1, KTFILEP(id)))
X	return KRB5_KT_END;
X    /* key type */
X    if (!xfread(&ret_entry->key.keytype, sizeof(ret_entry->key.keytype), 1,
X		KTFILEP(id)))
X	return KRB5_KT_END;
X    /* key contents */
X    if (!xfread(&count, sizeof(count), 1, KTFILEP(id)))
X	return KRB5_KT_END;
X    if (!count || (count < 0))
X	return KRB5_KT_END;
X    ret_entry->key.length = count;
X    if (!(ret_entry->key.contents = (krb5_octet *)malloc(count)))
X	return ENOMEM;
X    if (!xfread(ret_entry->key.contents, sizeof(krb5_octet), count,
X		KTFILEP(id)))
X	return KRB5_KT_END;
X
X    *entrypp = ret_entry;
X
X    /*
X     * Reposition file pointer to the next inter-record length field.
X     */
X    fseek(KTFILEP(id), start_pos + size, SEEK_SET);
X    return 0;
}
X
krb5_error_code
krb5_ktfileint_read_entry(id, entrypp)
krb5_keytab id;
krb5_keytab_entry **entrypp;
{
X    krb5_int32 delete_point;
X
X    return krb5_ktfileint_internal_read_entry(id, entrypp, &delete_point);
}
X
krb5_error_code
krb5_ktfileint_write_entry(id, entry)
krb5_keytab id;
krb5_keytab_entry *entry;
{
X    krb5_data **princp;
X    krb5_int16 count, size;
X    krb5_error_code retval = 0;
X    krb5_int32  size_needed;
X    krb5_int32  commit_point;
X    char iobuf[BUFSIZ];
X
X    retval = krb5_ktfileint_size_entry(entry, &size_needed);
X    if (retval)
X        return retval;
X    retval = krb5_ktfileint_find_slot(id, &size_needed, &commit_point);
X    if (retval)
X        return retval;
X
X    setbuf(KTFILEP(id), iobuf);
X
X    /* count up principal components */
X    for (count = 0, princp = entry->principal; *princp; princp++, count++);
X
X    if (!xfwrite(&count, sizeof(count), 1, KTFILEP(id))) {
X    abend:
X	setbuf(KTFILEP(id), 0);
X	return KRB5_KT_IOERR;
X    }
X
X    for (princp = entry->principal; *princp; princp++) {
X	size = (*princp)->length;
X	if (!xfwrite(&size, sizeof(size), 1, KTFILEP(id))) {
X	    goto abend;
X	}
X	if (!xfwrite((*princp)->data, sizeof(char), size, KTFILEP(id))) {
X	    goto abend;
X	}
X    }
X    /*
X     * Fill in the time of day the entry was written to the keytab.
X     */
X    if (krb5_timeofday(&entry->timestamp)) {
X        entry->timestamp = 0;
X    }
X    if (!xfwrite(&entry->timestamp, sizeof(entry->timestamp), 1, KTFILEP(id))) {
X	goto abend;
X    }
X    if (!xfwrite(&entry->vno, sizeof(entry->vno), 1, KTFILEP(id))) {
X	goto abend;
X    }
X    if (!xfwrite(&entry->key.keytype, sizeof(entry->key.keytype), 1,
X		 KTFILEP(id))) {
X	goto abend;
X    }
X    size = entry->key.length;
X    if (!xfwrite(&size, sizeof(size), 1, KTFILEP(id))) {
X	goto abend;
X    }
X    if (!xfwrite(entry->key.contents, sizeof(krb5_octet), size, KTFILEP(id))) {
X	memset(iobuf, 0, sizeof(iobuf));
X	setbuf(KTFILEP(id), 0);
X	return KRB5_KT_IOERR;
X    }	
X
X    retval = krb5_sync_disk_file(KTFILEP(id));
X    (void) memset(iobuf, 0, sizeof(iobuf));
X    setbuf(KTFILEP(id), 0);
X
X    if (retval) {
X        return retval;
X    }
X
X    if (fseek(KTFILEP(id), commit_point, SEEK_SET)) {
X        return errno;
X    }
X    if (!xfwrite(&size_needed, sizeof(size_needed), 1, KTFILEP(id))) {
X        goto abend;
X    }
X    retval = krb5_sync_disk_file(KTFILEP(id));
X
X    return retval;
}
X
/*
X * Determine the size needed for a file entry for the given
X * keytab entry.
X */
krb5_error_code
krb5_ktfileint_size_entry(entry, size_needed)
krb5_keytab_entry *entry;
krb5_int32 *size_needed;
{
X    krb5_data **princp;
X    krb5_int16 count, size;
X    krb5_int32 total_size;
X    krb5_error_code retval = 0;
X
X    /* count up principal components */
X    for (count = 0, princp = entry->principal; *princp; princp++, count++);
X
X    total_size = sizeof(count);
X
X    for (princp = entry->principal; *princp; princp++) {
X	total_size += (*princp)->length + (sizeof(size));
X    }
X
X    total_size += sizeof(entry->timestamp);
X    total_size += sizeof(entry->vno);
X    total_size += sizeof(entry->key.keytype);
X    total_size += sizeof(size) + entry->key.length;
X
X    *size_needed = total_size;
X    return retval;
}
X
/*
X * Find and reserve a slot in the file for an entry of the needed size.
X * The commit point will be set to the position in the file where the
X * the length (sizeof(krb5_int32) bytes) of this node should be written
X * when commiting the write.  The file position left as a result of this
X * call is the position where the actual data should be written.
X *
X * The size_needed argument may be adjusted if we find a hole that is
X * larger than the size needed.  (Recall that size_needed will be used
X * to commit the write, but that this field must indicate the size of the
X * block in the file rather than the size of the actual entry)  
X */
krb5_error_code
krb5_ktfileint_find_slot(id, size_needed, commit_point)
krb5_keytab id;
krb5_int32 *size_needed;
krb5_int32 *commit_point;
{
X    krb5_int32      size;
X    krb5_int32      remainder;
X    krb5_int32      zero_point;
X    krb5_kt_vno     kt_vno;
X    krb5_boolean    found = FALSE;
X    char            iobuf[BUFSIZ];
X
X    /*
X     * Skip over file version number
X     */
X    if (fseek(KTFILEP(id), 0, SEEK_SET)) {
X        return errno;
X    }
X    if (!xfread(&kt_vno, sizeof(kt_vno), 1, KTFILEP(id))) {
X        return KRB5_KT_IOERR;
X    }
X
X    while (!found) {
X        *commit_point = ftell(KTFILEP(id));
X        if (!xfread(&size, sizeof(size), 1, KTFILEP(id))) {
X            /*
X             * Hit the end of file, reserve this slot.
X             */
X            setbuf(KTFILEP(id), 0);
X            size = 0;
X            if (!xfwrite(&size, sizeof(size), 1, KTFILEP(id))) {
X            abend:
X                return KRB5_KT_IOERR;
X            }
X            found = TRUE;
X        }
X
X        if (size > 0) {
X            if (fseek(KTFILEP(id), size, SEEK_CUR)) {
X                return errno;
X            }
X        } else if (!found) {
X            size = -size;
X            if (size >= *size_needed) {
X                *size_needed = size;
X                found = TRUE;	
X            } else if (size > 0) {
X                /*
X                 * The current hole is not large enough, so skip it
X                 */
X                if (fseek(KTFILEP(id), size, SEEK_CUR)) {
X                    return errno;
X                }
X            } else {
X                /*
X                 * Found the end of the file (marked by a 0 length buffer)
X                 * Make sure we zero any trailing data.
X                 */
X                zero_point = ftell(KTFILEP(id));
X                setbuf(KTFILEP(id), iobuf);
X                while (size = xfread(iobuf, 1, sizeof(iobuf), KTFILEP(id))) {
X                    if (size != sizeof(iobuf)) {
X                        remainder = size % sizeof(krb5_int32);
X                        if (remainder) {
X                            size += sizeof(krb5_int32) - remainder;
X                        }
X                    }
X                    memset(iobuf, 0, size);
X                    xfwrite(iobuf, 1, size, KTFILEP(id));
X                    if (feof(KTFILEP(id))) {
X                        break;
X                    }
X                }
X                setbuf(KTFILEP(id), 0);
X                if (fseek(KTFILEP(id), zero_point, SEEK_SET)) {
X                    return errno;
X                }
X            }
X        }
X    }
X
X    return 0;
}
X
SHAR_EOF
chmod 0664 krb5.src/lib/keytab/file/ktf_util.c ||
echo 'restore of krb5.src/lib/keytab/file/ktf_util.c failed'
Wc_c="`wc -c < 'krb5.src/lib/keytab/file/ktf_util.c'`"
test 15979 -eq "$Wc_c" ||
	echo 'krb5.src/lib/keytab/file/ktf_util.c: original size 15979, current size' "$Wc_c"
fi
# ============= krb5.src/lib/keytab/file/ktfile.h ==============
if test -f 'krb5.src/lib/keytab/file/ktfile.h' -a X"$1" != X"-c"; then
	echo 'x - skipping krb5.src/lib/keytab/file/ktfile.h (File already exists)'
else
echo 'x - extracting krb5.src/lib/keytab/file/ktfile.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'krb5.src/lib/keytab/file/ktfile.h' &&
/*
X * $Source: /afs/athena.mit.edu/astaff/project/krb5/src/lib/keytab/file/RCS/ktfile.h,v $
X * $Author: jtkohl $
X * $Id: ktfile.h,v 5.7 91/06/06 09:45:18 jtkohl Exp $
X *
X * Copyright 1990 by the Massachusetts Institute of Technology.
X * All Rights Reserved.
X *
X * Export of this software from the United States of America is assumed
X *   to require a specific license from the United States Government.
X *   It is the responsibility of any person or organization contemplating
X *   export to obtain such a license before exporting.
X * 
X * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
X * distribute this software and its documentation for any purpose and
X * without fee is hereby granted, provided that the above copyright
X * notice appear in all copies and that both that copyright notice and
X * this permission notice appear in supporting documentation, and that
X * the name of M.I.T. not be used in advertising or publicity pertaining
X * to distribution of the software without specific, written prior
X * permission.  M.I.T. makes no representations about the suitability of
X * this software for any purpose.  It is provided "as is" without express
X * or implied warranty.
X * 
X *
X * This header file contains information needed by internal routines
X * of the file-based ticket cache implementation.
X */
X
X
#ifndef KRB5_KTFILE__
#define KRB5_KTFILE__
X
#include <stdio.h>
X
/*
X * Constants
X */
#define IGNORE_VNO 0
X
X
/* 
X * Types
X */
typedef struct _krb5_ktfile_data {
X    char *name;			/* Name of the file */
X    FILE *openf;		/* open file, if any. */
} krb5_ktfile_data;
X
/*
X * Macros
X */
#define KTPRIVATE(id) ((krb5_ktfile_data *)(id)->data)
#define KTFILENAME(id) (((krb5_ktfile_data *)(id)->data)->name)
#define KTFILEP(id) (((krb5_ktfile_data *)(id)->data)->openf)
X
extern struct _krb5_kt_ops krb5_ktf_ops;
extern struct _krb5_kt_ops krb5_ktf_writable_ops;
X
/* widen prototypes, if needed */
#include <krb5/widen.h>
X
krb5_error_code krb5_ktfile_resolve PROTOTYPE((char *,
X					       krb5_keytab *));
krb5_error_code krb5_ktfile_wresolve PROTOTYPE((char *,
X					       krb5_keytab *));
krb5_error_code krb5_ktfile_get_name PROTOTYPE((krb5_keytab,
X						char *,
X						int));
krb5_error_code krb5_ktfile_close PROTOTYPE((krb5_keytab));
krb5_error_code krb5_ktfile_get_entry PROTOTYPE((krb5_keytab,
X						 krb5_principal,
X						 krb5_kvno,
X						 krb5_keytab_entry *));
krb5_error_code krb5_ktfile_start_seq_get PROTOTYPE((krb5_keytab,
X						     krb5_kt_cursor *));
krb5_error_code krb5_ktfile_get_next PROTOTYPE((krb5_keytab,
X						krb5_keytab_entry *,
X						krb5_kt_cursor *));
krb5_error_code krb5_ktfile_end_get PROTOTYPE((krb5_keytab,
X					       krb5_kt_cursor *));
/* routines to be included on extended version (write routines) */
krb5_error_code krb5_ktfile_add PROTOTYPE((krb5_keytab,
X					   krb5_keytab_entry *));
krb5_error_code krb5_ktfile_remove PROTOTYPE((krb5_keytab,
X					      krb5_keytab_entry *));
X
krb5_error_code krb5_ktfileint_openr PROTOTYPE((krb5_keytab));
krb5_error_code krb5_ktfileint_openw PROTOTYPE((krb5_keytab));
krb5_error_code krb5_ktfileint_close PROTOTYPE((krb5_keytab));
krb5_error_code krb5_ktfileint_read_entry PROTOTYPE((krb5_keytab,
X						     krb5_keytab_entry **));
krb5_error_code krb5_ktfileint_write_entry PROTOTYPE((krb5_keytab,
X						      krb5_keytab_entry *));
krb5_error_code krb5_ktfileint_delete_entry PROTOTYPE((krb5_keytab,
X                                                      krb5_int32));
krb5_error_code krb5_ktfileint_internal_read_entry PROTOTYPE((krb5_keytab,
X						     krb5_keytab_entry **,
X                                                     krb5_int32 *));
krb5_error_code krb5_ktfileint_size_entry PROTOTYPE((krb5_keytab_entry *,
X                                                      krb5_int32 *));
krb5_error_code krb5_ktfileint_find_slot PROTOTYPE((krb5_keytab,
X                                                      krb5_int32 *,
X                                                      krb5_int32 *));
/* and back to normal... */
#include <krb5/narrow.h>
X
#endif /* KRB5_KTFILE__ */
SHAR_EOF
chmod 0664 krb5.src/lib/keytab/file/ktfile.h ||
echo 'restore of krb5.src/lib/keytab/file/ktfile.h failed'
Wc_c="`wc -c < 'krb5.src/lib/keytab/file/ktfile.h'`"
test 4072 -eq "$Wc_c" ||
	echo 'krb5.src/lib/keytab/file/ktfile.h: original size 4072, current size' "$Wc_c"
fi
# ============= krb5.src/lib/os/Imakefile ==============
if test ! -d 'krb5.src/lib/os'; then
    echo 'x - creating directory krb5.src/lib/os'
    mkdir 'krb5.src/lib/os'
fi
if test -f 'krb5.src/lib/os/Imakefile' -a X"$1" != X"-c"; then
	echo 'x - skipping krb5.src/lib/os/Imakefile (File already exists)'
else
echo 'x - extracting krb5.src/lib/os/Imakefile (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'krb5.src/lib/os/Imakefile' &&
#	$Source: /afs/athena.mit.edu/astaff/project/krb5/src/lib/os/RCS/Imakefile,v $
#	$Author: jfc $
#	$Id: Imakefile,v 5.19 91/06/06 20:51:51 jfc Exp $
#
#  Copyright 1990,1991 by the Massachusetts Institute of Technology.
#  All Rights Reserved.
# 
# Export of this software from the United States of America is assumed
#   to require a specific license from the United States Government.
#   It is the responsibility of any person or organization contemplating
#   export to obtain such a license before exporting.
# 
# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
# distribute this software and its documentation for any purpose and
# without fee is hereby granted, provided that the above copyright
# notice appear in all copies and that both that copyright notice and
# this permission notice appear in supporting documentation, and that
# the name of M.I.T. not be used in advertising or publicity pertaining
# to distribution of the software without specific, written prior
# permission.  M.I.T. makes no representations about the suitability of
# this software for any purpose.  It is provided "as is" without express
# or implied warranty.
# 
# 
NormalLibraryObjectRule()
X
OBJS= \
X	an_to_ln.o	\
X	def_realm.o	\
X	ccdefname.o	\
X	free_krbhs.o	\
X	free_hstrl.o	\
X	full_ipadr.o	\
X	get_krbhst.o	\
X	gen_port.o	\
X	gen_rname.o	\
X	hst_realm.o	\
X        krbfileio.o     \
X	ktdefname.o	\
X	kuserok.o	\
X	localaddr.o	\
X	locate_kdc.o	\
X	lock_file.o	\
X	net_read.o	\
X	net_write.o	\
X	osconfig.o	\
X	port2ip.o	\
X	rnd_confoun.o	\
X	read_msg.o	\
X	read_pwd.o	\
X	sendto_kdc.o	\
X	sn2princ.o	\
X	timeofday.o	\
X	unlck_file.o	\
X	ustime.o	\
X	write_msg.o
X
X
SRCS= \
X	an_to_ln.c	\
X	def_realm.c	\
X	ccdefname.c	\
X	free_krbhs.c	\
X	free_hstrl.c	\
X	full_ipadr.c	\
X	get_krbhst.c	\
X	gen_port.c	\
X	gen_rname.c	\
X	hst_realm.c	\
X        krbfileio.c     \
X	ktdefname.c	\
X	kuserok.c	\
X	localaddr.c	\
X	locate_kdc.c	\
X	lock_file.c	\
X	net_read.c	\
X	net_write.c	\
X	osconfig.c	\
X	read_msg.c	\
X	read_pwd.c	\
X	port2ip.c	\
X	rnd_confoun.c	\
X	sendto_kdc.c	\
X	sn2princ.c	\
X	timeofday.c	\
X	unlck_file.c	\
X	ustime.c	\
X	write_msg.c
X
OtherdirLibraryTarget(..,krb5,$(OBJS))
SHAR_EOF
chmod 0664 krb5.src/lib/os/Imakefile ||
echo 'restore of krb5.src/lib/os/Imakefile failed'
Wc_c="`wc -c < 'krb5.src/lib/os/Imakefile'`"
test 2131 -eq "$Wc_c" ||
	echo 'krb5.src/lib/os/Imakefile: original size 2131, current size' "$Wc_c"
fi
# ============= krb5.src/lib/os/krbfileio.c ==============
if test -f 'krb5.src/lib/os/krbfileio.c' -a X"$1" != X"-c"; then
	echo 'x - skipping krb5.src/lib/os/krbfileio.c (File already exists)'
else
echo 'x - extracting krb5.src/lib/os/krbfileio.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'krb5.src/lib/os/krbfileio.c' &&
/*
X * $Source: /afs/athena.mit.edu/astaff/project/krb5/src/lib/os/RCS/krbfileio.c,v $
X * $Author: pato $
X *
X *
X * Copyright (c) Hewlett-Packard Company 1991
X * Released to the Massachusetts Institute of Technology for inclusion
X * in the Kerberos source code distribution.
X *
X * Copyright 1991 by the Massachusetts Institute of Technology.
X * All Rights Reserved.
X *
X * Export of this software from the United States of America is assumed
X *   to require a specific license from the United States Government.
X *   It is the responsibility of any person or organization contemplating
X *   export to obtain such a license before exporting.
X * 
X * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
X * distribute this software and its documentation for any purpose and
X * without fee is hereby granted, provided that the above copyright
X * notice appear in all copies and that both that copyright notice and
X * this permission notice appear in supporting documentation, and that
X * the name of M.I.T. not be used in advertising or publicity pertaining
X * to distribution of the software without specific, written prior
X * permission.  M.I.T. makes no representations about the suitability of
X * this software for any purpose.  It is provided "as is" without express
X * or implied warranty.
X * 
X *
X * krb5_create_secure_file
X * krb5_sync_disk_file
X */
X
#ifdef MODULE_VERSION_ID
static char *VersionID = "@(#)krbfileio.c	2 - 08/22/91";
#endif
X
#include <krb5/krb5.h>
#include <krb5/libos.h>
X
#include <stdio.h>
#include <sys/file.h>
X
#include <sys/types.h>
#include <krb5/ext-proto.h>
X
#ifdef apollo
#   define OPEN_MODE_NOT_TRUSTWORTHY
#endif
X
krb5_error_code
krb5_create_secure_file(pathname)
X    char *pathname;
{
X    int fd;
X
X    /*
X     * Create the file with access restricted to the owner
X     */
X    fd = open(pathname, O_RDWR | O_CREAT | O_EXCL, 0600);
X
#ifdef OPEN_MODE_NOT_TRUSTWORTHY
X    /*
X     * Some systems that support default acl inheritance do not 
X     * apply ownership information from the process - force the file
X     * to have the proper info.
X     */
X    if (fd > -1) {
X        uid_t   uid;
X        gid_t   gid;
X
X        uid = getuid();
X        gid = getgid();
X
X        fchown(fd, uid, gid);
X
X        fchmod(fd, 0600);
X    }
#endif /* OPEN_MODE_NOT_TRUSTWORTHY */
X
X    if (fd > -1) {
X        close(fd);
X        return 0;
X    } else {
X        return errno;
X    }
}
X
krb5_error_code
krb5_sync_disk_file(fp)
X    FILE *fp;
{
X    fflush(fp);
X    if (fsync(fileno(fp))) {
X        return errno;
X    }
X
X    return 0;
}
X
SHAR_EOF
chmod 0664 krb5.src/lib/os/krbfileio.c ||
echo 'restore of krb5.src/lib/os/krbfileio.c failed'
Wc_c="`wc -c < 'krb5.src/lib/os/krbfileio.c'`"
test 2543 -eq "$Wc_c" ||
	echo 'krb5.src/lib/os/krbfileio.c: original size 2543, current size' "$Wc_c"
fi
exit 0
-------

home help back first fref pref prev next nref lref last post