MIT's librkinit. Part of the rkinit suite. Rkinit allows you to forward

tickets to other kerberos hosts safely in one easy step.
This commit is contained in:
Justin T. Gibbs 1995-09-15 06:09:30 +00:00
parent d69caef5ed
commit b00d18e592
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor-crypto/eBones/dist/; revision=10764
7 changed files with 1235 additions and 0 deletions

View file

@ -0,0 +1,19 @@
# @(#)Makefile 8.1 (Berkeley) 6/4/93
LIB= rkinit
CFLAGS+=-DKERBEROS -DCRYPT -DDEBUG -I${RKINITOBJDIR}
SRCS= rkinit_err.c rk_lib.c rk_rpc.c rk_util.c rk_krb.c rkinit_err.c
LDADD+= -lcom_err
beforeinstall:
-cd ${.OBJDIR}; cmp -s rkinit_err.h \
${DESTDIR}/usr/include/kerberosIV/rkinit_err.h || \
install -c -o ${BINOWN} -g ${BINGRP} -m 444 rkinit_err.h \
${DESTDIR}/usr/include/kerberosIV
MAN3= rkinit.3
.include <bsd.lib.mk>
rkinit_err.c: ${RKINITOBJDIR}/rkinit_err.h

View file

@ -0,0 +1,316 @@
/*
* $Id: rk_krb.c,v 1.1 1993/12/10 19:36:09 dglo Exp gibbs $
* $Source: /usr/src/eBones/librkinit/RCS/rk_krb.c,v $
* $Author: dglo $
*
* This file contains the kerberos parts of the rkinit library.
* See the comment at the top of rk_lib.c for a description of the naming
* conventions used within the rkinit library.
*/
#if !defined(lint) && !defined(SABER) && !defined(LOCORE) && defined(RCS_HDRS)
static char *rcsid = "$Id: rk_krb.c,v 1.1 1993/12/10 19:36:09 dglo Exp gibbs $";
#endif /* lint || SABER || LOCORE || RCS_HDRS */
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <krb.h>
#include <des.h>
#include <signal.h>
#include <setjmp.h>
#ifdef POSIX
#include <termios.h>
#else
#include <sgtty.h>
#endif
#include <rkinit.h>
#include <rkinit_err.h>
#include <rkinit_private.h>
static jmp_buf env;
static void sig_restore();
static void push_signals();
static void pop_signals();
/* Information to be passed around within client get_in_tkt */
typedef struct {
KTEXT scip; /* Server KDC packet */
char *username;
char *host;
} rkinit_intkt_info;
static char errbuf[BUFSIZ];
/* The compiler complains if this is declared static. */
#ifdef __STDC__
int rki_key_proc(char *user, char *instance, char *realm, char *arg,
des_cblock *key)
#else
int rki_key_proc(user, instance, realm, arg, key)
char *user;
char *instance;
char *realm;
char *arg;
des_cblock *key;
#endif /* __STDC__ */
{
rkinit_intkt_info *rii = (rkinit_intkt_info *)arg;
char password[BUFSIZ];
int ok = 0;
#ifdef POSIX
struct termios ttyb;
#else
struct sgttyb ttyb; /* For turning off echo */
#endif
SBCLEAR(ttyb);
BCLEAR(password);
/*
* If the username does not match the aname in the ticket,
* we will print that too. Otherwise, we won't.
*/
printf("Kerberos initialization (%s)", rii->host);
if (strcmp(rii->username, user))
printf(": tickets will be owned by %s", rii->username);
printf("\nPassword for %s%s%s@%s: ", user,
(instance[0]) ? "." : "", instance, realm);
fflush(stdout);
push_signals();
if (setjmp(env)) {
ok = -1;
goto lose;
}
#ifndef POSIX
ioctl(0, TIOCGETP, &ttyb);
ttyb.sg_flags &= ~ECHO;
ioctl(0, TIOCSETP, &ttyb);
#else
(void) tcgetattr(0, &ttyb);
ttyb.c_lflag &= ~ECHO;
(void) tcsetattr(0, TCSAFLUSH, &ttyb);
#endif
bzero(password, sizeof(password));
if (read(0, password, sizeof(password)) == -1) {
perror("read");
ok = -1;
goto lose;
}
if (password[strlen(password)-1] == '\n')
password[strlen(password)-1] = 0;
/* Generate the key from the password and destroy the password */
des_string_to_key(password, key);
lose:
BCLEAR(password);
#ifndef POSIX
ttyb.sg_flags |= ECHO;
ioctl(0, TIOCSETP, &ttyb);
#else
ttyb.c_lflag |= ECHO;
(void) tcsetattr(0, TCSAFLUSH, &ttyb);
#endif
pop_signals();
printf("\n");
return(ok);
}
#ifdef __STDC__
static int rki_decrypt_tkt(char *user, char *instance, char *realm,
char *arg, int (*key_proc)(), KTEXT *cipp)
#else
static int rki_decrypt_tkt(user, instance, realm, arg, key_proc, cipp)
char *user;
char *instance;
char *realm;
char *arg;
int (*key_proc)();
KTEXT *cipp;
#endif /* __STDC__ */
{
KTEXT cip = *cipp;
C_Block key; /* Key for decrypting cipher */
Key_schedule key_s;
KTEXT scip = 0; /* cipher from rkinit server */
rkinit_intkt_info *rii = (rkinit_intkt_info *)arg;
/* generate a key */
{
register int rc;
rc = (*key_proc)(user, instance, realm, arg, key);
if (rc)
return(rc);
}
des_key_sched(&key, key_s);
/* Decrypt information from KDC */
des_pcbc_encrypt((C_Block *)cip->dat,(C_Block *)cip->dat,
(long) cip->length, key_s, &key, 0);
/* DescrYPT rkinit server's information from KDC */
scip = rii->scip;
des_pcbc_encrypt((C_Block *)scip->dat,(C_Block *)scip->dat,
(long) scip->length, key_s, &key, 0);
/* Get rid of all traces of key */
bzero((char *)key, sizeof(key));
bzero((char *)key_s, sizeof(key_s));
return(0);
}
#ifdef __STDC__
int rki_get_tickets(int version, char *host, char *r_krealm, rkinit_info *info)
#else
int rki_get_tickets(version, host, r_krealm, info)
int version;
char *host;
char *r_krealm;
rkinit_info *info;
#endif /* __STDC__ */
{
int status = RKINIT_SUCCESS;
KTEXT_ST auth;
char phost[MAXHOSTNAMELEN];
KTEXT_ST scip; /* server's KDC packet */
des_cblock key;
des_key_schedule sched;
struct sockaddr_in caddr;
struct sockaddr_in saddr;
CREDENTIALS cred;
MSG_DAT msg_data;
u_char enc_data[MAX_KTXT_LEN];
rkinit_intkt_info rii;
SBCLEAR(auth);
BCLEAR(phost);
SBCLEAR(rii);
SBCLEAR(scip);
SBCLEAR(caddr);
SBCLEAR(saddr);
SBCLEAR(cred);
SBCLEAR(msg_data);
BCLEAR(enc_data);
if ((status = rki_send_rkinit_info(version, info)) != RKINIT_SUCCESS)
return(status);
if ((status = rki_rpc_get_skdc(&scip)) != RKINIT_SUCCESS)
return(status);
rii.scip = &scip;
rii.host = host;
rii.username = info->username;
if ((status = krb_get_in_tkt(info->aname, info->inst, info->realm,
"krbtgt", info->realm, 1,
rki_key_proc, rki_decrypt_tkt, (char *)&rii))) {
strcpy(errbuf, krb_err_txt[status]);
rkinit_errmsg(errbuf);
return(RKINIT_KERBEROS);
}
/* Create an authenticator */
strcpy(phost, krb_get_phost(host));
if ((status = krb_mk_req(&auth, KEY, phost, r_krealm, 0))) {
sprintf(errbuf, "krb_mk_req: %s", krb_err_txt[status]);
rkinit_errmsg(errbuf);
return(RKINIT_KERBEROS);
}
/* Re-encrypt server KDC packet in session key */
/* Get credentials from ticket file */
if ((status = krb_get_cred(KEY, phost, r_krealm, &cred))) {
sprintf(errbuf, "krb_get_cred: %s", krb_err_txt[status]);
rkinit_errmsg(errbuf);
return(RKINIT_KERBEROS);
}
/* Exctract the session key and make the schedule */
bcopy(cred.session, key, sizeof(key));
if ((status = des_key_sched(&key, sched))) {
sprintf(errbuf, "des_key_sched: %s", krb_err_txt[status]);
rkinit_errmsg(errbuf);
return(RKINIT_DES);
}
/* Get client and server addresses */
if ((status = rki_get_csaddr(&caddr, &saddr)) != RKINIT_SUCCESS)
return(status);
/*
* scip was passed to krb_get_in_tkt, where it was decrypted.
* Now re-encrypt in the session key.
*/
msg_data.app_data = enc_data;
if ((msg_data.app_length =
krb_mk_priv(scip.dat, msg_data.app_data, scip.length, sched, key,
&caddr, &saddr)) == -1) {
sprintf(errbuf, "krb_mk_priv failed.");
rkinit_errmsg(errbuf);
return(RKINIT_KERBEROS);
}
/* Destroy tickets, which we no longer need */
dest_tkt();
if ((status = rki_rpc_send_ckdc(&msg_data)) != RKINIT_SUCCESS)
return(status);
if ((status = rki_rpc_sendauth(&auth)) != RKINIT_SUCCESS)
return(status);
if ((status = rki_rpc_get_status()))
return(status);
return(RKINIT_SUCCESS);
}
static void (*old_sigfunc[NSIG])(int);
static void push_signals()
{
register i;
for (i = 0; i < NSIG; i++)
old_sigfunc[i] = signal(i,sig_restore);
}
static void pop_signals()
{
register i;
for (i = 0; i < NSIG; i++)
signal(i,old_sigfunc[i]);
}
static void sig_restore(sig,code,scp)
int sig,code;
struct sigcontext *scp;
{
longjmp(env,1);
}

View file

@ -0,0 +1,100 @@
/*
* $Id: rk_lib.c,v 1.1 1993/12/10 19:32:01 dglo Exp gibbs $
* $Source: /usr/src/eBones/librkinit/RCS/rk_lib.c,v $
* $Author: dglo $
*
* This file contains the non-rpc top-level rkinit library routines.
* The routines in the rkinit library that should be called from clients
* are exactly those defined in this file.
*
* The naming convetions used within the rkinit library are as follows:
* Functions intended for general client use start with rkinit_
* Functions intended for use only inside the library or server start with
* rki_
* Functions that do network communcation start with rki_rpc_
* Static functions can be named in any fashion.
*/
#if !defined(lint) && !defined(SABER) && !defined(LOCORE) && defined(RCS_HDRS)
static char *rcsid = "$Id: rk_lib.c,v 1.1 1993/12/10 19:32:01 dglo Exp gibbs $";
#endif /* lint || SABER || LOCORE || RCS_HDRS */
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <setjmp.h>
#include <krb.h>
#include <rkinit.h>
#include <rkinit_private.h>
#include <rkinit_err.h>
#ifdef __STDC__
char *rkinit_errmsg(char *string)
#else
char *rkinit_errmsg(string)
char *string;
#endif /* __STDC__ */
{
static char errmsg[BUFSIZ];
if (string) {
BCLEAR(errmsg);
strncpy(errmsg, string, sizeof(errmsg) - 1);
}
return(errmsg);
}
#ifdef __STDC__
int rkinit(char *host, char *r_krealm, rkinit_info *info, int timeout)
#else
int rkinit(host, r_krealm, info, timeout)
char *host;
char *r_krealm;
rkinit_info *info;
int timeout;
#endif /* __STDC__ */
{
int status = RKINIT_SUCCESS;
int version = 0;
char phost[MAXHOSTNAMELEN];
jmp_buf timeout_env;
void (*old_alrm)(int) = NULL;
char origtktfilename[MAXPATHLEN]; /* original ticket file name */
char tktfilename[MAXPATHLEN]; /* temporary client ticket file */
BCLEAR(phost);
BCLEAR(origtktfilename);
BCLEAR(tktfilename);
BCLEAR(timeout_env);
init_rkin_err_tbl();
if ((status = rki_setup_rpc(host)))
return(status);
if (timeout)
old_alrm = rki_setup_timer(timeout_env);
/* The alarm handler longjmps us to here. */
if ((status = setjmp(timeout_env)) == 0) {
strcpy(origtktfilename, tkt_string());
sprintf(tktfilename, "/tmp/tkt_rkinit.%ld", getpid());
krb_set_tkt_string(tktfilename);
if ((status = rki_choose_version(&version)) == RKINIT_SUCCESS)
status = rki_get_tickets(version, host, r_krealm, info);
}
if (timeout)
rki_restore_timer(old_alrm);
dest_tkt();
krb_set_tkt_string(origtktfilename);
rki_cleanup_rpc();
return(status);
}

View file

@ -0,0 +1,387 @@
/*
* $Id: rk_rpc.c,v 1.1 1993/12/10 19:36:09 dglo Exp gibbs $
* $Source: /usr/src/eBones/librkinit/RCS/rk_rpc.c,v $
* $Author: dglo $
*
* This file contains functions that are used for network communication.
* See the comment at the top of rk_lib.c for a description of the naming
* conventions used within the rkinit library.
*/
#if !defined(lint) && !defined(SABER) && !defined(LOCORE) && defined(RCS_HDRS)
static char *rcsid = "$Id: rk_rpc.c,v 1.1 1993/12/10 19:36:09 dglo Exp gibbs $";
#endif /* lint || SABER || LOCORE || RCS_HDRS */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <rkinit.h>
#include <rkinit_err.h>
#include <rkinit_private.h>
extern int errno;
static int sock;
struct sockaddr_in saddr;
static char errbuf[BUFSIZ];
char *calloc();
#ifdef __STDC__
int rki_send_packet(int sock, char type, u_int32_t length, const char *data)
#else
int rki_send_packet(sock, type, length, data)
int sock;
char type;
u_int32_t length;
const char *data;
#endif /* __STDC__ */
{
int len;
u_char *packet;
u_int32_t pkt_len;
u_int32_t net_pkt_len;
pkt_len = length + PKT_DATA;
if ((packet = (u_char *)calloc(pkt_len, sizeof(u_char))) == NULL) {
sprintf(errbuf, "rki_send_packet: failure allocating %d bytes",
pkt_len * sizeof(u_char));
rkinit_errmsg(errbuf);
return(RKINIT_MEMORY);
}
net_pkt_len = htonl(pkt_len);
packet[PKT_TYPE] = type;
bcopy((char *)&net_pkt_len, packet + PKT_LEN, sizeof(u_int32_t));
bcopy(data, packet + PKT_DATA, length);
if ((len = write(sock, packet, pkt_len)) != pkt_len) {
if (len == -1)
sprintf(errbuf, "write: %s", sys_errlist[errno]);
else
sprintf(errbuf, "write: %d bytes written; %d bytes actually sent",
pkt_len, len);
rkinit_errmsg(errbuf);
free(packet);
return(RKINIT_WRITE);
}
free(packet);
return(RKINIT_SUCCESS);
}
#ifdef __STDC__
int rki_get_packet(int sock, u_char type, u_int32_t *length, char *data)
#else
int rki_get_packet(sock, type, length, data)
int sock;
u_char type;
u_int32_t *length;
char *data;
#endif /* __STDC__ */
{
int len;
int len_sofar = 0;
u_int32_t expected_length = 0;
int got_full_packet = FALSE;
int tries = 0;
u_char *packet;
u_int32_t max_pkt_len;
max_pkt_len = *length + PKT_DATA;
if ((packet = (u_char *)calloc(max_pkt_len, sizeof(u_char))) == NULL) {
sprintf(errbuf, "rki_get_packet: failure allocating %d bytes",
max_pkt_len * sizeof(u_char));
rkinit_errmsg(errbuf);
return(RKINIT_MEMORY);
}
/* Read the packet type and length */
while ((len_sofar < PKT_DATA) && (tries < RETRIES)) {
if ((len = read(sock, packet + len_sofar, PKT_DATA - len_sofar)) < 0) {
sprintf(errbuf, "read: %s", sys_errlist[errno]);
rkinit_errmsg(errbuf);
return(RKINIT_READ);
}
len_sofar += len;
tries++;
}
if (len_sofar < PKT_DATA) {
sprintf(errbuf,
"read: expected to receive at least %d bytes; received %d",
PKT_DATA, len_sofar);
rkinit_errmsg(errbuf);
return(RKINIT_PACKET);
}
bcopy(packet + PKT_LEN, (char *)&expected_length, sizeof(u_int32_t));
expected_length = ntohl(expected_length);
if (expected_length > max_pkt_len) {
sprintf(errbuf, "%s %d %s %d",
"rki_get_packet: incoming message of size",
expected_length,
"is larger than message buffer of size",
max_pkt_len);
rkinit_errmsg(errbuf);
return(RKINIT_PACKET);
}
tries = 0;
while (!got_full_packet && (tries < RETRIES)) {
if ((len = read(sock, packet + len_sofar,
expected_length - len_sofar)) < 0) {
sprintf(errbuf, "read: %s", sys_errlist[errno]);
rkinit_errmsg(errbuf);
return(RKINIT_READ);
}
len_sofar += len;
if (expected_length == len_sofar)
got_full_packet = TRUE;
}
if (len_sofar < expected_length) {
sprintf(errbuf,
"read: expected to receive at least %d bytes; received %d",
expected_length, len_sofar);
rkinit_errmsg(errbuf);
return(RKINIT_PACKET);
}
if (packet[PKT_TYPE] == MT_DROP) {
BCLEAR(errbuf);
rkinit_errmsg(errbuf);
return(RKINIT_DROPPED);
}
if (packet[PKT_TYPE] != type) {
sprintf(errbuf, "Expected packet type of %s; got %s",
rki_mt_to_string(type),
rki_mt_to_string(packet[PKT_TYPE]));
rkinit_errmsg(errbuf);
return(RKINIT_PACKET);
}
*length = len_sofar - PKT_DATA;
bcopy(packet + PKT_DATA, data, *length);
free(packet);
return(RKINIT_SUCCESS);
}
#ifdef __STDC__
int rki_setup_rpc(char *host)
#else
int rki_setup_rpc(host)
char *host;
#endif /* __STDC__ */
{
struct hostent *hp;
struct servent *sp;
int port;
SBCLEAR(saddr);
SBCLEAR(hp);
SBCLEAR(sp);
if ((hp = gethostbyname(host)) == NULL) {
sprintf(errbuf, "%s: unknown host.", host);
rkinit_errmsg(errbuf);
return(RKINIT_HOST);
}
if ((sp = getservbyname(SERVENT, "tcp")))
port = sp->s_port;
else
/* Fall back on known port number */
port = htons(PORT);
saddr.sin_family = hp->h_addrtype;
bcopy(hp->h_addr, (char *)&saddr.sin_addr, hp->h_length);
saddr.sin_port = port;
if ((sock = socket(hp->h_addrtype, SOCK_STREAM, IPPROTO_IP)) < 0) {
sprintf(errbuf, "socket: %s", sys_errlist[errno]);
rkinit_errmsg(errbuf);
return(RKINIT_SOCKET);
}
if (connect(sock, (struct sockaddr *)&saddr, sizeof (saddr)) < 0) {
sprintf(errbuf, "connect: %s", sys_errlist[errno]);
rkinit_errmsg(errbuf);
close(sock);
return(RKINIT_CONNECT);
}
return(RKINIT_SUCCESS);
}
#ifdef __STDC__
int rki_rpc_exchange_version_info(int c_lversion, int c_hversion,
int *s_lversion, int *s_hversion)
#else
int rki_rpc_exchange_version_info(c_lversion, c_hversion,
s_lversion, s_hversion)
int c_lversion;
int c_hversion;
int *s_lversion;
int *s_hversion;
#endif /* __STDC__ */
{
int status = RKINIT_SUCCESS;
u_char version_info[VERSION_INFO_SIZE];
u_int32_t length = sizeof(version_info);
version_info[0] = (u_char) c_lversion;
version_info[1] = (u_char) c_hversion;
if ((status = rki_send_packet(sock, MT_CVERSION, length,
(char *)version_info)) != RKINIT_SUCCESS)
return(status);
if ((status = rki_get_packet(sock, MT_SVERSION, &length,
(char *)version_info)) != RKINIT_SUCCESS)
return(status);
*s_lversion = (int) version_info[0];
*s_hversion = (int) version_info[1];
return(RKINIT_SUCCESS);
}
#ifdef __STDC__
int rki_rpc_send_rkinit_info(rkinit_info *info)
#else
int rki_rpc_send_rkinit_info(info)
rkinit_info *info;
#endif /* __STDC__ */
{
rkinit_info info_copy;
bcopy(info, &info_copy, sizeof(rkinit_info));
info_copy.lifetime = htonl(info_copy.lifetime);
return(rki_send_packet(sock, MT_RKINIT_INFO, sizeof(rkinit_info),
(char *)&info_copy));
}
#ifdef __STDC__
int rki_rpc_get_status(void)
#else
int rki_rpc_get_status()
#endif /* __STDC__ */
{
char msg[BUFSIZ];
int status = RKINIT_SUCCESS;
u_int32_t length = sizeof(msg);
if ((status = rki_get_packet(sock, MT_STATUS, &length, msg)))
return(status);
if (length == 0)
return(RKINIT_SUCCESS);
else {
rkinit_errmsg(msg);
return(RKINIT_DAEMON);
}
}
#ifdef __STDC__
int rki_rpc_get_ktext(int sock, KTEXT auth, u_char type)
#else
int rki_rpc_get_ktext(sock, auth, type)
int sock;
KTEXT auth;
u_char type;
#endif /* __STDC__ */
{
int status = RKINIT_SUCCESS;
u_int32_t length = MAX_KTXT_LEN;
if ((status = rki_get_packet(sock, type, &length, (char *)auth->dat)))
return(status);
auth->length = length;
return(RKINIT_SUCCESS);
}
#ifdef __STDC__
int rki_rpc_sendauth(KTEXT auth)
#else
int rki_rpc_sendauth(auth)
KTEXT auth;
#endif /* __STDC__ */
{
return(rki_send_packet(sock, MT_AUTH, auth->length, (char *)auth->dat));
}
#ifdef __STDC__
int rki_rpc_get_skdc(KTEXT scip)
#else
int rki_rpc_get_skdc(scip)
KTEXT scip;
#endif /* __STDC__ */
{
return(rki_rpc_get_ktext(sock, scip, MT_SKDC));
}
#ifdef __STDC__
int rki_rpc_send_ckdc(MSG_DAT *scip)
#else
int rki_rpc_send_ckdc(scip)
MSG_DAT *scip;
#endif /* __STDC__ */
{
return(rki_send_packet(sock, MT_CKDC, scip->app_length,
(char *)scip->app_data));
}
#ifdef __STDC__
int rki_get_csaddr(struct sockaddr_in *caddrp, struct sockaddr_in *saddrp)
#else
int rki_get_csaddr(caddrp, saddrp)
struct sockaddr_in *caddrp;
struct sockaddr_in *saddrp;
#endif /* __STDC__ */
{
int addrlen = sizeof(struct sockaddr_in);
bcopy((char *)&saddr, (char *)saddrp, addrlen);
if (getsockname(sock, (struct sockaddr *)caddrp, &addrlen) < 0) {
sprintf(errbuf, "getsockname: %s", sys_errlist[errno]);
rkinit_errmsg(errbuf);
return(RKINIT_GETSOCK);
}
return(RKINIT_SUCCESS);
}
#ifdef __STDC__
void rki_drop_server(void)
#else
void rki_drop_server()
#endif /* __STDC__ */
{
(void) rki_send_packet(sock, MT_DROP, 0, "");
}
#ifdef __STDC__
void rki_cleanup_rpc(void)
#else
void rki_cleanup_rpc()
#endif /* __STDC__ */
{
rki_drop_server();
(void) close(sock);
}

View file

@ -0,0 +1,214 @@
/*
* $Id: rk_util.c,v 1.1 1993/12/10 19:36:09 dglo Exp gibbs $
* $Source: /usr/src/eBones/librkinit/RCS/rk_util.c,v $
* $Author: dglo $
*
* This file contains internal routines for general use by the rkinit
* library and server.
*
* See the comment at the top of rk_lib.c for a description of the naming
* conventions used within the rkinit library.
*/
#if !defined(lint) && !defined(SABER) && !defined(LOCORE) && defined(RCS_HDRS)
static char *rcsid = "$Id: rk_util.c,v 1.1 1993/12/10 19:36:09 dglo Exp gibbs $";
#endif /* lint || SABER || LOCORE || RCS_HDRS */
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <setjmp.h>
#include <signal.h>
#include <sys/time.h>
#ifdef DEBUG
#include <syslog.h>
#endif /* DEBUG */
#include <rkinit.h>
#include <rkinit_private.h>
#include <rkinit_err.h>
#define RKINIT_TIMEOUTVAL 60
static char errbuf[BUFSIZ];
static jmp_buf timeout_env;
#ifdef DEBUG
static int _rkinit_server_ = FALSE;
#ifdef __STDC__
void rki_dmsg(char *string)
#else
void rki_dmsg(string)
char *string;
#endif /* __STDC__ */
{
if (_rkinit_server_)
syslog(LOG_NOTICE, string);
else
printf("%s\n", string);
}
#ifdef __STDC__
void rki_i_am_server(void)
#else
void rki_i_am_server()
#endif /* __STDC__ */
{
_rkinit_server_ = TRUE;
}
#else /* DEBUG */
#ifdef __STDC__
void rki_dmsg(char *string)
#else
void rki_dmsg(string)
char *string;
#endif /* __STDC__ */
{
return;
}
#endif /* DEBUG */
#ifdef __STDC__
const char *rki_mt_to_string(int mt)
#else
const char *rki_mt_to_string(mt)
int mt;
#endif /* __STDC__ */
{
char *string = 0;
switch(mt) {
case MT_STATUS:
string = "Status message";
break;
case MT_CVERSION:
string = "Client version";
break;
case MT_SVERSION:
string = "Server version";
break;
case MT_RKINIT_INFO:
string = "Rkinit information";
break;
case MT_SKDC:
string = "Server kdc packet";
break;
case MT_CKDC:
string = "Client kdc packet";
break;
case MT_AUTH:
string = "Authenticator";
break;
case MT_DROP:
string = "Drop server";
break;
default:
string = "Unknown message type";
break;
}
return(string);
}
#ifdef __STDC__
int rki_choose_version(int *version)
#else
int rki_choose_version(version)
int *version;
#endif /* __STDC__ */
{
int s_lversion; /* lowest version number server supports */
int s_hversion; /* highest version number server supports */
int status = RKINIT_SUCCESS;
if ((status =
rki_rpc_exchange_version_info(RKINIT_LVERSION, RKINIT_HVERSION,
&s_lversion,
&s_hversion)) != RKINIT_SUCCESS)
return(status);
*version = min(RKINIT_HVERSION, s_hversion);
if (*version < max(RKINIT_LVERSION, s_lversion)) {
sprintf(errbuf,
"Can't run version %d client against version %d server.",
RKINIT_HVERSION, s_hversion);
rkinit_errmsg(errbuf);
status = RKINIT_VERSION;
}
return(status);
}
#ifdef __STDC__
int rki_send_rkinit_info(int version, rkinit_info *info)
#else
int rki_send_rkinit_info(version, info)
int version;
rkinit_info *info;
#endif /* __STDC__ */
{
int status = 0;
if ((status = rki_rpc_send_rkinit_info(info)) != RKINIT_SUCCESS)
return(status);
return(rki_rpc_get_status());
}
#ifdef __STDC__
static void rki_timeout(int signal)
#else
static void rki_timeout(signal)
int signal;
#endif /* __STDC__ */
{
sprintf(errbuf, "%d seconds exceeded.", RKINIT_TIMEOUTVAL);
rkinit_errmsg(errbuf);
longjmp(timeout_env, RKINIT_TIMEOUT);
return;
}
#ifdef __STDC__
static void set_timer(int secs)
#else
static void set_timer(secs)
int secs;
#endif /* __STDC__ */
{
struct itimerval timer; /* Time structure for timeout */
/* Set up an itimer structure to send an alarm signal after TIMEOUT
seconds. */
timer.it_interval.tv_sec = secs;
timer.it_interval.tv_usec = 0;
timer.it_value = timer.it_interval;
(void) setitimer (ITIMER_REAL, &timer, (struct itimerval *)0);
}
#ifdef __STDC__
void (*rki_setup_timer(jmp_buf env))(int)
#else
void (*rki_setup_timer(env))(int)
jmp_buf env;
#endif /* __STDC__ */
{
bcopy((char *)env, (char *)timeout_env, sizeof(jmp_buf));
set_timer(RKINIT_TIMEOUTVAL);
return(signal(SIGALRM, rki_timeout));
}
#ifdef __STDC__
void rki_restore_timer(void (*old_alrm)(int))
#else
void rki_restore_timer(old_alrm)
void (*old_alrm)(int);
#endif /* __STDC__ */
{
set_timer(0);
(void) signal(SIGALRM, old_alrm);
}

View file

@ -0,0 +1,167 @@
.\"
.\" $Header: /local/cvsfiles/kerberos/src/appl/rkinit/man/rkinit.3,v 1.1 1991/12/03 23:21:29 eichin Exp $
.\" $Source: /local/cvsfiles/kerberos/src/appl/rkinit/man/rkinit.3,v $
.\" $Author: eichin $
.\"
.\"
.TH RKINIT 3 "November 12, 1989"
.SH NAME
rkinit, rkinit_errmsg
.SH SYNOPSIS
.nf
.nj
.ft B
#include <rkinit.h>
#include <rkinit_err.h>
.PP
.ft B
int rkinit(host, r_krealm, info, timeout)
char *host;
char *r_krealm;
rkinit_info *info;
int timeout;
.PP
.ft B
char *rkinit_errmsg(string)
char *string;
.fi
.ft R
.SH DESCRIPTION
This library contains the calls necessary to interface with the
.I rkinit
system of remote ticket establishment. See
.IR rkinit (1)
for more information on
.I rkinit
.PP
.I rkinit.h
is the header file that contains information that all clients
will need to use.
.PP
.I rkinit_err.h
is the
.I com_err
error table header file. See
.IR com_err (3)
for more information about
.I com_err.
.PP
.IR rkinit ()
takes as arguments the name of the host on which you wish to
establish tickets, the kerberos realm of the remote host, a
fully initialized rkinit_info structure, and a boolean value
telling
whether or not
.IR rkinit ()
should time out if the transaction
fails to complete after a certain about of time.
This call does not know about about default values, so
something must be filled in for everything except for the ticket
filename in the rkinit_info structure described below.
.nf
.nj
.ft B
This is the rkinit_info type:
typedef struct {
char aname[ANAME_SZ + 1];
char inst[INST_SZ + 1];
char realm[REALM_SZ + 1];
char sname[ANAME_SZ + 1];
char sinst[INST_SZ + 1];
char username[9]; /* max local name length + 1 */
char tktfilename[MAXPATHLEN + 1];
long lifetime;
} rkinit_info;
.fi
.ft R
.I aname
is the name part of the kerberos principal for which tickets are
being requested.
.I inst
is the instance part.
.I realm
is the realm part.
.I sname
is the service name of the key that will appear in the remote
initial ticket (for example, "krbtgt").
.I sname
is the service instance.
.I username
is the name of the local user on the remote host who will own
the ticket file.
.I tktfilename
is the name of the file on the remote host in which the
tickets will be stored. This is the only field in the structure
for which a blank value is filled in. If this value is left
blank, the server will figure out what to call the ticket file
by using the kerberos library default as determined by
.I TKT_FILE
as defined in
.IR krb.h .
.I lifetime
is the lifetime of the tickets in the usual five minute
intervals. It is possible with this routine, as with
.IR krb_get_in_tkt (3)
to request tickets with zero lifetime.
.IR rkinit (),
while it is running, opens a socket, changes the name
of the default kerberos ticket file, and changes the signal
handler for the ALRM signal (if timeout != 0). rkinit()
restores all these values when it exits whether it exits with
an error or not, so clients using the rkinit library need not
worry about this information.
.IR rkinit_errmsg ()
takes a string as its only argument. Passing
other than NULL to this routine should be done
by only the rkinit library and server.
Doing this sets the current rkinit
error message. Calling
.IR rkinit_errmsg ()
with NULL as the argument returns the current rkinit error
message.
Although the rkinit library uses
.IR com_err (3)
for error handling, the error messages returned by
.IR com_err ()
may not be specific enough. A client could report the error
message returned by rkinit as follows:
.nf
.nj
.ft B
if (status = rkinit(host, r_krealm, &info, timeout)) {
com_err(argv[0], status, "while obtaining remote tickets:");
fprintf(stderr, "%s\\n", rkinit_errmsg(0));
exit(1);
}
.fi
.ft R
.SH SEE ALSO
kerberos(1), kerberos(3), rkinit(1), rkinitd(8)
.SH DIAGNOSTICS
.IR rkinit ()
is usually good about reporting error messages to the client.
It will probably not handle uninitialized variables well,
however. Make sure that things like the realm of the remote
host and the lifetime of the tickets have been properly
initialized before calling
.IR rkinit ().
.SH AUTHOR
Emanuel Jay Berkenbilt (MIT-Project Athena)

View file

@ -0,0 +1,32 @@
#
# $Header: /local/cvsfiles/kerberos/src/appl/rkinit/lib/rkinit_err.et,v 1.1 1991/12/03 23:20:58 eichin Exp $
# $Source: /local/cvsfiles/kerberos/src/appl/rkinit/lib/rkinit_err.et,v $
# $Author: eichin $
#
# These error messages will probably not be printed by com_err.
# Instead, a better error message (with specific information)
# will be obtained by a call to rkinit_errmsg().
#
et rkin
ec RKINIT_RCSID, "$Header: /local/cvsfiles/kerberos/src/appl/rkinit/lib/rkinit_err.et,v 1.1 1991/12/03 23:20:58 eichin Exp $"
ec RKINIT_VERSION, "Version mismatch"
ec RKINIT_HOST, "Failure getting host information"
ec RKINIT_SERV, "Failure getting service information (/etc/services)"
ec RKINIT_SOCKET, "Failure setting up socket"
ec RKINIT_CONNECT, "Failure connecting"
ec RKINIT_PACKET, "Bad packet type"
ec RKINIT_WRITE, "Failure writing"
ec RKINIT_READ, "Failure reading"
ec RKINIT_DAEMON, "Error reported by rkinitd"
ec RKINIT_KERBEROS, "Kerberos error"
ec RKINIT_DES, "Des error"
ec RKINIT_GETPEER, "Failure in getpeername"
ec RKINIT_GETSOCK, "Failure in getsockname"
ec RKINIT_MEMORY, "Out of memory"
ec RKINIT_TIMEOUT, "Timed out"
ec RKINIT_DROPPED, "Connection dropped"
ec RKINIT_LAST, "Last error message"
end