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 36 static krb5_error_code 37 make_etypelist(krb5_context context, 38 krb5_authdata **auth_data) 39 { 40 EtypeList etypes; 41 krb5_error_code ret; 42 krb5_authdata ad; 43 u_char *buf; 44 size_t len = 0; 45 size_t buf_size; 46 47 ret = _krb5_init_etype(context, KRB5_PDU_NONE, 48 &etypes.len, &etypes.val, 49 NULL); 50 if (ret) 51 return ret; 52 53 ASN1_MALLOC_ENCODE(EtypeList, buf, buf_size, &etypes, &len, ret); 54 if (ret) { 55 free_EtypeList(&etypes); 56 return ret; 57 } 58 if(buf_size != len) 59 krb5_abortx(context, "internal error in ASN.1 encoder"); 60 free_EtypeList(&etypes); 61 62 ALLOC_SEQ(&ad, 1); 63 if (ad.val == NULL) { 64 free(buf); 65 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 66 return ENOMEM; 67 } 68 69 ad.val[0].ad_type = KRB5_AUTHDATA_GSS_API_ETYPE_NEGOTIATION; 70 ad.val[0].ad_data.length = len; 71 ad.val[0].ad_data.data = buf; 72 73 ASN1_MALLOC_ENCODE(AD_IF_RELEVANT, buf, buf_size, &ad, &len, ret); 74 if (ret) { 75 free_AuthorizationData(&ad); 76 return ret; 77 } 78 if(buf_size != len) 79 krb5_abortx(context, "internal error in ASN.1 encoder"); 80 free_AuthorizationData(&ad); 81 82 ALLOC(*auth_data, 1); 83 if (*auth_data == NULL) { 84 free(buf); 85 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 86 return ENOMEM; 87 } 88 89 ALLOC_SEQ(*auth_data, 1); 90 if ((*auth_data)->val == NULL) { 91 free(*auth_data); 92 free(buf); 93 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 94 return ENOMEM; 95 } 96 97 (*auth_data)->val[0].ad_type = KRB5_AUTHDATA_IF_RELEVANT; 98 (*auth_data)->val[0].ad_data.length = len; 99 (*auth_data)->val[0].ad_data.data = buf; 100 101 return 0; 102 } 103 104 KRB5_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 auth.authorization_data = NULL; 146 147 if (cksum) { 148 ALLOC(auth.cksum, 1); 149 if (auth.cksum == NULL) { 150 ret = ENOMEM; 151 goto fail; 152 } 153 ret = copy_Checksum(cksum, auth.cksum); 154 if (ret) 155 goto fail; 156 157 if (auth.cksum->cksumtype == CKSUMTYPE_GSSAPI) { 158 /* 159 * This is not GSS-API specific, we only enable it for 160 * GSS for now 161 */ 162 ret = make_etypelist(context, &auth.authorization_data); 163 if (ret) 164 goto fail; 165 } 166 } 167 168 /* XXX - Copy more to auth_context? */ 169 170 auth_context->authenticator->ctime = auth.ctime; 171 auth_context->authenticator->cusec = auth.cusec; 172 173 ASN1_MALLOC_ENCODE(Authenticator, buf, buf_size, &auth, &len, ret); 174 if (ret) 175 goto fail; 176 if(buf_size != len) 177 krb5_abortx(context, "internal error in ASN.1 encoder"); 178 179 ret = krb5_crypto_init(context, &cred->session, enctype, &crypto); 180 if (ret) 181 goto fail; 182 ret = krb5_encrypt (context, 183 crypto, 184 usage /* KRB5_KU_AP_REQ_AUTH */, 185 buf, 186 len, 187 result); 188 krb5_crypto_destroy(context, crypto); 189 190 if (ret) 191 goto fail; 192 193 fail: 194 free_Authenticator (&auth); 195 free (buf); 196 197 return ret; 198 } 199