Path: blob/main/crypto/krb5/src/tests/hammer/kdc5_hammer.c
34914 views
/* tests/hammer/kdc5_hammer.c */1/*2* Copyright 1990,1991 by the Massachusetts Institute of Technology.3* All Rights Reserved.4*5* Export of this software from the United States of America may6* require a specific license from the United States Government.7* It is the responsibility of any person or organization contemplating8* export to obtain such a license before exporting.9*10* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and11* distribute this software and its documentation for any purpose and12* without fee is hereby granted, provided that the above copyright13* notice appear in all copies and that both that copyright notice and14* this permission notice appear in supporting documentation, and that15* the name of M.I.T. not be used in advertising or publicity pertaining16* to distribution of the software without specific, written prior17* permission. Furthermore if you modify this software you must label18* your software as modified software and not distribute it in such a19* fashion that it might be confused with the original M.I.T. software.20* M.I.T. makes no representations about the suitability of21* this software for any purpose. It is provided "as is" without express22* or implied warranty.23*/2425#include "k5-int.h"26#include "com_err.h"27#include <sys/time.h>2829#define KRB5_DEFAULT_OPTIONS 030#define KRB5_DEFAULT_LIFE 60*60*8 /* 8 hours */31#define KRB5_RENEWABLE_LIFE 60*60*2 /* 2 hours */3233struct h_timer {34float ht_cumulative;35float ht_min;36float ht_max;37krb5_int32 ht_observations;38};3940extern int optind;41extern char *optarg;42char *prog;4344static int brief;45static char *cur_realm = 0;46static int do_timer = 0;4748krb5_data tgtname = {490,50KRB5_TGS_NAME_SIZE,51KRB5_TGS_NAME52};5354int verify_cs_pair55(krb5_context,56char *,57krb5_principal,58char *,59char *,60int, int, int,61krb5_ccache);6263int get_tgt64(krb5_context,65char *,66krb5_principal *,67krb5_ccache);6869static void70usage(char *who, int status)71{72fprintf(stderr,73"usage: %s -p prefix -n num_to_check [-c cachename] [-r realmname]\n",74who);75fprintf(stderr, "\t [-D depth]\n");76fprintf(stderr, "\t [-P preauth type] [-R repeat_count] [-t] [-b] [-v] \n");7778exit(status);79}8081static krb5_preauthtype * patype = NULL, patypedata[2] = { 0, -1 };82static krb5_context test_context;8384struct timeval tstart_time, tend_time;85struct timezone dontcare;8687struct h_timer in_tkt_times = { 0.0, 1000000.0, -1.0, 0 };88struct h_timer tgs_req_times = { 0.0, 1000000.0, -1.0, 0 };89/*90* Timer macros.91*/92#define swatch_on() ((void) gettimeofday(&tstart_time, &dontcare))93#define swatch_eltime() ((gettimeofday(&tend_time, &dontcare)) ? -1.0 : \94(((float) (tend_time.tv_sec - \95tstart_time.tv_sec)) + \96(((float) (tend_time.tv_usec - \97tstart_time.tv_usec))/1000000.0)))9899int100main(int argc, char **argv)101{102krb5_ccache ccache = NULL;103char *cache_name = NULL; /* -f option */104int option;105int errflg = 0;106krb5_error_code code;107int num_to_check, n, i, j, repeat_count, counter;108int n_tried, errors;109char prefix[BUFSIZ], client[4096], server[4096];110int depth;111char ctmp[4096], ctmp2[BUFSIZ], stmp[4096], stmp2[BUFSIZ];112krb5_principal client_princ;113krb5_error_code retval;114115krb5_init_context(&test_context);116117if (strrchr(argv[0], '/'))118prog = strrchr(argv[0], '/')+1;119else120prog = argv[0];121122num_to_check = 0;123depth = 1;124repeat_count = 1;125brief = 0;126n_tried = 0;127errors = 0;128129while ((option = getopt(argc, argv, "D:p:n:c:R:P:e:bvr:t")) != -1) {130switch (option) {131case 't':132do_timer = 1;133break;134case 'b':135brief = 1;136break;137case 'v':138brief = 0;139break;140case 'R':141repeat_count = atoi(optarg); /* how many times? */142break;143case 'r':144cur_realm = optarg;145break;146case 'D':147depth = atoi(optarg); /* how deep to go */148break;149case 'p': /* prefix name to check */150strncpy(prefix, optarg, sizeof(prefix) - 1);151prefix[sizeof(prefix) - 1] = '\0';152break;153case 'n': /* how many to check */154num_to_check = atoi(optarg);155break;156case 'P':157patypedata[0] = atoi(optarg);158patype = patypedata;159break;160case 'c':161if (ccache == NULL) {162cache_name = optarg;163164code = krb5_cc_resolve (test_context, cache_name, &ccache);165if (code != 0) {166com_err (prog, code, "resolving %s", cache_name);167errflg++;168}169} else {170fprintf(stderr, "Only one -c option allowed\n");171errflg++;172}173break;174case '?':175default:176errflg++;177break;178}179}180181if (!(num_to_check && prefix[0]) || errflg)182usage(prog, 1);183184if (!cur_realm) {185if ((retval = krb5_get_default_realm(test_context, &cur_realm))) {186com_err(prog, retval, "while retrieving default realm name");187exit(1);188}189}190191if (ccache == NULL) {192if ((code = krb5_cc_default(test_context, &ccache))) {193com_err(prog, code, "while getting default ccache");194exit(1);195}196}197198memset(ctmp, 0, sizeof(ctmp));199memset(stmp, 0, sizeof(stmp));200201for (counter = 0; counter < repeat_count; counter++) {202fprintf(stderr, "\nRound %d\n", counter);203204for (n = 1; n <= num_to_check; n++) {205/* build the new principal name */206/* we can't pick random names because we need to generate all the names207again given a prefix and count to test the db lib and kdb */208ctmp[0] = '\0';209for (i = 1; i <= depth; i++) {210(void) snprintf(ctmp2, sizeof(ctmp2), "%s%s%d-DEPTH-%d",211(i != 1) ? "/" : "", prefix, n, i);212ctmp2[sizeof(ctmp2) - 1] = '\0';213strncat(ctmp, ctmp2, sizeof(ctmp) - 1 - strlen(ctmp));214ctmp[sizeof(ctmp) - 1] = '\0';215snprintf(client, sizeof(client), "%s@%s", ctmp, cur_realm);216217if (get_tgt (test_context, client, &client_princ, ccache)) {218errors++;219n_tried++;220continue;221}222n_tried++;223224stmp[0] = '\0';225for (j = 1; j <= depth; j++) {226(void) snprintf(stmp2, sizeof(stmp2), "%s%s%d-DEPTH-%d",227(j != 1) ? "/" : "", prefix, n, j);228stmp2[sizeof (stmp2) - 1] = '\0';229strncat(stmp, stmp2, sizeof(stmp) - 1 - strlen(stmp));230stmp[sizeof(stmp) - 1] = '\0';231snprintf(server, sizeof(server), "%s@%s", stmp, cur_realm);232if (verify_cs_pair(test_context, client, client_princ,233stmp, cur_realm, n, i, j, ccache))234errors++;235n_tried++;236}237krb5_free_principal(test_context, client_princ);238}239}240}241fprintf (stderr, "\nTried %d. Got %d errors.\n", n_tried, errors);242if (do_timer) {243if (in_tkt_times.ht_observations)244fprintf(stderr,245"%8d AS_REQ requests: %9.6f average (min: %9.6f, max:%9.6f)\n",246in_tkt_times.ht_observations,247in_tkt_times.ht_cumulative /248(float) in_tkt_times.ht_observations,249in_tkt_times.ht_min,250in_tkt_times.ht_max);251if (tgs_req_times.ht_observations)252fprintf(stderr,253"%8d TGS_REQ requests: %9.6f average (min: %9.6f, max:%9.6f)\n",254tgs_req_times.ht_observations,255tgs_req_times.ht_cumulative /256(float) tgs_req_times.ht_observations,257tgs_req_times.ht_min,258tgs_req_times.ht_max);259}260261(void) krb5_cc_close(test_context, ccache);262263krb5_free_context(test_context);264265exit(errors);266}267268269static krb5_error_code270get_server_key(krb5_context context, krb5_principal server,271krb5_enctype enctype, krb5_keyblock **key)272{273krb5_error_code retval;274krb5_encrypt_block eblock;275char * string;276krb5_data salt;277krb5_data pwd;278279*key = NULL;280281if ((retval = krb5_principal2salt(context, server, &salt)))282return retval;283284if ((retval = krb5_unparse_name(context, server, &string)))285goto cleanup_salt;286287pwd.data = string;288pwd.length = strlen(string);289290if ((*key = (krb5_keyblock *)malloc(sizeof(krb5_keyblock)))) {291krb5_use_enctype(context, &eblock, enctype);292retval = krb5_string_to_key(context, &eblock, *key, &pwd, &salt);293if (retval) {294free(*key);295*key = NULL;296}297} else298retval = ENOMEM;299300free(string);301302cleanup_salt:303free(salt.data);304return retval;305}306307int308verify_cs_pair(krb5_context context, char *p_client_str,309krb5_principal p_client, char *service, char *hostname,310int p_num, int c_depth, int s_depth, krb5_ccache ccache)311{312krb5_error_code retval;313krb5_creds creds;314krb5_creds * credsp = NULL;315krb5_ticket * ticket = NULL;316krb5_keyblock * keyblock = NULL;317krb5_auth_context auth_context = NULL;318krb5_data request_data = empty_data();319char * sname;320float dt;321322if (brief)323fprintf(stderr, "\tprinc (%d) client (%d) for server (%d)\n",324p_num, c_depth, s_depth);325else326fprintf(stderr, "\tclient %s for server %s\n", p_client_str,327service);328329/* Initialize variables */330memset(&creds, 0, sizeof(creds));331332/* Do client side */333if (asprintf(&sname, "%s@%s", service, hostname) >= 0) {334retval = krb5_parse_name(context, sname, &creds.server);335free(sname);336}337else338retval = ENOMEM;339if (retval)340return(retval);341342/* obtain ticket & session key */343if ((retval = krb5_cc_get_principal(context, ccache, &creds.client))) {344com_err(prog, retval, "while getting client princ for %s", hostname);345return retval;346}347348if ((retval = krb5_get_credentials(context, 0,349ccache, &creds, &credsp))) {350com_err(prog, retval, "while getting creds for %s", hostname);351return retval;352}353354if (do_timer)355swatch_on();356357if ((retval = krb5_mk_req_extended(context, &auth_context, 0, NULL,358credsp, &request_data))) {359com_err(prog, retval, "while preparing AP_REQ for %s", hostname);360goto cleanup;361}362363krb5_auth_con_free(context, auth_context);364auth_context = NULL;365366/* Do server side now */367if ((retval = get_server_key(context, credsp->server,368credsp->keyblock.enctype, &keyblock))) {369com_err(prog, retval, "while getting server key for %s", hostname);370goto cleanup;371}372373if (krb5_auth_con_init(context, &auth_context)) {374com_err(prog, retval, "while creating auth_context for %s", hostname);375goto cleanup;376}377378if (krb5_auth_con_setuseruserkey(context, auth_context, keyblock)) {379com_err(prog, retval, "while setting auth_context key %s", hostname);380goto cleanup;381}382383if ((retval = krb5_rd_req(context, &auth_context, &request_data,384NULL /* server */, 0, NULL, &ticket))) {385com_err(prog, retval, "while decoding AP_REQ for %s", hostname);386goto cleanup;387}388389if (do_timer) {390dt = swatch_eltime();391tgs_req_times.ht_cumulative += dt;392tgs_req_times.ht_observations++;393if (dt > tgs_req_times.ht_max)394tgs_req_times.ht_max = dt;395if (dt < tgs_req_times.ht_min)396tgs_req_times.ht_min = dt;397}398399if (!(krb5_principal_compare(context,ticket->enc_part2->client,p_client))){400char *returned_client;401if ((retval = krb5_unparse_name(context, ticket->enc_part2->client,402&returned_client)))403com_err (prog, retval,404"Client not as expected, but cannot unparse client name");405else406com_err (prog, 0, "Client not as expected (%s).", returned_client);407retval = KRB5_PRINC_NOMATCH;408free(returned_client);409} else {410retval = 0;411}412413cleanup:414krb5_free_cred_contents(context, &creds);415krb5_free_ticket(context, ticket);416krb5_auth_con_free(context, auth_context);417krb5_free_keyblock(context, keyblock);418krb5_free_data_contents(context, &request_data);419krb5_free_creds(context, credsp);420421return retval;422}423424int425get_tgt(krb5_context context, char *p_client_str, krb5_principal *p_client,426krb5_ccache ccache)427{428long lifetime = KRB5_DEFAULT_LIFE; /* -l option */429krb5_error_code code;430krb5_creds my_creds;431krb5_timestamp start;432float dt;433krb5_get_init_creds_opt *options;434435if (!brief)436fprintf(stderr, "\tgetting TGT for %s\n", p_client_str);437438if ((code = krb5_timeofday(context, &start))) {439com_err(prog, code, "while getting time of day");440return(-1);441}442443memset(&my_creds, 0, sizeof(my_creds));444445if ((code = krb5_parse_name (context, p_client_str, p_client))) {446com_err (prog, code, "when parsing name %s", p_client_str);447return(-1);448}449450code = krb5_cc_initialize (context, ccache, *p_client);451if (code != 0) {452com_err (prog, code, "when initializing cache");453return(-1);454}455456if (do_timer)457swatch_on();458459code = krb5_get_init_creds_opt_alloc(context, &options);460if (code != 0) {461com_err(prog, code, "when allocating init cred options");462return(-1);463}464465krb5_get_init_creds_opt_set_tkt_life(options, lifetime);466467code = krb5_get_init_creds_opt_set_out_ccache(context, options, ccache);468if (code != 0) {469com_err(prog, code, "when setting init cred output ccache");470return(-1);471}472473code = krb5_get_init_creds_password(context, &my_creds, *p_client,474p_client_str, NULL, NULL, 0, NULL,475options);476if (do_timer) {477dt = swatch_eltime();478in_tkt_times.ht_cumulative += dt;479in_tkt_times.ht_observations++;480if (dt > in_tkt_times.ht_max)481in_tkt_times.ht_max = dt;482if (dt < in_tkt_times.ht_min)483in_tkt_times.ht_min = dt;484}485krb5_get_init_creds_opt_free(context, options);486krb5_free_cred_contents(context, &my_creds);487if (code != 0) {488com_err (prog, code, "while getting initial credentials");489return(-1);490}491492return(0);493}494495496