get_for_creds.c revision 78527
111126Sjulian/* 211126Sjulian * Copyright (c) 1997 - 2001 Kungliga Tekniska H�gskolan 311126Sjulian * (Royal Institute of Technology, Stockholm, Sweden). 411126Sjulian * All rights reserved. 511126Sjulian * 611126Sjulian * Redistribution and use in source and binary forms, with or without 711126Sjulian * modification, are permitted provided that the following conditions 811126Sjulian * are met: 911126Sjulian * 1011126Sjulian * 1. Redistributions of source code must retain the above copyright 1111126Sjulian * notice, this list of conditions and the following disclaimer. 1211126Sjulian * 1311126Sjulian * 2. Redistributions in binary form must reproduce the above copyright 1411126Sjulian * notice, this list of conditions and the following disclaimer in the 1511126Sjulian * documentation and/or other materials provided with the distribution. 1611126Sjulian * 1711126Sjulian * 3. Neither the name of the Institute nor the names of its contributors 1811126Sjulian * may be used to endorse or promote products derived from this software 1911126Sjulian * without specific prior written permission. 2011126Sjulian * 2111126Sjulian * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 2211126Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2311126Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2411126Sjulian * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 2511126Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2611126Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2711126Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2811126Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2911126Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3011126Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3111126Sjulian * SUCH DAMAGE. 3211126Sjulian */ 3348948Sgreen 3411126Sjulian#include <krb5_locl.h> 3511126Sjulian 3611126SjulianRCSID("$Id: get_for_creds.c,v 1.29 2001/05/14 22:49:55 assar Exp $"); 3748936Sphk 3811127Sjulianstatic krb5_error_code 3936735Sdfradd_addrs(krb5_context context, 4048936Sphk krb5_addresses *addr, 4111126Sjulian struct addrinfo *ai) 4212954Sjulian{ 4348936Sphk krb5_error_code ret; 4411126Sjulian unsigned n, i, j; 4548936Sphk void *tmp; 4648936Sphk struct addrinfo *a; 4747640Sphk 4812954Sjulian n = 0; 4947640Sphk for (a = ai; a != NULL; a = a->ai_next) 5012954Sjulian ++n; 5148936Sphk 5246635Sphk i = addr->len; 5348936Sphk addr->len += n; 5448936Sphk tmp = realloc(addr->val, addr->len * sizeof(*addr->val)); 5548936Sphk if (tmp == NULL) { 5648936Sphk krb5_set_error_string(context, "malloc: out of memory"); 5748936Sphk ret = ENOMEM; 5848936Sphk goto fail; 5948936Sphk } 6048936Sphk addr->val = tmp; 6148936Sphk for (j = i; j < addr->len; ++j) { 6211126Sjulian addr->val[i].addr_type = 0; 6312954Sjulian krb5_data_zero(&addr->val[i].address); 6412954Sjulian } 6512954Sjulian for (a = ai; a != NULL; a = a->ai_next) { 6612954Sjulian ret = krb5_sockaddr2address (context, a->ai_addr, &addr->val[i]); 6712954Sjulian if (ret == 0) 6812954Sjulian ++i; 6912954Sjulian else if (ret == KRB5_PROG_ATYPE_NOSUPP) 7012954Sjulian krb5_clear_error_string (context); 7112954Sjulian else 7246676Sphk goto fail; 7337389Sjulian } 7448864Sphk addr->len = i; 7512954Sjulian return 0; 7612954Sjulianfail: 7712954Sjulian krb5_free_addresses (context, addr); 7812954Sjulian return ret; 7947640Sphk} 8047640Sphk 8147640Sphk/* 8247640Sphk * 8347640Sphk */ 8447640Sphk 8547640Sphkkrb5_error_code 8647640Sphkkrb5_fwd_tgt_creds (krb5_context context, 8747640Sphk krb5_auth_context auth_context, 8848892Sphk const char *hostname, 8947640Sphk krb5_principal client, 9047640Sphk krb5_principal server, 9147640Sphk krb5_ccache ccache, 9247640Sphk int forwardable, 9347640Sphk krb5_data *out_data) 9447640Sphk{ 9537389Sjulian krb5_flags flags = 0; 9647640Sphk krb5_creds creds; 9717264Sphk krb5_error_code ret; 9847028Sphk 9947028Sphk flags |= KDC_OPT_FORWARDED; 10017264Sphk 10147028Sphk if (forwardable) 10247640Sphk flags |= KDC_OPT_FORWARDABLE; 10347028Sphk 10448936Sphk 10547028Sphk memset (&creds, 0, sizeof(creds)); 10647028Sphk creds.client = client; 10747028Sphk creds.server = server; 10847640Sphk 10947640Sphk ret = krb5_get_forwarded_creds (context, 11047640Sphk auth_context, 11147640Sphk ccache, 11237389Sjulian flags, 11317264Sphk hostname, 11448510Sphk &creds, 11548510Sphk out_data); 11648510Sphk return ret; 11748510Sphk} 11847640Sphk 11937389Sjulian/* 12048510Sphk * 12148936Sphk */ 12248510Sphk 12348510Sphkkrb5_error_code 12448510Sphkkrb5_get_forwarded_creds (krb5_context context, 12548510Sphk krb5_auth_context auth_context, 12647640Sphk krb5_ccache ccache, 12748510Sphk krb5_flags flags, 12847640Sphk const char *hostname, 12937389Sjulian krb5_creds *in_creds, 13037389Sjulian krb5_data *out_data) 13137389Sjulian{ 13248211Sgrog krb5_error_code ret; 13348211Sgrog krb5_creds *out_creds; 13448211Sgrog krb5_addresses addrs; 13548211Sgrog KRB_CRED cred; 13636735Sdfr KrbCredInfo *krb_cred_info; 13748211Sgrog EncKrbCredPart enc_krb_cred_part; 13848211Sgrog size_t len; 13948211Sgrog u_char buf[1024]; 14048211Sgrog int32_t sec, usec; 14148211Sgrog krb5_kdc_flags kdc_flags; 14248211Sgrog krb5_crypto crypto; 14348211Sgrog struct addrinfo *ai; 14448211Sgrog int save_errno; 14548211Sgrog 14648211Sgrog addrs.len = 0; 14748211Sgrog addrs.val = NULL; 14848211Sgrog 14948211Sgrog ret = getaddrinfo (hostname, NULL, NULL, &ai); 15048211Sgrog if (ret) { 15148211Sgrog save_errno = errno; 15248211Sgrog krb5_set_error_string(context, "resolving %s: %s", 15348211Sgrog hostname, gai_strerror(ret)); 15446635Sphk return krb5_eai_to_heim_errno(ret, save_errno); 15536735Sdfr } 15646635Sphk 15748240Sdfr ret = add_addrs (context, &addrs, ai); 15836735Sdfr freeaddrinfo (ai); 15936735Sdfr if (ret) 16036735Sdfr return ret; 16147640Sphk 16244975Sdfr kdc_flags.i = flags; 16344975Sdfr 16444975Sdfr ret = krb5_get_kdc_cred (context, 16536735Sdfr ccache, 16636735Sdfr kdc_flags, 16744975Sdfr &addrs, 16844975Sdfr NULL, 16944975Sdfr in_creds, 17044975Sdfr &out_creds); 17144975Sdfr krb5_free_addresses (context, &addrs); 17248240Sdfr if (ret) { 17344975Sdfr return ret; 17436735Sdfr } 17536735Sdfr 17636735Sdfr memset (&cred, 0, sizeof(cred)); 17736735Sdfr cred.pvno = 5; 17836735Sdfr cred.msg_type = krb_cred; 17936735Sdfr ALLOC_SEQ(&cred.tickets, 1); 18036735Sdfr if (cred.tickets.val == NULL) { 18147028Sphk ret = ENOMEM; 18247028Sphk krb5_set_error_string(context, "malloc: out of memory"); 18347028Sphk goto out2; 18447028Sphk } 18547028Sphk ret = decode_Ticket(out_creds->ticket.data, 18647028Sphk out_creds->ticket.length, 18747028Sphk cred.tickets.val, &len); 18847028Sphk if (ret) 18948936Sphk goto out3; 19048936Sphk 19148936Sphk memset (&enc_krb_cred_part, 0, sizeof(enc_krb_cred_part)); 19247028Sphk ALLOC_SEQ(&enc_krb_cred_part.ticket_info, 1); 19347028Sphk if (enc_krb_cred_part.ticket_info.val == NULL) { 19447028Sphk ret = ENOMEM; 19547028Sphk krb5_set_error_string(context, "malloc: out of memory"); 19647028Sphk goto out4; 19748936Sphk } 19848936Sphk 19948936Sphk krb5_us_timeofday (context, &sec, &usec); 20047028Sphk 20147028Sphk ALLOC(enc_krb_cred_part.timestamp, 1); 20247028Sphk if (enc_krb_cred_part.timestamp == NULL) { 20347680Sphk ret = ENOMEM; 20447680Sphk krb5_set_error_string(context, "malloc: out of memory"); 20548892Sphk goto out4; 20647680Sphk } 20747680Sphk *enc_krb_cred_part.timestamp = sec; 20847680Sphk ALLOC(enc_krb_cred_part.usec, 1); 20947028Sphk if (enc_krb_cred_part.usec == NULL) { 21047028Sphk ret = ENOMEM; 21148936Sphk krb5_set_error_string(context, "malloc: out of memory"); 21248936Sphk goto out4; 21348936Sphk } 21448936Sphk *enc_krb_cred_part.usec = usec; 21548936Sphk 21648936Sphk if (auth_context->local_address && auth_context->local_port) { 21748936Sphk ret = krb5_make_addrport (context, 21848936Sphk &enc_krb_cred_part.s_address, 21948936Sphk auth_context->local_address, 22048936Sphk auth_context->local_port); 22148936Sphk if (ret) 22248936Sphk goto out4; 22348936Sphk } 22448936Sphk 22548936Sphk if (auth_context->remote_address) { 22648936Sphk ALLOC(enc_krb_cred_part.r_address, 1); 22748936Sphk if (enc_krb_cred_part.r_address == NULL) { 22848936Sphk ret = ENOMEM; 22948936Sphk krb5_set_error_string(context, "malloc: out of memory"); 23048936Sphk goto out4; 23148936Sphk } 23248936Sphk 23348936Sphk ret = krb5_copy_address (context, auth_context->remote_address, 23448936Sphk enc_krb_cred_part.r_address); 23547028Sphk if (ret) 23647028Sphk goto out4; 23747028Sphk } 23847028Sphk 23947028Sphk /* fill ticket_info.val[0] */ 24048936Sphk 24148936Sphk enc_krb_cred_part.ticket_info.len = 1; 24248936Sphk 24347028Sphk krb_cred_info = enc_krb_cred_part.ticket_info.val; 24447028Sphk 24548948Sgreen copy_EncryptionKey (&out_creds->session, &krb_cred_info->key); 24648948Sgreen ALLOC(krb_cred_info->prealm, 1); 24748948Sgreen copy_Realm (&out_creds->client->realm, krb_cred_info->prealm); 24848948Sgreen ALLOC(krb_cred_info->pname, 1); 24948948Sgreen copy_PrincipalName(&out_creds->client->name, krb_cred_info->pname); 25048948Sgreen ALLOC(krb_cred_info->flags, 1); 25148948Sgreen *krb_cred_info->flags = out_creds->flags.b; 25248948Sgreen ALLOC(krb_cred_info->authtime, 1); 25348948Sgreen *krb_cred_info->authtime = out_creds->times.authtime; 25447028Sphk ALLOC(krb_cred_info->starttime, 1); 25547028Sphk *krb_cred_info->starttime = out_creds->times.starttime; 25647028Sphk ALLOC(krb_cred_info->endtime, 1); 25748864Sphk *krb_cred_info->endtime = out_creds->times.endtime; 25848864Sphk ALLOC(krb_cred_info->renew_till, 1); 25948864Sphk *krb_cred_info->renew_till = out_creds->times.renew_till; 26048864Sphk ALLOC(krb_cred_info->srealm, 1); 26148864Sphk copy_Realm (&out_creds->server->realm, krb_cred_info->srealm); 26248864Sphk ALLOC(krb_cred_info->sname, 1); 26348864Sphk copy_PrincipalName (&out_creds->server->name, krb_cred_info->sname); 26448864Sphk ALLOC(krb_cred_info->caddr, 1); 26548864Sphk copy_HostAddresses (&out_creds->addresses, krb_cred_info->caddr); 26647028Sphk 26747028Sphk krb5_free_creds (context, out_creds); 26847028Sphk 26947028Sphk /* encode EncKrbCredPart */ 27047028Sphk 27147028Sphk ret = krb5_encode_EncKrbCredPart (context, 27247028Sphk buf + sizeof(buf) - 1, sizeof(buf), 27347028Sphk &enc_krb_cred_part, &len); 27447028Sphk free_EncKrbCredPart (&enc_krb_cred_part); 27547028Sphk if (ret) { 27647028Sphk free_KRB_CRED(&cred); 27747028Sphk return ret; 27847028Sphk } 27947028Sphk 28047028Sphk ret = krb5_crypto_init(context, auth_context->local_subkey, 0, &crypto); 28148859Sphk if (ret) { 28247028Sphk free_KRB_CRED(&cred); 28347028Sphk return ret; 28447028Sphk } 28547028Sphk ret = krb5_encrypt_EncryptedData (context, 286 crypto, 287 KRB5_KU_KRB_CRED, 288 buf + sizeof(buf) - len, 289 len, 290 0, 291 &cred.enc_part); 292 krb5_crypto_destroy(context, crypto); 293 if (ret) { 294 free_KRB_CRED(&cred); 295 return ret; 296 } 297 298 ret = encode_KRB_CRED (buf + sizeof(buf) - 1, sizeof(buf), 299 &cred, &len); 300 free_KRB_CRED (&cred); 301 if (ret) 302 return ret; 303 out_data->length = len; 304 out_data->data = malloc(len); 305 if (out_data->data == NULL) { 306 krb5_set_error_string(context, "malloc: out of memory"); 307 return ENOMEM; 308 } 309 memcpy (out_data->data, buf + sizeof(buf) - len, len); 310 return 0; 311out4: 312 free_EncKrbCredPart(&enc_krb_cred_part); 313out3: 314 free_KRB_CRED(&cred); 315out2: 316 krb5_free_creds (context, out_creds); 317 return ret; 318} 319