1178825Sdfr/* 2178825Sdfr * Copyright (c) 2005, PADL Software Pty Ltd. 3178825Sdfr * All rights reserved. 4178825Sdfr * 5178825Sdfr * Redistribution and use in source and binary forms, with or without 6178825Sdfr * modification, are permitted provided that the following conditions 7178825Sdfr * are met: 8178825Sdfr * 9178825Sdfr * 1. Redistributions of source code must retain the above copyright 10178825Sdfr * notice, this list of conditions and the following disclaimer. 11178825Sdfr * 12178825Sdfr * 2. Redistributions in binary form must reproduce the above copyright 13178825Sdfr * notice, this list of conditions and the following disclaimer in the 14178825Sdfr * documentation and/or other materials provided with the distribution. 15178825Sdfr * 16178825Sdfr * 3. Neither the name of PADL Software nor the names of its contributors 17178825Sdfr * may be used to endorse or promote products derived from this software 18178825Sdfr * without specific prior written permission. 19178825Sdfr * 20178825Sdfr * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND 21178825Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23178825Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE 24178825Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25178825Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26178825Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27178825Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28178825Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29178825Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30178825Sdfr * SUCH DAMAGE. 31178825Sdfr */ 32178825Sdfr 33178825Sdfr#include "kcm_locl.h" 34178825Sdfr 35178825Sdfr/* 36178825Sdfr * Get a new ticket using a keytab/cached key and swap it into 37178825Sdfr * an existing redentials cache 38178825Sdfr */ 39178825Sdfr 40178825Sdfrkrb5_error_code 41178825Sdfrkcm_ccache_acquire(krb5_context context, 42178825Sdfr kcm_ccache ccache, 43178825Sdfr krb5_creds **credp) 44178825Sdfr{ 45178825Sdfr krb5_error_code ret = 0; 46178825Sdfr krb5_creds cred; 47178825Sdfr krb5_const_realm realm; 48233294Sstas krb5_get_init_creds_opt *opt = NULL; 49178825Sdfr krb5_ccache_data ccdata; 50178825Sdfr char *in_tkt_service = NULL; 51178825Sdfr 52178825Sdfr memset(&cred, 0, sizeof(cred)); 53178825Sdfr 54178825Sdfr KCM_ASSERT_VALID(ccache); 55178825Sdfr 56178825Sdfr /* We need a cached key or keytab to acquire credentials */ 57178825Sdfr if (ccache->flags & KCM_FLAGS_USE_CACHED_KEY) { 58178825Sdfr if (ccache->key.keyblock.keyvalue.length == 0) 59178825Sdfr krb5_abortx(context, 60178825Sdfr "kcm_ccache_acquire: KCM_FLAGS_USE_CACHED_KEY without key"); 61178825Sdfr } else if (ccache->flags & KCM_FLAGS_USE_KEYTAB) { 62178825Sdfr if (ccache->key.keytab == NULL) 63178825Sdfr krb5_abortx(context, 64178825Sdfr "kcm_ccache_acquire: KCM_FLAGS_USE_KEYTAB without keytab"); 65178825Sdfr } else { 66178825Sdfr kcm_log(0, "Cannot acquire initial credentials for cache %s without key", 67178825Sdfr ccache->name); 68178825Sdfr return KRB5_FCC_INTERNAL; 69178825Sdfr } 70233294Sstas 71178825Sdfr HEIMDAL_MUTEX_lock(&ccache->mutex); 72178825Sdfr 73178825Sdfr /* Fake up an internal ccache */ 74178825Sdfr kcm_internal_ccache(context, ccache, &ccdata); 75178825Sdfr 76178825Sdfr /* Now, actually acquire the creds */ 77178825Sdfr if (ccache->server != NULL) { 78178825Sdfr ret = krb5_unparse_name(context, ccache->server, &in_tkt_service); 79178825Sdfr if (ret) { 80178825Sdfr kcm_log(0, "Failed to unparse service principal name for cache %s: %s", 81178825Sdfr ccache->name, krb5_get_err_text(context, ret)); 82178825Sdfr return ret; 83178825Sdfr } 84178825Sdfr } 85178825Sdfr 86178825Sdfr realm = krb5_principal_get_realm(context, ccache->client); 87178825Sdfr 88233294Sstas ret = krb5_get_init_creds_opt_alloc(context, &opt); 89233294Sstas if (ret) 90233294Sstas goto out; 91233294Sstas krb5_get_init_creds_opt_set_default_flags(context, "kcm", realm, opt); 92178825Sdfr if (ccache->tkt_life != 0) 93233294Sstas krb5_get_init_creds_opt_set_tkt_life(opt, ccache->tkt_life); 94178825Sdfr if (ccache->renew_life != 0) 95233294Sstas krb5_get_init_creds_opt_set_renew_life(opt, ccache->renew_life); 96178825Sdfr 97178825Sdfr if (ccache->flags & KCM_FLAGS_USE_CACHED_KEY) { 98178825Sdfr ret = krb5_get_init_creds_keyblock(context, 99178825Sdfr &cred, 100178825Sdfr ccache->client, 101178825Sdfr &ccache->key.keyblock, 102178825Sdfr 0, 103178825Sdfr in_tkt_service, 104233294Sstas opt); 105178825Sdfr } else { 106178825Sdfr /* loosely based on lib/krb5/init_creds_pw.c */ 107233294Sstas ret = krb5_get_init_creds_keytab(context, 108233294Sstas &cred, 109233294Sstas ccache->client, 110233294Sstas ccache->key.keytab, 111233294Sstas 0, 112233294Sstas in_tkt_service, 113233294Sstas opt); 114178825Sdfr } 115178825Sdfr 116178825Sdfr if (ret) { 117178825Sdfr kcm_log(0, "Failed to acquire credentials for cache %s: %s", 118178825Sdfr ccache->name, krb5_get_err_text(context, ret)); 119178825Sdfr if (in_tkt_service != NULL) 120178825Sdfr free(in_tkt_service); 121178825Sdfr goto out; 122178825Sdfr } 123178825Sdfr 124178825Sdfr if (in_tkt_service != NULL) 125178825Sdfr free(in_tkt_service); 126178825Sdfr 127178825Sdfr /* Swap them in */ 128178825Sdfr kcm_ccache_remove_creds_internal(context, ccache); 129178825Sdfr 130178825Sdfr ret = kcm_ccache_store_cred_internal(context, ccache, &cred, 0, credp); 131178825Sdfr if (ret) { 132178825Sdfr kcm_log(0, "Failed to store credentials for cache %s: %s", 133178825Sdfr ccache->name, krb5_get_err_text(context, ret)); 134178825Sdfr krb5_free_cred_contents(context, &cred); 135178825Sdfr goto out; 136178825Sdfr } 137178825Sdfr 138178825Sdfrout: 139233294Sstas if (opt) 140233294Sstas krb5_get_init_creds_opt_free(context, opt); 141233294Sstas 142178825Sdfr HEIMDAL_MUTEX_unlock(&ccache->mutex); 143178825Sdfr 144178825Sdfr return ret; 145178825Sdfr} 146