30b525f7accad47c03a15b77761d8b89c10baeaf
[mech_eap.orig] / util_adshim.c
1 /*
2  * Copyright (c) 2011, JANET(UK)
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * 3. Neither the name of JANET(UK) nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32
33 #include "gssapiP_eap.h"
34 #include "authdata_plugin.h"
35
36 /*
37  * This rubbish is necessary because MIT doesn't provide another way
38  * to access verified AD-KDCIssued elements. We can't verify them
39  * ourselves because they're signed in the ticket session key, which
40  * is destroyed immediately after the AP-REQ is processed.
41  */
42
43 struct radius_ad_context {
44     krb5_data avpdata;
45     krb5_boolean verified;
46 };
47
48 static krb5_data radius_ad_attr = {
49     KV5M_DATA, sizeof("urn:authdata-radius-avp") - 1, "urn:authdata-radius-avp" };
50
51 static krb5_error_code
52 radius_ad_init(krb5_context kcontext, void **plugin_context)
53 {
54     *plugin_context = 0;
55     return 0;
56 }
57
58 static void
59 radius_ad_flags(krb5_context kcontext,
60                 void *plugin_context,
61                 krb5_authdatatype ad_type,
62                 krb5_flags *flags)
63 {
64     *flags = AD_USAGE_KDC_ISSUED | AD_INFORMATIONAL;
65 }
66
67 static void
68 radius_ad_fini(krb5_context kcontext, void *plugin_context)
69 {
70     return;
71 }
72
73 static krb5_error_code
74 radius_ad_request_init(krb5_context kcontext,
75                        struct _krb5_authdata_context *context,
76                        void *plugin_context,
77                        void **request_context)
78 {
79     struct radius_ad_context *ctx;
80
81     ctx = GSSEAP_CALLOC(1, sizeof(*ctx));
82     if (ctx == NULL)
83         return ENOMEM;
84
85     *request_context = ctx;
86
87     return 0;
88 }
89
90 static krb5_error_code
91 radius_ad_export_authdata(krb5_context kcontext,
92                           struct _krb5_authdata_context *context,
93                           void *plugin_context,
94                           void *request_context,
95                           krb5_flags usage,
96                           krb5_authdata ***out_authdata)
97 {
98     struct radius_ad_context *radius_ad = (struct radius_ad_context *)request_context;
99     krb5_authdata *data[2];
100     krb5_authdata datum;
101
102     datum.ad_type = KRB5_AUTHDATA_RADIUS_AVP;
103     datum.length = radius_ad->avpdata.length;
104     datum.contents = (krb5_octet *)radius_ad->avpdata.data;
105
106     data[0] = &datum;
107     data[1] = NULL;
108
109     return krb5_copy_authdata(kcontext, data, out_authdata);
110 }
111
112 static krb5_error_code
113 radius_ad_import_authdata(krb5_context kcontext,
114                           struct _krb5_authdata_context *context,
115                           void *plugin_context,
116                           void *request_context,
117                           krb5_authdata **authdata,
118                           krb5_boolean kdc_issued_flag,
119                           krb5_const_principal issuer)
120 {
121     struct radius_ad_context *radius_ad = (struct radius_ad_context *)request_context;
122
123     krb5_free_data_contents(kcontext, &radius_ad->avpdata);
124     radius_ad->verified = FALSE;
125
126     assert(authdata[0] != NULL);
127
128     radius_ad->avpdata.data = GSSEAP_MALLOC(authdata[0]->length);
129     if (radius_ad->avpdata.data == NULL)
130         return ENOMEM;
131
132     memcpy(radius_ad->avpdata.data, authdata[0]->contents,
133            authdata[0]->length);
134     radius_ad->avpdata.length = authdata[0]->length;
135
136     radius_ad->verified = kdc_issued_flag;
137
138     return 0;
139 }
140
141 static void
142 radius_ad_request_fini(krb5_context kcontext,
143                        struct _krb5_authdata_context *context,
144                        void *plugin_context,
145                        void *request_context)
146 {
147     struct radius_ad_context *radius_ad = (struct radius_ad_context *)request_context;
148
149     if (radius_ad != NULL) {
150         krb5_free_data_contents(kcontext, &radius_ad->avpdata);
151         GSSEAP_FREE(radius_ad);
152     }
153 }
154
155 static krb5_error_code
156 radius_ad_get_attribute(krb5_context kcontext,
157                         struct _krb5_authdata_context *context,
158                         void *plugin_context,
159                         void *request_context,
160                         const krb5_data *attribute,
161                         krb5_boolean *authenticated,
162                         krb5_boolean *complete,
163                         krb5_data *value,
164                         krb5_data *display_value,
165                         int *more)
166 {
167     struct radius_ad_context *radius_ad = (struct radius_ad_context *)request_context;
168
169     if (attribute->length != radius_ad_attr.length ||
170         memcmp(attribute->data, radius_ad_attr.data,
171                radius_ad_attr.length) != 0)
172         return ENOENT;
173
174     if (radius_ad->avpdata.length == 0)
175         return ENOENT;
176
177     *authenticated = radius_ad->verified;
178     *complete = TRUE;
179     *more = 0;
180
181     value->data = GSSEAP_MALLOC(radius_ad->avpdata.length);
182     if (value->data == NULL)
183         return ENOMEM;
184
185     memcpy(value->data, radius_ad->avpdata.data, radius_ad->avpdata.length);
186     value->length = radius_ad->avpdata.length;
187
188     return 0;
189 }
190
191 static krb5_error_code
192 radius_ad_copy(krb5_context kcontext,
193                struct _krb5_authdata_context *context,
194                void *plugin_context,
195                void *request_context,
196                void *dst_plugin_context,
197                void *dst_request_context)
198 {
199     struct radius_ad_context *radius_ad_src =
200         (struct radius_ad_context *)request_context;
201     struct radius_ad_context *radius_ad_dst =
202         (struct radius_ad_context *)dst_request_context;
203
204     radius_ad_dst->avpdata.data = GSSEAP_MALLOC(radius_ad_src->avpdata.length);
205     if (radius_ad_dst->avpdata.data == NULL)
206         return ENOMEM;
207
208     memcpy(radius_ad_dst->avpdata.data, radius_ad_src->avpdata.data,
209            radius_ad_src->avpdata.length);
210     radius_ad_dst->avpdata.length = radius_ad_src->avpdata.length;
211     radius_ad_dst->verified = radius_ad_src->verified;
212
213     return 0;
214 }
215
216 static krb5_authdatatype radius_ad_ad_types[] =
217     { KRB5_AUTHDATA_RADIUS_AVP, 0 };
218
219 krb5plugin_authdata_client_ftable_v0 authdata_client_0 = {
220     "radius_ad",
221     radius_ad_ad_types,
222     radius_ad_init,
223     radius_ad_fini,
224     radius_ad_flags,
225     radius_ad_request_init,
226     radius_ad_request_fini,
227     NULL,
228     radius_ad_get_attribute,
229     NULL,
230     NULL,
231     radius_ad_export_authdata,
232     radius_ad_import_authdata,
233     NULL,
234     NULL,
235     NULL,
236     NULL,
237     NULL,
238     NULL,
239     radius_ad_copy
240 };