1/*
2 * Copyright (c) 2008-2010 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Portions Copyright (c) 2008-2010 Apple Inc. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * 3. Neither the name of the Institute nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#include "heim.h"
37#include "mit-krb5.h"
38#include <string.h>
39#include <errno.h>
40
41static krb5_flags
42mshim_mit_ap_req_flags(mit_krb5_flags ap_req_options)
43{
44    krb5_flags flags = 0;
45
46    if (ap_req_options & MIT_AP_OPTS_USE_SUBKEY)
47	flags |= AP_OPTS_USE_SUBKEY;
48    if (ap_req_options & MIT_AP_OPTS_USE_SESSION_KEY)
49	flags |= AP_OPTS_USE_SESSION_KEY;
50    if (ap_req_options & MIT_AP_OPTS_MUTUAL_REQUIRED)
51	flags |= AP_OPTS_MUTUAL_REQUIRED;
52
53    return flags;
54}
55
56
57
58mit_krb5_error_code KRB5_CALLCONV
59krb5_mk_req(mit_krb5_context context,
60	    mit_krb5_auth_context *ac,
61	    mit_krb5_flags ap_req_options,
62	    char *service,
63	    char *hostname,
64	    mit_krb5_data *inbuf,
65	    mit_krb5_ccache ccache,
66	    mit_krb5_data *outbuf)
67{
68    krb5_data idata, *d = NULL;
69    krb5_data odata;
70    krb5_flags flags = mshim_mit_ap_req_flags(ap_req_options);
71    krb5_error_code ret;
72
73    LOG_ENTRY();
74
75    memset(outbuf, 0, sizeof(*outbuf));
76
77    if (inbuf) {
78	d = &idata;
79	idata.data = inbuf->data;
80	idata.length = inbuf->length;
81    }
82
83    ret = heim_krb5_mk_req(HC(context), (krb5_auth_context *)ac,
84			   flags, service, hostname, d,
85			   (krb5_ccache)ccache, &odata);
86    if (ret == 0)
87	mshim_hdata2mdata(&odata, outbuf);
88
89    return ret;
90}
91
92
93mit_krb5_error_code KRB5_CALLCONV
94krb5_mk_req_extended(mit_krb5_context context,
95		     mit_krb5_auth_context *ac,
96		     mit_krb5_flags ap_req_options,
97		     mit_krb5_data *inbuf,
98		     mit_krb5_creds *cred,
99		     mit_krb5_data *outbuf)
100 {
101    krb5_data idata, *d = NULL;
102    krb5_data odata;
103    krb5_flags flags = mshim_mit_ap_req_flags(ap_req_options);
104    krb5_error_code ret;
105    krb5_creds hcreds;
106
107    LOG_ENTRY();
108
109    memset(outbuf, 0, sizeof(*outbuf));
110
111    mshim_mcred2hcred(HC(context), cred, &hcreds);
112
113    if (inbuf) {
114	d = &idata;
115	idata.data = inbuf->data;
116	idata.length = inbuf->length;
117    }
118
119    ret = heim_krb5_mk_req_extended(HC(context), (krb5_auth_context *)ac,
120				    flags, d, &hcreds, &odata);
121    heim_krb5_free_cred_contents(HC(context), &hcreds);
122    if (ret == 0)
123	mshim_hdata2mdata(&odata, outbuf);
124
125    return ret;
126}
127
128mit_krb5_error_code KRB5_CALLCONV
129krb5_sendauth(mit_krb5_context context,
130	      mit_krb5_auth_context *auth_context,
131	      mit_krb5_pointer fd,
132	      char *appl_version,
133	      mit_krb5_principal client,
134	      mit_krb5_principal server,
135	      mit_krb5_flags ap_req_options,
136	      mit_krb5_data *in_data,
137	      mit_krb5_creds *in_creds,
138	      mit_krb5_ccache ccache,
139	      mit_krb5_error **error,
140	      mit_krb5_ap_rep_enc_part **rep_result,
141	      mit_krb5_creds **out_creds)
142{
143    mit_krb5_error_code ret;
144    struct comb_principal *c = (struct comb_principal *)client;
145    struct comb_principal *s = (struct comb_principal *)server;
146    krb5_flags flags = mshim_mit_ap_req_flags(ap_req_options);
147    krb5_ap_rep_enc_part *hrep_result = NULL;
148    krb5_error *herror = NULL;
149    krb5_data hin_data;
150    krb5_creds hin_creds, *hout_creds = NULL;
151
152    memset(&hin_creds, 0, sizeof(hin_creds));
153    heim_krb5_data_zero(&hin_data);
154
155    if (in_data)
156	mshim_mdata2hdata(in_data, &hin_data);
157    if (in_creds)
158	mshim_mcred2hcred(HC(context), in_creds, &hin_creds);
159
160    ret = heim_krb5_sendauth(HC(context),
161			     (krb5_auth_context *)auth_context,
162			     fd,
163			     appl_version,
164			     c->heim,
165			     s->heim,
166			     flags,
167			     in_data ? &hin_data : NULL,
168			     in_creds ? &hin_creds : NULL,
169			     (krb5_ccache)ccache,
170			     &herror,
171			     &hrep_result,
172			     &hout_creds);
173    if (in_data)
174	free(hin_data.data);
175    if (in_creds)
176	heim_krb5_free_cred_contents(HC(context), &hin_creds);
177
178    if (herror && error) {
179	*error = mshim_malloc(sizeof(**error));
180	mshim_herror2merror(HC(context), herror, *error);
181    }
182    if (hrep_result && rep_result) {
183	*rep_result = mshim_malloc(sizeof(**rep_result));
184	mshim_haprepencpart2maprepencpart(hrep_result, *rep_result);
185    }
186    if (hout_creds && out_creds) {
187	*out_creds = mshim_malloc(sizeof(**out_creds));
188	mshim_hcred2mcred(HC(context), hout_creds, *out_creds);
189    }
190    if (hrep_result)
191	heim_krb5_free_ap_rep_enc_part(HC(context), hrep_result);
192    if (herror)
193	heim_krb5_free_error(HC(context), herror);
194    if (hout_creds)
195	heim_krb5_free_creds(HC(context), hout_creds);
196
197    return ret;
198}
199
200mit_krb5_error_code KRB5_CALLCONV
201krb5_mk_priv(mit_krb5_context context,
202	     mit_krb5_auth_context auth_context,
203	     const mit_krb5_data *inbuf,
204	     mit_krb5_data *outbuf,
205	     mit_krb5_replay_data *replay)
206{
207    krb5_replay_data outdata;
208    mit_krb5_error_code ret;
209    krb5_data in, out;
210
211    LOG_ENTRY();
212
213    memset(outbuf, 0, sizeof(*outbuf));
214    memset(&outdata, 0, sizeof(outdata));
215
216    in.data = inbuf->data;
217    in.length = inbuf->length;
218
219    ret = heim_krb5_mk_priv(HC(context),
220			    (krb5_auth_context)auth_context,
221			    &in,
222			    &out,
223			    &outdata);
224    if (ret)
225	return ret;
226
227    mshim_hdata2mdata(&out, outbuf);
228    heim_krb5_data_free(&out);
229
230    if (replay) {
231	memset(replay, 0, sizeof(*replay));
232	mshim_hreplay2mreplay(&outdata, replay);
233    }
234
235    return 0;
236}
237
238mit_krb5_error_code KRB5_CALLCONV
239krb5_mk_safe(mit_krb5_context context,
240	     mit_krb5_auth_context auth_context,
241	     const mit_krb5_data *inbuf,
242	     mit_krb5_data *outbuf,
243	     mit_krb5_replay_data *replay)
244{
245    krb5_replay_data outdata;
246    mit_krb5_error_code ret;
247    krb5_data in, out;
248
249    LOG_ENTRY();
250
251    memset(outbuf, 0, sizeof(*outbuf));
252    memset(&outdata, 0, sizeof(outdata));
253
254    in.data = inbuf->data;
255    in.length = inbuf->length;
256
257    ret = heim_krb5_mk_safe(HC(context),
258			    (krb5_auth_context)auth_context,
259			    &in,
260			    &out,
261			    &outdata);
262    if (ret)
263	return ret;
264
265    mshim_hdata2mdata(&out, outbuf);
266    heim_krb5_data_free(&out);
267
268    if (replay) {
269	memset(replay, 0, sizeof(*replay));
270	mshim_hreplay2mreplay(&outdata, replay);
271    }
272
273    return 0;
274}
275
276