#include <mit-copyright.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/types.h>
#include "kadm_server.h"
#include <kadm.h>
#include <kadm_err.h>
#include <krb_err.h>
#include <syslog.h>
#ifdef KADM5
#include <kadm5/admin.h>
#endif
Kadm_Server server_parm;
#ifdef KADM5
int
kadm_ser_init(inter, realm, params)
int inter;
char realm[];
kadm5_config_params *params;
#else
int
kadm_ser_init(inter, realm)
int inter;
char realm[];
#endif
{
struct servent *sep;
struct hostent *hp;
char hostname[MAXHOSTNAMELEN];
char *mkey_name;
krb5_error_code retval;
int numfound = 1;
krb5_boolean more;
krb5_db_entry master_entry;
krb5_key_data *kdatap;
if (gethostname(hostname, sizeof(hostname)))
return KADM_NO_HOSTNAME;
(void) strcpy(server_parm.sname, PWSERV_NAME);
(void) strcpy(server_parm.sinst, KRB_MASTER);
if (strlen (realm) > REALM_SZ)
return KADM_REALM_TOO_LONG;
(void) strncpy(server_parm.krbrlm, realm, sizeof(server_parm.krbrlm)-1);
server_parm.krbrlm[sizeof(server_parm.krbrlm) - 1] = '\0';
if (krb5_425_conv_principal(kadm_context, server_parm.sname,
server_parm.sinst, server_parm.krbrlm,
&server_parm.sprinc))
return KADM_NO_MAST;
server_parm.admin_fd = -1;
if ((sep = getservbyname(KADM_SNAME, "tcp")) == NULL)
return KADM_NO_SERV;
memset((char *)&server_parm.admin_addr, 0,sizeof(server_parm.admin_addr));
server_parm.admin_addr.sin_family = AF_INET;
if ((hp = gethostbyname(hostname)) == NULL)
return KADM_NO_HOSTNAME;
memcpy((char *) &server_parm.admin_addr.sin_addr.s_addr, hp->h_addr,
sizeof(server_parm.admin_addr.sin_addr.s_addr));
server_parm.admin_addr.sin_port = sep->s_port;
mkey_name = KRB5_KDB_M_NAME;
server_parm.master_keyblock.enctype = params->enctype;
retval = krb5_db_setup_mkey_name(kadm_context, mkey_name, realm,
(char **) 0,
&server_parm.master_princ);
if (retval)
return KADM_NO_MAST;
krb5_db_fetch_mkey(kadm_context, server_parm.master_princ,
server_parm.master_keyblock.enctype,
(inter == 1), FALSE,
params->stash_file,
NULL,
&server_parm.master_keyblock);
if (retval)
return KADM_NO_MAST;
retval = krb5_db_verify_master_key(kadm_context, server_parm.master_princ,
&server_parm.master_keyblock);
if (retval)
return KADM_NO_VERI;
retval = krb5_db_get_principal(kadm_context, server_parm.master_princ,
&master_entry, &numfound, &more);
if (retval || more || !numfound)
return KADM_NO_VERI;
retval = krb5_dbe_find_enctype(kadm_context,
&master_entry,
-1, -1, -1,
&kdatap);
if (retval)
return KRB5_PROG_KEYTYPE_NOSUPP;
server_parm.max_life = master_entry.max_life;
server_parm.max_rlife = master_entry.max_renewable_life;
server_parm.expiration = master_entry.expiration;
server_parm.mkvno = kdatap->key_data_kvno;
krb5_db_free_principal(kadm_context, &master_entry, numfound);
return KADM_SUCCESS;
}
static void errpkt(dat, dat_len, code)
u_char **dat;
int *dat_len;
int code;
{
krb5_ui_4 retcode;
char *pdat;
free((char *)*dat);
*dat_len = KADM_VERSIZE + sizeof(krb5_ui_4);
*dat = (u_char *) malloc((unsigned)*dat_len);
if (!(*dat)) {
syslog(LOG_ERR, "malloc(%d) returned null while in errpkt!", *dat_len);
abort();
}
pdat = (char *) *dat;
retcode = htonl((krb5_ui_4) code);
(void) strncpy(pdat, KADM_ULOSE, KADM_VERSIZE);
memcpy(&pdat[KADM_VERSIZE], (char *)&retcode, sizeof(krb5_ui_4));
return;
}
int
kadm_ser_in(dat,dat_len)
u_char **dat;
int *dat_len;
{
u_char *in_st;
int in_len,retc;
krb5_ui_4 r_len;
KTEXT_ST authent;
AUTH_DAT ad;
krb5_ui_4 ncksum;
des_key_schedule sess_sched;
MSG_DAT msg_st;
u_char *retdat, *tmpdat;
int retval, retlen;
if ((*dat_len < KADM_VERSIZE + sizeof(krb5_ui_4))
|| strncmp(KADM_VERSTR, (char *)*dat, KADM_VERSIZE)) {
errpkt(dat, dat_len, KADM_BAD_VER);
return KADM_BAD_VER;
}
in_len = KADM_VERSIZE;
if ((retc = stv_long(*dat, &r_len, in_len, *dat_len)) < 0
|| (r_len > *dat_len - KADM_VERSIZE - sizeof(krb5_ui_4))
|| (*dat_len - r_len - KADM_VERSIZE -
sizeof(krb5_ui_4) > sizeof(authent.dat))) {
errpkt(dat, dat_len, KADM_LENGTH_ERROR);
return KADM_LENGTH_ERROR;
}
in_len += retc;
authent.length = *dat_len - r_len - KADM_VERSIZE - sizeof(krb5_ui_4);
memcpy((char *)authent.dat, (char *)(*dat) + in_len, authent.length);
authent.mbz = 0;
retc = krb_rd_req(&authent, server_parm.sname, server_parm.sinst,
server_parm.recv_addr.sin_addr.s_addr, &ad, (char *)0);
if (retc)
{
errpkt(dat, dat_len,retc + krb_err_base);
return retc + krb_err_base;
}
#define clr_cli_secrets() {memset((char *)sess_sched, 0, sizeof(sess_sched)); memset((char *)ad.session, 0, sizeof(ad.session));}
in_st = *dat + *dat_len - r_len;
#ifdef NOENCRYPTION
ncksum = 0;
#else
ncksum = quad_cksum(in_st, (krb5_ui_4 *)0, (long) r_len, 0, &ad.session);
#endif
if (ncksum!=ad.checksum) {
clr_cli_secrets();
errpkt(dat, dat_len,KADM_BAD_CHK);
return KADM_BAD_CHK;
}
#ifdef NOENCRYPTION
memset(sess_sched, 0, sizeof(sess_sched));
#else
des_key_sched(ad.session, sess_sched);
#endif
retc = (int) krb_rd_priv(in_st, r_len, sess_sched, &ad.session,
&server_parm.recv_addr,
&server_parm.admin_addr, &msg_st);
if (retc) {
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 MOD_ENT:
retval = kadm_ser_mod(msg_st.app_data+1,(int) msg_st.app_length,&ad,
&retdat, &retlen);
break;
case CHECK_PW:
retval = kadm_ser_ckpw(msg_st.app_data+1,(int) msg_st.app_length,&ad,
&retdat, &retlen);
break;
#ifndef KADM5
case DEL_ENT:
retval = kadm_ser_del(msg_st.app_data+1,(int) msg_st.app_length,&ad,
&retdat, &retlen);
break;
#endif
case GET_ENT:
retval = kadm_ser_get(msg_st.app_data+1,(int) msg_st.app_length,&ad,
&retdat, &retlen);
break;
case CHG_STAB:
retval = kadm_ser_stab(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;
}
free((char *)*dat);
tmpdat = (u_char *) malloc((unsigned)(retlen + KADM_VERSIZE +
sizeof(krb5_ui_4)));
if (!tmpdat) {
clr_cli_secrets();
syslog(LOG_ERR, "malloc(%d) returned null while in kadm_ser_in!",
retlen + KADM_VERSIZE + sizeof(krb5_ui_4));
errpkt(dat, dat_len, KADM_NOMEM);
return KADM_NOMEM;
}
(void) strncpy((char *)tmpdat, KADM_VERSTR, KADM_VERSIZE);
retval = htonl((krb5_ui_4)retval);
memcpy((char *)tmpdat + KADM_VERSIZE, (char *)&retval, sizeof(krb5_ui_4));
if (retlen) {
memcpy((char *)tmpdat + KADM_VERSIZE + sizeof(krb5_ui_4), (char *)retdat,
retlen);
free((char *)retdat);
}
*dat = (u_char *) malloc((unsigned) (retlen + KADM_VERSIZE +
sizeof(krb5_ui_4) + 200));
if ((*dat_len = krb_mk_priv(tmpdat, *dat,
(u_long) (retlen + KADM_VERSIZE +
sizeof(krb5_ui_4)),
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;
}