Path: blob/main/crypto/krb5/src/tests/create/kdb5_mkdums.c
34878 views
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */1/* tests/create/kdb5_mkdums.c */2/*3* Copyright 1990,1991 by the Massachusetts Institute of Technology.4* All Rights Reserved.5*6* Export of this software from the United States of America may7* require a specific license from the United States Government.8* It is the responsibility of any person or organization contemplating9* export to obtain such a license before exporting.10*11* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and12* distribute this software and its documentation for any purpose and13* without fee is hereby granted, provided that the above copyright14* notice appear in all copies and that both that copyright notice and15* this permission notice appear in supporting documentation, and that16* the name of M.I.T. not be used in advertising or publicity pertaining17* to distribution of the software without specific, written prior18* permission. Furthermore if you modify this software you must label19* your software as modified software and not distribute it in such a20* fashion that it might be confused with the original M.I.T. software.21* M.I.T. makes no representations about the suitability of22* this software for any purpose. It is provided "as is" without express23* or implied warranty.24*/2526/*27*28* Edit a KDC database.29*/3031#include "k5-int.h"32#include "kdb.h"33#include "com_err.h"34#include <ss/ss.h>35#include <stdio.h>363738#define REALM_SEP '@'39#define REALM_SEP_STR "@"4041struct mblock {42krb5_deltat max_life;43krb5_deltat max_rlife;44krb5_timestamp expiration;45krb5_flags flags;46krb5_kvno mkvno;47} mblock = { /* XXX */48KRB5_KDB_MAX_LIFE,49KRB5_KDB_MAX_RLIFE,50KRB5_KDB_EXPIRATION,51KRB5_KDB_DEF_FLAGS,52153};5455int set_dbname_help (char *, char *);5657static void58usage(char *who, int status)59{60fprintf(stderr,61"usage: %s -p prefix -n num_to_create [-d dbpathname] [-r realmname]\n",62who);63fprintf(stderr, "\t [-D depth] [-k enctype] [-M mkeyname]\n");6465exit(status);66}6768int master_princ_set = 0;69krb5_keyblock master_keyblock;70krb5_principal master_princ;71krb5_pointer master_random;72krb5_context test_context;7374static char *progname;75static char *cur_realm = 0;76static char *mkey_name = 0;77static char *mkey_password = 0;78static krb5_boolean manual_mkey = FALSE;7980void add_princ (krb5_context, char *);8182int83main(int argc, char *argv[])84{85extern char *optarg;86int optchar, i, n;87char tmp[4096], tmp2[BUFSIZ], *str_newprinc;8889krb5_error_code retval;90char *dbname = 0;91int enctypedone = 0;92int num_to_create;93char principal_string[BUFSIZ];94char *suffix = 0;95size_t suffix_size = 0;96int depth;9798krb5_init_context(&test_context);99100if (strrchr(argv[0], '/'))101argv[0] = strrchr(argv[0], '/')+1;102103progname = argv[0];104105memset(principal_string, 0, sizeof(principal_string));106num_to_create = 0;107depth = 1;108109while ((optchar = getopt(argc, argv, "D:P:p:n:d:r:k:M:e:m")) != -1) {110switch(optchar) {111case 'D':112depth = atoi(optarg); /* how deep to go */113break;114case 'P': /* Only used for testing!!! */115mkey_password = optarg;116break;117case 'p': /* prefix name to create */118strncpy(principal_string, optarg, sizeof(principal_string) - 1);119principal_string[sizeof(principal_string) - 1] = '\0';120suffix = principal_string + strlen(principal_string);121suffix_size = sizeof(principal_string) -122(suffix - principal_string);123break;124case 'n': /* how many to create */125num_to_create = atoi(optarg);126break;127case 'd': /* set db name */128dbname = optarg;129break;130case 'r':131cur_realm = optarg;132break;133case 'k':134master_keyblock.enctype = atoi(optarg);135enctypedone++;136break;137case 'M': /* master key name in DB */138mkey_name = optarg;139break;140case 'm':141manual_mkey = TRUE;142break;143case '?':144default:145usage(progname, 1);146/*NOTREACHED*/147}148}149150if (!(num_to_create && suffix)) usage(progname, 1);151152if (!enctypedone)153master_keyblock.enctype = DEFAULT_KDC_ENCTYPE;154155if (!krb5_c_valid_enctype(master_keyblock.enctype)) {156com_err(progname, KRB5_PROG_ETYPE_NOSUPP,157"while setting up enctype %d", master_keyblock.enctype);158exit(1);159}160161if (!dbname)162dbname = DEFAULT_KDB_FILE; /* XXX? */163164if (!cur_realm) {165if ((retval = krb5_get_default_realm(test_context, &cur_realm))) {166com_err(progname, retval, "while retrieving default realm name");167exit(1);168}169}170if ((retval = set_dbname_help(progname, dbname)))171exit(retval);172173for (n = 1; n <= num_to_create; n++) {174/* build the new principal name */175/* we can't pick random names because we need to generate all the names176again given a prefix and count to test the db lib and kdb */177(void) snprintf(suffix, suffix_size, "%d", n);178(void) snprintf(tmp, sizeof(tmp), "%s-DEPTH-1", principal_string);179tmp[sizeof(tmp) - 1] = '\0';180str_newprinc = tmp;181add_princ(test_context, str_newprinc);182183for (i = 2; i <= depth; i++) {184(void) snprintf(tmp2, sizeof(tmp2), "/%s-DEPTH-%d",185principal_string, i);186tmp2[sizeof(tmp2) - 1] = '\0';187strncat(tmp, tmp2, sizeof(tmp) - 1 - strlen(tmp));188str_newprinc = tmp;189add_princ(test_context, str_newprinc);190}191}192193retval = krb5_db_fini(test_context);194memset(master_keyblock.contents, 0,195(size_t) master_keyblock.length);196if (retval && retval != KRB5_KDB_DBNOTINITED) {197com_err(progname, retval, "while closing database");198exit(1);199}200if (master_princ_set)201krb5_free_principal(test_context, master_princ);202krb5_free_context(test_context);203exit(0);204}205206void207add_princ(krb5_context context, char *str_newprinc)208{209krb5_error_code retval;210krb5_principal newprinc;211krb5_db_entry *newentry;212char princ_name[4096];213214newentry = calloc(1, sizeof(*newentry));215if (newentry == NULL) {216com_err(progname, ENOMEM, "while allocating DB entry");217return;218}219snprintf(princ_name, sizeof(princ_name), "%s@%s", str_newprinc, cur_realm);220if ((retval = krb5_parse_name(context, princ_name, &newprinc))) {221com_err(progname, retval, "while parsing '%s'", princ_name);222return;223}224225/* Add basic data */226newentry->len = KRB5_KDB_V1_BASE_LENGTH;227newentry->attributes = mblock.flags;228newentry->max_life = mblock.max_life;229newentry->max_renewable_life = mblock.max_rlife;230newentry->expiration = mblock.expiration;231newentry->pw_expiration = mblock.expiration;232233/* Add princ to db entry */234if ((retval = krb5_copy_principal(context, newprinc, &newentry->princ))) {235com_err(progname, retval, "while encoding princ to db entry for '%s'",236princ_name);237krb5_free_principal(context, newprinc);238goto error;239}240241{242/* Add mod princ to db entry */243krb5_timestamp now;244245retval = krb5_timeofday(context, &now);246if (retval) {247com_err(progname, retval, "while fetching date");248krb5_free_principal(context, newprinc);249goto error;250}251retval = krb5_dbe_update_mod_princ_data(context, newentry, now,252master_princ);253if (retval) {254com_err(progname, retval, "while encoding mod_princ data");255krb5_free_principal(context, newprinc);256goto error;257}258}259260{ /* Add key and salt data to db entry */261krb5_data pwd, salt;262krb5_keyblock key;263264if ((retval = krb5_principal2salt(context, newprinc, &salt))) {265com_err(progname, retval, "while converting princ to salt for '%s'",266princ_name);267krb5_free_principal(context, newprinc);268goto error;269}270271krb5_free_principal(context, newprinc);272273pwd.length = strlen(princ_name);274pwd.data = princ_name; /* must be able to regenerate */275if ((retval = krb5_c_string_to_key(context, master_keyblock.enctype,276&pwd, &salt, &key))) {277com_err(progname,retval,"while converting password to key for '%s'",278princ_name);279krb5_free_data_contents(context, &salt);280goto error;281}282krb5_free_data_contents(context, &salt);283284if ((retval = krb5_dbe_create_key_data(context, newentry))) {285com_err(progname, retval, "while creating key_data for '%s'",286princ_name);287free(key.contents);288goto error;289}290291if ((retval = krb5_dbe_encrypt_key_data(context, &master_keyblock,292&key, NULL, 1,293newentry->key_data))) {294com_err(progname, retval, "while encrypting key for '%s'",295princ_name);296free(key.contents);297goto error;298}299free(key.contents);300}301302if ((retval = krb5_db_put_principal(context, newentry))) {303com_err(progname, retval, "while storing principal date");304goto error;305}306307error: /* Do cleanup of newentry regardless of error */308krb5_db_free_principal(context, newentry);309return;310}311312int313set_dbname_help(char *pname, char *dbname)314{315krb5_error_code retval;316krb5_data pwd, scratch;317char *args[2];318krb5_db_entry *master_entry;319320/* assemble & parse the master key name */321322if ((retval = krb5_db_setup_mkey_name(test_context, mkey_name, cur_realm,3230, &master_princ))) {324com_err(pname, retval, "while setting up master key name");325return(1);326}327master_princ_set = 1;328if (mkey_password) {329pwd.data = mkey_password;330pwd.length = strlen(mkey_password);331retval = krb5_principal2salt(test_context, master_princ, &scratch);332if (retval) {333com_err(pname, retval, "while calculated master key salt");334return(1);335}336if ((retval = krb5_c_string_to_key(test_context,337master_keyblock.enctype,338&pwd, &scratch,339&master_keyblock))) {340com_err(pname, retval,341"while transforming master key from password");342return(1);343}344free(scratch.data);345} else {346if ((retval = krb5_db_fetch_mkey(test_context, master_princ,347master_keyblock.enctype, manual_mkey,348FALSE, 0, NULL, NULL,349&master_keyblock))) {350com_err(pname, retval, "while reading master key");351return(1);352}353}354355/* Ick! Current DAL interface requires that the default_realm356field be set in the krb5_context. */357if ((retval = krb5_set_default_realm(test_context, cur_realm))) {358com_err(pname, retval, "setting default realm");359return 1;360}361/* Pathname is passed to db2 via 'args' parameter. */362args[1] = NULL;363if (asprintf(&args[0], "dbname=%s", dbname) < 0) {364com_err(pname, errno, "while setting up db parameters");365return 1;366}367368if ((retval = krb5_db_open(test_context, args, KRB5_KDB_OPEN_RO))) {369com_err(pname, retval, "while initializing database");370return(1);371}372/* Done with args */373free(args[0]);374375if ((retval = krb5_db_fetch_mkey_list(test_context, master_princ,376&master_keyblock))){377com_err(pname, retval, "while verifying master key");378(void) krb5_db_fini(test_context);379return(1);380}381if ((retval = krb5_db_get_principal(test_context, master_princ, 0,382&master_entry))) {383com_err(pname, retval, "while retrieving master entry");384(void) krb5_db_fini(test_context);385return(1);386}387388mblock.max_life = master_entry->max_life;389mblock.max_rlife = master_entry->max_renewable_life;390mblock.expiration = master_entry->expiration;391392/* don't set flags, master has some extra restrictions */393mblock.mkvno = master_entry->key_data[0].key_data_kvno;394395krb5_db_free_principal(test_context, master_entry);396return 0;397}398399400