get_for_creds.c revision 78527
1139743Simp/* 239213Sgibbs * Copyright (c) 1997 - 2001 Kungliga Tekniska H�gskolan 339213Sgibbs * (Royal Institute of Technology, Stockholm, Sweden). 439213Sgibbs * All rights reserved. 539213Sgibbs * 639213Sgibbs * Redistribution and use in source and binary forms, with or without 739213Sgibbs * modification, are permitted provided that the following conditions 839213Sgibbs * are met: 939213Sgibbs * 1039213Sgibbs * 1. Redistributions of source code must retain the above copyright 1139213Sgibbs * notice, this list of conditions and the following disclaimer. 1239213Sgibbs * 1339213Sgibbs * 2. Redistributions in binary form must reproduce the above copyright 1439213Sgibbs * notice, this list of conditions and the following disclaimer in the 1539213Sgibbs * documentation and/or other materials provided with the distribution. 1639213Sgibbs * 1739213Sgibbs * 3. Neither the name of the Institute nor the names of its contributors 1839213Sgibbs * may be used to endorse or promote products derived from this software 1939213Sgibbs * without specific prior written permission. 2039213Sgibbs * 2139213Sgibbs * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 2239213Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2339213Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2439213Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 2539213Sgibbs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2639213Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2739213Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2839213Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29116162Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30116162Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31116162Sobrien * SUCH DAMAGE. 3239213Sgibbs */ 3339213Sgibbs 3439213Sgibbs#include <krb5_locl.h> 3539213Sgibbs 3639213SgibbsRCSID("$Id: get_for_creds.c,v 1.29 2001/05/14 22:49:55 assar Exp $"); 3760041Sphk 3839213Sgibbsstatic krb5_error_code 3939213Sgibbsadd_addrs(krb5_context context, 4039213Sgibbs krb5_addresses *addr, 4150073Sken struct addrinfo *ai) 4239213Sgibbs{ 4339213Sgibbs krb5_error_code ret; 4439213Sgibbs unsigned n, i, j; 4539213Sgibbs void *tmp; 4639213Sgibbs struct addrinfo *a; 4739213Sgibbs 4839213Sgibbs n = 0; 4939213Sgibbs for (a = ai; a != NULL; a = a->ai_next) 5039213Sgibbs ++n; 5139213Sgibbs 5239213Sgibbs i = addr->len; 5350073Sken addr->len += n; 5450073Sken tmp = realloc(addr->val, addr->len * sizeof(*addr->val)); 5539213Sgibbs if (tmp == NULL) { 5639213Sgibbs krb5_set_error_string(context, "malloc: out of memory"); 5739213Sgibbs ret = ENOMEM; 5839213Sgibbs goto fail; 5939213Sgibbs } 6039213Sgibbs addr->val = tmp; 6139213Sgibbs for (j = i; j < addr->len; ++j) { 6239213Sgibbs addr->val[i].addr_type = 0; 6339213Sgibbs krb5_data_zero(&addr->val[i].address); 6439213Sgibbs } 6539213Sgibbs for (a = ai; a != NULL; a = a->ai_next) { 6639213Sgibbs ret = krb5_sockaddr2address (context, a->ai_addr, &addr->val[i]); 6739213Sgibbs if (ret == 0) 6839213Sgibbs ++i; 6939213Sgibbs else if (ret == KRB5_PROG_ATYPE_NOSUPP) 7039213Sgibbs krb5_clear_error_string (context); 7139213Sgibbs else 7239213Sgibbs goto fail; 7339213Sgibbs } 7439213Sgibbs addr->len = i; 7539213Sgibbs return 0; 7639213Sgibbsfail: 7739213Sgibbs krb5_free_addresses (context, addr); 7839213Sgibbs return ret; 7959249Sphk} 80112006Sphk 8160938Sjake/* 8239213Sgibbs * 8339213Sgibbs */ 8439213Sgibbs 8550073Skenkrb5_error_code 86130585Sphkkrb5_fwd_tgt_creds (krb5_context context, 8739213Sgibbs krb5_auth_context auth_context, 8839213Sgibbs const char *hostname, 8939213Sgibbs krb5_principal client, 9039213Sgibbs krb5_principal server, 9139213Sgibbs krb5_ccache ccache, 9239213Sgibbs int forwardable, 9339213Sgibbs krb5_data *out_data) 9439213Sgibbs{ 9539213Sgibbs krb5_flags flags = 0; 9640603Sken krb5_creds creds; 9739213Sgibbs krb5_error_code ret; 9839213Sgibbs 9939213Sgibbs flags |= KDC_OPT_FORWARDED; 10039213Sgibbs 10150073Sken if (forwardable) 10239213Sgibbs flags |= KDC_OPT_FORWARDABLE; 10339213Sgibbs 10439213Sgibbs 10539213Sgibbs memset (&creds, 0, sizeof(creds)); 10639213Sgibbs creds.client = client; 10739213Sgibbs creds.server = server; 10839213Sgibbs 10939213Sgibbs ret = krb5_get_forwarded_creds (context, 11039213Sgibbs auth_context, 11139213Sgibbs ccache, 11239213Sgibbs flags, 11339213Sgibbs hostname, 11439213Sgibbs &creds, 11539213Sgibbs out_data); 11639213Sgibbs return ret; 11772119Speter} 11839213Sgibbs 11939213Sgibbs/* 12047625Sphk * 121126080Sphk */ 122168752Sscottl 123111815Sphkkrb5_error_code 124111815Sphkkrb5_get_forwarded_creds (krb5_context context, 125111815Sphk krb5_auth_context auth_context, 126111815Sphk krb5_ccache ccache, 127111815Sphk krb5_flags flags, 128111815Sphk const char *hostname, 129111815Sphk krb5_creds *in_creds, 13039213Sgibbs krb5_data *out_data) 13139213Sgibbs{ 13250073Sken krb5_error_code ret; 13350073Sken krb5_creds *out_creds; 13450073Sken krb5_addresses addrs; 13550073Sken KRB_CRED cred; 13639213Sgibbs KrbCredInfo *krb_cred_info; 137130585Sphk EncKrbCredPart enc_krb_cred_part; 13839213Sgibbs size_t len; 13939213Sgibbs u_char buf[1024]; 14039213Sgibbs int32_t sec, usec; 141168752Sscottl krb5_kdc_flags kdc_flags; 14239213Sgibbs krb5_crypto crypto; 143101940Snjl struct addrinfo *ai; 144168752Sscottl int save_errno; 14539213Sgibbs 14639213Sgibbs addrs.len = 0; 14739213Sgibbs addrs.val = NULL; 14839213Sgibbs 149168752Sscottl ret = getaddrinfo (hostname, NULL, NULL, &ai); 15040603Sken if (ret) { 151168752Sscottl save_errno = errno; 152168752Sscottl krb5_set_error_string(context, "resolving %s: %s", 15340603Sken hostname, gai_strerror(ret)); 15440603Sken return krb5_eai_to_heim_errno(ret, save_errno); 15540603Sken } 156168752Sscottl 157168752Sscottl ret = add_addrs (context, &addrs, ai); 158168752Sscottl freeaddrinfo (ai); 159168752Sscottl if (ret) 160168752Sscottl return ret; 16141297Sken 16239213Sgibbs kdc_flags.i = flags; 163168752Sscottl 164168752Sscottl ret = krb5_get_kdc_cred (context, 16541297Sken ccache, 16639213Sgibbs kdc_flags, 16739213Sgibbs &addrs, 16839213Sgibbs NULL, 16939213Sgibbs in_creds, 17039213Sgibbs &out_creds); 171130585Sphk krb5_free_addresses (context, &addrs); 17239213Sgibbs if (ret) { 17339213Sgibbs return ret; 17439213Sgibbs } 17539213Sgibbs 176101940Snjl memset (&cred, 0, sizeof(cred)); 17739213Sgibbs cred.pvno = 5; 17839213Sgibbs cred.msg_type = krb_cred; 17939213Sgibbs ALLOC_SEQ(&cred.tickets, 1); 18039213Sgibbs if (cred.tickets.val == NULL) { 18139213Sgibbs ret = ENOMEM; 182168752Sscottl krb5_set_error_string(context, "malloc: out of memory"); 18339213Sgibbs goto out2; 18439213Sgibbs } 18539213Sgibbs ret = decode_Ticket(out_creds->ticket.data, 18639213Sgibbs out_creds->ticket.length, 18739213Sgibbs cred.tickets.val, &len); 18839213Sgibbs if (ret) 18939213Sgibbs goto out3; 19039213Sgibbs 19139213Sgibbs memset (&enc_krb_cred_part, 0, sizeof(enc_krb_cred_part)); 19239213Sgibbs ALLOC_SEQ(&enc_krb_cred_part.ticket_info, 1); 19339213Sgibbs if (enc_krb_cred_part.ticket_info.val == NULL) { 19439213Sgibbs ret = ENOMEM; 19539213Sgibbs krb5_set_error_string(context, "malloc: out of memory"); 19659249Sphk goto out4; 19739213Sgibbs } 19839213Sgibbs 19939213Sgibbs krb5_us_timeofday (context, &sec, &usec); 20039213Sgibbs 201101940Snjl ALLOC(enc_krb_cred_part.timestamp, 1); 20276362Sphk if (enc_krb_cred_part.timestamp == NULL) { 20339213Sgibbs ret = ENOMEM; 20476362Sphk krb5_set_error_string(context, "malloc: out of memory"); 20576362Sphk goto out4; 20639213Sgibbs } 207168752Sscottl *enc_krb_cred_part.timestamp = sec; 20839213Sgibbs ALLOC(enc_krb_cred_part.usec, 1); 20939213Sgibbs if (enc_krb_cred_part.usec == NULL) { 21039213Sgibbs ret = ENOMEM; 21139213Sgibbs krb5_set_error_string(context, "malloc: out of memory"); 21239213Sgibbs goto out4; 21339213Sgibbs } 214168752Sscottl *enc_krb_cred_part.usec = usec; 21576362Sphk 21676362Sphk if (auth_context->local_address && auth_context->local_port) { 21739213Sgibbs ret = krb5_make_addrport (context, 21839213Sgibbs &enc_krb_cred_part.s_address, 21939213Sgibbs auth_context->local_address, 22039213Sgibbs auth_context->local_port); 22139213Sgibbs if (ret) 22259249Sphk goto out4; 22339213Sgibbs } 22439213Sgibbs 22539213Sgibbs if (auth_context->remote_address) { 22639213Sgibbs ALLOC(enc_krb_cred_part.r_address, 1); 22739213Sgibbs if (enc_krb_cred_part.r_address == NULL) { 228168752Sscottl ret = ENOMEM; 22939213Sgibbs krb5_set_error_string(context, "malloc: out of memory"); 23039213Sgibbs goto out4; 23139213Sgibbs } 23239213Sgibbs 23339213Sgibbs ret = krb5_copy_address (context, auth_context->remote_address, 23439213Sgibbs enc_krb_cred_part.r_address); 23539213Sgibbs if (ret) 23639213Sgibbs goto out4; 23739213Sgibbs } 23839213Sgibbs 23939213Sgibbs /* fill ticket_info.val[0] */ 24039213Sgibbs 24139213Sgibbs enc_krb_cred_part.ticket_info.len = 1; 242169605Sscottl 24339213Sgibbs krb_cred_info = enc_krb_cred_part.ticket_info.val; 24439213Sgibbs 24539213Sgibbs copy_EncryptionKey (&out_creds->session, &krb_cred_info->key); 24639213Sgibbs ALLOC(krb_cred_info->prealm, 1); 24739213Sgibbs copy_Realm (&out_creds->client->realm, krb_cred_info->prealm); 24839213Sgibbs ALLOC(krb_cred_info->pname, 1); 24939213Sgibbs copy_PrincipalName(&out_creds->client->name, krb_cred_info->pname); 25039213Sgibbs ALLOC(krb_cred_info->flags, 1); 25139213Sgibbs *krb_cred_info->flags = out_creds->flags.b; 25239213Sgibbs ALLOC(krb_cred_info->authtime, 1); 25339213Sgibbs *krb_cred_info->authtime = out_creds->times.authtime; 25439213Sgibbs ALLOC(krb_cred_info->starttime, 1); 25539213Sgibbs *krb_cred_info->starttime = out_creds->times.starttime; 25639213Sgibbs ALLOC(krb_cred_info->endtime, 1); 25739213Sgibbs *krb_cred_info->endtime = out_creds->times.endtime; 25839213Sgibbs ALLOC(krb_cred_info->renew_till, 1); 25939213Sgibbs *krb_cred_info->renew_till = out_creds->times.renew_till; 26039213Sgibbs ALLOC(krb_cred_info->srealm, 1); 26139213Sgibbs copy_Realm (&out_creds->server->realm, krb_cred_info->srealm); 26239213Sgibbs ALLOC(krb_cred_info->sname, 1); 26339213Sgibbs copy_PrincipalName (&out_creds->server->name, krb_cred_info->sname); 26439213Sgibbs ALLOC(krb_cred_info->caddr, 1); 26539213Sgibbs copy_HostAddresses (&out_creds->addresses, krb_cred_info->caddr); 26639213Sgibbs 26739213Sgibbs krb5_free_creds (context, out_creds); 26839213Sgibbs 26939213Sgibbs /* encode EncKrbCredPart */ 27039213Sgibbs 27139213Sgibbs ret = krb5_encode_EncKrbCredPart (context, 27239213Sgibbs buf + sizeof(buf) - 1, sizeof(buf), 27339213Sgibbs &enc_krb_cred_part, &len); 27439213Sgibbs free_EncKrbCredPart (&enc_krb_cred_part); 27539213Sgibbs if (ret) { 27639213Sgibbs free_KRB_CRED(&cred); 27739213Sgibbs return ret; 27859249Sphk } 27939213Sgibbs 28050073Sken ret = krb5_crypto_init(context, auth_context->local_subkey, 0, &crypto); 28150073Sken if (ret) { 28239213Sgibbs free_KRB_CRED(&cred); 28339213Sgibbs return ret; 284169605Sscottl } 285112006Sphk ret = krb5_encrypt_EncryptedData (context, 28639213Sgibbs crypto, 28739213Sgibbs KRB5_KU_KRB_CRED, 28856148Smjacob buf + sizeof(buf) - len, 28943819Sken len, 29039213Sgibbs 0, 29153257Sken &cred.enc_part); 29253257Sken krb5_crypto_destroy(context, crypto); 29353257Sken if (ret) { 294168872Sscottl free_KRB_CRED(&cred); 295101940Snjl return ret; 296101940Snjl } 29739213Sgibbs 29839213Sgibbs ret = encode_KRB_CRED (buf + sizeof(buf) - 1, sizeof(buf), 29939213Sgibbs &cred, &len); 30039213Sgibbs free_KRB_CRED (&cred); 30139213Sgibbs if (ret) 30239213Sgibbs return ret; 30339213Sgibbs out_data->length = len; 30439213Sgibbs out_data->data = malloc(len); 305169605Sscottl if (out_data->data == NULL) { 306169605Sscottl krb5_set_error_string(context, "malloc: out of memory"); 30739213Sgibbs return ENOMEM; 30839213Sgibbs } 30939213Sgibbs memcpy (out_data->data, buf + sizeof(buf) - len, len); 31039213Sgibbs return 0; 31139213Sgibbsout4: 31239213Sgibbs free_EncKrbCredPart(&enc_krb_cred_part); 31339213Sgibbsout3: 31439213Sgibbs free_KRB_CRED(&cred); 31540603Skenout2: 31640603Sken krb5_free_creds (context, out_creds); 31740603Sken return ret; 31840603Sken} 31940603Sken