#include "string_table.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <k5-int.h>
#include <kdb.h>
#include <kadm5/admin.h>
#include <krb5/adm_proto.h>
#include <krb5.h>
#include <krb5/kdb.h>
#include "kdb5_util.h"
#include <libintl.h>
int
add_admin_old_princ(void *handle, krb5_context context,
char *name, char *realm, int attrs, int lifetime);
int
add_admin_sname_princ(void *handle, krb5_context context,
char *sname, int attrs, int lifetime);
static int
add_admin_princ(void *handle, krb5_context context,
krb5_principal principal, int attrs, int lifetime);
static int add_admin_princs(void *handle, krb5_context context, char *realm);
#define ERR 1
#define OK 0
#define ADMIN_LIFETIME 60*60*3
#define CHANGEPW_LIFETIME 60*5
extern char *progname;
int kadm5_create(kadm5_config_params *params)
{
int retval;
krb5_context context;
kadm5_config_params lparams;
if ((retval = kadm5_init_krb5_context(&context)))
exit(ERR);
(void) memset(&lparams, 0, sizeof (kadm5_config_params));
if ((retval = kadm5_get_config_params(context, 1,
params, &lparams))) {
com_err(progname, retval, gettext("while looking up the Kerberos configuration"));
return 1;
}
retval = kadm5_create_magic_princs(&lparams, context);
kadm5_free_config_params(context, &lparams);
krb5_free_context(context);
return retval;
}
int kadm5_create_magic_princs(kadm5_config_params *params,
krb5_context context)
{
int retval;
void *handle;
retval = krb5_klog_init(context, "admin_server", progname, 0);
if (retval)
return retval;
if ((retval = kadm5_init(progname, NULL, NULL, params,
KADM5_STRUCT_VERSION,
KADM5_API_VERSION_2,
db5util_db_args,
&handle))) {
com_err(progname, retval, gettext("while initializing the Kerberos admin interface"));
return retval;
}
retval = add_admin_princs(handle, context, params->realm);
kadm5_destroy(handle);
krb5_klog_close(context);
return retval;
}
static char *build_name_with_realm(char *name, char *realm)
{
char *n;
n = (char *) malloc(strlen(name) + strlen(realm) + 2);
sprintf(n, "%s@%s", name, realm);
return n;
}
static int add_admin_princs(void *handle, krb5_context context, char *realm)
{
krb5_error_code ret = 0;
#if 0
if ((ret = add_admin_old_princ(handle, context,
KADM5_ADMIN_SERVICE, realm,
KRB5_KDB_DISALLOW_TGT_BASED,
ADMIN_LIFETIME)))
goto clean_and_exit;
#endif
if ((ret = add_admin_old_princ(handle, context,
KADM5_CHANGEPW_SERVICE, realm,
KRB5_KDB_DISALLOW_TGT_BASED |
KRB5_KDB_PWCHANGE_SERVICE,
CHANGEPW_LIFETIME)))
goto clean_and_exit;
if ((ret = add_admin_sname_princ(handle, context,
KADM5_ADMIN_HOST_SERVICE,
KRB5_KDB_DISALLOW_TGT_BASED,
ADMIN_LIFETIME)))
goto clean_and_exit;
if ((ret = add_admin_sname_princ(handle, context,
KADM5_CHANGEPW_HOST_SERVICE,
KRB5_KDB_DISALLOW_TGT_BASED |
KRB5_KDB_PWCHANGE_SERVICE,
ADMIN_LIFETIME)))
goto clean_and_exit;
if ((ret = add_admin_sname_princ(handle, context,
KADM5_KIPROP_HOST_SERVICE,
KRB5_KDB_DISALLOW_TGT_BASED,
ADMIN_LIFETIME)))
goto clean_and_exit;
clean_and_exit:
return ret;
}
static int add_admin_princ(void *handle, krb5_context context,
krb5_principal principal, int attrs, int lifetime)
{
char *fullname;
krb5_error_code ret;
kadm5_principal_ent_rec ent;
memset(&ent, 0, sizeof(ent));
if (krb5_unparse_name(context, principal, &fullname))
return ERR;
ent.principal = principal;
ent.max_life = lifetime;
ent.attributes = attrs | KRB5_KDB_DISALLOW_ALL_TIX;
ret = kadm5_create_principal(handle, &ent,
(KADM5_PRINCIPAL | KADM5_MAX_LIFE |
KADM5_ATTRIBUTES),
"to-be-random");
if (ret) {
if (ret != KADM5_DUP) {
com_err(progname, ret,
gettext(str_PUT_PRINC), fullname);
krb5_free_principal(context, ent.principal);
free(fullname);
return ERR;
}
} else {
krb5_enctype *tmpenc, *enctype = NULL;
krb5_key_salt_tuple *keysalt;
int num_ks, i;
krb5_int32 normalsalttype;
ret = krb5_get_permitted_enctypes(context, &enctype);
if (ret || *enctype == 0) {
com_err(progname, ret,
gettext("while getting list of permitted encryption types"));
krb5_free_principal(context, ent.principal);
free(fullname);
return ERR;
}
for (tmpenc = enctype, num_ks = 0; *tmpenc; tmpenc++)
num_ks++;
keysalt = malloc (sizeof (krb5_key_salt_tuple) * num_ks);
if (keysalt == NULL) {
com_err(progname, ENOMEM,
gettext("while generating list of key salt tuples"));
krb5_free_ktypes(context, enctype);
krb5_free_principal(context, ent.principal);
free(fullname);
return ERR;
}
ret = krb5_string_to_salttype("normal", &normalsalttype);
if (ret) {
com_err(progname, ret,
gettext("while converting \"normal\" to a salttype"));
free(keysalt);
krb5_free_ktypes(context, enctype);
krb5_free_principal(context, ent.principal);
free(fullname);
return ERR;
}
for (i = 0; i < num_ks; i++) {
keysalt[i].ks_enctype = enctype[i];
keysalt[i].ks_salttype = normalsalttype;
}
ret = kadm5_randkey_principal_3(handle, ent.principal, FALSE, num_ks,
keysalt, NULL, NULL);
free(keysalt);
krb5_free_ktypes (context, enctype);
if (ret) {
com_err(progname, ret,
gettext(str_RANDOM_KEY), fullname);
krb5_free_principal(context, ent.principal);
free(fullname);
return ERR;
}
ent.attributes = attrs;
ret = kadm5_modify_principal(handle, &ent, KADM5_ATTRIBUTES);
if (ret) {
com_err(progname, ret,
gettext(str_PUT_PRINC), fullname);
krb5_free_principal(context, ent.principal);
free(fullname);
return ERR;
}
}
krb5_free_principal(context, ent.principal);
free(fullname);
return OK;
}
int
add_admin_old_princ(void *handle, krb5_context context,
char *name, char *realm, int attrs, int lifetime)
{
char *fullname;
krb5_error_code ret;
krb5_principal principal;
fullname = build_name_with_realm(name, realm);
if (ret = krb5_parse_name(context, fullname, &principal)) {
com_err(progname, ret, gettext(str_PARSE_NAME));
return (ERR);
}
return (add_admin_princ(handle, context, principal, attrs, lifetime));
}
int
add_admin_sname_princ(void *handle, krb5_context context,
char *sname, int attrs, int lifetime)
{
krb5_error_code ret;
krb5_principal principal;
if (ret = krb5_sname_to_principal(context, NULL, sname,
KRB5_NT_SRV_HST, &principal)) {
com_err(progname, ret,
gettext("Could not get host based "
"service name for %s principal\n"), sname);
return (ERR);
}
return (add_admin_princ(handle, context, principal, attrs, lifetime));
}