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.17 2002/08/09 17:07:12 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 u_char buf[1024]; 218 size_t len; 219 220 creds = calloc(1, sizeof(*creds)); 221 if(creds == NULL) { 222 ret = ENOMEM; 223 krb5_set_error_string (context, "malloc: out of memory"); 224 goto out; 225 } 226 227 ret = encode_Ticket (buf + sizeof(buf) - 1, sizeof(buf), 228 &cred.tickets.val[i], 229 &len); 230 if (ret) 231 goto out; 232 krb5_data_copy (&creds->ticket, buf + sizeof(buf) - len, len); 233 copy_EncryptionKey (&kci->key, &creds->session); 234 if (kci->prealm && kci->pname) 235 principalname2krb5_principal (&creds->client, 236 *kci->pname, 237 *kci->prealm); 238 if (kci->flags) 239 creds->flags.b = *kci->flags; 240 if (kci->authtime) 241 creds->times.authtime = *kci->authtime; 242 if (kci->starttime) 243 creds->times.starttime = *kci->starttime; 244 if (kci->endtime) 245 creds->times.endtime = *kci->endtime; 246 if (kci->renew_till) 247 creds->times.renew_till = *kci->renew_till; 248 if (kci->srealm && kci->sname) 249 principalname2krb5_principal (&creds->server, 250 *kci->sname, 251 *kci->srealm); 252 if (kci->caddr) 253 krb5_copy_addresses (context, 254 kci->caddr, 255 &creds->addresses); 256 257 (*ret_creds)[i] = creds; 258 259 } 260 (*ret_creds)[i] = NULL; 261 return 0; 262 263 out: 264 free_KRB_CRED (&cred); 265 if(*ret_creds) { 266 for(i = 0; (*ret_creds)[i]; i++) 267 krb5_free_creds(context, (*ret_creds)[i]); 268 free(*ret_creds); 269 } 270 return ret; 271 } 272 273 krb5_error_code 274 krb5_rd_cred2 (krb5_context context, 275 krb5_auth_context auth_context, 276 krb5_ccache ccache, 277 krb5_data *in_data) 278 { 279 krb5_error_code ret; 280 krb5_creds **creds; 281 int i; 282 283 ret = krb5_rd_cred(context, auth_context, in_data, &creds, NULL); 284 if(ret) 285 return ret; 286 287 /* Store the creds in the ccache */ 288 289 for(i = 0; creds && creds[i]; i++) { 290 krb5_cc_store_cred(context, ccache, creds[i]); 291 krb5_free_creds(context, creds[i]); 292 } 293 free(creds); 294 return 0; 295 } 296