1/* 2 * Copyright (c) 2005, PADL Software Pty Ltd. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * 3. Neither the name of PADL Software nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33#include "kcm_locl.h" 34 35/* 36 * Get a new ticket using a keytab/password and swap it into 37 * an existing redentials cache 38 */ 39 40krb5_error_code 41kcm_ccache_acquire(krb5_context context, 42 kcm_ccache ccache, 43 time_t *expire) 44{ 45 krb5_error_code ret = 0; 46 krb5_creds cred; 47 krb5_const_realm realm; 48 krb5_get_init_creds_opt *opt = NULL; 49 krb5_ccache_data ccdata; 50 char *in_tkt_service = NULL; 51 52 *expire = 0; 53 memset(&cred, 0, sizeof(cred)); 54 55 KCM_ASSERT_VALID(ccache); 56 57 /* We need a cached key or keytab to acquire credentials */ 58 if (ccache->flags & KCM_FLAGS_USE_PASSWORD) { 59 if (ccache->password == NULL) 60 krb5_abortx(context, 61 "kcm_ccache_acquire: KCM_FLAGS_USE_PASSWORD without password"); 62 } else if (ccache->flags & KCM_FLAGS_USE_KEYTAB) { 63 if (ccache->keytab == NULL) 64 krb5_abortx(context, 65 "kcm_ccache_acquire: KCM_FLAGS_USE_KEYTAB without keytab"); 66 } else { 67 kcm_log(0, "Cannot acquire initial credentials for cache %s without key", 68 ccache->name); 69 return KRB5_FCC_INTERNAL; 70 } 71 72 /* Fake up an internal ccache */ 73 kcm_internal_ccache(context, ccache, &ccdata); 74 75 /* Now, actually acquire the creds */ 76 if (ccache->server != NULL) { 77 ret = krb5_unparse_name(context, ccache->server, &in_tkt_service); 78 if (ret) { 79 kcm_log(0, "Failed to unparse service name for cache %s", 80 ccache->name); 81 return ret; 82 } 83 } 84 85 realm = krb5_principal_get_realm(context, ccache->client); 86 87 ret = krb5_get_init_creds_opt_alloc(context, &opt); 88 if (ret) 89 goto out; 90 krb5_get_init_creds_opt_set_default_flags(context, "kcm", realm, opt); 91 if (ccache->tkt_life != 0) 92 krb5_get_init_creds_opt_set_tkt_life(opt, ccache->tkt_life); 93 if (ccache->renew_life != 0) 94 krb5_get_init_creds_opt_set_renew_life(opt, ccache->renew_life); 95 96 if (ccache->flags & KCM_FLAGS_USE_PASSWORD) { 97 ret = krb5_get_init_creds_password(context, 98 &cred, 99 ccache->client, 100 ccache->password, 101 NULL, 102 NULL, 103 0, 104 in_tkt_service, 105 opt); 106 } else { 107 ret = krb5_get_init_creds_keytab(context, 108 &cred, 109 ccache->client, 110 ccache->keytab, 111 0, 112 in_tkt_service, 113 opt); 114 } 115 116 if (ret) { 117 const char *msg = krb5_get_error_message(context, ret); 118 kcm_log(0, "Failed to acquire credentials for cache %s: %s", 119 ccache->name, msg); 120 krb5_free_error_message(context, msg); 121 if (in_tkt_service != NULL) 122 free(in_tkt_service); 123 goto out; 124 } 125 126 if (in_tkt_service != NULL) 127 free(in_tkt_service); 128 129 /* Swap them in */ 130 kcm_ccache_remove_creds_internal(context, ccache); 131 132 ret = kcm_ccache_store_cred_internal(context, ccache, &cred, NULL, 0); 133 if (ret) { 134 const char *msg = krb5_get_error_message(context, ret); 135 kcm_log(0, "Failed to store credentials for cache %s: %s", 136 ccache->name, msg); 137 krb5_free_error_message(context, msg); 138 krb5_free_cred_contents(context, &cred); 139 goto out; 140 } 141 142 *expire = cred.times.endtime; 143 144out: 145 if (opt) 146 krb5_get_init_creds_opt_free(context, opt); 147 148 return ret; 149} 150