[2221] in Kerberos_V5_Development
v4srvtab.c
daemon@ATHENA.MIT.EDU (Greg Hudson)
Fri Feb 14 13:57:39 1997
Date: Fri, 14 Feb 1997 13:56:28 -0500
From: Greg Hudson <ghudson@MIT.EDU>
To: krbdev@MIT.EDU
Sam said you guys might be interested in this. It's an implementation
of a keytab type (which doesn't currently support iteration) which
uses a Kerberos 4 srvtab. It uses the krb4 libraries, so it isn't
suitable for inclusion in under lib/krb5/keytab.
A few things (the filename, the #ifdef KERBEROS, the ktv4_init()
function, the lack of the krb5() prefix on symbols) reflect that I
wrote this for inclusion in klogind and kshd, and not for inclusion in
the krb5 library.
One interesting screw you should be aware of: this implementation uses
get_service_key() in the krb4 compatibility library, which does not
have the code for falling back to the krb5 srvtab code (a good thing,
for my purposes, since I don't want to get into a loop). I have no
idea why the fallback code was implemented in read_service_key() (a
wrapper function) and not in get_service_key().
/*
* appl/bsd/v4srvtab.c
*
* Copyright 1997 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
* 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.
*
*/
#ifdef KERBEROS
#include "k5-int.h"
/* The maximum sizes for V4 aname, realm, sname, and instance +1 */
/* Taken from krb.h */
#define ANAME_SZ 40
#define REALM_SZ 40
#define SNAME_SZ 40
#define INST_SZ 40
static krb5_error_code ktv4_resolve(krb5_context context, const char *name,
krb5_keytab *id);
static krb5_error_code ktv4_get_name(krb5_context context, krb5_keytab id,
char *name, int len);
static krb5_error_code ktv4_close(krb5_context context, krb5_keytab id);
static krb5_error_code ktv4_get_entry(krb5_context context, krb5_keytab id,
krb5_principal principal, krb5_kvno kvno,
krb5_enctype enctype,
krb5_keytab_entry *entry);
krb5_kt_ops ktv4_ops = {
0,
"V4SRVTAB", /* Prefix -- this string should not appear anywhere else! */
ktv4_resolve,
ktv4_get_name,
ktv4_close,
ktv4_get_entry,
0,
0,
0,
0,
0,
NULL
};
typedef struct _ktv4_data {
char *name;
} ktv4_data;
void ktv4_init(krb5_context context)
{
krb5_kt_register(context, &ktv4_ops);
setenv("KRB5_KTNAME", "V4SRVTAB:/etc/athena/srvtab", 0);
}
static krb5_error_code ktv4_resolve(krb5_context context, const char *name,
krb5_keytab *id)
{
ktv4_data *data;
if ((*id = (krb5_keytab) malloc(sizeof(**id))) == NULL)
return(ENOMEM);
(*id)->ops = &ktv4_ops;
if ((data = (ktv4_data *)malloc(sizeof(ktv4_data))) == NULL) {
krb5_xfree(*id);
return(ENOMEM);
}
if ((data->name = (char *)malloc(strlen(name) + 1)) == NULL) {
krb5_xfree(data);
krb5_xfree(*id);
return(ENOMEM);
}
(void) strcpy(data->name, name);
(*id)->data = (krb5_pointer)data;
(*id)->magic = KV5M_KEYTAB;
return(0);
}
static krb5_error_code ktv4_get_name(krb5_context context, krb5_keytab id,
char *name, int len)
{
ktv4_data *data = (ktv4_data *)id->data;
if (len < strlen(id->ops->prefix) + strlen(data->name) + 2)
return(KRB5_KT_NAME_TOOLONG);
sprintf(name, "%s:%s", id->ops->prefix, data->name);
return(0);
}
static krb5_error_code ktv4_close(krb5_context context, krb5_keytab id)
{
krb5_xfree(((ktv4_data *)id->data)->name);
krb5_xfree(id->data);
id->ops = 0;
krb5_xfree(id);
return(0);
}
static krb5_error_code ktv4_get_entry(krb5_context context, krb5_keytab id,
krb5_principal principal, krb5_kvno kvno,
krb5_enctype enctype,
krb5_keytab_entry *entry)
{
char *filename = ((ktv4_data *)id->data)->name;
krb5_error_code code;
int v4code, v4kvno = kvno;
char v4name[ANAME_SZ], v4inst[INST_SZ], v4realm[REALM_SZ], v4key[8];
/* Translate to a Kerberos 4 principal. */
code = krb5_524_conv_principal(context, principal, v4name, v4inst,
v4realm);
if (code)
return(code);
/* Look up the requested key in the srvtab. */
v4code = get_service_key(v4name, v4inst, v4realm, &v4kvno, filename,
v4key);
if (v4code)
return(KRB5_KT_NOTFOUND);
/* In case v4inst is modified (it could be a wildcard, maybe), convert
* back to a Kerberos 5 principal for entry->principal. */
code = krb5_425_conv_principal(context, v4name, v4inst, v4realm,
&entry->principal);
if (code)
return(code);
/* Set up the rest of principal and return. */
entry->magic = KV5M_KEYTAB_ENTRY;
entry->timestamp = 0;
entry->vno = v4kvno;
entry->key.magic = KV5M_KEYBLOCK;
entry->key.enctype = ENCTYPE_DES_CBC_CRC;
entry->key.length = sizeof(v4key);
entry->key.contents = (krb5_octet *)malloc(sizeof(v4key));
if (!entry->key.contents)
return(ENOMEM);
memcpy(entry->key.contents, v4key, sizeof(v4key));
return 0;
}
#endif /* KERBEROS */