1b528cefcSMark Murray /* 2*ae771770SStanislav Sedov * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan 3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden). 4b528cefcSMark Murray * All rights reserved. 5b528cefcSMark Murray * 6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without 7b528cefcSMark Murray * modification, are permitted provided that the following conditions 8b528cefcSMark Murray * are met: 9b528cefcSMark Murray * 10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright 11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer. 12b528cefcSMark Murray * 13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright 14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the 15b528cefcSMark Murray * documentation and/or other materials provided with the distribution. 16b528cefcSMark Murray * 17b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors 18b528cefcSMark Murray * may be used to endorse or promote products derived from this software 19b528cefcSMark Murray * without specific prior written permission. 20b528cefcSMark Murray * 21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31b528cefcSMark Murray * SUCH DAMAGE. 32b528cefcSMark Murray */ 33b528cefcSMark Murray 34b528cefcSMark Murray #include "krb5_locl.h" 35b528cefcSMark Murray 36*ae771770SStanislav Sedov KRB5_LIB_FUNCTION void KRB5_LIB_CALL 37b528cefcSMark Murray krb5_verify_init_creds_opt_init(krb5_verify_init_creds_opt *options) 38b528cefcSMark Murray { 39b528cefcSMark Murray memset (options, 0, sizeof(*options)); 40b528cefcSMark Murray } 41b528cefcSMark Murray 42*ae771770SStanislav Sedov KRB5_LIB_FUNCTION void KRB5_LIB_CALL 43b528cefcSMark Murray krb5_verify_init_creds_opt_set_ap_req_nofail(krb5_verify_init_creds_opt *options, 44b528cefcSMark Murray int ap_req_nofail) 45b528cefcSMark Murray { 46b528cefcSMark Murray options->flags |= KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL; 47b528cefcSMark Murray options->ap_req_nofail = ap_req_nofail; 48b528cefcSMark Murray } 49b528cefcSMark Murray 50b528cefcSMark Murray /* 51b528cefcSMark Murray * 52b528cefcSMark Murray */ 53b528cefcSMark Murray 54b528cefcSMark Murray static krb5_boolean 55b528cefcSMark Murray fail_verify_is_ok (krb5_context context, 56b528cefcSMark Murray krb5_verify_init_creds_opt *options) 57b528cefcSMark Murray { 58b528cefcSMark Murray if ((options->flags & KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL 598373020dSJacques Vidrine && options->ap_req_nofail != 0) 60b528cefcSMark Murray || krb5_config_get_bool (context, 61b528cefcSMark Murray NULL, 62b528cefcSMark Murray "libdefaults", 63b528cefcSMark Murray "verify_ap_req_nofail", 64b528cefcSMark Murray NULL)) 65b528cefcSMark Murray return FALSE; 66b528cefcSMark Murray else 67b528cefcSMark Murray return TRUE; 68b528cefcSMark Murray } 69b528cefcSMark Murray 70*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 71b528cefcSMark Murray krb5_verify_init_creds(krb5_context context, 72b528cefcSMark Murray krb5_creds *creds, 73b528cefcSMark Murray krb5_principal ap_req_server, 74b528cefcSMark Murray krb5_keytab ap_req_keytab, 75b528cefcSMark Murray krb5_ccache *ccache, 76b528cefcSMark Murray krb5_verify_init_creds_opt *options) 77b528cefcSMark Murray { 78b528cefcSMark Murray krb5_error_code ret; 79b528cefcSMark Murray krb5_data req; 80adb0ddaeSAssar Westerlund krb5_ccache local_ccache = NULL; 81b528cefcSMark Murray krb5_creds *new_creds = NULL; 82b528cefcSMark Murray krb5_auth_context auth_context = NULL; 83b528cefcSMark Murray krb5_principal server = NULL; 84b528cefcSMark Murray krb5_keytab keytab = NULL; 85b528cefcSMark Murray 86b528cefcSMark Murray krb5_data_zero (&req); 87b528cefcSMark Murray 88b528cefcSMark Murray if (ap_req_server == NULL) { 89b528cefcSMark Murray char local_hostname[MAXHOSTNAMELEN]; 90b528cefcSMark Murray 91adb0ddaeSAssar Westerlund if (gethostname (local_hostname, sizeof(local_hostname)) < 0) { 92adb0ddaeSAssar Westerlund ret = errno; 93*ae771770SStanislav Sedov krb5_set_error_message (context, ret, "gethostname: %s", 94adb0ddaeSAssar Westerlund strerror(ret)); 95adb0ddaeSAssar Westerlund return ret; 96adb0ddaeSAssar Westerlund } 97b528cefcSMark Murray 98b528cefcSMark Murray ret = krb5_sname_to_principal (context, 99b528cefcSMark Murray local_hostname, 100b528cefcSMark Murray "host", 101b528cefcSMark Murray KRB5_NT_SRV_HST, 102b528cefcSMark Murray &server); 103b528cefcSMark Murray if (ret) 104b528cefcSMark Murray goto cleanup; 105b528cefcSMark Murray } else 106b528cefcSMark Murray server = ap_req_server; 107b528cefcSMark Murray 108b528cefcSMark Murray if (ap_req_keytab == NULL) { 109b528cefcSMark Murray ret = krb5_kt_default (context, &keytab); 110b528cefcSMark Murray if (ret) 111b528cefcSMark Murray goto cleanup; 112b528cefcSMark Murray } else 113b528cefcSMark Murray keytab = ap_req_keytab; 114b528cefcSMark Murray 115b528cefcSMark Murray if (ccache && *ccache) 116b528cefcSMark Murray local_ccache = *ccache; 117b528cefcSMark Murray else { 118*ae771770SStanislav Sedov ret = krb5_cc_new_unique(context, krb5_cc_type_memory, 119*ae771770SStanislav Sedov NULL, &local_ccache); 120b528cefcSMark Murray if (ret) 121b528cefcSMark Murray goto cleanup; 122b528cefcSMark Murray ret = krb5_cc_initialize (context, 123b528cefcSMark Murray local_ccache, 124b528cefcSMark Murray creds->client); 125b528cefcSMark Murray if (ret) 126b528cefcSMark Murray goto cleanup; 127b528cefcSMark Murray ret = krb5_cc_store_cred (context, 128b528cefcSMark Murray local_ccache, 129b528cefcSMark Murray creds); 130b528cefcSMark Murray if (ret) 131b528cefcSMark Murray goto cleanup; 132b528cefcSMark Murray } 133b528cefcSMark Murray 134b528cefcSMark Murray if (!krb5_principal_compare (context, server, creds->server)) { 135b528cefcSMark Murray krb5_creds match_cred; 136b528cefcSMark Murray 137b528cefcSMark Murray memset (&match_cred, 0, sizeof(match_cred)); 138b528cefcSMark Murray 139b528cefcSMark Murray match_cred.client = creds->client; 140b528cefcSMark Murray match_cred.server = server; 141b528cefcSMark Murray 142b528cefcSMark Murray ret = krb5_get_credentials (context, 143b528cefcSMark Murray 0, 144b528cefcSMark Murray local_ccache, 145b528cefcSMark Murray &match_cred, 146b528cefcSMark Murray &new_creds); 147b528cefcSMark Murray if (ret) { 148b528cefcSMark Murray if (fail_verify_is_ok (context, options)) 149b528cefcSMark Murray ret = 0; 150b528cefcSMark Murray goto cleanup; 151b528cefcSMark Murray } 15213e3f4d6SMark Murray creds = new_creds; 15313e3f4d6SMark Murray } 154b528cefcSMark Murray 155b528cefcSMark Murray ret = krb5_mk_req_extended (context, 156b528cefcSMark Murray &auth_context, 157b528cefcSMark Murray 0, 158b528cefcSMark Murray NULL, 15913e3f4d6SMark Murray creds, 160b528cefcSMark Murray &req); 161b528cefcSMark Murray 162b528cefcSMark Murray krb5_auth_con_free (context, auth_context); 163b528cefcSMark Murray auth_context = NULL; 164b528cefcSMark Murray 165b528cefcSMark Murray if (ret) 166b528cefcSMark Murray goto cleanup; 167b528cefcSMark Murray 168b528cefcSMark Murray ret = krb5_rd_req (context, 169b528cefcSMark Murray &auth_context, 170b528cefcSMark Murray &req, 171b528cefcSMark Murray server, 172b528cefcSMark Murray keytab, 173b528cefcSMark Murray 0, 174b528cefcSMark Murray NULL); 175b528cefcSMark Murray 176b528cefcSMark Murray if (ret == KRB5_KT_NOTFOUND && fail_verify_is_ok (context, options)) 177b528cefcSMark Murray ret = 0; 178b528cefcSMark Murray cleanup: 179b528cefcSMark Murray if (auth_context) 180b528cefcSMark Murray krb5_auth_con_free (context, auth_context); 181b528cefcSMark Murray krb5_data_free (&req); 18213e3f4d6SMark Murray if (new_creds != NULL) 183b528cefcSMark Murray krb5_free_creds (context, new_creds); 184b528cefcSMark Murray if (ap_req_server == NULL && server) 185b528cefcSMark Murray krb5_free_principal (context, server); 186b528cefcSMark Murray if (ap_req_keytab == NULL && keytab) 187b528cefcSMark Murray krb5_kt_close (context, keytab); 188adb0ddaeSAssar Westerlund if (local_ccache != NULL 189adb0ddaeSAssar Westerlund && 190adb0ddaeSAssar Westerlund (ccache == NULL 191adb0ddaeSAssar Westerlund || (ret != 0 && *ccache == NULL))) 192b528cefcSMark Murray krb5_cc_destroy (context, local_ccache); 193b528cefcSMark Murray 194b528cefcSMark Murray if (ret == 0 && ccache != NULL && *ccache == NULL) 195b528cefcSMark Murray *ccache = local_ccache; 196b528cefcSMark Murray 197b528cefcSMark Murray return ret; 198b528cefcSMark Murray } 199*ae771770SStanislav Sedov 200*ae771770SStanislav Sedov /** 201*ae771770SStanislav Sedov * Validate the newly fetch credential, see also krb5_verify_init_creds(). 202*ae771770SStanislav Sedov * 203*ae771770SStanislav Sedov * @param context a Kerberos 5 context 204*ae771770SStanislav Sedov * @param creds the credentials to verify 205*ae771770SStanislav Sedov * @param client the client name to match up 206*ae771770SStanislav Sedov * @param ccache the credential cache to use 207*ae771770SStanislav Sedov * @param service a service name to use, used with 208*ae771770SStanislav Sedov * krb5_sname_to_principal() to build a hostname to use to 209*ae771770SStanislav Sedov * verify. 210*ae771770SStanislav Sedov * 211*ae771770SStanislav Sedov * @ingroup krb5_ccache 212*ae771770SStanislav Sedov */ 213*ae771770SStanislav Sedov 214*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 215*ae771770SStanislav Sedov krb5_get_validated_creds(krb5_context context, 216*ae771770SStanislav Sedov krb5_creds *creds, 217*ae771770SStanislav Sedov krb5_principal client, 218*ae771770SStanislav Sedov krb5_ccache ccache, 219*ae771770SStanislav Sedov char *service) 220*ae771770SStanislav Sedov { 221*ae771770SStanislav Sedov krb5_verify_init_creds_opt vopt; 222*ae771770SStanislav Sedov krb5_principal server; 223*ae771770SStanislav Sedov krb5_error_code ret; 224*ae771770SStanislav Sedov 225*ae771770SStanislav Sedov if (krb5_principal_compare(context, creds->client, client) != TRUE) { 226*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_PRINC_NOMATCH, 227*ae771770SStanislav Sedov N_("Validation credentials and client " 228*ae771770SStanislav Sedov "doesn't match", "")); 229*ae771770SStanislav Sedov return KRB5_PRINC_NOMATCH; 230*ae771770SStanislav Sedov } 231*ae771770SStanislav Sedov 232*ae771770SStanislav Sedov ret = krb5_sname_to_principal (context, NULL, service, 233*ae771770SStanislav Sedov KRB5_NT_SRV_HST, &server); 234*ae771770SStanislav Sedov if(ret) 235*ae771770SStanislav Sedov return ret; 236*ae771770SStanislav Sedov 237*ae771770SStanislav Sedov krb5_verify_init_creds_opt_init(&vopt); 238*ae771770SStanislav Sedov 239*ae771770SStanislav Sedov ret = krb5_verify_init_creds(context, creds, server, NULL, NULL, &vopt); 240*ae771770SStanislav Sedov krb5_free_principal(context, server); 241*ae771770SStanislav Sedov 242*ae771770SStanislav Sedov return ret; 243*ae771770SStanislav Sedov } 244