Path: blob/main/crypto/krb5/src/plugins/kadm5_auth/test/main.c
34907 views
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */1/* plugins/kadm5_auth/test/main.c - test modules for kadm5_auth interface */2/*3* Copyright (C) 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 file implements two testing kadm5_auth modules, the welcomer and the34* bouncer. The welcomer implements permissive behavior, while the bouncer35* implements restrictive behavior.36*37* Module data objects and restrictions are adequately tested by the acl38* module, so we do not test them here. Focus instead on the ability to39* examine principal and policy objects and to perform DB operations.40*/4142#include "k5-int.h"43#include <kadm5/admin.h>44#include <krb5/kadm5_auth_plugin.h>4546krb5_error_code47kadm5_auth_welcomer_initvt(krb5_context context, int maj_ver, int min_ver,48krb5_plugin_vtable vtable);49krb5_error_code50kadm5_auth_bouncer_initvt(krb5_context context, int maj_ver, int min_ver,51krb5_plugin_vtable vtable);5253/* The welcomer authorizes all getprinc operations, since kadmin uses them as a54* precursor to modprinc. */55static krb5_error_code56welcomer_getprinc(krb5_context context, kadm5_auth_moddata data,57krb5_const_principal client, krb5_const_principal target)58{59return 0;60}6162/* The welcomer authorizes addprinc operations which set a policy "VIP". */63static krb5_error_code64welcomer_addprinc(krb5_context context, kadm5_auth_moddata data,65krb5_const_principal client, krb5_const_principal target,66const struct _kadm5_principal_ent_t *ent, long mask,67struct kadm5_auth_restrictions **rs_out)68{69if ((mask & KADM5_POLICY) && strcmp(ent->policy, "VIP") == 0)70return 0;71return KRB5_PLUGIN_NO_HANDLE;72}7374/* The bouncer denies addprinc operations which include a maximum lifetime. */75static krb5_error_code76bouncer_addprinc(krb5_context context, kadm5_auth_moddata data,77krb5_const_principal client, krb5_const_principal target,78const struct _kadm5_principal_ent_t *ent, long mask,79struct kadm5_auth_restrictions **rs_out)80{81return (mask & KADM5_MAX_LIFE) ? EPERM : KRB5_PLUGIN_NO_HANDLE;82}8384/* The welcomer authorizes modprinc operations which only set maxrenewlife. */85static krb5_error_code86welcomer_modprinc(krb5_context context, kadm5_auth_moddata data,87krb5_const_principal client, krb5_const_principal target,88const struct _kadm5_principal_ent_t *ent, long mask,89struct kadm5_auth_restrictions **rs_out)90{91return (mask == KADM5_MAX_RLIFE) ? 0 : KRB5_PLUGIN_NO_HANDLE;92}9394/* The bouncer denies modprinc operations if the target principal has an even95* number of components. */96static krb5_error_code97bouncer_modprinc(krb5_context context, kadm5_auth_moddata data,98krb5_const_principal client, krb5_const_principal target,99const struct _kadm5_principal_ent_t *ent, long mask,100struct kadm5_auth_restrictions **rs_out)101{102return (target->length % 2 == 0) ? EPERM : KRB5_PLUGIN_NO_HANDLE;103}104105/* The welcomer authorizes setstr operations for the attribute "note". */106static krb5_error_code107welcomer_setstr(krb5_context context, kadm5_auth_moddata data,108krb5_const_principal client, krb5_const_principal target,109const char *key, const char *value)110{111return (strcmp(key, "note") == 0) ? 0 : KRB5_PLUGIN_NO_HANDLE;112}113114/* The bouncer denies setstr operations if the value is more than 10 bytes. */115static krb5_error_code116bouncer_setstr(krb5_context context, kadm5_auth_moddata data,117krb5_const_principal client, krb5_const_principal target,118const char *key, const char *value)119{120return (strlen(value) > 10) ? EPERM : KRB5_PLUGIN_NO_HANDLE;121}122123/* The welcomer authorizes delprinc operations if the target principal starts124* with "d". */125static krb5_error_code126welcomer_delprinc(krb5_context context, kadm5_auth_moddata data,127krb5_const_principal client, krb5_const_principal target)128{129if (target->length > 0 && target->data[0].length > 0 &&130*target->data[0].data == 'd')131return 0;132return KRB5_PLUGIN_NO_HANDLE;133}134135/* The bouncer denies delprinc operations if the target principal has the136* "nodelete" string attribute. */137static krb5_error_code138bouncer_delprinc(krb5_context context, kadm5_auth_moddata data,139krb5_const_principal client, krb5_const_principal target)140{141krb5_error_code ret;142krb5_db_entry *ent;143char *val = NULL;144145if (krb5_db_get_principal(context, target, 0, &ent) != 0)146return EPERM;147ret = krb5_dbe_get_string(context, ent, "nodelete", &val);148krb5_db_free_principal(context, ent);149ret = (ret != 0 || val != NULL) ? EPERM : KRB5_PLUGIN_NO_HANDLE;150krb5_dbe_free_string(context, val);151return ret;152}153154/* The welcomer authorizes rename operations if the first components of the155* principals have the same length. */156static krb5_error_code157welcomer_renprinc(krb5_context context, kadm5_auth_moddata data,158krb5_const_principal client, krb5_const_principal src,159krb5_const_principal dest)160{161if (src->length > 0 && dest->length > 0 &&162src->data[0].length == dest->data[0].length)163return 0;164return KRB5_PLUGIN_NO_HANDLE;165}166167/* The bouncer denies rename operations if the source principal starts with168* "a". */169static krb5_error_code170bouncer_renprinc(krb5_context context, kadm5_auth_moddata data,171krb5_const_principal client, krb5_const_principal src,172krb5_const_principal dest)173{174if (src->length > 0 && src->data[0].length > 0 &&175*src->data[0].data == 'a')176return EPERM;177return KRB5_PLUGIN_NO_HANDLE;178}179180/* The welcomer authorizes addpol operations which set a minlength of 3. */181static krb5_error_code182welcomer_addpol(krb5_context context, kadm5_auth_moddata data,183krb5_const_principal client, const char *policy,184const struct _kadm5_policy_ent_t *ent, long mask)185{186if ((mask & KADM5_PW_MIN_LENGTH) && ent->pw_min_length == 3)187return 0;188return KRB5_PLUGIN_NO_HANDLE;189}190191/* The bouncer denies addpol operations if the name is 3 bytes or less. */192static krb5_error_code193bouncer_addpol(krb5_context context, kadm5_auth_moddata data,194krb5_const_principal client, const char *policy,195const struct _kadm5_policy_ent_t *ent, long mask)196{197return (strlen(policy) <= 3) ? EPERM : KRB5_PLUGIN_NO_HANDLE;198}199200/* The welcomer authorizes modpol operations which only change min_life. */201static krb5_error_code202welcomer_modpol(krb5_context context, kadm5_auth_moddata data,203krb5_const_principal client, const char *policy,204const struct _kadm5_policy_ent_t *ent, long mask)205{206return (mask == KADM5_PW_MIN_LIFE) ? 0 : KRB5_PLUGIN_NO_HANDLE;207}208209/* The bouncer denies modpol operations which set pw_min_life above 10. */210static krb5_error_code211bouncer_modpol(krb5_context context, kadm5_auth_moddata data,212krb5_const_principal client, const char *policy,213const struct _kadm5_policy_ent_t *ent, long mask)214{215if ((mask & KADM5_PW_MIN_LIFE) && ent->pw_min_life > 10)216return EPERM;217return KRB5_PLUGIN_NO_HANDLE;218}219220/* The welcomer authorizes getpol operations if the policy and client principal221* policy have the same length. */222static krb5_error_code223welcomer_getpol(krb5_context context, kadm5_auth_moddata data,224krb5_const_principal client, const char *policy,225const char *client_policy)226{227if (client_policy != NULL && strlen(policy) == strlen(client_policy))228return 0;229return KRB5_PLUGIN_NO_HANDLE;230}231232/* The bouncer denies getpol operations if the policy name begins with 'x'. */233static krb5_error_code234bouncer_getpol(krb5_context context, kadm5_auth_moddata data,235krb5_const_principal client, const char *policy,236const char *client_policy)237{238return (*policy == 'x') ? EPERM : KRB5_PLUGIN_NO_HANDLE;239}240241/* The welcomer counts end calls by incrementing the "ends" string attribute on242* the "opcount" principal, if it exists. */243static void244welcomer_end(krb5_context context, kadm5_auth_moddata data)245{246krb5_principal princ = NULL;247krb5_db_entry *ent = NULL;248char *val = NULL, buf[10];249250if (krb5_parse_name(context, "opcount", &princ) != 0)251goto cleanup;252if (krb5_db_get_principal(context, princ, 0, &ent) != 0)253goto cleanup;254if (krb5_dbe_get_string(context, ent, "ends", &val) != 0 || val == NULL)255goto cleanup;256snprintf(buf, sizeof(buf), "%d", atoi(val) + 1);257if (krb5_dbe_set_string(context, ent, "ends", buf) != 0)258goto cleanup;259ent->mask = KADM5_TL_DATA;260krb5_db_put_principal(context, ent);261262cleanup:263krb5_dbe_free_string(context, val);264krb5_db_free_principal(context, ent);265krb5_free_principal(context, princ);266}267268krb5_error_code269kadm5_auth_welcomer_initvt(krb5_context context, int maj_ver, int min_ver,270krb5_plugin_vtable vtable)271{272kadm5_auth_vtable vt = (kadm5_auth_vtable)vtable;273274vt->name = "welcomer";275vt->addprinc = welcomer_addprinc;276vt->modprinc = welcomer_modprinc;277vt->setstr = welcomer_setstr;278vt->delprinc = welcomer_delprinc;279vt->renprinc = welcomer_renprinc;280vt->getprinc = welcomer_getprinc;281vt->addpol = welcomer_addpol;282vt->modpol = welcomer_modpol;283vt->getpol = welcomer_getpol;284vt->end = welcomer_end;285return 0;286}287288krb5_error_code289kadm5_auth_bouncer_initvt(krb5_context context, int maj_ver, int min_ver,290krb5_plugin_vtable vtable)291{292kadm5_auth_vtable vt = (kadm5_auth_vtable)vtable;293294vt->name = "bouncer";295vt->addprinc = bouncer_addprinc;296vt->modprinc = bouncer_modprinc;297vt->setstr = bouncer_setstr;298vt->delprinc = bouncer_delprinc;299vt->renprinc = bouncer_renprinc;300vt->addpol = bouncer_addpol;301vt->modpol = bouncer_modpol;302vt->getpol = bouncer_getpol;303return 0;304}305306307