lib/krb5: krb5_init_creds_set_service fail if set_realm fails
[heimdal.git] / lib / krb5 / build_auth.c
blob3e0012562a3c60fb8659dfa0695b3a53a4d2e316
1 /*
2 * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
34 #include "krb5_locl.h"
36 static krb5_error_code
37 add_auth_data(krb5_context context,
38 AuthorizationData *src,
39 AuthorizationData **dst)
41 krb5_error_code ret = 0;
42 size_t i;
44 if (*dst == NULL &&
45 (*dst = calloc(1, sizeof(**dst))) == NULL)
46 return krb5_enomem(context);
47 for (i = 0; ret == 0 && i < src->len; i++)
48 ret = add_AuthorizationData(*dst, &src->val[i]);
49 return ret;
52 static krb5_error_code
53 add_etypelist(krb5_context context,
54 krb5_authdata *auth_data)
56 AuthorizationDataElement ade;
57 EtypeList etypes;
58 krb5_error_code ret;
59 krb5_data e;
60 size_t len = 0;
62 ret = _krb5_init_etype(context, KRB5_PDU_NONE,
63 &etypes.len, &etypes.val,
64 NULL);
65 if (ret)
66 return ret;
68 ASN1_MALLOC_ENCODE(EtypeList, e.data, e.length, &etypes, &len, ret);
69 if (ret) {
70 free_EtypeList(&etypes);
71 return ret;
73 if(e.length != len)
74 krb5_abortx(context, "internal error in ASN.1 encoder");
75 free_EtypeList(&etypes);
77 ade.ad_type = KRB5_AUTHDATA_GSS_API_ETYPE_NEGOTIATION;
78 ade.ad_data = e;
80 ret = add_AuthorizationData(auth_data, &ade);
82 krb5_data_free(&e);
84 return ret;
87 static krb5_error_code
88 add_ap_options(krb5_context context,
89 krb5_authdata *auth_data)
91 krb5_error_code ret;
92 AuthorizationDataElement ade;
93 krb5_boolean require_cb;
94 uint8_t ap_options[4];
96 require_cb = krb5_config_get_bool_default(context, NULL, FALSE,
97 "libdefaults",
98 "client_aware_channel_bindings",
99 NULL);
101 if (!require_cb)
102 return 0;
104 ap_options[0] = (KERB_AP_OPTIONS_CBT >> 0 ) & 0xFF;
105 ap_options[1] = (KERB_AP_OPTIONS_CBT >> 8 ) & 0xFF;
106 ap_options[2] = (KERB_AP_OPTIONS_CBT >> 16) & 0xFF;
107 ap_options[3] = (KERB_AP_OPTIONS_CBT >> 24) & 0xFF;
109 ade.ad_type = KRB5_AUTHDATA_AP_OPTIONS;
110 ade.ad_data.length = sizeof(ap_options);
111 ade.ad_data.data = ap_options;
113 ret = add_AuthorizationData(auth_data, &ade);
115 return ret;
118 static krb5_error_code
119 make_ap_authdata(krb5_context context,
120 krb5_authdata **auth_data)
122 krb5_error_code ret;
123 AuthorizationData ad;
124 krb5_data ir;
125 size_t len;
127 ad.len = 0;
128 ad.val = NULL;
130 ret = add_etypelist(context, &ad);
131 if (ret)
132 return ret;
135 * Windows has a bug and only looks for first occurrence of AD-IF-RELEVANT
136 * in the AP authenticator when looking for AD-AP-OPTIONS. Make sure to
137 * bundle it together with etypes.
139 ret = add_ap_options(context, &ad);
140 if (ret) {
141 free_AuthorizationData(&ad);
142 return ret;
145 ASN1_MALLOC_ENCODE(AuthorizationData, ir.data, ir.length, &ad, &len, ret);
146 if (ret) {
147 free_AuthorizationData(&ad);
148 return ret;
150 if(ir.length != len)
151 krb5_abortx(context, "internal error in ASN.1 encoder");
153 ret = _krb5_add_1auth_data(context, KRB5_AUTHDATA_IF_RELEVANT, &ir, 1,
154 auth_data);
156 free_AuthorizationData(&ad);
157 krb5_data_free(&ir);
159 return ret;
162 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
163 _krb5_build_authenticator (krb5_context context,
164 krb5_auth_context auth_context,
165 krb5_enctype enctype,
166 krb5_creds *cred,
167 Checksum *cksum,
168 krb5_data *result,
169 krb5_key_usage usage)
171 Authenticator auth;
172 u_char *buf = NULL;
173 size_t buf_size;
174 size_t len = 0;
175 krb5_error_code ret;
176 krb5_crypto crypto;
178 memset(&auth, 0, sizeof(auth));
180 auth.authenticator_vno = 5;
181 ret = copy_Realm(&cred->client->realm, &auth.crealm);
182 if (ret)
183 goto fail;
184 ret = copy_PrincipalName(&cred->client->name, &auth.cname);
185 if (ret)
186 goto fail;
188 krb5_us_timeofday (context, &auth.ctime, &auth.cusec);
190 ret = krb5_auth_con_getlocalsubkey(context, auth_context, &auth.subkey);
191 if(ret)
192 goto fail;
194 if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
195 if(auth_context->local_seqnumber == 0)
196 krb5_generate_seq_number (context,
197 &cred->session,
198 &auth_context->local_seqnumber);
199 ALLOC(auth.seq_number, 1);
200 if(auth.seq_number == NULL) {
201 ret = krb5_enomem(context);
202 goto fail;
204 *auth.seq_number = auth_context->local_seqnumber;
205 } else
206 auth.seq_number = NULL;
207 auth.authorization_data = NULL;
209 if (cksum) {
210 ALLOC(auth.cksum, 1);
211 if (auth.cksum == NULL) {
212 ret = krb5_enomem(context);
213 goto fail;
215 ret = copy_Checksum(cksum, auth.cksum);
216 if (ret)
217 goto fail;
219 if (auth.cksum->cksumtype == CKSUMTYPE_GSSAPI) {
221 * This is not GSS-API specific, we only enable it for
222 * GSS for now
224 ret = make_ap_authdata(context, &auth.authorization_data);
225 if (ret)
226 goto fail;
230 /* Copy other authz data from auth_context */
231 if (auth_context->auth_data) {
232 ret = add_auth_data(context, auth_context->auth_data, &auth.authorization_data);
233 if (ret)
234 goto fail;
237 /* XXX - Copy more to auth_context? */
239 auth_context->authenticator->ctime = auth.ctime;
240 auth_context->authenticator->cusec = auth.cusec;
242 ASN1_MALLOC_ENCODE(Authenticator, buf, buf_size, &auth, &len, ret);
243 if (ret)
244 goto fail;
245 if(buf_size != len)
246 krb5_abortx(context, "internal error in ASN.1 encoder");
248 ret = krb5_crypto_init(context, &cred->session, enctype, &crypto);
249 if (ret)
250 goto fail;
251 ret = krb5_encrypt (context,
252 crypto,
253 usage /* KRB5_KU_AP_REQ_AUTH */,
254 buf,
255 len,
256 result);
257 krb5_crypto_destroy(context, crypto);
259 if (ret)
260 goto fail;
262 fail:
263 free_Authenticator (&auth);
264 free (buf);
266 return ret;