1 /* 2 * Copyright (c) 1997 - 2001 Kungliga Tekniska H�gskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #include <krb5_locl.h> 35 36 RCSID("$Id: rd_cred.c,v 1.12 2001/01/04 16:19:00 joda Exp $"); 37 38 krb5_error_code 39 krb5_rd_cred(krb5_context context, 40 krb5_auth_context auth_context, 41 krb5_data *in_data, 42 krb5_creds ***ret_creds, 43 krb5_replay_data *out_data) 44 { 45 krb5_error_code ret; 46 size_t len; 47 KRB_CRED cred; 48 EncKrbCredPart enc_krb_cred_part; 49 krb5_data enc_krb_cred_part_data; 50 krb5_crypto crypto; 51 int i; 52 53 ret = decode_KRB_CRED(in_data->data, in_data->length, 54 &cred, &len); 55 if(ret) 56 return ret; 57 58 if (cred.pvno != 5) { 59 ret = KRB5KRB_AP_ERR_BADVERSION; 60 goto out; 61 } 62 63 if (cred.msg_type != krb_cred) { 64 ret = KRB5KRB_AP_ERR_MSG_TYPE; 65 goto out; 66 } 67 68 if (cred.enc_part.etype == ETYPE_NULL) { 69 /* DK: MIT GSS-API Compatibility */ 70 enc_krb_cred_part_data.length = cred.enc_part.cipher.length; 71 enc_krb_cred_part_data.data = cred.enc_part.cipher.data; 72 } else { 73 if (auth_context->remote_subkey) 74 ret = krb5_crypto_init(context, auth_context->remote_subkey, 75 0, &crypto); 76 else 77 ret = krb5_crypto_init(context, auth_context->keyblock, 78 0, &crypto); 79 /* DK: MIT rsh */ 80 81 if (ret) 82 goto out; 83 84 ret = krb5_decrypt_EncryptedData(context, 85 crypto, 86 KRB5_KU_KRB_CRED, 87 &cred.enc_part, 88 &enc_krb_cred_part_data); 89 90 krb5_crypto_destroy(context, crypto); 91 if (ret) 92 goto out; 93 } 94 95 ret = krb5_decode_EncKrbCredPart (context, 96 enc_krb_cred_part_data.data, 97 enc_krb_cred_part_data.length, 98 &enc_krb_cred_part, 99 &len); 100 if (ret) 101 goto out; 102 103 /* check sender address */ 104 105 if (enc_krb_cred_part.s_address 106 && auth_context->remote_address 107 && auth_context->remote_port) { 108 krb5_address *a; 109 int cmp; 110 111 ret = krb5_make_addrport (&a, 112 auth_context->remote_address, 113 auth_context->remote_port); 114 if (ret) 115 goto out; 116 117 118 cmp = krb5_address_compare (context, 119 a, 120 enc_krb_cred_part.s_address); 121 122 krb5_free_address (context, a); 123 free (a); 124 125 if (cmp == 0) { 126 ret = KRB5KRB_AP_ERR_BADADDR; 127 goto out; 128 } 129 } 130 131 /* check receiver address */ 132 133 if (enc_krb_cred_part.r_address 134 && auth_context->local_address 135 && !krb5_address_compare (context, 136 auth_context->local_address, 137 enc_krb_cred_part.r_address)) { 138 ret = KRB5KRB_AP_ERR_BADADDR; 139 goto out; 140 } 141 142 /* check timestamp */ 143 if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) { 144 krb5_timestamp sec; 145 146 krb5_timeofday (context, &sec); 147 148 if (enc_krb_cred_part.timestamp == NULL || 149 enc_krb_cred_part.usec == NULL || 150 abs(*enc_krb_cred_part.timestamp - sec) 151 > context->max_skew) { 152 ret = KRB5KRB_AP_ERR_SKEW; 153 goto out; 154 } 155 } 156 157 if(out_data != NULL) { 158 if(enc_krb_cred_part.timestamp) 159 out_data->timestamp = *enc_krb_cred_part.timestamp; 160 else 161 out_data->timestamp = 0; 162 if(enc_krb_cred_part.usec) 163 out_data->usec = *enc_krb_cred_part.usec; 164 else 165 out_data->usec = 0; 166 if(enc_krb_cred_part.nonce) 167 out_data->seq = *enc_krb_cred_part.nonce; 168 else 169 out_data->seq = 0; 170 } 171 172 /* Convert to NULL terminated list of creds */ 173 174 *ret_creds = calloc(enc_krb_cred_part.ticket_info.len + 1, 175 sizeof(**ret_creds)); 176 177 for (i = 0; i < enc_krb_cred_part.ticket_info.len; ++i) { 178 KrbCredInfo *kci = &enc_krb_cred_part.ticket_info.val[i]; 179 krb5_creds *creds; 180 u_char buf[1024]; 181 size_t len; 182 183 creds = calloc(1, sizeof(*creds)); 184 if(creds == NULL) { 185 ret = ENOMEM; 186 goto out; 187 } 188 189 ret = encode_Ticket (buf + sizeof(buf) - 1, sizeof(buf), 190 &cred.tickets.val[i], 191 &len); 192 if (ret) 193 goto out; 194 krb5_data_copy (&creds->ticket, buf + sizeof(buf) - len, len); 195 copy_EncryptionKey (&kci->key, &creds->session); 196 if (kci->prealm && kci->pname) 197 principalname2krb5_principal (&creds->client, 198 *kci->pname, 199 *kci->prealm); 200 if (kci->flags) 201 creds->flags.b = *kci->flags; 202 if (kci->authtime) 203 creds->times.authtime = *kci->authtime; 204 if (kci->starttime) 205 creds->times.starttime = *kci->starttime; 206 if (kci->endtime) 207 creds->times.endtime = *kci->endtime; 208 if (kci->renew_till) 209 creds->times.renew_till = *kci->renew_till; 210 if (kci->srealm && kci->sname) 211 principalname2krb5_principal (&creds->server, 212 *kci->sname, 213 *kci->srealm); 214 if (kci->caddr) 215 krb5_copy_addresses (context, 216 kci->caddr, 217 &creds->addresses); 218 219 (*ret_creds)[i] = creds; 220 221 } 222 (*ret_creds)[i] = NULL; 223 return 0; 224 225 out: 226 free_KRB_CRED (&cred); 227 if(*ret_creds) { 228 for(i = 0; (*ret_creds)[i]; i++) 229 krb5_free_creds(context, (*ret_creds)[i]); 230 free(*ret_creds); 231 } 232 return ret; 233 } 234 235 krb5_error_code 236 krb5_rd_cred2 (krb5_context context, 237 krb5_auth_context auth_context, 238 krb5_ccache ccache, 239 krb5_data *in_data) 240 { 241 krb5_error_code ret; 242 krb5_creds **creds; 243 int i; 244 245 ret = krb5_rd_cred(context, auth_context, in_data, &creds, NULL); 246 if(ret) 247 return ret; 248 249 /* Store the creds in the ccache */ 250 251 for(i = 0; creds && creds[i]; i++) { 252 krb5_cc_store_cred(context, ccache, creds[i]); 253 krb5_free_creds(context, creds[i]); 254 } 255 free(creds); 256 return 0; 257 } 258