xref: /freebsd/crypto/krb5/src/plugins/authdata/greet_client/greet.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* plugins/authdata/greet_client/greet.c - Sample authorization data plugin */
3 /*
4  * Copyright 2009 by the Massachusetts Institute of Technology.
5  *
6  * Export of this software from the United States of America may
7  *   require a specific license from the United States Government.
8  *   It is the responsibility of any person or organization contemplating
9  *   export to obtain such a license before exporting.
10  *
11  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
12  * distribute this software and its documentation for any purpose and
13  * without fee is hereby granted, provided that the above copyright
14  * notice appear in all copies and that both that copyright notice and
15  * this permission notice appear in supporting documentation, and that
16  * the name of M.I.T. not be used in advertising or publicity pertaining
17  * to distribution of the software without specific, written prior
18  * permission.  Furthermore if you modify this software you must label
19  * your software as modified software and not distribute it in such a
20  * fashion that it might be confused with the original M.I.T. software.
21  * M.I.T. makes no representations about the suitability of
22  * this software for any purpose.  It is provided "as is" without express
23  * or implied warranty.
24  */
25 
26 #include "k5-int.h"
27 #include <krb5/authdata_plugin.h>
28 #include <assert.h>
29 
30 struct greet_context {
31     krb5_data greeting;
32     krb5_boolean verified;
33 };
34 
35 static krb5_data greet_attr = {
36     KV5M_DATA, sizeof("urn:greet:greeting") - 1, "urn:greet:greeting" };
37 
38 static krb5_error_code
greet_init(krb5_context kcontext,void ** plugin_context)39 greet_init(krb5_context kcontext, void **plugin_context)
40 {
41     *plugin_context = 0;
42     return 0;
43 }
44 
45 static void
greet_flags(krb5_context kcontext,void * plugin_context,krb5_authdatatype ad_type,krb5_flags * flags)46 greet_flags(krb5_context kcontext,
47             void *plugin_context,
48             krb5_authdatatype ad_type,
49             krb5_flags *flags)
50 {
51     *flags = AD_USAGE_AP_REQ | AD_USAGE_KDC_ISSUED | AD_INFORMATIONAL;
52 }
53 
54 static void
greet_fini(krb5_context kcontext,void * plugin_context)55 greet_fini(krb5_context kcontext, void *plugin_context)
56 {
57     return;
58 }
59 
60 static krb5_error_code
greet_request_init(krb5_context kcontext,krb5_authdata_context context,void * plugin_context,void ** request_context)61 greet_request_init(krb5_context kcontext,
62                    krb5_authdata_context context,
63                    void *plugin_context,
64                    void **request_context)
65 {
66     struct greet_context *greet;
67 
68     greet = malloc(sizeof(*greet));
69     if (greet == NULL)
70         return ENOMEM;
71 
72     greet->greeting.data = NULL;
73     greet->greeting.length = 0;
74     greet->verified = FALSE;
75 
76     *request_context = greet;
77 
78     return 0;
79 }
80 
81 static krb5_error_code
greet_export_authdata(krb5_context kcontext,krb5_authdata_context context,void * plugin_context,void * request_context,krb5_flags usage,krb5_authdata *** out_authdata)82 greet_export_authdata(krb5_context kcontext,
83                       krb5_authdata_context context,
84                       void *plugin_context,
85                       void *request_context,
86                       krb5_flags usage,
87                       krb5_authdata ***out_authdata)
88 {
89     struct greet_context *greet = (struct greet_context *)request_context;
90     krb5_authdata *data[2];
91     krb5_authdata datum;
92     krb5_error_code code;
93 
94     datum.ad_type = -42;
95     datum.length = greet->greeting.length;
96     datum.contents = (krb5_octet *)greet->greeting.data;
97 
98     data[0] = &datum;
99     data[1] = NULL;
100 
101     code = krb5_copy_authdata(kcontext, data, out_authdata);
102 
103     return code;
104 }
105 
106 static krb5_error_code
greet_import_authdata(krb5_context kcontext,krb5_authdata_context context,void * plugin_context,void * request_context,krb5_authdata ** authdata,krb5_boolean kdc_issued_flag,krb5_const_principal issuer)107 greet_import_authdata(krb5_context kcontext,
108                       krb5_authdata_context context,
109                       void *plugin_context,
110                       void *request_context,
111                       krb5_authdata **authdata,
112                       krb5_boolean kdc_issued_flag,
113                       krb5_const_principal issuer)
114 {
115     krb5_error_code code;
116     struct greet_context *greet = (struct greet_context *)request_context;
117     krb5_data data;
118 
119     krb5_free_data_contents(kcontext, &greet->greeting);
120     greet->verified = FALSE;
121 
122     assert(authdata[0] != NULL);
123 
124     data.length = authdata[0]->length;
125     data.data = (char *)authdata[0]->contents;
126 
127     code = krb5int_copy_data_contents_add0(kcontext, &data, &greet->greeting);
128     if (code == 0)
129         greet->verified = kdc_issued_flag;
130 
131     return code;
132 }
133 
134 static void
greet_request_fini(krb5_context kcontext,krb5_authdata_context context,void * plugin_context,void * request_context)135 greet_request_fini(krb5_context kcontext,
136                    krb5_authdata_context context,
137                    void *plugin_context,
138                    void *request_context)
139 {
140     struct greet_context *greet = (struct greet_context *)request_context;
141 
142     if (greet != NULL) {
143         krb5_free_data_contents(kcontext, &greet->greeting);
144         free(greet);
145     }
146 }
147 
148 static krb5_error_code
greet_get_attribute_types(krb5_context kcontext,krb5_authdata_context context,void * plugin_context,void * request_context,krb5_data ** out_attrs)149 greet_get_attribute_types(krb5_context kcontext,
150                           krb5_authdata_context context,
151                           void *plugin_context,
152                           void *request_context,
153                           krb5_data **out_attrs)
154 {
155     krb5_error_code code;
156     struct greet_context *greet = (struct greet_context *)request_context;
157 
158     if (greet->greeting.length == 0)
159         return ENOENT;
160 
161     *out_attrs = calloc(2, sizeof(krb5_data));
162     if (*out_attrs == NULL)
163         return ENOMEM;
164 
165     code = krb5int_copy_data_contents_add0(kcontext,
166                                            &greet_attr,
167                                            &(*out_attrs)[0]);
168     if (code != 0) {
169         free(*out_attrs);
170         *out_attrs = NULL;
171         return code;
172     }
173 
174     return 0;
175 }
176 
177 static krb5_error_code
greet_get_attribute(krb5_context kcontext,krb5_authdata_context context,void * plugin_context,void * request_context,const krb5_data * attribute,krb5_boolean * authenticated,krb5_boolean * complete,krb5_data * value,krb5_data * display_value,int * more)178 greet_get_attribute(krb5_context kcontext,
179                     krb5_authdata_context context,
180                     void *plugin_context,
181                     void *request_context,
182                     const krb5_data *attribute,
183                     krb5_boolean *authenticated,
184                     krb5_boolean *complete,
185                     krb5_data *value,
186                     krb5_data *display_value,
187                     int *more)
188 {
189     struct greet_context *greet = (struct greet_context *)request_context;
190     krb5_error_code code;
191 
192     if (!data_eq(*attribute, greet_attr) || greet->greeting.length == 0)
193         return ENOENT;
194 
195     *authenticated = greet->verified;
196     *complete = TRUE;
197     *more = 0;
198 
199     code = krb5int_copy_data_contents_add0(kcontext, &greet->greeting, value);
200     if (code == 0) {
201         code = krb5int_copy_data_contents_add0(kcontext,
202                                                &greet->greeting,
203                                                display_value);
204         if (code != 0)
205             krb5_free_data_contents(kcontext, value);
206     }
207 
208     return code;
209 }
210 
211 static krb5_error_code
greet_set_attribute(krb5_context kcontext,krb5_authdata_context context,void * plugin_context,void * request_context,krb5_boolean complete,const krb5_data * attribute,const krb5_data * value)212 greet_set_attribute(krb5_context kcontext,
213                     krb5_authdata_context context,
214                     void *plugin_context,
215                     void *request_context,
216                     krb5_boolean complete,
217                     const krb5_data *attribute,
218                     const krb5_data *value)
219 {
220     struct greet_context *greet = (struct greet_context *)request_context;
221     krb5_data data;
222     krb5_error_code code;
223 
224     if (!data_eq(*attribute, greet_attr))
225         return ENOENT;
226 
227     if (greet->greeting.data != NULL)
228         return EEXIST;
229 
230     code = krb5int_copy_data_contents_add0(kcontext, value, &data);
231     if (code != 0)
232         return code;
233 
234     krb5_free_data_contents(kcontext, &greet->greeting);
235     greet->greeting = data;
236     greet->verified = FALSE;
237 
238     return 0;
239 }
240 
241 static krb5_error_code
greet_delete_attribute(krb5_context kcontext,krb5_authdata_context context,void * plugin_context,void * request_context,const krb5_data * attribute)242 greet_delete_attribute(krb5_context kcontext,
243                        krb5_authdata_context context,
244                        void *plugin_context,
245                        void *request_context,
246                        const krb5_data *attribute)
247 {
248     struct greet_context *greet = (struct greet_context *)request_context;
249 
250     krb5_free_data_contents(kcontext, &greet->greeting);
251     greet->verified = FALSE;
252 
253     return 0;
254 }
255 
256 static krb5_error_code
greet_size(krb5_context kcontext,krb5_authdata_context context,void * plugin_context,void * request_context,size_t * sizep)257 greet_size(krb5_context kcontext,
258            krb5_authdata_context context,
259            void *plugin_context,
260            void *request_context,
261            size_t *sizep)
262 {
263     struct greet_context *greet = (struct greet_context *)request_context;
264 
265     *sizep += sizeof(krb5_int32) +
266         greet->greeting.length +
267         sizeof(krb5_int32);
268 
269     return 0;
270 }
271 
272 static krb5_error_code
greet_externalize(krb5_context kcontext,krb5_authdata_context context,void * plugin_context,void * request_context,krb5_octet ** buffer,size_t * lenremain)273 greet_externalize(krb5_context kcontext,
274                   krb5_authdata_context context,
275                   void *plugin_context,
276                   void *request_context,
277                   krb5_octet **buffer,
278                   size_t *lenremain)
279 {
280     size_t required = 0;
281     struct greet_context *greet = (struct greet_context *)request_context;
282 
283     greet_size(kcontext, context, plugin_context,
284                request_context, &required);
285 
286     if (*lenremain < required)
287         return ENOMEM;
288 
289     /* Greeting Length | Greeting Contents | Verified */
290     krb5_ser_pack_int32(greet->greeting.length, buffer, lenremain);
291     krb5_ser_pack_bytes((krb5_octet *)greet->greeting.data,
292                         (size_t)greet->greeting.length,
293                         buffer, lenremain);
294     krb5_ser_pack_int32((krb5_int32)greet->verified, buffer, lenremain);
295 
296     return 0;
297 }
298 
299 static krb5_error_code
greet_internalize(krb5_context kcontext,krb5_authdata_context context,void * plugin_context,void * request_context,krb5_octet ** buffer,size_t * lenremain)300 greet_internalize(krb5_context kcontext,
301                   krb5_authdata_context context,
302                   void *plugin_context,
303                   void *request_context,
304                   krb5_octet **buffer,
305                   size_t *lenremain)
306 {
307     struct greet_context *greet = (struct greet_context *)request_context;
308     krb5_error_code code;
309     krb5_int32 length;
310     krb5_octet *contents = NULL;
311     krb5_int32 verified;
312     krb5_octet *bp;
313     size_t remain;
314 
315     bp = *buffer;
316     remain = *lenremain;
317 
318     /* Greeting Length */
319     code = krb5_ser_unpack_int32(&length, &bp, &remain);
320     if (code != 0)
321         return code;
322 
323     /* Greeting Contents */
324     if (length != 0) {
325         contents = malloc(length);
326         if (contents == NULL)
327             return ENOMEM;
328 
329         code = krb5_ser_unpack_bytes(contents, (size_t)length, &bp, &remain);
330         if (code != 0) {
331             free(contents);
332             return code;
333         }
334     }
335 
336     /* Verified */
337     code = krb5_ser_unpack_int32(&verified, &bp, &remain);
338     if (code != 0) {
339         free(contents);
340         return code;
341     }
342 
343     krb5_free_data_contents(kcontext, &greet->greeting);
344     greet->greeting.length = length;
345     greet->greeting.data = (char *)contents;
346     greet->verified = (verified != 0);
347 
348     *buffer = bp;
349     *lenremain = remain;
350 
351     return 0;
352 }
353 
354 static krb5_authdatatype greet_ad_types[] = { -42, 0 };
355 
356 krb5plugin_authdata_client_ftable_v0 authdata_client_0 = {
357     "greet",
358     greet_ad_types,
359     greet_init,
360     greet_fini,
361     greet_flags,
362     greet_request_init,
363     greet_request_fini,
364     greet_get_attribute_types,
365     greet_get_attribute,
366     greet_set_attribute,
367     greet_delete_attribute,
368     greet_export_authdata,
369     greet_import_authdata,
370     NULL,
371     NULL,
372     NULL,
373     greet_size,
374     greet_externalize,
375     greet_internalize,
376     NULL
377 };
378