#include <string.h>
#include <stdlib.h>
#include "kadm.h"
#include "kadm_err.h"
#include "prot.h"
#define min(a,b) (((a) < (b)) ? (a) : (b))
int
vals_to_stream(Kadm_vals *dt_in, u_char **dt_out)
{
int vsloop, stsize;
stsize = build_field_header(dt_in->fields, dt_out);
for (vsloop = 31; vsloop >= 0; vsloop--)
if (IS_FIELD(vsloop, dt_in->fields)) {
switch (vsloop) {
case KADM_NAME:
stsize += vts_string(dt_in->name, dt_out, stsize);
break;
case KADM_INST:
stsize += vts_string(dt_in->instance, dt_out, stsize);
break;
case KADM_EXPDATE:
stsize += vts_long((KRB_UINT32)dt_in->exp_date,
dt_out, stsize);
break;
case KADM_ATTR:
stsize += vts_short(dt_in->attributes, dt_out, stsize);
break;
case KADM_MAXLIFE:
stsize += vts_char(dt_in->max_life, dt_out, stsize);
break;
case KADM_DESKEY:
stsize += vts_long(dt_in->key_high, dt_out, stsize);
stsize += vts_long(dt_in->key_low, dt_out, stsize);
break;
default:
break;
}
}
return stsize;
}
int
build_field_header(
u_char *cont,
u_char **st)
{
*st = malloc(4);
if (*st == NULL)
return -1;
memcpy(*st, cont, 4);
return 4;
}
int
vts_string(char *dat, u_char **st, int loc)
{
size_t len;
unsigned char *p;
if (loc < 0)
return -1;
len = strlen(dat) + 1;
p = realloc(*st, (size_t)loc + len);
if (p == NULL)
return -1;
memcpy(p + loc, dat, len);
*st = p;
return len;
}
int
vts_short(KRB_UINT32 dat, u_char **st, int loc)
{
unsigned char *p;
if (loc < 0)
return -1;
p = realloc(*st, (size_t)loc + 2);
if (p == NULL)
return -1;
*st = p;
p += loc;
KRB4_PUT16BE(p, dat);
return 2;
}
int
vts_long(KRB_UINT32 dat, u_char **st, int loc)
{
unsigned char *p;
if (loc < 0)
return -1;
p = realloc(*st, (size_t)loc + 4);
if (p == NULL)
return -1;
*st = p;
p += loc;
KRB4_PUT32BE(p, dat);
return 4;
}
int
vts_char(KRB_UINT32 dat, u_char **st, int loc)
{
unsigned char *p;
if (loc < 0)
return -1;
p = realloc(*st, (size_t)loc + 1);
if (p == NULL)
return -1;
p[loc] = dat & 0xff;
*st = p;
return 1;
}
int
stream_to_vals(
u_char *dt_in,
Kadm_vals *dt_out,
int maxlen)
{
register int vsloop, stsize;
register int status;
memset(dt_out, 0, sizeof(*dt_out));
stsize = check_field_header(dt_in, dt_out->fields, maxlen);
if (stsize < 0)
return -1;
for (vsloop = 31; vsloop >= 0; vsloop--)
if (IS_FIELD(vsloop, dt_out->fields))
switch (vsloop) {
case KADM_NAME:
status = stv_string(dt_in, dt_out->name, stsize,
sizeof(dt_out->name), maxlen);
if (status < 0)
return -1;
stsize += status;
break;
case KADM_INST:
status = stv_string(dt_in, dt_out->instance, stsize,
sizeof(dt_out->instance), maxlen);
if (status < 0)
return -1;
stsize += status;
break;
case KADM_EXPDATE:
{
KRB_UINT32 exp_date;
status = stv_long(dt_in, &exp_date, stsize, maxlen);
if (status < 0)
return -1;
dt_out->exp_date = exp_date;
stsize += status;
}
break;
case KADM_ATTR:
status = stv_short(dt_in, &dt_out->attributes, stsize,
maxlen);
if (status < 0)
return -1;
stsize += status;
break;
case KADM_MAXLIFE:
status = stv_char(dt_in, &dt_out->max_life, stsize,
maxlen);
if (status < 0)
return -1;
stsize += status;
break;
case KADM_DESKEY:
status = stv_long(dt_in, &dt_out->key_high, stsize,
maxlen);
if (status < 0)
return -1;
stsize += status;
status = stv_long(dt_in, &dt_out->key_low, stsize,
maxlen);
if (status < 0)
return -1;
stsize += status;
break;
default:
break;
}
return stsize;
}
int
check_field_header(
u_char *st,
u_char *cont,
int maxlen)
{
if (4 > maxlen)
return -1;
memcpy(cont, st, 4);
return 4;
}
int
stv_string(
register u_char *st,
char *dat,
register int loc,
int stlen,
int maxlen)
{
int maxcount;
if (loc < 0)
return -1;
maxcount = min(maxlen - loc, stlen);
if (maxcount <= 0)
return -1;
(void) strncpy(dat, (char *)st + loc, (size_t)maxcount);
if (dat[maxcount - 1])
return -1;
return strlen(dat) + 1;
}
int
stv_short(u_char *st, u_short *dat, int loc, int maxlen)
{
u_short temp;
unsigned char *p;
if (loc < 0 || loc + 2 > maxlen)
return -1;
p = st + loc;
KRB4_GET16BE(temp, p);
*dat = temp;
return 2;
}
int
stv_long(u_char *st, KRB_UINT32 *dat, int loc, int maxlen)
{
KRB_UINT32 temp;
unsigned char *p;
if (loc < 0 || loc + 4 > maxlen)
return -1;
p = st + loc;
KRB4_GET32BE(temp, p);
*dat = temp;
return 4;
}
int
stv_char(u_char *st, u_char *dat, int loc, int maxlen)
{
if (loc < 0 || loc + 1 > maxlen)
return -1;
*dat = *(st + loc);
return 1;
}