Blame src/plugins/certauth/test/main.c

Packit fd8b60
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
Packit fd8b60
/* plugins/certauth/main.c - certauth plugin test modules. */
Packit fd8b60
/*
Packit fd8b60
 * Copyright (C) 2017 by Red Hat, Inc.
Packit fd8b60
 * All rights reserved.
Packit fd8b60
 *
Packit fd8b60
 * Redistribution and use in source and binary forms, with or without
Packit fd8b60
 * modification, are permitted provided that the following conditions
Packit fd8b60
 * are met:
Packit fd8b60
 *
Packit fd8b60
 * * Redistributions of source code must retain the above copyright
Packit fd8b60
 *   notice, this list of conditions and the following disclaimer.
Packit fd8b60
 *
Packit fd8b60
 * * Redistributions in binary form must reproduce the above copyright
Packit fd8b60
 *   notice, this list of conditions and the following disclaimer in
Packit fd8b60
 *   the documentation and/or other materials provided with the
Packit fd8b60
 *   distribution.
Packit fd8b60
 *
Packit fd8b60
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit fd8b60
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit fd8b60
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
Packit fd8b60
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
Packit fd8b60
 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
Packit fd8b60
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
Packit fd8b60
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
Packit fd8b60
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
Packit fd8b60
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
Packit fd8b60
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
Packit fd8b60
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
Packit fd8b60
 * OF THE POSSIBILITY OF SUCH DAMAGE.
Packit fd8b60
 */
Packit fd8b60
Packit fd8b60
#include <k5-int.h>
rpm-build eee9e1
#include <kdb.h>
Packit fd8b60
#include "krb5/certauth_plugin.h"
Packit fd8b60
Packit fd8b60
struct krb5_certauth_moddata_st {
Packit fd8b60
    int initialized;
Packit fd8b60
};
Packit fd8b60
Packit fd8b60
/* Test module 1 returns OK with an indicator. */
Packit fd8b60
static krb5_error_code
Packit fd8b60
test1_authorize(krb5_context context, krb5_certauth_moddata moddata,
Packit fd8b60
                const uint8_t *cert, size_t cert_len,
Packit fd8b60
                krb5_const_principal princ, const void *opts,
Packit fd8b60
                const struct _krb5_db_entry_new *db_entry,
Packit fd8b60
                char ***authinds_out)
Packit fd8b60
{
Packit fd8b60
    char **ais = NULL;
Packit fd8b60
Packit fd8b60
    ais = calloc(2, sizeof(*ais));
Packit fd8b60
    assert(ais != NULL);
Packit fd8b60
    ais[0] = strdup("test1");
Packit fd8b60
    assert(ais[0] != NULL);
Packit fd8b60
    *authinds_out = ais;
Packit fd8b60
    return KRB5_PLUGIN_NO_HANDLE;
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
static void
Packit fd8b60
test_free_ind(krb5_context context, krb5_certauth_moddata moddata,
Packit fd8b60
              char **authinds)
Packit fd8b60
{
Packit fd8b60
    size_t i;
Packit fd8b60
Packit fd8b60
    if (authinds == NULL)
Packit fd8b60
        return;
Packit fd8b60
    for (i = 0; authinds[i] != NULL; i++)
Packit fd8b60
        free(authinds[i]);
Packit fd8b60
    free(authinds);
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
/* A basic moddata test. */
Packit fd8b60
static krb5_error_code
Packit fd8b60
test2_init(krb5_context context, krb5_certauth_moddata *moddata_out)
Packit fd8b60
{
Packit fd8b60
    krb5_certauth_moddata mod;
Packit fd8b60
Packit fd8b60
    mod = calloc(1, sizeof(*mod));
Packit fd8b60
    assert(mod != NULL);
Packit fd8b60
    mod->initialized = 1;
Packit fd8b60
    *moddata_out = mod;
Packit fd8b60
    return 0;
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
static void
Packit fd8b60
test2_fini(krb5_context context, krb5_certauth_moddata moddata)
Packit fd8b60
{
Packit fd8b60
    free(moddata);
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
/* Return true if cert appears to contain the CN name, based on a search of the
Packit fd8b60
 * DER encoding. */
Packit fd8b60
static krb5_boolean
Packit fd8b60
has_cn(krb5_context context, const uint8_t *cert, size_t cert_len,
Packit fd8b60
       const char *name)
Packit fd8b60
{
Packit fd8b60
    krb5_boolean match = FALSE;
Packit fd8b60
    uint8_t name_len, cntag[5] = "\x06\x03\x55\x04\x03";
Packit fd8b60
    const uint8_t *c;
Packit fd8b60
    struct k5buf buf;
Packit fd8b60
    size_t c_left;
Packit fd8b60
Packit fd8b60
    /* Construct a DER search string of the CN AttributeType encoding followed
Packit fd8b60
     * by a UTF8String encoding containing name as the AttributeValue. */
Packit fd8b60
    k5_buf_init_dynamic(&buf;;
Packit fd8b60
    k5_buf_add_len(&buf, cntag, sizeof(cntag));
Packit fd8b60
    k5_buf_add(&buf, "\x0C");
Packit fd8b60
    assert(strlen(name) < 128);
Packit fd8b60
    name_len = strlen(name);
Packit fd8b60
    k5_buf_add_len(&buf, &name_len, 1);
Packit fd8b60
    k5_buf_add_len(&buf, name, name_len);
Packit fd8b60
    assert(k5_buf_status(&buf) == 0);
Packit fd8b60
Packit fd8b60
    /* Check for the CN needle in the certificate haystack. */
Packit fd8b60
    c_left = cert_len;
Packit fd8b60
    c = memchr(cert, *cntag, c_left);
Packit fd8b60
    while (c != NULL) {
Packit fd8b60
        c_left = cert_len - (c - cert);
Packit fd8b60
        if (buf.len > c_left)
Packit fd8b60
            break;
Packit fd8b60
        if (memcmp(c, buf.data, buf.len) == 0) {
Packit fd8b60
            match = TRUE;
Packit fd8b60
            break;
Packit fd8b60
        }
Packit fd8b60
        assert(c_left >= 1);
Packit fd8b60
        c = memchr(c + 1, *cntag, c_left - 1);
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    k5_buf_free(&buf;;
Packit fd8b60
    return match;
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
/*
Packit fd8b60
 * Test module 2 returns OK if princ matches the CN part of the subject name,
rpm-build eee9e1
 * and returns indicators of the module name and princ.  If the "hwauth" string
rpm-build eee9e1
 * attribute is set on db_entry, it returns KRB5_CERTAUTH_HWAUTH.
Packit fd8b60
 */
Packit fd8b60
static krb5_error_code
Packit fd8b60
test2_authorize(krb5_context context, krb5_certauth_moddata moddata,
Packit fd8b60
                const uint8_t *cert, size_t cert_len,
Packit fd8b60
                krb5_const_principal princ, const void *opts,
Packit fd8b60
                const struct _krb5_db_entry_new *db_entry,
Packit fd8b60
                char ***authinds_out)
Packit fd8b60
{
Packit fd8b60
    krb5_error_code ret;
rpm-build eee9e1
    char *name = NULL, *strval = NULL, **ais = NULL;
Packit fd8b60
Packit fd8b60
    *authinds_out = NULL;
Packit fd8b60
Packit fd8b60
    assert(moddata != NULL && moddata->initialized);
Packit fd8b60
Packit fd8b60
    ret = krb5_unparse_name_flags(context, princ,
Packit fd8b60
                                  KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name);
Packit fd8b60
    if (ret)
Packit fd8b60
        goto cleanup;
Packit fd8b60
Packit fd8b60
    if (!has_cn(context, cert, cert_len, name)) {
Packit fd8b60
        ret = KRB5KDC_ERR_CERTIFICATE_MISMATCH;
Packit fd8b60
        goto cleanup;
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    /* Create an indicator list with the module name and CN. */
Packit fd8b60
    ais = calloc(3, sizeof(*ais));
Packit fd8b60
    assert(ais != NULL);
Packit fd8b60
    ais[0] = strdup("test2");
Packit fd8b60
    ais[1] = strdup(name);
Packit fd8b60
    assert(ais[0] != NULL && ais[1] != NULL);
Packit fd8b60
    *authinds_out = ais;
Packit fd8b60
Packit fd8b60
    ais = NULL;
Packit fd8b60
rpm-build eee9e1
    ret = krb5_dbe_get_string(context, (krb5_db_entry *)db_entry, "hwauth",
rpm-build eee9e1
                              &strval);
rpm-build eee9e1
    ret = (strval != NULL) ? KRB5_CERTAUTH_HWAUTH : 0;
rpm-build eee9e1
    krb5_dbe_free_string(context, strval);
rpm-build eee9e1
Packit fd8b60
cleanup:
Packit fd8b60
    krb5_free_unparsed_name(context, name);
Packit fd8b60
    return ret;
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
krb5_error_code
Packit fd8b60
certauth_test1_initvt(krb5_context context, int maj_ver, int min_ver,
Packit fd8b60
                      krb5_plugin_vtable vtable);
Packit fd8b60
krb5_error_code
Packit fd8b60
certauth_test1_initvt(krb5_context context, int maj_ver, int min_ver,
Packit fd8b60
                      krb5_plugin_vtable vtable)
Packit fd8b60
{
Packit fd8b60
    krb5_certauth_vtable vt;
Packit fd8b60
Packit fd8b60
    if (maj_ver != 1)
Packit fd8b60
        return KRB5_PLUGIN_VER_NOTSUPP;
Packit fd8b60
    vt = (krb5_certauth_vtable)vtable;
Packit fd8b60
    vt->name = "test1";
Packit fd8b60
    vt->authorize = test1_authorize;
Packit fd8b60
    vt->free_ind = test_free_ind;
Packit fd8b60
    return 0;
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
krb5_error_code
Packit fd8b60
certauth_test2_initvt(krb5_context context, int maj_ver, int min_ver,
Packit fd8b60
                      krb5_plugin_vtable vtable);
Packit fd8b60
krb5_error_code
Packit fd8b60
certauth_test2_initvt(krb5_context context, int maj_ver, int min_ver,
Packit fd8b60
                      krb5_plugin_vtable vtable)
Packit fd8b60
{
Packit fd8b60
    krb5_certauth_vtable vt;
Packit fd8b60
Packit fd8b60
    if (maj_ver != 1)
Packit fd8b60
        return KRB5_PLUGIN_VER_NOTSUPP;
Packit fd8b60
    vt = (krb5_certauth_vtable)vtable;
Packit fd8b60
    vt->name = "test2";
Packit fd8b60
    vt->authorize = test2_authorize;
Packit fd8b60
    vt->init = test2_init;
Packit fd8b60
    vt->fini = test2_fini;
Packit fd8b60
    vt->free_ind = test_free_ind;
Packit fd8b60
    return 0;
Packit fd8b60
}