diff --git a/lib/krb5/get_for_creds.c b/lib/krb5/get_for_creds.c new file mode 100644 index 000000000..73cba8556 --- /dev/null +++ b/lib/krb5/get_for_creds.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +RCSID("$Id$"); + +krb5_error_code +krb5_get_forwarded_creds (krb5_context context, + krb5_auth_context auth_context, + krb5_ccache ccache, + krb5_flags flags, + const char *hostname, + krb5_creds *in_creds, + krb5_data *out_data) +{ + krb5_error_code ret; + krb5_creds *out_creds; + krb5_creds in_cred; + krb5_addresses addrs; + struct hostent *hostent; + unsigned n; + struct in_addr **h; + KRB_CRED cred; + KrbCredInfo *krb_cred_info; + EncKrbCredPart enc_krb_cred_part; + size_t len; + u_char buf[1024]; + krb5_data enc_data; + struct timeval tv; + + out_creds = malloc(sizeof(*out_creds)); + if (out_creds == NULL) + return ENOMEM; + + hostent = gethostbyname (hostname); + if (hostent == NULL) + return h_errno; /* XXX */ + + if (hostent->h_addrtype != AF_INET) + abort (); + + n = 0; + for (h = (struct in_addr **)hostent->h_addr_list; + *h != NULL; + ++h) + ++n; + + addrs.len = n; + addrs.val = calloc (n, sizeof(*addrs.val)); + if (addrs.val == NULL) + return ENOMEM; + + n = 0; + for (h = (struct in_addr **)hostent->h_addr_list; + *h != NULL; + ++h) { + addrs.val[n].addr_type = AF_INET; + addrs.val[n].address.length = sizeof(struct in_addr); + addrs.val[n].address.data = malloc(sizeof(struct in_addr)); + if (addrs.val[n].address.data == NULL) { + krb5_free_addresses (context, &addrs); + return ENOMEM; + } + memcpy (addrs.val[n].address.data, *h, sizeof(struct in_addr)); + } + + ret = krb5_get_kdc_cred (context, + ccache, + flags, + &addrs, + NULL, + in_creds, + &out_creds); + if (ret) + return ret; + + memset (&cred, 0, sizeof(cred)); + cred.pvno = 5; + cred.msg_type = krb_cred; + cred.tickets.len = 1; + ALLOC(cred.tickets.val, 1); + if (cred.tickets.val == NULL) + return ENOMEM; /* XXX */ + if (decode_Ticket(out_creds->ticket.data, + out_creds->ticket.length, + cred.tickets.val, &len)) + abort (); /* XXX */ + + + memset (&enc_krb_cred_part, 0, sizeof(enc_krb_cred_part)); + enc_krb_cred_part.ticket_info.len = 1; + ALLOC(enc_krb_cred_part.ticket_info.val, 1); + + gettimeofday (&tv, NULL); + ALLOC(enc_krb_cred_part.timestamp, 1); + *enc_krb_cred_part.timestamp = tv.tv_sec; + ALLOC(enc_krb_cred_part.usec, 1); + *enc_krb_cred_part.usec = tv.tv_usec; + + enc_krb_cred_part.s_address = NULL; /* XXX */ + enc_krb_cred_part.r_address = NULL; /* XXX */ + + /* fill ticket_info.val[0] */ + + krb_cred_info = enc_krb_cred_part.ticket_info.val; + + copy_EncryptionKey (&out_creds->session, &krb_cred_info->key); + ALLOC(krb_cred_info->prealm, 1); + copy_Realm (&out_creds->client->realm, krb_cred_info->prealm); + ALLOC(krb_cred_info->pname, 1); + copy_PrincipalName(&out_creds->client->name, krb_cred_info->pname); + ALLOC(krb_cred_info->flags, 1); + *krb_cred_info->flags = out_creds->flags.b; + ALLOC(krb_cred_info->authtime, 1); + *krb_cred_info->authtime = out_creds->times.authtime; + ALLOC(krb_cred_info->starttime, 1); + *krb_cred_info->starttime = out_creds->times.starttime; + ALLOC(krb_cred_info->endtime, 1); + *krb_cred_info->endtime = out_creds->times.endtime; + ALLOC(krb_cred_info->renew_till, 1); + *krb_cred_info->renew_till = out_creds->times.renew_till; + ALLOC(krb_cred_info->srealm, 1); + copy_Realm (&out_creds->server->realm, krb_cred_info->srealm); + ALLOC(krb_cred_info->sname, 1); + copy_PrincipalName (&out_creds->server->name, krb_cred_info->sname); + ALLOC(krb_cred_info->caddr, 1); + copy_HostAddresses (&out_creds->addresses, krb_cred_info->caddr); + + /* encode EncKrbCredPart */ + + ret = encode_EncKrbCredPart (buf + sizeof(buf) - 1, sizeof(buf), + &enc_krb_cred_part, &len); + free_EncKrbCredPart (&enc_krb_cred_part); + if (ret) + return ret; /* XXX */ + + ret = krb5_encrypt_EncryptedData (context, + buf + sizeof(buf) - len, + len, + auth_context->enctype, + &auth_context->local_subkey, + &cred.enc_part); + if (ret) + return ret; /* XXX */ + + ret = encode_KRB_CRED (buf + sizeof(buf) - 1, sizeof(buf), + &cred, &len); + free_KRB_CRED (&cred); + if (ret) + return ret; + out_data->length = len; + out_data->data = malloc(len); + memcpy (out_data->data, buf + sizeof(buf) - len, len); + return 0; +} diff --git a/lib/krb5/rd_cred.c b/lib/krb5/rd_cred.c new file mode 100644 index 000000000..f27c20aff --- /dev/null +++ b/lib/krb5/rd_cred.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +RCSID("$Id$"); + +krb5_error_code +krb5_rd_cred (krb5_context context, + krb5_auth_context auth_context, + krb5_ccache ccache, + krb5_data *in_data) +{ + krb5_error_code ret = 0; + size_t len; + KRB_CRED cred; + EncKrbCredPart enc_krb_cred_part; + krb5_data enc_krb_cred_part_data; + int i; + + ret = decode_KRB_CRED (in_data->data, in_data->length, + &cred, &len); + if (ret) + return ret; + + if (cred.pvno != 5) { + ret = KRB5KRB_AP_ERR_BADVERSION; + goto out; + } + + if (cred.msg_type != krb_cred) { + ret = KRB5KRB_AP_ERR_MSG_TYPE; + goto out; + } + + ret = krb5_decrypt (context, + cred.enc_part.cipher.data, + cred.enc_part.cipher.length, + cred.enc_part.etype, + &auth_context->remote_subkey, + &enc_krb_cred_part_data); + if (ret) + goto out; + + + ret = decode_EncKrbCredPart (enc_krb_cred_part_data.data, + enc_krb_cred_part_data.length, + &enc_krb_cred_part, + &len); + if (ret) + goto out; + + /* check sender address */ + + if (enc_krb_cred_part.s_address + && auth_context->remote_address + && !krb5_address_compare (context, + auth_context->remote_address, + enc_krb_cred_part.s_address)) { + ret = KRB5KRB_AP_ERR_BADADDR; + goto out; + } + + /* check receiver address */ + + if (enc_krb_cred_part.r_address + && !krb5_address_compare (context, + auth_context->local_address, + enc_krb_cred_part.r_address)) { + ret = KRB5KRB_AP_ERR_BADADDR; + goto out; + } + + /* check timestamp */ + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) { + struct timeval tv; + + gettimeofday (&tv, NULL); + if (enc_krb_cred_part.timestamp == NULL || + enc_krb_cred_part.usec == NULL || + abs(*enc_krb_cred_part.timestamp - tv.tv_sec) + > context->max_skew) { + ret = KRB5KRB_AP_ERR_SKEW; + goto out; + } + } + + /* XXX - check replay cache */ + + /* Store the creds in the ccache */ + + for (i = 0; i < enc_krb_cred_part.ticket_info.len; ++i) { + KrbCredInfo *kci = &enc_krb_cred_part.ticket_info.val[i]; + krb5_creds creds; + u_char buf[1024]; + size_t len; + + memset (&creds, 0, sizeof(creds)); + + ret = encode_Ticket (buf + sizeof(buf) - 1, sizeof(buf), + &cred.tickets.val[i], + &len); + if (ret) + goto out; + krb5_data_copy (&creds.ticket, buf + sizeof(buf) - len, len); + copy_EncryptionKey (&kci->key, &creds.session); + if (kci->prealm && kci->pname) + principalname2krb5_principal (&creds.client, + *kci->pname, + *kci->prealm); + if (kci->flags) + creds.flags.b = *kci->flags; + if (kci->authtime) + creds.times.authtime = *kci->authtime; + if (kci->starttime) + creds.times.starttime = *kci->starttime; + if (kci->endtime) + creds.times.endtime = *kci->endtime; + if (kci->renew_till) + creds.times.renew_till = *kci->renew_till; + if (kci->srealm && kci->sname) + principalname2krb5_principal (&creds.server, + *kci->sname, + *kci->srealm); + if (kci->caddr) + krb5_copy_addresses (context, + kci->caddr, + &creds.addresses); + krb5_cc_store_cred (context, ccache, &creds); + } + +out: + free_KRB_CRED (&cred); + return ret; +}