Path: blob/main/crypto/krb5/src/plugins/certauth/test/main.c
34890 views
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */1/* plugins/certauth/main.c - certauth plugin test modules. */2/*3* Copyright (C) 2017 by Red Hat, Inc.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#include <k5-int.h>33#include <kdb.h>34#include "krb5/certauth_plugin.h"3536struct krb5_certauth_moddata_st {37int initialized;38};3940/* Test module 1 passes with an indicator. */41static krb5_error_code42test1_authorize(krb5_context context, krb5_certauth_moddata moddata,43const uint8_t *cert, size_t cert_len,44krb5_const_principal princ, const void *opts,45const struct _krb5_db_entry_new *db_entry,46char ***authinds_out)47{48char **ais = NULL;4950ais = calloc(2, sizeof(*ais));51assert(ais != NULL);52ais[0] = strdup("test1");53assert(ais[0] != NULL);54*authinds_out = ais;55return KRB5_PLUGIN_NO_HANDLE;56}5758static void59test_free_ind(krb5_context context, krb5_certauth_moddata moddata,60char **authinds)61{62size_t i;6364if (authinds == NULL)65return;66for (i = 0; authinds[i] != NULL; i++)67free(authinds[i]);68free(authinds);69}7071/* A basic moddata test. */72static krb5_error_code73test2_init(krb5_context context, krb5_certauth_moddata *moddata_out)74{75krb5_certauth_moddata mod;7677mod = calloc(1, sizeof(*mod));78assert(mod != NULL);79mod->initialized = 1;80*moddata_out = mod;81return 0;82}8384static void85test2_fini(krb5_context context, krb5_certauth_moddata moddata)86{87free(moddata);88}8990/* Return true if cert appears to contain the CN name, based on a search of the91* DER encoding. */92static krb5_boolean93has_cn(krb5_context context, const uint8_t *cert, size_t cert_len,94const char *name)95{96krb5_boolean match = FALSE;97uint8_t name_len, cntag[5] = "\x06\x03\x55\x04\x03";98const uint8_t *c;99struct k5buf buf;100size_t c_left;101102/* Construct a DER search string of the CN AttributeType encoding followed103* by a UTF8String encoding containing name as the AttributeValue. */104k5_buf_init_dynamic(&buf);105k5_buf_add_len(&buf, cntag, sizeof(cntag));106k5_buf_add(&buf, "\x0C");107assert(strlen(name) < 128);108name_len = strlen(name);109k5_buf_add_len(&buf, &name_len, 1);110k5_buf_add_len(&buf, name, name_len);111assert(k5_buf_status(&buf) == 0);112113/* Check for the CN needle in the certificate haystack. */114c_left = cert_len;115c = memchr(cert, *cntag, c_left);116while (c != NULL) {117c_left = cert_len - (c - cert);118if (buf.len > c_left)119break;120if (memcmp(c, buf.data, buf.len) == 0) {121match = TRUE;122break;123}124assert(c_left >= 1);125c = memchr(c + 1, *cntag, c_left - 1);126}127128k5_buf_free(&buf);129return match;130}131132/*133* Test module 2 passes if the principal name is "nocert". Otherwise it134* returns OK if the CN of the cert matches the principal name, with indicators135* of the module name and princ, and errors if the certificate does not match.136*/137static krb5_error_code138test2_authorize(krb5_context context, krb5_certauth_moddata moddata,139const uint8_t *cert, size_t cert_len,140krb5_const_principal princ, const void *opts,141const struct _krb5_db_entry_new *db_entry,142char ***authinds_out)143{144krb5_error_code ret;145char *name = NULL, **ais = NULL;146147*authinds_out = NULL;148149assert(moddata != NULL && moddata->initialized);150151ret = krb5_unparse_name_flags(context, princ,152KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name);153if (ret)154goto cleanup;155if (strcmp(name, "nocert") == 0) {156ret = KRB5_PLUGIN_NO_HANDLE;157goto cleanup;158}159160if (!has_cn(context, cert, cert_len, name)) {161ret = KRB5KDC_ERR_CERTIFICATE_MISMATCH;162goto cleanup;163}164165/* Create an indicator list with the module name and CN. */166ais = calloc(3, sizeof(*ais));167assert(ais != NULL);168ais[0] = strdup("test2");169ais[1] = strdup(name);170assert(ais[0] != NULL && ais[1] != NULL);171*authinds_out = ais;172173ais = NULL;174175cleanup:176krb5_free_unparsed_name(context, name);177return ret;178}179180/*181* Test module 3 reads the "hwauth" string attribute on db_entry, and adds an182* authentication indicator of "hwauth:<value>" if the attribute is set. It183* returns KRB5_CERTAUTH_HWAUTH if the value is "ok", and184* KRB5_CERTAUTH_HWAUTH_PASS if the value is "pass". Otherwise it passes.185*/186static krb5_error_code187test3_authorize(krb5_context context, krb5_certauth_moddata moddata,188const uint8_t *cert, size_t cert_len,189krb5_const_principal princ, const void *opts,190const struct _krb5_db_entry_new *db_entry,191char ***authinds_out)192{193krb5_error_code ret;194char *strval = NULL, **ais = NULL;195196ret = krb5_dbe_get_string(context, (krb5_db_entry *)db_entry, "hwauth",197&strval);198if (ret)199return ret;200if (strval != NULL && strcmp(strval, "ok") == 0)201ret = KRB5_CERTAUTH_HWAUTH;202else if (strval != NULL && strcmp(strval, "pass") == 0)203ret = KRB5_CERTAUTH_HWAUTH_PASS;204else205ret = KRB5_PLUGIN_NO_HANDLE;206207if (strval != NULL) {208ais = calloc(2, sizeof(*ais));209assert(ais != NULL);210if (asprintf(&ais[0], "hwauth:%s", strval) < 0)211abort();212assert(ais[0] != NULL);213}214215*authinds_out = ais;216ais = NULL;217218krb5_dbe_free_string(context, strval);219return ret;220}221222krb5_error_code223certauth_test1_initvt(krb5_context context, int maj_ver, int min_ver,224krb5_plugin_vtable vtable);225krb5_error_code226certauth_test1_initvt(krb5_context context, int maj_ver, int min_ver,227krb5_plugin_vtable vtable)228{229krb5_certauth_vtable vt;230231if (maj_ver != 1)232return KRB5_PLUGIN_VER_NOTSUPP;233vt = (krb5_certauth_vtable)vtable;234vt->name = "test1";235vt->authorize = test1_authorize;236vt->free_ind = test_free_ind;237return 0;238}239240krb5_error_code241certauth_test2_initvt(krb5_context context, int maj_ver, int min_ver,242krb5_plugin_vtable vtable);243krb5_error_code244certauth_test2_initvt(krb5_context context, int maj_ver, int min_ver,245krb5_plugin_vtable vtable)246{247krb5_certauth_vtable vt;248249if (maj_ver != 1)250return KRB5_PLUGIN_VER_NOTSUPP;251vt = (krb5_certauth_vtable)vtable;252vt->name = "test2";253vt->authorize = test2_authorize;254vt->init = test2_init;255vt->fini = test2_fini;256vt->free_ind = test_free_ind;257return 0;258}259260krb5_error_code261certauth_test3_initvt(krb5_context context, int maj_ver, int min_ver,262krb5_plugin_vtable vtable);263264krb5_error_code265certauth_test3_initvt(krb5_context context, int maj_ver, int min_ver,266krb5_plugin_vtable vtable)267{268krb5_certauth_vtable vt;269270if (maj_ver != 1)271return KRB5_PLUGIN_VER_NOTSUPP;272vt = (krb5_certauth_vtable)vtable;273vt->name = "test3";274vt->authorize = test3_authorize;275vt->free_ind = test_free_ind;276return 0;277}278279280