Path: blob/main/crypto/krb5/src/plugins/preauth/test/cltest.c
34890 views
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */1/* plugins/preauth/test/cltest.c - Test clpreauth module */2/*3* Copyright (C) 2015, 2017 by the Massachusetts Institute of Technology.4* All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9*10* * Redistributions of source code must retain the above copyright11* notice, this list of conditions and the following disclaimer.12*13* * Redistributions in binary form must reproduce the above copyright14* notice, this list of conditions and the following disclaimer in15* the documentation and/or other materials provided with the16* distribution.17*18* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS19* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT20* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS21* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE22* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,23* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES24* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR25* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)26* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,27* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)28* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED29* OF THE POSSIBILITY OF SUCH DAMAGE.30*/3132/*33* This module is used to test preauth interface features. At this time, the34* clpreauth module does the following:35*36* - It decrypts a message from the initial KDC pa-data using the reply key and37* prints it to stdout. (The unencrypted message "no key" can also be38* displayed.)39*40* - If a second round trip is requested, it prints the pa-data contents41* accompanying the second round trip request.42*43* - It pulls an "indicators" attribute from the gic preauth options and sends44* it to the server, instructing the kdcpreauth module to assert one or more45* space-separated authentication indicators. (This string is sent on both46* round trips if a second round trip is requested.)47*48* - If a KDC_ERR_ENCTYPE_NOSUPP error with e-data is received, it prints the49* accompanying error padata and sends a follow-up request containing50* "tryagain".51*52* - If the "fail_optimistic", "fail_2rt", or "fail_tryagain" gic options are53* set, it fails with a recognizable error string at the requested point in54* processing.55*56* - If the "disable_fallback" gic option is set, fallback is disabled when a57* client message is generated.58*/5960#include "k5-int.h"61#include <krb5/clpreauth_plugin.h>62#include "common.h"6364static krb5_preauthtype pa_types[] = { TEST_PA_TYPE, 0 };6566struct client_state {67char *indicators;68krb5_boolean fail_optimistic;69krb5_boolean fail_2rt;70krb5_boolean fail_tryagain;71krb5_boolean disable_fallback;72};7374struct client_request_state {75krb5_boolean second_round_trip;76};7778static krb5_error_code79test_init(krb5_context context, krb5_clpreauth_moddata *moddata_out)80{81struct client_state *st;8283st = malloc(sizeof(*st));84assert(st != NULL);85st->indicators = NULL;86st->fail_optimistic = st->fail_2rt = st->fail_tryagain = FALSE;87st->disable_fallback = FALSE;88*moddata_out = (krb5_clpreauth_moddata)st;89return 0;90}9192static void93test_fini(krb5_context context, krb5_clpreauth_moddata moddata)94{95struct client_state *st = (struct client_state *)moddata;9697free(st->indicators);98free(st);99}100101static void102test_request_init(krb5_context context, krb5_clpreauth_moddata moddata,103krb5_clpreauth_modreq *modreq_out)104{105struct client_request_state *reqst;106107reqst = malloc(sizeof(*reqst));108assert(reqst != NULL);109reqst->second_round_trip = FALSE;110*modreq_out = (krb5_clpreauth_modreq)reqst;111}112113static void114test_request_fini(krb5_context context, krb5_clpreauth_moddata moddata,115krb5_clpreauth_modreq modreq)116{117free(modreq);118}119120static krb5_error_code121test_process(krb5_context context, krb5_clpreauth_moddata moddata,122krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt,123krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock,124krb5_kdc_req *request, krb5_data *encoded_request_body,125krb5_data *encoded_previous_request, krb5_pa_data *pa_data,126krb5_prompter_fct prompter, void *prompter_data,127krb5_pa_data ***out_pa_data)128{129struct client_state *st = (struct client_state *)moddata;130struct client_request_state *reqst = (struct client_request_state *)modreq;131krb5_error_code ret;132krb5_keyblock *k;133krb5_enc_data enc;134krb5_data plain;135const char *indstr;136137if (pa_data->length == 0) {138/* This is an optimistic preauth test. Send a recognizable padata139* value so the KDC knows not to expect a cookie. */140if (st->fail_optimistic) {141k5_setmsg(context, KRB5_PREAUTH_FAILED, "induced optimistic fail");142return KRB5_PREAUTH_FAILED;143}144*out_pa_data = make_pa_list("optimistic", 10);145if (st->disable_fallback)146cb->disable_fallback(context, rock);147return 0;148} else if (reqst->second_round_trip) {149printf("2rt: %.*s\n", pa_data->length, pa_data->contents);150if (st->fail_2rt) {151k5_setmsg(context, KRB5_PREAUTH_FAILED, "induced 2rt fail");152return KRB5_PREAUTH_FAILED;153}154} else if (pa_data->length == 6 &&155memcmp(pa_data->contents, "no key", 6) == 0) {156printf("no key\n");157} else {158/* This fails during s4u_identify_user(), so don't assert. */159ret = cb->get_as_key(context, rock, &k);160if (ret)161return ret;162ret = alloc_data(&plain, pa_data->length);163assert(!ret);164enc.enctype = k->enctype;165enc.ciphertext = make_data(pa_data->contents, pa_data->length);166ret = krb5_c_decrypt(context, k, 1024, NULL, &enc, &plain);167assert(!ret);168printf("%.*s\n", plain.length, plain.data);169free(plain.data);170}171reqst->second_round_trip = TRUE;172173indstr = (st->indicators != NULL) ? st->indicators : "";174*out_pa_data = make_pa_list(indstr, strlen(indstr));175if (st->disable_fallback)176cb->disable_fallback(context, rock);177return 0;178}179180static krb5_error_code181test_tryagain(krb5_context context, krb5_clpreauth_moddata moddata,182krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt,183krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock,184krb5_kdc_req *request, krb5_data *enc_req, krb5_data *enc_prev,185krb5_preauthtype pa_type, krb5_error *error,186krb5_pa_data **padata, krb5_prompter_fct prompter,187void *prompter_data, krb5_pa_data ***padata_out)188{189struct client_state *st = (struct client_state *)moddata;190int i;191192*padata_out = NULL;193if (st->fail_tryagain) {194k5_setmsg(context, KRB5_PREAUTH_FAILED, "induced tryagain fail");195return KRB5_PREAUTH_FAILED;196}197if (error->error != KDC_ERR_ENCTYPE_NOSUPP)198return KRB5_PREAUTH_FAILED;199for (i = 0; padata[i] != NULL; i++) {200if (padata[i]->pa_type == TEST_PA_TYPE)201printf("tryagain: %.*s\n", padata[i]->length, padata[i]->contents);202}203*padata_out = make_pa_list("tryagain", 8);204return 0;205}206207static krb5_error_code208test_gic_opt(krb5_context kcontext, krb5_clpreauth_moddata moddata,209krb5_get_init_creds_opt *opt, const char *attr, const char *value)210{211struct client_state *st = (struct client_state *)moddata;212213if (strcmp(attr, "indicators") == 0) {214free(st->indicators);215st->indicators = strdup(value);216assert(st->indicators != NULL);217} else if (strcmp(attr, "fail_optimistic") == 0) {218st->fail_optimistic = TRUE;219} else if (strcmp(attr, "fail_2rt") == 0) {220st->fail_2rt = TRUE;221} else if (strcmp(attr, "fail_tryagain") == 0) {222st->fail_tryagain = TRUE;223} else if (strcmp(attr, "disable_fallback") == 0) {224st->disable_fallback = TRUE;225}226return 0;227}228229krb5_error_code230clpreauth_test_initvt(krb5_context context, int maj_ver,231int min_ver, krb5_plugin_vtable vtable);232233krb5_error_code234clpreauth_test_initvt(krb5_context context, int maj_ver,235int min_ver, krb5_plugin_vtable vtable)236{237krb5_clpreauth_vtable vt;238239if (maj_ver != 1)240return KRB5_PLUGIN_VER_NOTSUPP;241vt = (krb5_clpreauth_vtable)vtable;242vt->name = "test";243vt->pa_type_list = pa_types;244vt->init = test_init;245vt->fini = test_fini;246vt->request_init = test_request_init;247vt->request_fini = test_request_fini;248vt->process = test_process;249vt->tryagain = test_tryagain;250vt->gic_opts = test_gic_opt;251return 0;252}253254255