1*ae771770SStanislav Sedov /*
2*ae771770SStanislav Sedov * Copyright (c) 2008 Kungliga Tekniska Högskolan
3*ae771770SStanislav Sedov * (Royal Institute of Technology, Stockholm, Sweden).
4*ae771770SStanislav Sedov * All rights reserved.
5*ae771770SStanislav Sedov *
6*ae771770SStanislav Sedov * Redistribution and use in source and binary forms, with or without
7*ae771770SStanislav Sedov * modification, are permitted provided that the following conditions
8*ae771770SStanislav Sedov * are met:
9*ae771770SStanislav Sedov *
10*ae771770SStanislav Sedov * 1. Redistributions of source code must retain the above copyright
11*ae771770SStanislav Sedov * notice, this list of conditions and the following disclaimer.
12*ae771770SStanislav Sedov *
13*ae771770SStanislav Sedov * 2. Redistributions in binary form must reproduce the above copyright
14*ae771770SStanislav Sedov * notice, this list of conditions and the following disclaimer in the
15*ae771770SStanislav Sedov * documentation and/or other materials provided with the distribution.
16*ae771770SStanislav Sedov *
17*ae771770SStanislav Sedov * 3. Neither the name of the Institute nor the names of its contributors
18*ae771770SStanislav Sedov * may be used to endorse or promote products derived from this software
19*ae771770SStanislav Sedov * without specific prior written permission.
20*ae771770SStanislav Sedov *
21*ae771770SStanislav Sedov * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22*ae771770SStanislav Sedov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23*ae771770SStanislav Sedov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24*ae771770SStanislav Sedov * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25*ae771770SStanislav Sedov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26*ae771770SStanislav Sedov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27*ae771770SStanislav Sedov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28*ae771770SStanislav Sedov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29*ae771770SStanislav Sedov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30*ae771770SStanislav Sedov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*ae771770SStanislav Sedov * SUCH DAMAGE.
32*ae771770SStanislav Sedov */
33*ae771770SStanislav Sedov
34*ae771770SStanislav Sedov #include "kadmin_locl.h"
35*ae771770SStanislav Sedov
36*ae771770SStanislav Sedov #include <gssapi/gssapi.h>
37*ae771770SStanislav Sedov //#include <gssapi_krb5.h>
38*ae771770SStanislav Sedov //#include <gssapi_spnego.h>
39*ae771770SStanislav Sedov
40*ae771770SStanislav Sedov static gss_OID_desc krb5_mechanism =
41*ae771770SStanislav Sedov {9, (void *)(uintptr_t) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"};
42*ae771770SStanislav Sedov #define GSS_KRB5_MECHANISM (&krb5_mechanism)
43*ae771770SStanislav Sedov
44*ae771770SStanislav Sedov #define CHECK(x) \
45*ae771770SStanislav Sedov do { \
46*ae771770SStanislav Sedov int __r; \
47*ae771770SStanislav Sedov if ((__r = (x))) { \
48*ae771770SStanislav Sedov krb5_errx(dcontext, 1, "Failed (%d) on %s:%d", \
49*ae771770SStanislav Sedov __r, __FILE__, __LINE__); \
50*ae771770SStanislav Sedov } \
51*ae771770SStanislav Sedov } while(0)
52*ae771770SStanislav Sedov
53*ae771770SStanislav Sedov static krb5_context dcontext;
54*ae771770SStanislav Sedov
55*ae771770SStanislav Sedov #define INSIST(x) CHECK(!(x))
56*ae771770SStanislav Sedov
57*ae771770SStanislav Sedov #define VERSION2 0x12345702
58*ae771770SStanislav Sedov
59*ae771770SStanislav Sedov #define LAST_FRAGMENT 0x80000000
60*ae771770SStanislav Sedov
61*ae771770SStanislav Sedov #define RPC_VERSION 2
62*ae771770SStanislav Sedov #define KADM_SERVER 2112
63*ae771770SStanislav Sedov #define VVERSION 2
64*ae771770SStanislav Sedov #define FLAVOR_GSS 6
65*ae771770SStanislav Sedov #define FLAVOR_GSS_VERSION 1
66*ae771770SStanislav Sedov
67*ae771770SStanislav Sedov struct opaque_auth {
68*ae771770SStanislav Sedov uint32_t flavor;
69*ae771770SStanislav Sedov krb5_data data;
70*ae771770SStanislav Sedov };
71*ae771770SStanislav Sedov
72*ae771770SStanislav Sedov struct call_header {
73*ae771770SStanislav Sedov uint32_t xid;
74*ae771770SStanislav Sedov uint32_t rpcvers;
75*ae771770SStanislav Sedov uint32_t prog;
76*ae771770SStanislav Sedov uint32_t vers;
77*ae771770SStanislav Sedov uint32_t proc;
78*ae771770SStanislav Sedov struct opaque_auth cred;
79*ae771770SStanislav Sedov struct opaque_auth verf;
80*ae771770SStanislav Sedov };
81*ae771770SStanislav Sedov
82*ae771770SStanislav Sedov enum {
83*ae771770SStanislav Sedov RPG_DATA = 0,
84*ae771770SStanislav Sedov RPG_INIT = 1,
85*ae771770SStanislav Sedov RPG_CONTINUE_INIT = 2,
86*ae771770SStanislav Sedov RPG_DESTROY = 3
87*ae771770SStanislav Sedov };
88*ae771770SStanislav Sedov
89*ae771770SStanislav Sedov enum {
90*ae771770SStanislav Sedov rpg_privacy = 3
91*ae771770SStanislav Sedov };
92*ae771770SStanislav Sedov
93*ae771770SStanislav Sedov /*
94*ae771770SStanislav Sedov struct chrand_ret {
95*ae771770SStanislav Sedov krb5_ui_4 api_version;
96*ae771770SStanislav Sedov kadm5_ret_t ret;
97*ae771770SStanislav Sedov int n_keys;
98*ae771770SStanislav Sedov krb5_keyblock *keys;
99*ae771770SStanislav Sedov };
100*ae771770SStanislav Sedov */
101*ae771770SStanislav Sedov
102*ae771770SStanislav Sedov
103*ae771770SStanislav Sedov struct gcred {
104*ae771770SStanislav Sedov uint32_t version;
105*ae771770SStanislav Sedov uint32_t proc;
106*ae771770SStanislav Sedov uint32_t seq_num;
107*ae771770SStanislav Sedov uint32_t service;
108*ae771770SStanislav Sedov krb5_data handle;
109*ae771770SStanislav Sedov };
110*ae771770SStanislav Sedov
111*ae771770SStanislav Sedov static int
parse_name(const unsigned char * p,size_t len,const gss_OID oid,char ** name)112*ae771770SStanislav Sedov parse_name(const unsigned char *p, size_t len,
113*ae771770SStanislav Sedov const gss_OID oid, char **name)
114*ae771770SStanislav Sedov {
115*ae771770SStanislav Sedov size_t l;
116*ae771770SStanislav Sedov
117*ae771770SStanislav Sedov if (len < 4)
118*ae771770SStanislav Sedov return 1;
119*ae771770SStanislav Sedov
120*ae771770SStanislav Sedov /* TOK_ID */
121*ae771770SStanislav Sedov if (memcmp(p, "\x04\x01", 2) != 0)
122*ae771770SStanislav Sedov return 1;
123*ae771770SStanislav Sedov len -= 2;
124*ae771770SStanislav Sedov p += 2;
125*ae771770SStanislav Sedov
126*ae771770SStanislav Sedov /* MECH_LEN */
127*ae771770SStanislav Sedov l = (p[0] << 8) | p[1];
128*ae771770SStanislav Sedov len -= 2;
129*ae771770SStanislav Sedov p += 2;
130*ae771770SStanislav Sedov if (l < 2 || len < l)
131*ae771770SStanislav Sedov return 1;
132*ae771770SStanislav Sedov
133*ae771770SStanislav Sedov /* oid wrapping */
134*ae771770SStanislav Sedov if (p[0] != 6 || p[1] != l - 2)
135*ae771770SStanislav Sedov return 1;
136*ae771770SStanislav Sedov p += 2;
137*ae771770SStanislav Sedov l -= 2;
138*ae771770SStanislav Sedov len -= 2;
139*ae771770SStanislav Sedov
140*ae771770SStanislav Sedov /* MECH */
141*ae771770SStanislav Sedov if (l != oid->length || memcmp(p, oid->elements, oid->length) != 0)
142*ae771770SStanislav Sedov return 1;
143*ae771770SStanislav Sedov len -= l;
144*ae771770SStanislav Sedov p += l;
145*ae771770SStanislav Sedov
146*ae771770SStanislav Sedov /* MECHNAME_LEN */
147*ae771770SStanislav Sedov if (len < 4)
148*ae771770SStanislav Sedov return 1;
149*ae771770SStanislav Sedov l = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
150*ae771770SStanislav Sedov len -= 4;
151*ae771770SStanislav Sedov p += 4;
152*ae771770SStanislav Sedov
153*ae771770SStanislav Sedov /* MECH NAME */
154*ae771770SStanislav Sedov if (len != l)
155*ae771770SStanislav Sedov return 1;
156*ae771770SStanislav Sedov
157*ae771770SStanislav Sedov *name = malloc(l + 1);
158*ae771770SStanislav Sedov INSIST(*name != NULL);
159*ae771770SStanislav Sedov memcpy(*name, p, l);
160*ae771770SStanislav Sedov (*name)[l] = '\0';
161*ae771770SStanislav Sedov
162*ae771770SStanislav Sedov return 0;
163*ae771770SStanislav Sedov }
164*ae771770SStanislav Sedov
165*ae771770SStanislav Sedov
166*ae771770SStanislav Sedov
167*ae771770SStanislav Sedov static void
gss_error(krb5_context contextp,gss_OID mech,OM_uint32 type,OM_uint32 error)168*ae771770SStanislav Sedov gss_error(krb5_context contextp,
169*ae771770SStanislav Sedov gss_OID mech, OM_uint32 type, OM_uint32 error)
170*ae771770SStanislav Sedov {
171*ae771770SStanislav Sedov OM_uint32 new_stat;
172*ae771770SStanislav Sedov OM_uint32 msg_ctx = 0;
173*ae771770SStanislav Sedov gss_buffer_desc status_string;
174*ae771770SStanislav Sedov OM_uint32 ret;
175*ae771770SStanislav Sedov
176*ae771770SStanislav Sedov do {
177*ae771770SStanislav Sedov ret = gss_display_status (&new_stat,
178*ae771770SStanislav Sedov error,
179*ae771770SStanislav Sedov type,
180*ae771770SStanislav Sedov mech,
181*ae771770SStanislav Sedov &msg_ctx,
182*ae771770SStanislav Sedov &status_string);
183*ae771770SStanislav Sedov krb5_warnx(contextp, "%.*s",
184*ae771770SStanislav Sedov (int)status_string.length,
185*ae771770SStanislav Sedov (char *)status_string.value);
186*ae771770SStanislav Sedov gss_release_buffer (&new_stat, &status_string);
187*ae771770SStanislav Sedov } while (!GSS_ERROR(ret) && msg_ctx != 0);
188*ae771770SStanislav Sedov }
189*ae771770SStanislav Sedov
190*ae771770SStanislav Sedov static void
gss_print_errors(krb5_context contextp,OM_uint32 maj_stat,OM_uint32 min_stat)191*ae771770SStanislav Sedov gss_print_errors (krb5_context contextp,
192*ae771770SStanislav Sedov OM_uint32 maj_stat, OM_uint32 min_stat)
193*ae771770SStanislav Sedov {
194*ae771770SStanislav Sedov gss_error(contextp, GSS_C_NO_OID, GSS_C_GSS_CODE, maj_stat);
195*ae771770SStanislav Sedov gss_error(contextp, GSS_C_NO_OID, GSS_C_MECH_CODE, min_stat);
196*ae771770SStanislav Sedov }
197*ae771770SStanislav Sedov
198*ae771770SStanislav Sedov static int
read_data(krb5_storage * sp,krb5_storage * msg,size_t len)199*ae771770SStanislav Sedov read_data(krb5_storage *sp, krb5_storage *msg, size_t len)
200*ae771770SStanislav Sedov {
201*ae771770SStanislav Sedov char buf[1024];
202*ae771770SStanislav Sedov
203*ae771770SStanislav Sedov while (len) {
204*ae771770SStanislav Sedov size_t tlen = len;
205*ae771770SStanislav Sedov ssize_t slen;
206*ae771770SStanislav Sedov
207*ae771770SStanislav Sedov if (tlen > sizeof(buf))
208*ae771770SStanislav Sedov tlen = sizeof(buf);
209*ae771770SStanislav Sedov
210*ae771770SStanislav Sedov slen = krb5_storage_read(sp, buf, tlen);
211*ae771770SStanislav Sedov INSIST((size_t)slen == tlen);
212*ae771770SStanislav Sedov
213*ae771770SStanislav Sedov slen = krb5_storage_write(msg, buf, tlen);
214*ae771770SStanislav Sedov INSIST((size_t)slen == tlen);
215*ae771770SStanislav Sedov
216*ae771770SStanislav Sedov len -= tlen;
217*ae771770SStanislav Sedov }
218*ae771770SStanislav Sedov return 0;
219*ae771770SStanislav Sedov }
220*ae771770SStanislav Sedov
221*ae771770SStanislav Sedov static int
collect_framents(krb5_storage * sp,krb5_storage * msg)222*ae771770SStanislav Sedov collect_framents(krb5_storage *sp, krb5_storage *msg)
223*ae771770SStanislav Sedov {
224*ae771770SStanislav Sedov krb5_error_code ret;
225*ae771770SStanislav Sedov uint32_t len;
226*ae771770SStanislav Sedov int last_fragment;
227*ae771770SStanislav Sedov size_t total_len = 0;
228*ae771770SStanislav Sedov
229*ae771770SStanislav Sedov do {
230*ae771770SStanislav Sedov ret = krb5_ret_uint32(sp, &len);
231*ae771770SStanislav Sedov if (ret)
232*ae771770SStanislav Sedov return ret;
233*ae771770SStanislav Sedov
234*ae771770SStanislav Sedov last_fragment = (len & LAST_FRAGMENT);
235*ae771770SStanislav Sedov len &= ~LAST_FRAGMENT;
236*ae771770SStanislav Sedov
237*ae771770SStanislav Sedov CHECK(read_data(sp, msg, len));
238*ae771770SStanislav Sedov total_len += len;
239*ae771770SStanislav Sedov
240*ae771770SStanislav Sedov } while(!last_fragment || total_len == 0);
241*ae771770SStanislav Sedov
242*ae771770SStanislav Sedov return 0;
243*ae771770SStanislav Sedov }
244*ae771770SStanislav Sedov
245*ae771770SStanislav Sedov static krb5_error_code
store_data_xdr(krb5_storage * sp,krb5_data data)246*ae771770SStanislav Sedov store_data_xdr(krb5_storage *sp, krb5_data data)
247*ae771770SStanislav Sedov {
248*ae771770SStanislav Sedov krb5_error_code ret;
249*ae771770SStanislav Sedov size_t res;
250*ae771770SStanislav Sedov
251*ae771770SStanislav Sedov ret = krb5_store_data(sp, data);
252*ae771770SStanislav Sedov if (ret)
253*ae771770SStanislav Sedov return ret;
254*ae771770SStanislav Sedov res = 4 - (data.length % 4);
255*ae771770SStanislav Sedov if (res != 4) {
256*ae771770SStanislav Sedov static const char zero[4] = { 0, 0, 0, 0 };
257*ae771770SStanislav Sedov
258*ae771770SStanislav Sedov ret = krb5_storage_write(sp, zero, res);
259*ae771770SStanislav Sedov if((size_t)ret != res)
260*ae771770SStanislav Sedov return (ret < 0)? errno : krb5_storage_get_eof_code(sp);
261*ae771770SStanislav Sedov }
262*ae771770SStanislav Sedov return 0;
263*ae771770SStanislav Sedov }
264*ae771770SStanislav Sedov
265*ae771770SStanislav Sedov static krb5_error_code
ret_data_xdr(krb5_storage * sp,krb5_data * data)266*ae771770SStanislav Sedov ret_data_xdr(krb5_storage *sp, krb5_data *data)
267*ae771770SStanislav Sedov {
268*ae771770SStanislav Sedov krb5_error_code ret;
269*ae771770SStanislav Sedov ret = krb5_ret_data(sp, data);
270*ae771770SStanislav Sedov if (ret)
271*ae771770SStanislav Sedov return ret;
272*ae771770SStanislav Sedov
273*ae771770SStanislav Sedov if ((data->length % 4) != 0) {
274*ae771770SStanislav Sedov char buf[4];
275*ae771770SStanislav Sedov size_t res;
276*ae771770SStanislav Sedov
277*ae771770SStanislav Sedov res = 4 - (data->length % 4);
278*ae771770SStanislav Sedov if (res != 4) {
279*ae771770SStanislav Sedov ret = krb5_storage_read(sp, buf, res);
280*ae771770SStanislav Sedov if((size_t)ret != res)
281*ae771770SStanislav Sedov return (ret < 0)? errno : krb5_storage_get_eof_code(sp);
282*ae771770SStanislav Sedov }
283*ae771770SStanislav Sedov }
284*ae771770SStanislav Sedov return 0;
285*ae771770SStanislav Sedov }
286*ae771770SStanislav Sedov
287*ae771770SStanislav Sedov static krb5_error_code
ret_auth_opaque(krb5_storage * msg,struct opaque_auth * ao)288*ae771770SStanislav Sedov ret_auth_opaque(krb5_storage *msg, struct opaque_auth *ao)
289*ae771770SStanislav Sedov {
290*ae771770SStanislav Sedov krb5_error_code ret;
291*ae771770SStanislav Sedov ret = krb5_ret_uint32(msg, &ao->flavor);
292*ae771770SStanislav Sedov if (ret) return ret;
293*ae771770SStanislav Sedov ret = ret_data_xdr(msg, &ao->data);
294*ae771770SStanislav Sedov return ret;
295*ae771770SStanislav Sedov }
296*ae771770SStanislav Sedov
297*ae771770SStanislav Sedov static int
ret_gcred(krb5_data * data,struct gcred * gcred)298*ae771770SStanislav Sedov ret_gcred(krb5_data *data, struct gcred *gcred)
299*ae771770SStanislav Sedov {
300*ae771770SStanislav Sedov krb5_storage *sp;
301*ae771770SStanislav Sedov
302*ae771770SStanislav Sedov memset(gcred, 0, sizeof(*gcred));
303*ae771770SStanislav Sedov
304*ae771770SStanislav Sedov sp = krb5_storage_from_data(data);
305*ae771770SStanislav Sedov INSIST(sp != NULL);
306*ae771770SStanislav Sedov
307*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &gcred->version));
308*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &gcred->proc));
309*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &gcred->seq_num));
310*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &gcred->service));
311*ae771770SStanislav Sedov CHECK(ret_data_xdr(sp, &gcred->handle));
312*ae771770SStanislav Sedov
313*ae771770SStanislav Sedov krb5_storage_free(sp);
314*ae771770SStanislav Sedov
315*ae771770SStanislav Sedov return 0;
316*ae771770SStanislav Sedov }
317*ae771770SStanislav Sedov
318*ae771770SStanislav Sedov static krb5_error_code
store_gss_init_res(krb5_storage * sp,krb5_data handle,OM_uint32 maj_stat,OM_uint32 min_stat,uint32_t seq_window,gss_buffer_t gout)319*ae771770SStanislav Sedov store_gss_init_res(krb5_storage *sp, krb5_data handle,
320*ae771770SStanislav Sedov OM_uint32 maj_stat, OM_uint32 min_stat,
321*ae771770SStanislav Sedov uint32_t seq_window, gss_buffer_t gout)
322*ae771770SStanislav Sedov {
323*ae771770SStanislav Sedov krb5_error_code ret;
324*ae771770SStanislav Sedov krb5_data out;
325*ae771770SStanislav Sedov
326*ae771770SStanislav Sedov out.data = gout->value;
327*ae771770SStanislav Sedov out.length = gout->length;
328*ae771770SStanislav Sedov
329*ae771770SStanislav Sedov ret = store_data_xdr(sp, handle);
330*ae771770SStanislav Sedov if (ret) return ret;
331*ae771770SStanislav Sedov ret = krb5_store_uint32(sp, maj_stat);
332*ae771770SStanislav Sedov if (ret) return ret;
333*ae771770SStanislav Sedov ret = krb5_store_uint32(sp, min_stat);
334*ae771770SStanislav Sedov if (ret) return ret;
335*ae771770SStanislav Sedov ret = store_data_xdr(sp, out);
336*ae771770SStanislav Sedov return ret;
337*ae771770SStanislav Sedov }
338*ae771770SStanislav Sedov
339*ae771770SStanislav Sedov static int
store_string_xdr(krb5_storage * sp,const char * str)340*ae771770SStanislav Sedov store_string_xdr(krb5_storage *sp, const char *str)
341*ae771770SStanislav Sedov {
342*ae771770SStanislav Sedov krb5_data c;
343*ae771770SStanislav Sedov if (str) {
344*ae771770SStanislav Sedov c.data = rk_UNCONST(str);
345*ae771770SStanislav Sedov c.length = strlen(str) + 1;
346*ae771770SStanislav Sedov } else
347*ae771770SStanislav Sedov krb5_data_zero(&c);
348*ae771770SStanislav Sedov
349*ae771770SStanislav Sedov return store_data_xdr(sp, c);
350*ae771770SStanislav Sedov }
351*ae771770SStanislav Sedov
352*ae771770SStanislav Sedov static int
ret_string_xdr(krb5_storage * sp,char ** str)353*ae771770SStanislav Sedov ret_string_xdr(krb5_storage *sp, char **str)
354*ae771770SStanislav Sedov {
355*ae771770SStanislav Sedov krb5_data c;
356*ae771770SStanislav Sedov *str = NULL;
357*ae771770SStanislav Sedov CHECK(ret_data_xdr(sp, &c));
358*ae771770SStanislav Sedov if (c.length) {
359*ae771770SStanislav Sedov *str = malloc(c.length + 1);
360*ae771770SStanislav Sedov INSIST(*str != NULL);
361*ae771770SStanislav Sedov memcpy(*str, c.data, c.length);
362*ae771770SStanislav Sedov (*str)[c.length] = '\0';
363*ae771770SStanislav Sedov }
364*ae771770SStanislav Sedov krb5_data_free(&c);
365*ae771770SStanislav Sedov return 0;
366*ae771770SStanislav Sedov }
367*ae771770SStanislav Sedov
368*ae771770SStanislav Sedov static int
store_principal_xdr(krb5_context contextp,krb5_storage * sp,krb5_principal p)369*ae771770SStanislav Sedov store_principal_xdr(krb5_context contextp,
370*ae771770SStanislav Sedov krb5_storage *sp,
371*ae771770SStanislav Sedov krb5_principal p)
372*ae771770SStanislav Sedov {
373*ae771770SStanislav Sedov char *str;
374*ae771770SStanislav Sedov CHECK(krb5_unparse_name(contextp, p, &str));
375*ae771770SStanislav Sedov CHECK(store_string_xdr(sp, str));
376*ae771770SStanislav Sedov free(str);
377*ae771770SStanislav Sedov return 0;
378*ae771770SStanislav Sedov }
379*ae771770SStanislav Sedov
380*ae771770SStanislav Sedov static int
ret_principal_xdr(krb5_context contextp,krb5_storage * sp,krb5_principal * p)381*ae771770SStanislav Sedov ret_principal_xdr(krb5_context contextp,
382*ae771770SStanislav Sedov krb5_storage *sp,
383*ae771770SStanislav Sedov krb5_principal *p)
384*ae771770SStanislav Sedov {
385*ae771770SStanislav Sedov char *str;
386*ae771770SStanislav Sedov *p = NULL;
387*ae771770SStanislav Sedov CHECK(ret_string_xdr(sp, &str));
388*ae771770SStanislav Sedov if (str) {
389*ae771770SStanislav Sedov CHECK(krb5_parse_name(contextp, str, p));
390*ae771770SStanislav Sedov free(str);
391*ae771770SStanislav Sedov }
392*ae771770SStanislav Sedov return 0;
393*ae771770SStanislav Sedov }
394*ae771770SStanislav Sedov
395*ae771770SStanislav Sedov static int
store_principal_ent(krb5_context contextp,krb5_storage * sp,kadm5_principal_ent_rec * ent)396*ae771770SStanislav Sedov store_principal_ent(krb5_context contextp,
397*ae771770SStanislav Sedov krb5_storage *sp,
398*ae771770SStanislav Sedov kadm5_principal_ent_rec *ent)
399*ae771770SStanislav Sedov {
400*ae771770SStanislav Sedov int i;
401*ae771770SStanislav Sedov
402*ae771770SStanislav Sedov CHECK(store_principal_xdr(contextp, sp, ent->principal));
403*ae771770SStanislav Sedov CHECK(krb5_store_uint32(sp, ent->princ_expire_time));
404*ae771770SStanislav Sedov CHECK(krb5_store_uint32(sp, ent->pw_expiration));
405*ae771770SStanislav Sedov CHECK(krb5_store_uint32(sp, ent->last_pwd_change));
406*ae771770SStanislav Sedov CHECK(krb5_store_uint32(sp, ent->max_life));
407*ae771770SStanislav Sedov CHECK(krb5_store_int32(sp, ent->mod_name == NULL));
408*ae771770SStanislav Sedov if (ent->mod_name)
409*ae771770SStanislav Sedov CHECK(store_principal_xdr(contextp, sp, ent->mod_name));
410*ae771770SStanislav Sedov CHECK(krb5_store_uint32(sp, ent->mod_date));
411*ae771770SStanislav Sedov CHECK(krb5_store_uint32(sp, ent->attributes));
412*ae771770SStanislav Sedov CHECK(krb5_store_uint32(sp, ent->kvno));
413*ae771770SStanislav Sedov CHECK(krb5_store_uint32(sp, ent->mkvno));
414*ae771770SStanislav Sedov CHECK(store_string_xdr(sp, ent->policy));
415*ae771770SStanislav Sedov CHECK(krb5_store_int32(sp, ent->aux_attributes));
416*ae771770SStanislav Sedov CHECK(krb5_store_int32(sp, ent->max_renewable_life));
417*ae771770SStanislav Sedov CHECK(krb5_store_int32(sp, ent->last_success));
418*ae771770SStanislav Sedov CHECK(krb5_store_int32(sp, ent->last_failed));
419*ae771770SStanislav Sedov CHECK(krb5_store_int32(sp, ent->fail_auth_count));
420*ae771770SStanislav Sedov CHECK(krb5_store_int32(sp, ent->n_key_data));
421*ae771770SStanislav Sedov CHECK(krb5_store_int32(sp, ent->n_tl_data));
422*ae771770SStanislav Sedov CHECK(krb5_store_int32(sp, ent->n_tl_data == 0));
423*ae771770SStanislav Sedov if (ent->n_tl_data) {
424*ae771770SStanislav Sedov krb5_tl_data *tp;
425*ae771770SStanislav Sedov
426*ae771770SStanislav Sedov for (tp = ent->tl_data; tp; tp = tp->tl_data_next) {
427*ae771770SStanislav Sedov krb5_data c;
428*ae771770SStanislav Sedov c.length = tp->tl_data_length;
429*ae771770SStanislav Sedov c.data = tp->tl_data_contents;
430*ae771770SStanislav Sedov
431*ae771770SStanislav Sedov CHECK(krb5_store_int32(sp, 0)); /* last item */
432*ae771770SStanislav Sedov CHECK(krb5_store_int32(sp, tp->tl_data_type));
433*ae771770SStanislav Sedov CHECK(store_data_xdr(sp, c));
434*ae771770SStanislav Sedov }
435*ae771770SStanislav Sedov CHECK(krb5_store_int32(sp, 1)); /* last item */
436*ae771770SStanislav Sedov }
437*ae771770SStanislav Sedov
438*ae771770SStanislav Sedov CHECK(krb5_store_int32(sp, ent->n_key_data));
439*ae771770SStanislav Sedov for (i = 0; i < ent->n_key_data; i++) {
440*ae771770SStanislav Sedov CHECK(krb5_store_uint32(sp, 2));
441*ae771770SStanislav Sedov CHECK(krb5_store_uint32(sp, ent->kvno));
442*ae771770SStanislav Sedov CHECK(krb5_store_uint32(sp, ent->key_data[i].key_data_type[0]));
443*ae771770SStanislav Sedov CHECK(krb5_store_uint32(sp, ent->key_data[i].key_data_type[1]));
444*ae771770SStanislav Sedov }
445*ae771770SStanislav Sedov
446*ae771770SStanislav Sedov return 0;
447*ae771770SStanislav Sedov }
448*ae771770SStanislav Sedov
449*ae771770SStanislav Sedov static int
ret_principal_ent(krb5_context contextp,krb5_storage * sp,kadm5_principal_ent_rec * ent)450*ae771770SStanislav Sedov ret_principal_ent(krb5_context contextp,
451*ae771770SStanislav Sedov krb5_storage *sp,
452*ae771770SStanislav Sedov kadm5_principal_ent_rec *ent)
453*ae771770SStanislav Sedov {
454*ae771770SStanislav Sedov uint32_t flag, num;
455*ae771770SStanislav Sedov size_t i;
456*ae771770SStanislav Sedov
457*ae771770SStanislav Sedov memset(ent, 0, sizeof(*ent));
458*ae771770SStanislav Sedov
459*ae771770SStanislav Sedov CHECK(ret_principal_xdr(contextp, sp, &ent->principal));
460*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &flag));
461*ae771770SStanislav Sedov ent->princ_expire_time = flag;
462*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &flag));
463*ae771770SStanislav Sedov ent->pw_expiration = flag;
464*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &flag));
465*ae771770SStanislav Sedov ent->last_pwd_change = flag;
466*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &flag));
467*ae771770SStanislav Sedov ent->max_life = flag;
468*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &flag));
469*ae771770SStanislav Sedov if (flag == 0)
470*ae771770SStanislav Sedov ret_principal_xdr(contextp, sp, &ent->mod_name);
471*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &flag));
472*ae771770SStanislav Sedov ent->mod_date = flag;
473*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &flag));
474*ae771770SStanislav Sedov ent->attributes = flag;
475*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &flag));
476*ae771770SStanislav Sedov ent->kvno = flag;
477*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &flag));
478*ae771770SStanislav Sedov ent->mkvno = flag;
479*ae771770SStanislav Sedov CHECK(ret_string_xdr(sp, &ent->policy));
480*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &flag));
481*ae771770SStanislav Sedov ent->aux_attributes = flag;
482*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &flag));
483*ae771770SStanislav Sedov ent->max_renewable_life = flag;
484*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &flag));
485*ae771770SStanislav Sedov ent->last_success = flag;
486*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &flag));
487*ae771770SStanislav Sedov ent->last_failed = flag;
488*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &flag));
489*ae771770SStanislav Sedov ent->fail_auth_count = flag;
490*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &flag));
491*ae771770SStanislav Sedov ent->n_key_data = flag;
492*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &flag));
493*ae771770SStanislav Sedov ent->n_tl_data = flag;
494*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &flag));
495*ae771770SStanislav Sedov if (flag == 0) {
496*ae771770SStanislav Sedov krb5_tl_data **tp = &ent->tl_data;
497*ae771770SStanislav Sedov size_t count = 0;
498*ae771770SStanislav Sedov
499*ae771770SStanislav Sedov while(1) {
500*ae771770SStanislav Sedov krb5_data c;
501*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &flag)); /* last item */
502*ae771770SStanislav Sedov if (flag)
503*ae771770SStanislav Sedov break;
504*ae771770SStanislav Sedov *tp = calloc(1, sizeof(**tp));
505*ae771770SStanislav Sedov INSIST(*tp != NULL);
506*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &flag));
507*ae771770SStanislav Sedov (*tp)->tl_data_type = flag;
508*ae771770SStanislav Sedov CHECK(ret_data_xdr(sp, &c));
509*ae771770SStanislav Sedov (*tp)->tl_data_length = c.length;
510*ae771770SStanislav Sedov (*tp)->tl_data_contents = c.data;
511*ae771770SStanislav Sedov tp = &(*tp)->tl_data_next;
512*ae771770SStanislav Sedov
513*ae771770SStanislav Sedov count++;
514*ae771770SStanislav Sedov }
515*ae771770SStanislav Sedov INSIST((size_t)ent->n_tl_data == count);
516*ae771770SStanislav Sedov } else {
517*ae771770SStanislav Sedov INSIST(ent->n_tl_data == 0);
518*ae771770SStanislav Sedov }
519*ae771770SStanislav Sedov
520*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &num));
521*ae771770SStanislav Sedov INSIST(num == (uint32_t)ent->n_key_data);
522*ae771770SStanislav Sedov
523*ae771770SStanislav Sedov ent->key_data = calloc(num, sizeof(ent->key_data[0]));
524*ae771770SStanislav Sedov INSIST(ent->key_data != NULL);
525*ae771770SStanislav Sedov
526*ae771770SStanislav Sedov for (i = 0; i < num; i++) {
527*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &flag)); /* data version */
528*ae771770SStanislav Sedov INSIST(flag > 1);
529*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &flag));
530*ae771770SStanislav Sedov ent->kvno = flag;
531*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &flag));
532*ae771770SStanislav Sedov ent->key_data[i].key_data_type[0] = flag;
533*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp, &flag));
534*ae771770SStanislav Sedov ent->key_data[i].key_data_type[1] = flag;
535*ae771770SStanislav Sedov }
536*ae771770SStanislav Sedov
537*ae771770SStanislav Sedov return 0;
538*ae771770SStanislav Sedov }
539*ae771770SStanislav Sedov
540*ae771770SStanislav Sedov /*
541*ae771770SStanislav Sedov *
542*ae771770SStanislav Sedov */
543*ae771770SStanislav Sedov
544*ae771770SStanislav Sedov static void
proc_create_principal(kadm5_server_context * contextp,krb5_storage * in,krb5_storage * out)545*ae771770SStanislav Sedov proc_create_principal(kadm5_server_context *contextp,
546*ae771770SStanislav Sedov krb5_storage *in,
547*ae771770SStanislav Sedov krb5_storage *out)
548*ae771770SStanislav Sedov {
549*ae771770SStanislav Sedov uint32_t version, mask;
550*ae771770SStanislav Sedov kadm5_principal_ent_rec ent;
551*ae771770SStanislav Sedov krb5_error_code ret;
552*ae771770SStanislav Sedov char *password;
553*ae771770SStanislav Sedov
554*ae771770SStanislav Sedov memset(&ent, 0, sizeof(ent));
555*ae771770SStanislav Sedov
556*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(in, &version));
557*ae771770SStanislav Sedov INSIST(version == VERSION2);
558*ae771770SStanislav Sedov CHECK(ret_principal_ent(contextp->context, in, &ent));
559*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(in, &mask));
560*ae771770SStanislav Sedov CHECK(ret_string_xdr(in, &password));
561*ae771770SStanislav Sedov
562*ae771770SStanislav Sedov INSIST(ent.principal);
563*ae771770SStanislav Sedov
564*ae771770SStanislav Sedov
565*ae771770SStanislav Sedov ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_ADD, ent.principal);
566*ae771770SStanislav Sedov if (ret)
567*ae771770SStanislav Sedov goto fail;
568*ae771770SStanislav Sedov
569*ae771770SStanislav Sedov ret = kadm5_create_principal(contextp, &ent, mask, password);
570*ae771770SStanislav Sedov
571*ae771770SStanislav Sedov fail:
572*ae771770SStanislav Sedov krb5_warn(contextp->context, ret, "create principal");
573*ae771770SStanislav Sedov CHECK(krb5_store_uint32(out, VERSION2)); /* api version */
574*ae771770SStanislav Sedov CHECK(krb5_store_uint32(out, ret)); /* code */
575*ae771770SStanislav Sedov
576*ae771770SStanislav Sedov free(password);
577*ae771770SStanislav Sedov kadm5_free_principal_ent(contextp, &ent);
578*ae771770SStanislav Sedov }
579*ae771770SStanislav Sedov
580*ae771770SStanislav Sedov static void
proc_delete_principal(kadm5_server_context * contextp,krb5_storage * in,krb5_storage * out)581*ae771770SStanislav Sedov proc_delete_principal(kadm5_server_context *contextp,
582*ae771770SStanislav Sedov krb5_storage *in,
583*ae771770SStanislav Sedov krb5_storage *out)
584*ae771770SStanislav Sedov {
585*ae771770SStanislav Sedov uint32_t version;
586*ae771770SStanislav Sedov krb5_principal princ;
587*ae771770SStanislav Sedov krb5_error_code ret;
588*ae771770SStanislav Sedov
589*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(in, &version));
590*ae771770SStanislav Sedov INSIST(version == VERSION2);
591*ae771770SStanislav Sedov CHECK(ret_principal_xdr(contextp->context, in, &princ));
592*ae771770SStanislav Sedov
593*ae771770SStanislav Sedov ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_DELETE, princ);
594*ae771770SStanislav Sedov if (ret)
595*ae771770SStanislav Sedov goto fail;
596*ae771770SStanislav Sedov
597*ae771770SStanislav Sedov ret = kadm5_delete_principal(contextp, princ);
598*ae771770SStanislav Sedov
599*ae771770SStanislav Sedov fail:
600*ae771770SStanislav Sedov krb5_warn(contextp->context, ret, "delete principal");
601*ae771770SStanislav Sedov CHECK(krb5_store_uint32(out, VERSION2)); /* api version */
602*ae771770SStanislav Sedov CHECK(krb5_store_uint32(out, ret)); /* code */
603*ae771770SStanislav Sedov
604*ae771770SStanislav Sedov krb5_free_principal(contextp->context, princ);
605*ae771770SStanislav Sedov }
606*ae771770SStanislav Sedov
607*ae771770SStanislav Sedov static void
proc_get_principal(kadm5_server_context * contextp,krb5_storage * in,krb5_storage * out)608*ae771770SStanislav Sedov proc_get_principal(kadm5_server_context *contextp,
609*ae771770SStanislav Sedov krb5_storage *in,
610*ae771770SStanislav Sedov krb5_storage *out)
611*ae771770SStanislav Sedov {
612*ae771770SStanislav Sedov uint32_t version, mask;
613*ae771770SStanislav Sedov krb5_principal princ;
614*ae771770SStanislav Sedov kadm5_principal_ent_rec ent;
615*ae771770SStanislav Sedov krb5_error_code ret;
616*ae771770SStanislav Sedov
617*ae771770SStanislav Sedov memset(&ent, 0, sizeof(ent));
618*ae771770SStanislav Sedov
619*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(in, &version));
620*ae771770SStanislav Sedov INSIST(version == VERSION2);
621*ae771770SStanislav Sedov CHECK(ret_principal_xdr(contextp->context, in, &princ));
622*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(in, &mask));
623*ae771770SStanislav Sedov
624*ae771770SStanislav Sedov ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_GET, princ);
625*ae771770SStanislav Sedov if(ret)
626*ae771770SStanislav Sedov goto fail;
627*ae771770SStanislav Sedov
628*ae771770SStanislav Sedov ret = kadm5_get_principal(contextp, princ, &ent, mask);
629*ae771770SStanislav Sedov
630*ae771770SStanislav Sedov fail:
631*ae771770SStanislav Sedov krb5_warn(contextp->context, ret, "get principal principal");
632*ae771770SStanislav Sedov
633*ae771770SStanislav Sedov CHECK(krb5_store_uint32(out, VERSION2)); /* api version */
634*ae771770SStanislav Sedov CHECK(krb5_store_uint32(out, ret)); /* code */
635*ae771770SStanislav Sedov if (ret == 0) {
636*ae771770SStanislav Sedov CHECK(store_principal_ent(contextp->context, out, &ent));
637*ae771770SStanislav Sedov }
638*ae771770SStanislav Sedov krb5_free_principal(contextp->context, princ);
639*ae771770SStanislav Sedov kadm5_free_principal_ent(contextp, &ent);
640*ae771770SStanislav Sedov }
641*ae771770SStanislav Sedov
642*ae771770SStanislav Sedov static void
proc_chrand_principal_v2(kadm5_server_context * contextp,krb5_storage * in,krb5_storage * out)643*ae771770SStanislav Sedov proc_chrand_principal_v2(kadm5_server_context *contextp,
644*ae771770SStanislav Sedov krb5_storage *in,
645*ae771770SStanislav Sedov krb5_storage *out)
646*ae771770SStanislav Sedov {
647*ae771770SStanislav Sedov krb5_error_code ret;
648*ae771770SStanislav Sedov krb5_principal princ;
649*ae771770SStanislav Sedov uint32_t version;
650*ae771770SStanislav Sedov krb5_keyblock *new_keys;
651*ae771770SStanislav Sedov int n_keys;
652*ae771770SStanislav Sedov
653*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(in, &version));
654*ae771770SStanislav Sedov INSIST(version == VERSION2);
655*ae771770SStanislav Sedov CHECK(ret_principal_xdr(contextp->context, in, &princ));
656*ae771770SStanislav Sedov
657*ae771770SStanislav Sedov ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_CPW, princ);
658*ae771770SStanislav Sedov if(ret)
659*ae771770SStanislav Sedov goto fail;
660*ae771770SStanislav Sedov
661*ae771770SStanislav Sedov ret = kadm5_randkey_principal(contextp, princ,
662*ae771770SStanislav Sedov &new_keys, &n_keys);
663*ae771770SStanislav Sedov
664*ae771770SStanislav Sedov fail:
665*ae771770SStanislav Sedov krb5_warn(contextp->context, ret, "rand key principal");
666*ae771770SStanislav Sedov
667*ae771770SStanislav Sedov CHECK(krb5_store_uint32(out, VERSION2)); /* api version */
668*ae771770SStanislav Sedov CHECK(krb5_store_uint32(out, ret));
669*ae771770SStanislav Sedov if (ret == 0) {
670*ae771770SStanislav Sedov int i;
671*ae771770SStanislav Sedov CHECK(krb5_store_int32(out, n_keys));
672*ae771770SStanislav Sedov
673*ae771770SStanislav Sedov for(i = 0; i < n_keys; i++){
674*ae771770SStanislav Sedov CHECK(krb5_store_uint32(out, new_keys[i].keytype));
675*ae771770SStanislav Sedov CHECK(store_data_xdr(out, new_keys[i].keyvalue));
676*ae771770SStanislav Sedov krb5_free_keyblock_contents(contextp->context, &new_keys[i]);
677*ae771770SStanislav Sedov }
678*ae771770SStanislav Sedov free(new_keys);
679*ae771770SStanislav Sedov }
680*ae771770SStanislav Sedov krb5_free_principal(contextp->context, princ);
681*ae771770SStanislav Sedov }
682*ae771770SStanislav Sedov
683*ae771770SStanislav Sedov static void
proc_init(kadm5_server_context * contextp,krb5_storage * in,krb5_storage * out)684*ae771770SStanislav Sedov proc_init(kadm5_server_context *contextp,
685*ae771770SStanislav Sedov krb5_storage *in,
686*ae771770SStanislav Sedov krb5_storage *out)
687*ae771770SStanislav Sedov {
688*ae771770SStanislav Sedov CHECK(krb5_store_uint32(out, VERSION2)); /* api version */
689*ae771770SStanislav Sedov CHECK(krb5_store_uint32(out, 0)); /* code */
690*ae771770SStanislav Sedov CHECK(krb5_store_uint32(out, 0)); /* code */
691*ae771770SStanislav Sedov }
692*ae771770SStanislav Sedov
693*ae771770SStanislav Sedov struct krb5_proc {
694*ae771770SStanislav Sedov const char *name;
695*ae771770SStanislav Sedov void (*func)(kadm5_server_context *, krb5_storage *, krb5_storage *);
696*ae771770SStanislav Sedov } procs[] = {
697*ae771770SStanislav Sedov { "NULL", NULL },
698*ae771770SStanislav Sedov { "create principal", proc_create_principal },
699*ae771770SStanislav Sedov { "delete principal", proc_delete_principal },
700*ae771770SStanislav Sedov { "modify principal", NULL },
701*ae771770SStanislav Sedov { "rename principal", NULL },
702*ae771770SStanislav Sedov { "get principal", proc_get_principal },
703*ae771770SStanislav Sedov { "chpass principal", NULL },
704*ae771770SStanislav Sedov { "chrand principal", proc_chrand_principal_v2 },
705*ae771770SStanislav Sedov { "create policy", NULL },
706*ae771770SStanislav Sedov { "delete policy", NULL },
707*ae771770SStanislav Sedov { "modify policy", NULL },
708*ae771770SStanislav Sedov { "get policy", NULL },
709*ae771770SStanislav Sedov { "get privs", NULL },
710*ae771770SStanislav Sedov { "init", proc_init },
711*ae771770SStanislav Sedov { "get principals", NULL },
712*ae771770SStanislav Sedov { "get polices", NULL },
713*ae771770SStanislav Sedov { "setkey principal", NULL },
714*ae771770SStanislav Sedov { "setkey principal v4", NULL },
715*ae771770SStanislav Sedov { "create principal v3", NULL },
716*ae771770SStanislav Sedov { "chpass principal v3", NULL },
717*ae771770SStanislav Sedov { "chrand principal v3", NULL },
718*ae771770SStanislav Sedov { "setkey principal v3", NULL }
719*ae771770SStanislav Sedov };
720*ae771770SStanislav Sedov
721*ae771770SStanislav Sedov static krb5_error_code
copyheader(krb5_storage * sp,krb5_data * data)722*ae771770SStanislav Sedov copyheader(krb5_storage *sp, krb5_data *data)
723*ae771770SStanislav Sedov {
724*ae771770SStanislav Sedov off_t off;
725*ae771770SStanislav Sedov ssize_t sret;
726*ae771770SStanislav Sedov
727*ae771770SStanislav Sedov off = krb5_storage_seek(sp, 0, SEEK_CUR);
728*ae771770SStanislav Sedov
729*ae771770SStanislav Sedov CHECK(krb5_data_alloc(data, off));
730*ae771770SStanislav Sedov INSIST((size_t)off == data->length);
731*ae771770SStanislav Sedov krb5_storage_seek(sp, 0, SEEK_SET);
732*ae771770SStanislav Sedov sret = krb5_storage_read(sp, data->data, data->length);
733*ae771770SStanislav Sedov INSIST(sret == off);
734*ae771770SStanislav Sedov INSIST(off == krb5_storage_seek(sp, 0, SEEK_CUR));
735*ae771770SStanislav Sedov
736*ae771770SStanislav Sedov return 0;
737*ae771770SStanislav Sedov }
738*ae771770SStanislav Sedov
739*ae771770SStanislav Sedov struct gctx {
740*ae771770SStanislav Sedov krb5_data handle;
741*ae771770SStanislav Sedov gss_ctx_id_t ctx;
742*ae771770SStanislav Sedov uint32_t seq_num;
743*ae771770SStanislav Sedov int done;
744*ae771770SStanislav Sedov int inprogress;
745*ae771770SStanislav Sedov };
746*ae771770SStanislav Sedov
747*ae771770SStanislav Sedov static int
process_stream(krb5_context contextp,unsigned char * buf,size_t ilen,krb5_storage * sp)748*ae771770SStanislav Sedov process_stream(krb5_context contextp,
749*ae771770SStanislav Sedov unsigned char *buf, size_t ilen,
750*ae771770SStanislav Sedov krb5_storage *sp)
751*ae771770SStanislav Sedov {
752*ae771770SStanislav Sedov krb5_error_code ret;
753*ae771770SStanislav Sedov krb5_storage *msg, *reply, *dreply;
754*ae771770SStanislav Sedov OM_uint32 maj_stat, min_stat;
755*ae771770SStanislav Sedov gss_buffer_desc gin, gout;
756*ae771770SStanislav Sedov struct gctx gctx;
757*ae771770SStanislav Sedov void *server_handle = NULL;
758*ae771770SStanislav Sedov
759*ae771770SStanislav Sedov memset(&gctx, 0, sizeof(gctx));
760*ae771770SStanislav Sedov
761*ae771770SStanislav Sedov msg = krb5_storage_emem();
762*ae771770SStanislav Sedov reply = krb5_storage_emem();
763*ae771770SStanislav Sedov dreply = krb5_storage_emem();
764*ae771770SStanislav Sedov
765*ae771770SStanislav Sedov /*
766*ae771770SStanislav Sedov * First packet comes partly from the caller
767*ae771770SStanislav Sedov */
768*ae771770SStanislav Sedov
769*ae771770SStanislav Sedov INSIST(ilen >= 4);
770*ae771770SStanislav Sedov
771*ae771770SStanislav Sedov while (1) {
772*ae771770SStanislav Sedov struct call_header chdr;
773*ae771770SStanislav Sedov struct gcred gcred;
774*ae771770SStanislav Sedov uint32_t mtype;
775*ae771770SStanislav Sedov krb5_data headercopy;
776*ae771770SStanislav Sedov
777*ae771770SStanislav Sedov krb5_storage_truncate(dreply, 0);
778*ae771770SStanislav Sedov krb5_storage_truncate(reply, 0);
779*ae771770SStanislav Sedov krb5_storage_truncate(msg, 0);
780*ae771770SStanislav Sedov
781*ae771770SStanislav Sedov krb5_data_zero(&headercopy);
782*ae771770SStanislav Sedov memset(&chdr, 0, sizeof(chdr));
783*ae771770SStanislav Sedov memset(&gcred, 0, sizeof(gcred));
784*ae771770SStanislav Sedov
785*ae771770SStanislav Sedov /*
786*ae771770SStanislav Sedov * This is very icky to handle the the auto-detection between
787*ae771770SStanislav Sedov * the Heimdal protocol and the MIT ONC-RPC based protocol.
788*ae771770SStanislav Sedov */
789*ae771770SStanislav Sedov
790*ae771770SStanislav Sedov if (ilen) {
791*ae771770SStanislav Sedov int last_fragment;
792*ae771770SStanislav Sedov unsigned long len;
793*ae771770SStanislav Sedov ssize_t slen;
794*ae771770SStanislav Sedov unsigned char tmp[4];
795*ae771770SStanislav Sedov
796*ae771770SStanislav Sedov if (ilen < 4) {
797*ae771770SStanislav Sedov memcpy(tmp, buf, ilen);
798*ae771770SStanislav Sedov slen = krb5_storage_read(sp, tmp + ilen, sizeof(tmp) - ilen);
799*ae771770SStanislav Sedov INSIST((size_t)slen == sizeof(tmp) - ilen);
800*ae771770SStanislav Sedov
801*ae771770SStanislav Sedov ilen = sizeof(tmp);
802*ae771770SStanislav Sedov buf = tmp;
803*ae771770SStanislav Sedov }
804*ae771770SStanislav Sedov INSIST(ilen >= 4);
805*ae771770SStanislav Sedov
806*ae771770SStanislav Sedov _krb5_get_int(buf, &len, 4);
807*ae771770SStanislav Sedov last_fragment = (len & LAST_FRAGMENT) != 0;
808*ae771770SStanislav Sedov len &= ~LAST_FRAGMENT;
809*ae771770SStanislav Sedov
810*ae771770SStanislav Sedov ilen -= 4;
811*ae771770SStanislav Sedov buf += 4;
812*ae771770SStanislav Sedov
813*ae771770SStanislav Sedov if (ilen) {
814*ae771770SStanislav Sedov if (len < ilen) {
815*ae771770SStanislav Sedov slen = krb5_storage_write(msg, buf, len);
816*ae771770SStanislav Sedov INSIST((size_t)slen == len);
817*ae771770SStanislav Sedov ilen -= len;
818*ae771770SStanislav Sedov len = 0;
819*ae771770SStanislav Sedov } else {
820*ae771770SStanislav Sedov slen = krb5_storage_write(msg, buf, ilen);
821*ae771770SStanislav Sedov INSIST((size_t)slen == ilen);
822*ae771770SStanislav Sedov len -= ilen;
823*ae771770SStanislav Sedov }
824*ae771770SStanislav Sedov }
825*ae771770SStanislav Sedov
826*ae771770SStanislav Sedov CHECK(read_data(sp, msg, len));
827*ae771770SStanislav Sedov
828*ae771770SStanislav Sedov if (!last_fragment) {
829*ae771770SStanislav Sedov ret = collect_framents(sp, msg);
830*ae771770SStanislav Sedov if (ret == HEIM_ERR_EOF)
831*ae771770SStanislav Sedov krb5_errx(contextp, 0, "client disconnected");
832*ae771770SStanislav Sedov INSIST(ret == 0);
833*ae771770SStanislav Sedov }
834*ae771770SStanislav Sedov } else {
835*ae771770SStanislav Sedov
836*ae771770SStanislav Sedov ret = collect_framents(sp, msg);
837*ae771770SStanislav Sedov if (ret == HEIM_ERR_EOF)
838*ae771770SStanislav Sedov krb5_errx(contextp, 0, "client disconnected");
839*ae771770SStanislav Sedov INSIST(ret == 0);
840*ae771770SStanislav Sedov }
841*ae771770SStanislav Sedov krb5_storage_seek(msg, 0, SEEK_SET);
842*ae771770SStanislav Sedov
843*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(msg, &chdr.xid));
844*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(msg, &mtype));
845*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(msg, &chdr.rpcvers));
846*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(msg, &chdr.prog));
847*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(msg, &chdr.vers));
848*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(msg, &chdr.proc));
849*ae771770SStanislav Sedov CHECK(ret_auth_opaque(msg, &chdr.cred));
850*ae771770SStanislav Sedov CHECK(copyheader(msg, &headercopy));
851*ae771770SStanislav Sedov CHECK(ret_auth_opaque(msg, &chdr.verf));
852*ae771770SStanislav Sedov
853*ae771770SStanislav Sedov INSIST(chdr.rpcvers == RPC_VERSION);
854*ae771770SStanislav Sedov INSIST(chdr.prog == KADM_SERVER);
855*ae771770SStanislav Sedov INSIST(chdr.vers == VVERSION);
856*ae771770SStanislav Sedov INSIST(chdr.cred.flavor == FLAVOR_GSS);
857*ae771770SStanislav Sedov
858*ae771770SStanislav Sedov CHECK(ret_gcred(&chdr.cred.data, &gcred));
859*ae771770SStanislav Sedov
860*ae771770SStanislav Sedov INSIST(gcred.version == FLAVOR_GSS_VERSION);
861*ae771770SStanislav Sedov
862*ae771770SStanislav Sedov if (gctx.done) {
863*ae771770SStanislav Sedov INSIST(chdr.verf.flavor == FLAVOR_GSS);
864*ae771770SStanislav Sedov
865*ae771770SStanislav Sedov /* from first byte to last of credential */
866*ae771770SStanislav Sedov gin.value = headercopy.data;
867*ae771770SStanislav Sedov gin.length = headercopy.length;
868*ae771770SStanislav Sedov gout.value = chdr.verf.data.data;
869*ae771770SStanislav Sedov gout.length = chdr.verf.data.length;
870*ae771770SStanislav Sedov
871*ae771770SStanislav Sedov maj_stat = gss_verify_mic(&min_stat, gctx.ctx, &gin, &gout, NULL);
872*ae771770SStanislav Sedov INSIST(maj_stat == GSS_S_COMPLETE);
873*ae771770SStanislav Sedov }
874*ae771770SStanislav Sedov
875*ae771770SStanislav Sedov switch(gcred.proc) {
876*ae771770SStanislav Sedov case RPG_DATA: {
877*ae771770SStanislav Sedov krb5_data data;
878*ae771770SStanislav Sedov int conf_state;
879*ae771770SStanislav Sedov uint32_t seq;
880*ae771770SStanislav Sedov krb5_storage *sp1;
881*ae771770SStanislav Sedov
882*ae771770SStanislav Sedov INSIST(gcred.service == rpg_privacy);
883*ae771770SStanislav Sedov
884*ae771770SStanislav Sedov INSIST(gctx.done);
885*ae771770SStanislav Sedov
886*ae771770SStanislav Sedov INSIST(krb5_data_cmp(&gcred.handle, &gctx.handle) == 0);
887*ae771770SStanislav Sedov
888*ae771770SStanislav Sedov CHECK(ret_data_xdr(msg, &data));
889*ae771770SStanislav Sedov
890*ae771770SStanislav Sedov gin.value = data.data;
891*ae771770SStanislav Sedov gin.length = data.length;
892*ae771770SStanislav Sedov
893*ae771770SStanislav Sedov maj_stat = gss_unwrap(&min_stat, gctx.ctx, &gin, &gout,
894*ae771770SStanislav Sedov &conf_state, NULL);
895*ae771770SStanislav Sedov krb5_data_free(&data);
896*ae771770SStanislav Sedov INSIST(maj_stat == GSS_S_COMPLETE);
897*ae771770SStanislav Sedov INSIST(conf_state != 0);
898*ae771770SStanislav Sedov
899*ae771770SStanislav Sedov sp1 = krb5_storage_from_mem(gout.value, gout.length);
900*ae771770SStanislav Sedov INSIST(sp1 != NULL);
901*ae771770SStanislav Sedov
902*ae771770SStanislav Sedov CHECK(krb5_ret_uint32(sp1, &seq));
903*ae771770SStanislav Sedov INSIST (seq == gcred.seq_num);
904*ae771770SStanislav Sedov
905*ae771770SStanislav Sedov /*
906*ae771770SStanislav Sedov * Check sequence number
907*ae771770SStanislav Sedov */
908*ae771770SStanislav Sedov INSIST(seq > gctx.seq_num);
909*ae771770SStanislav Sedov gctx.seq_num = seq;
910*ae771770SStanislav Sedov
911*ae771770SStanislav Sedov /*
912*ae771770SStanislav Sedov * If contextp is setup, priv data have the seq_num stored
913*ae771770SStanislav Sedov * first in the block, so add it here before users data is
914*ae771770SStanislav Sedov * added.
915*ae771770SStanislav Sedov */
916*ae771770SStanislav Sedov CHECK(krb5_store_uint32(dreply, gctx.seq_num));
917*ae771770SStanislav Sedov
918*ae771770SStanislav Sedov if (chdr.proc >= sizeof(procs)/sizeof(procs[0])) {
919*ae771770SStanislav Sedov krb5_warnx(contextp, "proc number out of array");
920*ae771770SStanislav Sedov } else if (procs[chdr.proc].func == NULL) {
921*ae771770SStanislav Sedov krb5_warnx(contextp, "proc '%s' never implemented",
922*ae771770SStanislav Sedov procs[chdr.proc].name);
923*ae771770SStanislav Sedov } else {
924*ae771770SStanislav Sedov krb5_warnx(contextp, "proc %s", procs[chdr.proc].name);
925*ae771770SStanislav Sedov INSIST(server_handle != NULL);
926*ae771770SStanislav Sedov (*procs[chdr.proc].func)(server_handle, sp, dreply);
927*ae771770SStanislav Sedov }
928*ae771770SStanislav Sedov krb5_storage_free(sp);
929*ae771770SStanislav Sedov gss_release_buffer(&min_stat, &gout);
930*ae771770SStanislav Sedov
931*ae771770SStanislav Sedov break;
932*ae771770SStanislav Sedov }
933*ae771770SStanislav Sedov case RPG_INIT:
934*ae771770SStanislav Sedov INSIST(gctx.inprogress == 0);
935*ae771770SStanislav Sedov INSIST(gctx.ctx == NULL);
936*ae771770SStanislav Sedov
937*ae771770SStanislav Sedov gctx.inprogress = 1;
938*ae771770SStanislav Sedov /* FALL THOUGH */
939*ae771770SStanislav Sedov case RPG_CONTINUE_INIT: {
940*ae771770SStanislav Sedov gss_name_t src_name = GSS_C_NO_NAME;
941*ae771770SStanislav Sedov krb5_data in;
942*ae771770SStanislav Sedov
943*ae771770SStanislav Sedov INSIST(gctx.inprogress);
944*ae771770SStanislav Sedov
945*ae771770SStanislav Sedov CHECK(ret_data_xdr(msg, &in));
946*ae771770SStanislav Sedov
947*ae771770SStanislav Sedov gin.value = in.data;
948*ae771770SStanislav Sedov gin.length = in.length;
949*ae771770SStanislav Sedov gout.value = NULL;
950*ae771770SStanislav Sedov gout.length = 0;
951*ae771770SStanislav Sedov
952*ae771770SStanislav Sedov maj_stat = gss_accept_sec_context(&min_stat,
953*ae771770SStanislav Sedov &gctx.ctx,
954*ae771770SStanislav Sedov GSS_C_NO_CREDENTIAL,
955*ae771770SStanislav Sedov &gin,
956*ae771770SStanislav Sedov GSS_C_NO_CHANNEL_BINDINGS,
957*ae771770SStanislav Sedov &src_name,
958*ae771770SStanislav Sedov NULL,
959*ae771770SStanislav Sedov &gout,
960*ae771770SStanislav Sedov NULL,
961*ae771770SStanislav Sedov NULL,
962*ae771770SStanislav Sedov NULL);
963*ae771770SStanislav Sedov if (GSS_ERROR(maj_stat)) {
964*ae771770SStanislav Sedov gss_print_errors(contextp, maj_stat, min_stat);
965*ae771770SStanislav Sedov krb5_errx(contextp, 1, "gss error, exit");
966*ae771770SStanislav Sedov }
967*ae771770SStanislav Sedov if ((maj_stat & GSS_S_CONTINUE_NEEDED) == 0) {
968*ae771770SStanislav Sedov kadm5_config_params realm_params;
969*ae771770SStanislav Sedov gss_buffer_desc bufp;
970*ae771770SStanislav Sedov char *client;
971*ae771770SStanislav Sedov
972*ae771770SStanislav Sedov gctx.done = 1;
973*ae771770SStanislav Sedov
974*ae771770SStanislav Sedov memset(&realm_params, 0, sizeof(realm_params));
975*ae771770SStanislav Sedov
976*ae771770SStanislav Sedov maj_stat = gss_export_name(&min_stat, src_name, &bufp);
977*ae771770SStanislav Sedov INSIST(maj_stat == GSS_S_COMPLETE);
978*ae771770SStanislav Sedov
979*ae771770SStanislav Sedov CHECK(parse_name(bufp.value, bufp.length,
980*ae771770SStanislav Sedov GSS_KRB5_MECHANISM, &client));
981*ae771770SStanislav Sedov
982*ae771770SStanislav Sedov gss_release_buffer(&min_stat, &bufp);
983*ae771770SStanislav Sedov
984*ae771770SStanislav Sedov krb5_warnx(contextp, "%s connected", client);
985*ae771770SStanislav Sedov
986*ae771770SStanislav Sedov ret = kadm5_s_init_with_password_ctx(contextp,
987*ae771770SStanislav Sedov client,
988*ae771770SStanislav Sedov NULL,
989*ae771770SStanislav Sedov KADM5_ADMIN_SERVICE,
990*ae771770SStanislav Sedov &realm_params,
991*ae771770SStanislav Sedov 0, 0,
992*ae771770SStanislav Sedov &server_handle);
993*ae771770SStanislav Sedov INSIST(ret == 0);
994*ae771770SStanislav Sedov }
995*ae771770SStanislav Sedov
996*ae771770SStanislav Sedov INSIST(gctx.ctx != GSS_C_NO_CONTEXT);
997*ae771770SStanislav Sedov
998*ae771770SStanislav Sedov CHECK(krb5_store_uint32(dreply, 0));
999*ae771770SStanislav Sedov CHECK(store_gss_init_res(dreply, gctx.handle,
1000*ae771770SStanislav Sedov maj_stat, min_stat, 1, &gout));
1001*ae771770SStanislav Sedov if (gout.value)
1002*ae771770SStanislav Sedov gss_release_buffer(&min_stat, &gout);
1003*ae771770SStanislav Sedov if (src_name)
1004*ae771770SStanislav Sedov gss_release_name(&min_stat, &src_name);
1005*ae771770SStanislav Sedov
1006*ae771770SStanislav Sedov break;
1007*ae771770SStanislav Sedov }
1008*ae771770SStanislav Sedov case RPG_DESTROY:
1009*ae771770SStanislav Sedov krb5_errx(contextp, 1, "client destroyed gss contextp");
1010*ae771770SStanislav Sedov default:
1011*ae771770SStanislav Sedov krb5_errx(contextp, 1, "client sent unknown gsscode %d",
1012*ae771770SStanislav Sedov (int)gcred.proc);
1013*ae771770SStanislav Sedov }
1014*ae771770SStanislav Sedov
1015*ae771770SStanislav Sedov krb5_data_free(&gcred.handle);
1016*ae771770SStanislav Sedov krb5_data_free(&chdr.cred.data);
1017*ae771770SStanislav Sedov krb5_data_free(&chdr.verf.data);
1018*ae771770SStanislav Sedov krb5_data_free(&headercopy);
1019*ae771770SStanislav Sedov
1020*ae771770SStanislav Sedov CHECK(krb5_store_uint32(reply, chdr.xid));
1021*ae771770SStanislav Sedov CHECK(krb5_store_uint32(reply, 1)); /* REPLY */
1022*ae771770SStanislav Sedov CHECK(krb5_store_uint32(reply, 0)); /* MSG_ACCEPTED */
1023*ae771770SStanislav Sedov
1024*ae771770SStanislav Sedov if (!gctx.done) {
1025*ae771770SStanislav Sedov krb5_data data;
1026*ae771770SStanislav Sedov
1027*ae771770SStanislav Sedov CHECK(krb5_store_uint32(reply, 0)); /* flavor_none */
1028*ae771770SStanislav Sedov CHECK(krb5_store_uint32(reply, 0)); /* length */
1029*ae771770SStanislav Sedov
1030*ae771770SStanislav Sedov CHECK(krb5_store_uint32(reply, 0)); /* SUCCESS */
1031*ae771770SStanislav Sedov
1032*ae771770SStanislav Sedov CHECK(krb5_storage_to_data(dreply, &data));
1033*ae771770SStanislav Sedov INSIST((size_t)krb5_storage_write(reply, data.data, data.length) == data.length);
1034*ae771770SStanislav Sedov krb5_data_free(&data);
1035*ae771770SStanislav Sedov
1036*ae771770SStanislav Sedov } else {
1037*ae771770SStanislav Sedov uint32_t seqnum = htonl(gctx.seq_num);
1038*ae771770SStanislav Sedov krb5_data data;
1039*ae771770SStanislav Sedov
1040*ae771770SStanislav Sedov gin.value = &seqnum;
1041*ae771770SStanislav Sedov gin.length = sizeof(seqnum);
1042*ae771770SStanislav Sedov
1043*ae771770SStanislav Sedov maj_stat = gss_get_mic(&min_stat, gctx.ctx, 0, &gin, &gout);
1044*ae771770SStanislav Sedov INSIST(maj_stat == GSS_S_COMPLETE);
1045*ae771770SStanislav Sedov
1046*ae771770SStanislav Sedov data.data = gout.value;
1047*ae771770SStanislav Sedov data.length = gout.length;
1048*ae771770SStanislav Sedov
1049*ae771770SStanislav Sedov CHECK(krb5_store_uint32(reply, FLAVOR_GSS));
1050*ae771770SStanislav Sedov CHECK(store_data_xdr(reply, data));
1051*ae771770SStanislav Sedov gss_release_buffer(&min_stat, &gout);
1052*ae771770SStanislav Sedov
1053*ae771770SStanislav Sedov CHECK(krb5_store_uint32(reply, 0)); /* SUCCESS */
1054*ae771770SStanislav Sedov
1055*ae771770SStanislav Sedov CHECK(krb5_storage_to_data(dreply, &data));
1056*ae771770SStanislav Sedov
1057*ae771770SStanislav Sedov if (gctx.inprogress) {
1058*ae771770SStanislav Sedov ssize_t sret;
1059*ae771770SStanislav Sedov gctx.inprogress = 0;
1060*ae771770SStanislav Sedov sret = krb5_storage_write(reply, data.data, data.length);
1061*ae771770SStanislav Sedov INSIST((size_t)sret == data.length);
1062*ae771770SStanislav Sedov krb5_data_free(&data);
1063*ae771770SStanislav Sedov } else {
1064*ae771770SStanislav Sedov int conf_state;
1065*ae771770SStanislav Sedov
1066*ae771770SStanislav Sedov gin.value = data.data;
1067*ae771770SStanislav Sedov gin.length = data.length;
1068*ae771770SStanislav Sedov
1069*ae771770SStanislav Sedov maj_stat = gss_wrap(&min_stat, gctx.ctx, 1, 0,
1070*ae771770SStanislav Sedov &gin, &conf_state, &gout);
1071*ae771770SStanislav Sedov INSIST(maj_stat == GSS_S_COMPLETE);
1072*ae771770SStanislav Sedov INSIST(conf_state != 0);
1073*ae771770SStanislav Sedov krb5_data_free(&data);
1074*ae771770SStanislav Sedov
1075*ae771770SStanislav Sedov data.data = gout.value;
1076*ae771770SStanislav Sedov data.length = gout.length;
1077*ae771770SStanislav Sedov
1078*ae771770SStanislav Sedov store_data_xdr(reply, data);
1079*ae771770SStanislav Sedov gss_release_buffer(&min_stat, &gout);
1080*ae771770SStanislav Sedov }
1081*ae771770SStanislav Sedov }
1082*ae771770SStanislav Sedov
1083*ae771770SStanislav Sedov {
1084*ae771770SStanislav Sedov krb5_data data;
1085*ae771770SStanislav Sedov ssize_t sret;
1086*ae771770SStanislav Sedov CHECK(krb5_storage_to_data(reply, &data));
1087*ae771770SStanislav Sedov CHECK(krb5_store_uint32(sp, data.length | LAST_FRAGMENT));
1088*ae771770SStanislav Sedov sret = krb5_storage_write(sp, data.data, data.length);
1089*ae771770SStanislav Sedov INSIST((size_t)sret == data.length);
1090*ae771770SStanislav Sedov krb5_data_free(&data);
1091*ae771770SStanislav Sedov }
1092*ae771770SStanislav Sedov
1093*ae771770SStanislav Sedov }
1094*ae771770SStanislav Sedov }
1095*ae771770SStanislav Sedov
1096*ae771770SStanislav Sedov
1097*ae771770SStanislav Sedov int
handle_mit(krb5_context contextp,void * buf,size_t len,krb5_socket_t sock)1098*ae771770SStanislav Sedov handle_mit(krb5_context contextp, void *buf, size_t len, krb5_socket_t sock)
1099*ae771770SStanislav Sedov {
1100*ae771770SStanislav Sedov krb5_storage *sp;
1101*ae771770SStanislav Sedov
1102*ae771770SStanislav Sedov dcontext = contextp;
1103*ae771770SStanislav Sedov
1104*ae771770SStanislav Sedov sp = krb5_storage_from_fd(sock);
1105*ae771770SStanislav Sedov INSIST(sp != NULL);
1106*ae771770SStanislav Sedov
1107*ae771770SStanislav Sedov process_stream(contextp, buf, len, sp);
1108*ae771770SStanislav Sedov
1109*ae771770SStanislav Sedov return 0;
1110*ae771770SStanislav Sedov }
1111