159769Sgrog/* 259769Sgrog * Copyright (c) 2005, PADL Software Pty Ltd. 324424Swosch * All rights reserved. 424424Swosch * 524424Swosch * Redistribution and use in source and binary forms, with or without 624424Swosch * modification, are permitted provided that the following conditions 724424Swosch * are met: 824424Swosch * 924424Swosch * 1. Redistributions of source code must retain the above copyright 1024424Swosch * notice, this list of conditions and the following disclaimer. 1124424Swosch * 1224424Swosch * 2. Redistributions in binary form must reproduce the above copyright 1324424Swosch * notice, this list of conditions and the following disclaimer in the 1424424Swosch * documentation and/or other materials provided with the distribution. 1542704Swosch * 1642704Swosch * 3. Neither the name of PADL Software nor the names of its contributors 1742704Swosch * may be used to endorse or promote products derived from this software 1824424Swosch * without specific prior written permission. 1942704Swosch * 2042704Swosch * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND 2142704Swosch * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2242704Swosch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2342704Swosch * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE 2442704Swosch * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2542704Swosch * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2642704Swosch * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2742704Swosch * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2842704Swosch * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2942704Swosch * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3059769Sgrog * SUCH DAMAGE. 3159769Sgrog */ 3259769Sgrog 3359769Sgrog#include "kcm_locl.h" 3459769Sgrog 3559769Sgrog/* 3659769Sgrog * Get a new ticket using a keytab/cached key and swap it into 3759769Sgrog * an existing redentials cache 3859769Sgrog */ 3924424Swosch 4042704Swoschkrb5_error_code 4124424Swoschkcm_ccache_acquire(krb5_context context, 4242704Swosch kcm_ccache ccache, 4324424Swosch krb5_creds **credp) 4442704Swosch{ 4524424Swosch krb5_error_code ret = 0; 4624424Swosch krb5_creds cred; 4724424Swosch krb5_const_realm realm; 4842704Swosch krb5_get_init_creds_opt *opt = NULL; 4925031Swosch krb5_ccache_data ccdata; 5059156Swosch char *in_tkt_service = NULL; 5125031Swosch 5225031Swosch memset(&cred, 0, sizeof(cred)); 5324424Swosch 5424424Swosch KCM_ASSERT_VALID(ccache); 5524424Swosch 5624424Swosch /* We need a cached key or keytab to acquire credentials */ 5771231Sitojun if (ccache->flags & KCM_FLAGS_USE_CACHED_KEY) { 5824424Swosch if (ccache->key.keyblock.keyvalue.length == 0) 5971231Sitojun krb5_abortx(context, 6025031Swosch "kcm_ccache_acquire: KCM_FLAGS_USE_CACHED_KEY without key"); 6171231Sitojun } else if (ccache->flags & KCM_FLAGS_USE_KEYTAB) { 6224424Swosch if (ccache->key.keytab == NULL) 6325031Swosch krb5_abortx(context, 6425031Swosch "kcm_ccache_acquire: KCM_FLAGS_USE_KEYTAB without keytab"); 6571231Sitojun } else { 6625031Swosch kcm_log(0, "Cannot acquire initial credentials for cache %s without key", 6771231Sitojun ccache->name); 6870110Swosch return KRB5_FCC_INTERNAL; 6970110Swosch } 7070110Swosch 7170110Swosch HEIMDAL_MUTEX_lock(&ccache->mutex); 7270110Swosch 7370110Swosch /* Fake up an internal ccache */ 7470110Swosch kcm_internal_ccache(context, ccache, &ccdata); 7570110Swosch 7670110Swosch /* Now, actually acquire the creds */ 7770110Swosch if (ccache->server != NULL) { 7870110Swosch ret = krb5_unparse_name(context, ccache->server, &in_tkt_service); 7980675Sasmodai if (ret) { 8080675Sasmodai kcm_log(0, "Failed to unparse service principal name for cache %s: %s", 8180675Sasmodai ccache->name, krb5_get_err_text(context, ret)); 8280675Sasmodai return ret; 8380675Sasmodai } 8480675Sasmodai } 8580675Sasmodai 8680675Sasmodai realm = krb5_principal_get_realm(context, ccache->client); 8780675Sasmodai 8880675Sasmodai ret = krb5_get_init_creds_opt_alloc(context, &opt); 8980675Sasmodai if (ret) 9080675Sasmodai goto out; 9180675Sasmodai krb5_get_init_creds_opt_set_default_flags(context, "kcm", realm, opt); 9280675Sasmodai if (ccache->tkt_life != 0) 9380675Sasmodai krb5_get_init_creds_opt_set_tkt_life(opt, ccache->tkt_life); 9480675Sasmodai if (ccache->renew_life != 0) 9580675Sasmodai krb5_get_init_creds_opt_set_renew_life(opt, ccache->renew_life); 9680675Sasmodai 9780675Sasmodai if (ccache->flags & KCM_FLAGS_USE_CACHED_KEY) { 9880675Sasmodai ret = krb5_get_init_creds_keyblock(context, 9980675Sasmodai &cred, 10080675Sasmodai ccache->client, 10180675Sasmodai &ccache->key.keyblock, 10280675Sasmodai 0, 10380675Sasmodai in_tkt_service, 10480675Sasmodai opt); 10580675Sasmodai } else { 10680675Sasmodai /* loosely based on lib/krb5/init_creds_pw.c */ 10780675Sasmodai ret = krb5_get_init_creds_keytab(context, 10880675Sasmodai &cred, 10980675Sasmodai ccache->client, 11080675Sasmodai ccache->key.keytab, 11180675Sasmodai 0, 11280675Sasmodai in_tkt_service, 11380675Sasmodai opt); 11480675Sasmodai } 11580675Sasmodai 11680675Sasmodai if (ret) { 11780675Sasmodai kcm_log(0, "Failed to acquire credentials for cache %s: %s", 11880675Sasmodai ccache->name, krb5_get_err_text(context, ret)); 11980675Sasmodai if (in_tkt_service != NULL) 12080675Sasmodai free(in_tkt_service); 12180675Sasmodai goto out; 12280675Sasmodai } 12380675Sasmodai 12480675Sasmodai if (in_tkt_service != NULL) 12580675Sasmodai free(in_tkt_service); 12680675Sasmodai 12780675Sasmodai /* Swap them in */ 12880675Sasmodai kcm_ccache_remove_creds_internal(context, ccache); 12980675Sasmodai 13080675Sasmodai ret = kcm_ccache_store_cred_internal(context, ccache, &cred, 0, credp); 13180675Sasmodai if (ret) { 13280675Sasmodai kcm_log(0, "Failed to store credentials for cache %s: %s", 13380675Sasmodai ccache->name, krb5_get_err_text(context, ret)); 13480675Sasmodai krb5_free_cred_contents(context, &cred); 13580675Sasmodai goto out; 13680675Sasmodai } 13780675Sasmodai 138101401Swoschout: 13980675Sasmodai if (opt) 14087200Swosch krb5_get_init_creds_opt_free(context, opt); 14187200Swosch 14287200Swosch HEIMDAL_MUTEX_unlock(&ccache->mutex); 14380675Sasmodai 144104772Smaxim return ret; 145104772Smaxim} 146104772Smaxim