freebsd-dev/eBones/usr.sbin/kadmind/kadm_ser_wrap.c

207 lines
6.0 KiB
C

/*
* Copyright 1988 by the Massachusetts Institute of Technology.
*
* For copying and distribution information, please see the file
* Copyright.MIT.
*
* Kerberos administration server-side support functions
*/
#ifndef lint
static char rcsid_module_c[] =
"BonesHeader: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadm_ser_wrap.c,v 4.4 89/09/26 09:29:36 jtkohl Exp ";
#endif lint
/*
kadm_ser_wrap.c
unwraps wrapped packets and calls the appropriate server subroutine
*/
#include <stdio.h>
#include <sys/types.h>
#include <netdb.h>
#include <sys/socket.h>
#include <kadm.h>
#include <kadm_err.h>
#include <krb_err.h>
#include "kadm_server.h"
Kadm_Server server_parm;
/*
kadm_ser_init
set up the server_parm structure
*/
kadm_ser_init(inter, realm)
int inter; /* interactive or from file */
char realm[];
{
struct servent *sep;
struct hostent *hp;
char hostname[MAXHOSTNAMELEN];
(void) init_kadm_err_tbl();
(void) init_krb_err_tbl();
if (gethostname(hostname, sizeof(hostname)))
return KADM_NO_HOSTNAME;
(void) strcpy(server_parm.sname, PWSERV_NAME);
(void) strcpy(server_parm.sinst, KRB_MASTER);
(void) strcpy(server_parm.krbrlm, realm);
server_parm.admin_fd = -1;
/* setting up the addrs */
if ((sep = getservbyname(KADM_SNAME, "tcp")) == NULL)
return KADM_NO_SERV;
bzero((char *)&server_parm.admin_addr,sizeof(server_parm.admin_addr));
server_parm.admin_addr.sin_family = AF_INET;
if ((hp = gethostbyname(hostname)) == NULL)
return KADM_NO_HOSTNAME;
bcopy(hp->h_addr, (char *) &server_parm.admin_addr.sin_addr.s_addr,
hp->h_length);
server_parm.admin_addr.sin_port = sep->s_port;
/* setting up the database */
if (kdb_get_master_key((inter==1),server_parm.master_key,
server_parm.master_key_schedule) != 0)
return KADM_NO_MAST;
if ((server_parm.master_key_version =
kdb_verify_master_key(server_parm.master_key,
server_parm.master_key_schedule,stderr))<0)
return KADM_NO_VERI;
return KADM_SUCCESS;
}
static void errpkt(dat, dat_len, code)
u_char **dat;
int *dat_len;
int code;
{
u_long retcode;
char *pdat;
free((char *)*dat); /* free up req */
*dat_len = KADM_VERSIZE + sizeof(u_long);
*dat = (u_char *) malloc((unsigned)*dat_len);
pdat = (char *) *dat;
retcode = htonl((u_long) code);
(void) strncpy(pdat, KADM_ULOSE, KADM_VERSIZE);
bcopy((char *)&retcode, &pdat[KADM_VERSIZE], sizeof(u_long));
return;
}
/*
kadm_ser_in
unwrap the data stored in dat, process, and return it.
*/
kadm_ser_in(dat,dat_len)
u_char **dat;
int *dat_len;
{
u_char *in_st; /* pointer into the sent packet */
int in_len,retc; /* where in packet we are, for
returns */
u_long r_len; /* length of the actual packet */
KTEXT_ST authent; /* the authenticator */
AUTH_DAT ad; /* who is this, klink */
u_long ncksum; /* checksum of encrypted data */
des_key_schedule sess_sched; /* our schedule */
MSG_DAT msg_st;
u_char *retdat, *tmpdat;
int retval, retlen;
if (strncmp(KADM_VERSTR, (char *)*dat, KADM_VERSIZE)) {
errpkt(dat, dat_len, KADM_BAD_VER);
return KADM_BAD_VER;
}
in_len = KADM_VERSIZE;
/* get the length */
if ((retc = stv_long(*dat, &r_len, in_len, *dat_len)) < 0)
return KADM_LENGTH_ERROR;
in_len += retc;
authent.length = *dat_len - r_len - KADM_VERSIZE - sizeof(u_long);
bcopy((char *)(*dat) + in_len, (char *)authent.dat, authent.length);
authent.mbz = 0;
/* service key should be set before here */
if (retc = krb_rd_req(&authent, server_parm.sname, server_parm.sinst,
server_parm.recv_addr.sin_addr.s_addr, &ad, (char *)0))
{
errpkt(dat, dat_len,retc + krb_err_base);
return retc + krb_err_base;
}
#define clr_cli_secrets() {bzero((char *)sess_sched, sizeof(sess_sched)); bzero((char *)ad.session, sizeof(ad.session));}
in_st = *dat + *dat_len - r_len;
#ifdef NOENCRYPTION
ncksum = 0;
#else
ncksum = quad_cksum(in_st, (u_long *)0, (long) r_len, 0, ad.session);
#endif
if (ncksum!=ad.checksum) { /* yow, are we correct yet */
clr_cli_secrets();
errpkt(dat, dat_len,KADM_BAD_CHK);
return KADM_BAD_CHK;
}
#ifdef NOENCRYPTION
bzero(sess_sched, sizeof(sess_sched));
#else
des_key_sched(ad.session, sess_sched);
#endif
if (retc = (int) krb_rd_priv(in_st, r_len, sess_sched, ad.session,
&server_parm.recv_addr,
&server_parm.admin_addr, &msg_st)) {
clr_cli_secrets();
errpkt(dat, dat_len,retc + krb_err_base);
return retc + krb_err_base;
}
switch (msg_st.app_data[0]) {
case CHANGE_PW:
retval = kadm_ser_cpw(msg_st.app_data+1,(int) msg_st.app_length,&ad,
&retdat, &retlen);
break;
case ADD_ENT:
retval = kadm_ser_add(msg_st.app_data+1,(int) msg_st.app_length,&ad,
&retdat, &retlen);
break;
case GET_ENT:
retval = kadm_ser_get(msg_st.app_data+1,(int) msg_st.app_length,&ad,
&retdat, &retlen);
break;
case MOD_ENT:
retval = kadm_ser_mod(msg_st.app_data+1,(int) msg_st.app_length,&ad,
&retdat, &retlen);
break;
default:
clr_cli_secrets();
errpkt(dat, dat_len, KADM_NO_OPCODE);
return KADM_NO_OPCODE;
}
/* Now seal the response back into a priv msg */
free((char *)*dat);
tmpdat = (u_char *) malloc((unsigned)(retlen + KADM_VERSIZE +
sizeof(u_long)));
(void) strncpy((char *)tmpdat, KADM_VERSTR, KADM_VERSIZE);
retval = htonl((u_long)retval);
bcopy((char *)&retval, (char *)tmpdat + KADM_VERSIZE, sizeof(u_long));
if (retlen) {
bcopy((char *)retdat, (char *)tmpdat + KADM_VERSIZE + sizeof(u_long),
retlen);
free((char *)retdat);
}
/* slop for mk_priv stuff */
*dat = (u_char *) malloc((unsigned) (retlen + KADM_VERSIZE +
sizeof(u_long) + 200));
if ((*dat_len = krb_mk_priv(tmpdat, *dat,
(u_long) (retlen + KADM_VERSIZE +
sizeof(u_long)),
sess_sched,
ad.session, &server_parm.admin_addr,
&server_parm.recv_addr)) < 0) {
clr_cli_secrets();
errpkt(dat, dat_len, KADM_NO_ENCRYPT);
return KADM_NO_ENCRYPT;
}
clr_cli_secrets();
return KADM_SUCCESS;
}