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.15 2001/06/29 14:53:44 assar 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 && !krb5_address_compare (context, 141 auth_context->local_address, 142 enc_krb_cred_part.r_address)) { 143 krb5_clear_error_string (context); 144 ret = KRB5KRB_AP_ERR_BADADDR; 145 goto out; 146 } 147 148 /* check timestamp */ 149 if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) { 150 krb5_timestamp sec; 151 152 krb5_timeofday (context, &sec); 153 154 if (enc_krb_cred_part.timestamp == NULL || 155 enc_krb_cred_part.usec == NULL || 156 abs(*enc_krb_cred_part.timestamp - sec) 157 > context->max_skew) { 158 krb5_clear_error_string (context); 159 ret = KRB5KRB_AP_ERR_SKEW; 160 goto out; 161 } 162 } 163 164 if(out_data != NULL) { 165 if(enc_krb_cred_part.timestamp) 166 out_data->timestamp = *enc_krb_cred_part.timestamp; 167 else 168 out_data->timestamp = 0; 169 if(enc_krb_cred_part.usec) 170 out_data->usec = *enc_krb_cred_part.usec; 171 else 172 out_data->usec = 0; 173 if(enc_krb_cred_part.nonce) 174 out_data->seq = *enc_krb_cred_part.nonce; 175 else 176 out_data->seq = 0; 177 } 178 179 /* Convert to NULL terminated list of creds */ 180 181 *ret_creds = calloc(enc_krb_cred_part.ticket_info.len + 1, 182 sizeof(**ret_creds)); 183 184 if (*ret_creds == NULL) { 185 ret = ENOMEM; 186 krb5_set_error_string (context, "malloc: out of memory"); 187 goto out; 188 } 189 190 for (i = 0; i < enc_krb_cred_part.ticket_info.len; ++i) { 191 KrbCredInfo *kci = &enc_krb_cred_part.ticket_info.val[i]; 192 krb5_creds *creds; 193 u_char buf[1024]; 194 size_t len; 195 196 creds = calloc(1, sizeof(*creds)); 197 if(creds == NULL) { 198 ret = ENOMEM; 199 krb5_set_error_string (context, "malloc: out of memory"); 200 goto out; 201 } 202 203 ret = encode_Ticket (buf + sizeof(buf) - 1, sizeof(buf), 204 &cred.tickets.val[i], 205 &len); 206 if (ret) 207 goto out; 208 krb5_data_copy (&creds->ticket, buf + sizeof(buf) - len, len); 209 copy_EncryptionKey (&kci->key, &creds->session); 210 if (kci->prealm && kci->pname) 211 principalname2krb5_principal (&creds->client, 212 *kci->pname, 213 *kci->prealm); 214 if (kci->flags) 215 creds->flags.b = *kci->flags; 216 if (kci->authtime) 217 creds->times.authtime = *kci->authtime; 218 if (kci->starttime) 219 creds->times.starttime = *kci->starttime; 220 if (kci->endtime) 221 creds->times.endtime = *kci->endtime; 222 if (kci->renew_till) 223 creds->times.renew_till = *kci->renew_till; 224 if (kci->srealm && kci->sname) 225 principalname2krb5_principal (&creds->server, 226 *kci->sname, 227 *kci->srealm); 228 if (kci->caddr) 229 krb5_copy_addresses (context, 230 kci->caddr, 231 &creds->addresses); 232 233 (*ret_creds)[i] = creds; 234 235 } 236 (*ret_creds)[i] = NULL; 237 return 0; 238 239 out: 240 free_KRB_CRED (&cred); 241 if(*ret_creds) { 242 for(i = 0; (*ret_creds)[i]; i++) 243 krb5_free_creds(context, (*ret_creds)[i]); 244 free(*ret_creds); 245 } 246 return ret; 247 } 248 249 krb5_error_code 250 krb5_rd_cred2 (krb5_context context, 251 krb5_auth_context auth_context, 252 krb5_ccache ccache, 253 krb5_data *in_data) 254 { 255 krb5_error_code ret; 256 krb5_creds **creds; 257 int i; 258 259 ret = krb5_rd_cred(context, auth_context, in_data, &creds, NULL); 260 if(ret) 261 return ret; 262 263 /* Store the creds in the ccache */ 264 265 for(i = 0; creds && creds[i]; i++) { 266 krb5_cc_store_cred(context, ccache, creds[i]); 267 krb5_free_creds(context, creds[i]); 268 } 269 free(creds); 270 return 0; 271 } 272