1 /* 2 * Copyright (c) 1997 - 2002 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.18 2002/09/04 16:26:05 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_creds = NULL; 54 55 ret = decode_KRB_CRED(in_data->data, in_data->length, 56 &cred, &len); 57 if(ret) 58 return ret; 59 60 if (cred.pvno != 5) { 61 ret = KRB5KRB_AP_ERR_BADVERSION; 62 krb5_clear_error_string (context); 63 goto out; 64 } 65 66 if (cred.msg_type != krb_cred) { 67 ret = KRB5KRB_AP_ERR_MSG_TYPE; 68 krb5_clear_error_string (context); 69 goto out; 70 } 71 72 if (cred.enc_part.etype == ETYPE_NULL) { 73 /* DK: MIT GSS-API Compatibility */ 74 enc_krb_cred_part_data.length = cred.enc_part.cipher.length; 75 enc_krb_cred_part_data.data = cred.enc_part.cipher.data; 76 } else { 77 if (auth_context->remote_subkey) 78 ret = krb5_crypto_init(context, auth_context->remote_subkey, 79 0, &crypto); 80 else 81 ret = krb5_crypto_init(context, auth_context->keyblock, 82 0, &crypto); 83 /* DK: MIT rsh */ 84 85 if (ret) 86 goto out; 87 88 ret = krb5_decrypt_EncryptedData(context, 89 crypto, 90 KRB5_KU_KRB_CRED, 91 &cred.enc_part, 92 &enc_krb_cred_part_data); 93 94 krb5_crypto_destroy(context, crypto); 95 if (ret) 96 goto out; 97 } 98 99 ret = krb5_decode_EncKrbCredPart (context, 100 enc_krb_cred_part_data.data, 101 enc_krb_cred_part_data.length, 102 &enc_krb_cred_part, 103 &len); 104 if (ret) 105 goto out; 106 107 /* check sender address */ 108 109 if (enc_krb_cred_part.s_address 110 && auth_context->remote_address 111 && auth_context->remote_port) { 112 krb5_address *a; 113 int cmp; 114 115 ret = krb5_make_addrport (context, &a, 116 auth_context->remote_address, 117 auth_context->remote_port); 118 if (ret) 119 goto out; 120 121 122 cmp = krb5_address_compare (context, 123 a, 124 enc_krb_cred_part.s_address); 125 126 krb5_free_address (context, a); 127 free (a); 128 129 if (cmp == 0) { 130 krb5_clear_error_string (context); 131 ret = KRB5KRB_AP_ERR_BADADDR; 132 goto out; 133 } 134 } 135 136 /* check receiver address */ 137 138 if (enc_krb_cred_part.r_address 139 && auth_context->local_address) { 140 if(auth_context->local_port && 141 enc_krb_cred_part.r_address->addr_type == KRB5_ADDRESS_ADDRPORT) { 142 krb5_address *a; 143 int cmp; 144 ret = krb5_make_addrport (context, &a, 145 auth_context->local_address, 146 auth_context->local_port); 147 if (ret) 148 goto out; 149 150 cmp = krb5_address_compare (context, 151 a, 152 enc_krb_cred_part.r_address); 153 krb5_free_address (context, a); 154 free (a); 155 156 if (cmp == 0) { 157 krb5_clear_error_string (context); 158 ret = KRB5KRB_AP_ERR_BADADDR; 159 goto out; 160 } 161 } else { 162 if(!krb5_address_compare (context, 163 auth_context->local_address, 164 enc_krb_cred_part.r_address)) { 165 krb5_clear_error_string (context); 166 ret = KRB5KRB_AP_ERR_BADADDR; 167 goto out; 168 } 169 } 170 } 171 172 /* check timestamp */ 173 if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) { 174 krb5_timestamp sec; 175 176 krb5_timeofday (context, &sec); 177 178 if (enc_krb_cred_part.timestamp == NULL || 179 enc_krb_cred_part.usec == NULL || 180 abs(*enc_krb_cred_part.timestamp - sec) 181 > context->max_skew) { 182 krb5_clear_error_string (context); 183 ret = KRB5KRB_AP_ERR_SKEW; 184 goto out; 185 } 186 } 187 188 if(out_data != NULL) { 189 if(enc_krb_cred_part.timestamp) 190 out_data->timestamp = *enc_krb_cred_part.timestamp; 191 else 192 out_data->timestamp = 0; 193 if(enc_krb_cred_part.usec) 194 out_data->usec = *enc_krb_cred_part.usec; 195 else 196 out_data->usec = 0; 197 if(enc_krb_cred_part.nonce) 198 out_data->seq = *enc_krb_cred_part.nonce; 199 else 200 out_data->seq = 0; 201 } 202 203 /* Convert to NULL terminated list of creds */ 204 205 *ret_creds = calloc(enc_krb_cred_part.ticket_info.len + 1, 206 sizeof(**ret_creds)); 207 208 if (*ret_creds == NULL) { 209 ret = ENOMEM; 210 krb5_set_error_string (context, "malloc: out of memory"); 211 goto out; 212 } 213 214 for (i = 0; i < enc_krb_cred_part.ticket_info.len; ++i) { 215 KrbCredInfo *kci = &enc_krb_cred_part.ticket_info.val[i]; 216 krb5_creds *creds; 217 size_t len; 218 219 creds = calloc(1, sizeof(*creds)); 220 if(creds == NULL) { 221 ret = ENOMEM; 222 krb5_set_error_string (context, "malloc: out of memory"); 223 goto out; 224 } 225 226 ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length, 227 &cred.tickets.val[i], &len, ret); 228 if (ret) 229 goto out; 230 if(creds->ticket.length != len) 231 krb5_abortx(context, "internal error in ASN.1 encoder"); 232 copy_EncryptionKey (&kci->key, &creds->session); 233 if (kci->prealm && kci->pname) 234 principalname2krb5_principal (&creds->client, 235 *kci->pname, 236 *kci->prealm); 237 if (kci->flags) 238 creds->flags.b = *kci->flags; 239 if (kci->authtime) 240 creds->times.authtime = *kci->authtime; 241 if (kci->starttime) 242 creds->times.starttime = *kci->starttime; 243 if (kci->endtime) 244 creds->times.endtime = *kci->endtime; 245 if (kci->renew_till) 246 creds->times.renew_till = *kci->renew_till; 247 if (kci->srealm && kci->sname) 248 principalname2krb5_principal (&creds->server, 249 *kci->sname, 250 *kci->srealm); 251 if (kci->caddr) 252 krb5_copy_addresses (context, 253 kci->caddr, 254 &creds->addresses); 255 256 (*ret_creds)[i] = creds; 257 258 } 259 (*ret_creds)[i] = NULL; 260 return 0; 261 262 out: 263 free_KRB_CRED (&cred); 264 if(*ret_creds) { 265 for(i = 0; (*ret_creds)[i]; i++) 266 krb5_free_creds(context, (*ret_creds)[i]); 267 free(*ret_creds); 268 } 269 return ret; 270 } 271 272 krb5_error_code 273 krb5_rd_cred2 (krb5_context context, 274 krb5_auth_context auth_context, 275 krb5_ccache ccache, 276 krb5_data *in_data) 277 { 278 krb5_error_code ret; 279 krb5_creds **creds; 280 int i; 281 282 ret = krb5_rd_cred(context, auth_context, in_data, &creds, NULL); 283 if(ret) 284 return ret; 285 286 /* Store the creds in the ccache */ 287 288 for(i = 0; creds && creds[i]; i++) { 289 krb5_cc_store_cred(context, ccache, creds[i]); 290 krb5_free_creds(context, creds[i]); 291 } 292 free(creds); 293 return 0; 294 } 295