1/* 2 * Copyright (c) 1997 - 2003 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 36static krb5_error_code 37make_etypelist(krb5_context context, 38 krb5_authdata **auth_data) 39{ 40 AuthorizationDataElement el; 41 AuthorizationData ad; 42 EtypeList etypes; 43 krb5_error_code ret; 44 u_char *buf; 45 size_t len = 0; 46 size_t buf_size; 47 48 ret = _krb5_init_etype(context, KRB5_PDU_NONE, 49 &etypes.len, &etypes.val, 50 NULL); 51 if (ret) 52 return ret; 53 54 ASN1_MALLOC_ENCODE(EtypeList, buf, buf_size, &etypes, &len, ret); 55 if (ret) { 56 free_EtypeList(&etypes); 57 return ret; 58 } 59 if(buf_size != len) 60 krb5_abortx(context, "internal error in ASN.1 encoder"); 61 free_EtypeList(&etypes); 62 63 ALLOC_SEQ(&ad, 1); 64 if (ad.val == NULL) { 65 free(buf); 66 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 67 return ENOMEM; 68 } 69 70 el.ad_type = KRB5_AUTHDATA_GSS_API_ETYPE_NEGOTIATION; 71 el.ad_data.length = len; 72 el.ad_data.data = buf; 73 74 ret = add_AuthorizationData(&ad, &el); 75 free(buf); 76 if (ret) 77 return ret; 78 79 ASN1_MALLOC_ENCODE(AD_IF_RELEVANT, buf, buf_size, &ad, &len, ret); 80 free_AuthorizationData(&ad); 81 if (ret) 82 return ret; 83 if(buf_size != len) 84 krb5_abortx(context, "internal error in ASN.1 encoder"); 85 86 if (*auth_data == NULL) { 87 ALLOC(*auth_data, 1); 88 if (*auth_data == NULL) { 89 free(buf); 90 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 91 return ENOMEM; 92 } 93 } 94 95 el.ad_type = KRB5_AUTHDATA_IF_RELEVANT; 96 el.ad_data.length = len; 97 el.ad_data.data = buf; 98 99 ret = add_AuthorizationData(*auth_data, &el); 100 free(buf); 101 return ret; 102} 103 104KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 105_krb5_build_authenticator (krb5_context context, 106 krb5_auth_context auth_context, 107 krb5_enctype enctype, 108 krb5_creds *cred, 109 Checksum *cksum, 110 krb5_data *result, 111 krb5_key_usage usage) 112{ 113 Authenticator auth; 114 u_char *buf = NULL; 115 size_t buf_size; 116 size_t len = 0; 117 krb5_error_code ret; 118 krb5_crypto crypto; 119 120 memset(&auth, 0, sizeof(auth)); 121 122 auth.authenticator_vno = 5; 123 copy_Realm(&cred->client->realm, &auth.crealm); 124 copy_PrincipalName(&cred->client->name, &auth.cname); 125 126 krb5_us_timeofday (context, &auth.ctime, &auth.cusec); 127 128 ret = krb5_auth_con_getlocalsubkey(context, auth_context, &auth.subkey); 129 if(ret) 130 goto fail; 131 132 if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { 133 if(auth_context->local_seqnumber == 0) 134 krb5_generate_seq_number (context, 135 &cred->session, 136 &auth_context->local_seqnumber); 137 ALLOC(auth.seq_number, 1); 138 if(auth.seq_number == NULL) { 139 ret = ENOMEM; 140 goto fail; 141 } 142 *auth.seq_number = auth_context->local_seqnumber; 143 } else 144 auth.seq_number = NULL; 145 146 if (auth_context->auth_data) { 147 auth.authorization_data = calloc(1, sizeof(*auth.authorization_data)); 148 if (auth.authorization_data == NULL) { 149 ret = ENOMEM; 150 goto fail; 151 } 152 ret = copy_AuthorizationData(auth.authorization_data, auth_context->auth_data); 153 if (ret) 154 goto fail; 155 156 } else { 157 auth.authorization_data = NULL; 158 } 159 160 if (cksum) { 161 ALLOC(auth.cksum, 1); 162 if (auth.cksum == NULL) { 163 ret = ENOMEM; 164 goto fail; 165 } 166 ret = copy_Checksum(cksum, auth.cksum); 167 if (ret) 168 goto fail; 169 170 if (auth.cksum->cksumtype == CKSUMTYPE_GSSAPI) { 171 /* 172 * This is not GSS-API specific, we only enable it for 173 * GSS for now 174 */ 175 ret = make_etypelist(context, &auth.authorization_data); 176 if (ret) 177 goto fail; 178 } 179 } 180 181 /* XXX - Copy more to auth_context? */ 182 183 auth_context->authenticator->ctime = auth.ctime; 184 auth_context->authenticator->cusec = auth.cusec; 185 186 ASN1_MALLOC_ENCODE(Authenticator, buf, buf_size, &auth, &len, ret); 187 if (ret) 188 goto fail; 189 if(buf_size != len) 190 krb5_abortx(context, "internal error in ASN.1 encoder"); 191 192 ret = krb5_crypto_init(context, &cred->session, enctype, &crypto); 193 if (ret) 194 goto fail; 195 ret = krb5_encrypt (context, 196 crypto, 197 usage /* KRB5_KU_AP_REQ_AUTH */, 198 buf, 199 len, 200 result); 201 krb5_crypto_destroy(context, crypto); 202 203 if (ret) 204 goto fail; 205 206 fail: 207 free_Authenticator (&auth); 208 free (buf); 209 210 return ret; 211} 212