1 /* 2 * Kerberos test setup requiring the kadmin API. 3 * 4 * This file collects Kerberos test setup functions that use the kadmin API to 5 * put principals into particular configurations for testing. Currently, the 6 * only implemented functionality is to mark a password as expired. 7 * 8 * The canonical version of this file is maintained in the rra-c-util package, 9 * which can be found at <https://www.eyrie.org/~eagle/software/rra-c-util/>. 10 * 11 * Written by Russ Allbery <eagle@eyrie.org> 12 * Copyright 2017 Russ Allbery <eagle@eyrie.org> 13 * Copyright 2011 14 * The Board of Trustees of the Leland Stanford Junior University 15 * 16 * Permission is hereby granted, free of charge, to any person obtaining a 17 * copy of this software and associated documentation files (the "Software"), 18 * to deal in the Software without restriction, including without limitation 19 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 20 * and/or sell copies of the Software, and to permit persons to whom the 21 * Software is furnished to do so, subject to the following conditions: 22 * 23 * The above copyright notice and this permission notice shall be included in 24 * all copies or substantial portions of the Software. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 29 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 31 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 32 * DEALINGS IN THE SOFTWARE. 33 * 34 * SPDX-License-Identifier: MIT 35 */ 36 37 #include <config.h> 38 #ifdef HAVE_KADM5CLNT 39 # include <portable/kadmin.h> 40 # include <portable/krb5.h> 41 #endif 42 #include <portable/system.h> 43 44 #include <time.h> 45 46 #include <tests/tap/basic.h> 47 #include <tests/tap/kadmin.h> 48 #include <tests/tap/kerberos.h> 49 50 /* Used for unused parameters to silence gcc warnings. */ 51 #define UNUSED __attribute__((__unused__)) 52 53 54 /* 55 * Given the principal to set an expiration on, set that principal to have an 56 * expired password. This requires that the realm admin server be configured 57 * either in DNS (with SRV records) or in krb5.conf (possibly the one 58 * KRB5_CONFIG is pointing to). Authentication is done using the keytab 59 * stored in config/admin-keytab. 60 * 61 * Returns true on success. Returns false if necessary configuration is 62 * missing so that the caller can choose whether to call bail or skip_all. If 63 * the configuration is present but the operation fails, bails. 64 */ 65 #ifdef HAVE_KADM5CLNT 66 bool 67 kerberos_expire_password(const char *principal, time_t expires) 68 { 69 char *path, *user; 70 const char *realm; 71 krb5_context ctx; 72 krb5_principal admin = NULL; 73 krb5_principal princ = NULL; 74 kadm5_ret_t code; 75 kadm5_config_params params; 76 kadm5_principal_ent_rec ent; 77 void *handle; 78 bool okay = false; 79 80 /* Set up for making our call. */ 81 path = test_file_path("config/admin-keytab"); 82 if (path == NULL) 83 return false; 84 code = krb5_init_context(&ctx); 85 if (code != 0) 86 bail_krb5(ctx, code, "error initializing Kerberos"); 87 admin = kerberos_keytab_principal(ctx, path); 88 realm = krb5_principal_get_realm(ctx, admin); 89 code = krb5_set_default_realm(ctx, realm); 90 if (code != 0) 91 bail_krb5(ctx, code, "cannot set default realm"); 92 code = krb5_unparse_name(ctx, admin, &user); 93 if (code != 0) 94 bail_krb5(ctx, code, "cannot unparse admin principal"); 95 code = krb5_parse_name(ctx, principal, &princ); 96 if (code != 0) 97 bail_krb5(ctx, code, "cannot parse principal %s", principal); 98 99 /* 100 * If the actual kadmin calls fail, we may be built with MIT Kerberos 101 * against a Heimdal server or vice versa. Return false to skip the 102 * tests. 103 */ 104 memset(¶ms, 0, sizeof(params)); 105 params.realm = (char *) realm; 106 params.mask = KADM5_CONFIG_REALM; 107 code = kadm5_init_with_skey_ctx(ctx, user, path, KADM5_ADMIN_SERVICE, 108 ¶ms, KADM5_STRUCT_VERSION, 109 KADM5_API_VERSION, &handle); 110 if (code != 0) { 111 diag_krb5(ctx, code, "error initializing kadmin"); 112 goto done; 113 } 114 memset(&ent, 0, sizeof(ent)); 115 ent.principal = princ; 116 ent.pw_expiration = (krb5_timestamp) expires; 117 code = kadm5_modify_principal(handle, &ent, KADM5_PW_EXPIRATION); 118 if (code == 0) 119 okay = true; 120 else 121 diag_krb5(ctx, code, "error setting password expiration"); 122 123 done: 124 kadm5_destroy(handle); 125 krb5_free_unparsed_name(ctx, user); 126 krb5_free_principal(ctx, admin); 127 krb5_free_principal(ctx, princ); 128 krb5_free_context(ctx); 129 test_file_path_free(path); 130 return okay; 131 } 132 #else /* !HAVE_KADM5CLNT */ 133 bool 134 kerberos_expire_password(const char *principal UNUSED, time_t expires UNUSED) 135 { 136 return false; 137 } 138 #endif /* !HAVE_KADM5CLNT */ 139