marshall.c revision 1.2
1/*	$NetBSD: marshall.c,v 1.2 2017/01/28 21:31:49 christos Exp $	*/
2
3/*
4 * Copyright (c) 1997 - 1999 Kungliga Tekniska H��gskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * 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 "kadm5_locl.h"
37
38__RCSID("$NetBSD: marshall.c,v 1.2 2017/01/28 21:31:49 christos Exp $");
39
40int
41kadm5_some_keys_are_bogus(size_t n_keys, krb5_key_data *keys)
42{
43    size_t i;
44
45    for (i = 0; i < n_keys; i++) {
46	krb5_key_data *key = &keys[i];
47	if (key->key_data_length[0] == sizeof(KADM5_BOGUS_KEY_DATA) - 1 &&
48	    ct_memcmp(key->key_data_contents[1], KADM5_BOGUS_KEY_DATA,
49		      key->key_data_length[0]) == 0)
50	    return 1;
51    }
52    return 0;
53}
54
55int
56kadm5_all_keys_are_bogus(size_t n_keys, krb5_key_data *keys)
57{
58    size_t i;
59
60    if (n_keys == 0)
61	return 0;
62
63    for (i = 0; i < n_keys; i++) {
64	krb5_key_data *key = &keys[i];
65	if (key->key_data_length[0] != sizeof(KADM5_BOGUS_KEY_DATA) - 1 ||
66	    ct_memcmp(key->key_data_contents[1], KADM5_BOGUS_KEY_DATA,
67		      key->key_data_length[0]) != 0)
68	    return 0;
69    }
70    return 1;
71}
72
73kadm5_ret_t
74kadm5_store_key_data(krb5_storage *sp,
75		     krb5_key_data *key)
76{
77    krb5_data c;
78    krb5_store_int32(sp, key->key_data_ver);
79    krb5_store_int32(sp, key->key_data_kvno);
80    krb5_store_int32(sp, key->key_data_type[0]);
81    c.length = key->key_data_length[0];
82    c.data = key->key_data_contents[0];
83    krb5_store_data(sp, c);
84    krb5_store_int32(sp, key->key_data_type[1]);
85    c.length = key->key_data_length[1];
86    c.data = key->key_data_contents[1];
87    krb5_store_data(sp, c);
88    return 0;
89}
90
91kadm5_ret_t
92kadm5_store_fake_key_data(krb5_storage *sp,
93		          krb5_key_data *key)
94{
95    krb5_data c;
96
97    krb5_store_int32(sp, key->key_data_ver);
98    krb5_store_int32(sp, key->key_data_kvno);
99    krb5_store_int32(sp, key->key_data_type[0]);
100
101    /*
102     * This is the key contents.  We want it to be obvious to the client
103     * (if it really did want the keys) that the key won't work.
104     * 32-bit keys are no good for any enctype, so that should do.
105     * Clients that didn't need keys will ignore this, and clients that
106     * did want keys will either fail or they'll, say, create bogus
107     * keytab entries that will subsequently fail to be useful.
108     */
109    c.length = sizeof (KADM5_BOGUS_KEY_DATA) - 1;
110    c.data = KADM5_BOGUS_KEY_DATA;
111    krb5_store_data(sp, c);
112
113    /* This is the salt -- no need to send garbage */
114    krb5_store_int32(sp, key->key_data_type[1]);
115    c.length = key->key_data_length[1];
116    c.data = key->key_data_contents[1];
117    krb5_store_data(sp, c);
118    return 0;
119}
120
121kadm5_ret_t
122kadm5_ret_key_data(krb5_storage *sp,
123		   krb5_key_data *key)
124{
125    krb5_data c;
126    int32_t tmp;
127    krb5_ret_int32(sp, &tmp);
128    key->key_data_ver = tmp;
129    krb5_ret_int32(sp, &tmp);
130    key->key_data_kvno = tmp;
131    krb5_ret_int32(sp, &tmp);
132    key->key_data_type[0] = tmp;
133    krb5_ret_data(sp, &c);
134    key->key_data_length[0] = c.length;
135    key->key_data_contents[0] = c.data;
136    krb5_ret_int32(sp, &tmp);
137    key->key_data_type[1] = tmp;
138    krb5_ret_data(sp, &c);
139    key->key_data_length[1] = c.length;
140    key->key_data_contents[1] = c.data;
141    return 0;
142}
143
144kadm5_ret_t
145kadm5_store_tl_data(krb5_storage *sp,
146		    krb5_tl_data *tl)
147{
148    krb5_data c;
149    krb5_store_int32(sp, tl->tl_data_type);
150    c.length = tl->tl_data_length;
151    c.data = tl->tl_data_contents;
152    krb5_store_data(sp, c);
153    return 0;
154}
155
156kadm5_ret_t
157kadm5_ret_tl_data(krb5_storage *sp,
158		  krb5_tl_data *tl)
159{
160    krb5_data c;
161    int32_t tmp;
162    krb5_ret_int32(sp, &tmp);
163    tl->tl_data_type = tmp;
164    krb5_ret_data(sp, &c);
165    tl->tl_data_length = c.length;
166    tl->tl_data_contents = c.data;
167    return 0;
168}
169
170static kadm5_ret_t
171store_principal_ent(krb5_storage *sp,
172		    kadm5_principal_ent_t princ,
173		    uint32_t mask, int wkeys)
174{
175    int i;
176
177    if (mask & KADM5_PRINCIPAL)
178	krb5_store_principal(sp, princ->principal);
179    if (mask & KADM5_PRINC_EXPIRE_TIME)
180	krb5_store_int32(sp, princ->princ_expire_time);
181    if (mask & KADM5_PW_EXPIRATION)
182	krb5_store_int32(sp, princ->pw_expiration);
183    if (mask & KADM5_LAST_PWD_CHANGE)
184	krb5_store_int32(sp, princ->last_pwd_change);
185    if (mask & KADM5_MAX_LIFE)
186	krb5_store_int32(sp, princ->max_life);
187    if (mask & KADM5_MOD_NAME) {
188	krb5_store_int32(sp, princ->mod_name != NULL);
189	if(princ->mod_name)
190	    krb5_store_principal(sp, princ->mod_name);
191    }
192    if (mask & KADM5_MOD_TIME)
193	krb5_store_int32(sp, princ->mod_date);
194    if (mask & KADM5_ATTRIBUTES)
195	krb5_store_int32(sp, princ->attributes);
196    if (mask & KADM5_KVNO)
197	krb5_store_int32(sp, princ->kvno);
198    if (mask & KADM5_MKVNO)
199	krb5_store_int32(sp, princ->mkvno);
200    if (mask & KADM5_POLICY) {
201	krb5_store_int32(sp, princ->policy != NULL);
202	if(princ->policy)
203	    krb5_store_string(sp, princ->policy);
204    }
205    if (mask & KADM5_AUX_ATTRIBUTES)
206	krb5_store_int32(sp, princ->aux_attributes);
207    if (mask & KADM5_MAX_RLIFE)
208	krb5_store_int32(sp, princ->max_renewable_life);
209    if (mask & KADM5_LAST_SUCCESS)
210	krb5_store_int32(sp, princ->last_success);
211    if (mask & KADM5_LAST_FAILED)
212	krb5_store_int32(sp, princ->last_failed);
213    if (mask & KADM5_FAIL_AUTH_COUNT)
214	krb5_store_int32(sp, princ->fail_auth_count);
215    if (mask & KADM5_KEY_DATA) {
216	krb5_store_int32(sp, princ->n_key_data);
217	for(i = 0; i < princ->n_key_data; i++) {
218	    if (wkeys)
219		kadm5_store_key_data(sp, &princ->key_data[i]);
220	    else
221		kadm5_store_fake_key_data(sp, &princ->key_data[i]);
222	}
223    }
224    if (mask & KADM5_TL_DATA) {
225	krb5_tl_data *tp;
226
227	krb5_store_int32(sp, princ->n_tl_data);
228	for(tp = princ->tl_data; tp; tp = tp->tl_data_next)
229	    kadm5_store_tl_data(sp, tp);
230    }
231    return 0;
232}
233
234
235kadm5_ret_t
236kadm5_store_principal_ent(krb5_storage *sp,
237			  kadm5_principal_ent_t princ)
238{
239    return store_principal_ent (sp, princ, ~0, 1);
240}
241
242kadm5_ret_t
243kadm5_store_principal_ent_nokeys(krb5_storage *sp,
244			        kadm5_principal_ent_t princ)
245{
246    return store_principal_ent (sp, princ, ~0, 0);
247}
248
249kadm5_ret_t
250kadm5_store_principal_ent_mask(krb5_storage *sp,
251			       kadm5_principal_ent_t princ,
252			       uint32_t mask)
253{
254    krb5_store_int32(sp, mask);
255    return store_principal_ent (sp, princ, mask, 1);
256}
257
258static kadm5_ret_t
259ret_principal_ent(krb5_storage *sp,
260		  kadm5_principal_ent_t princ,
261		  uint32_t mask)
262{
263    int i;
264    int32_t tmp;
265
266    if (mask & KADM5_PRINCIPAL)
267	krb5_ret_principal(sp, &princ->principal);
268
269    if (mask & KADM5_PRINC_EXPIRE_TIME) {
270	krb5_ret_int32(sp, &tmp);
271	princ->princ_expire_time = tmp;
272    }
273    if (mask & KADM5_PW_EXPIRATION) {
274	krb5_ret_int32(sp, &tmp);
275	princ->pw_expiration = tmp;
276    }
277    if (mask & KADM5_LAST_PWD_CHANGE) {
278	krb5_ret_int32(sp, &tmp);
279	princ->last_pwd_change = tmp;
280    }
281    if (mask & KADM5_MAX_LIFE) {
282	krb5_ret_int32(sp, &tmp);
283	princ->max_life = tmp;
284    }
285    if (mask & KADM5_MOD_NAME) {
286	krb5_ret_int32(sp, &tmp);
287	if(tmp)
288	    krb5_ret_principal(sp, &princ->mod_name);
289	else
290	    princ->mod_name = NULL;
291    }
292    if (mask & KADM5_MOD_TIME) {
293	krb5_ret_int32(sp, &tmp);
294	princ->mod_date = tmp;
295    }
296    if (mask & KADM5_ATTRIBUTES) {
297	krb5_ret_int32(sp, &tmp);
298	princ->attributes = tmp;
299    }
300    if (mask & KADM5_KVNO) {
301	krb5_ret_int32(sp, &tmp);
302	princ->kvno = tmp;
303    }
304    if (mask & KADM5_MKVNO) {
305	krb5_ret_int32(sp, &tmp);
306	princ->mkvno = tmp;
307    }
308    if (mask & KADM5_POLICY) {
309	krb5_ret_int32(sp, &tmp);
310	if(tmp)
311	    krb5_ret_string(sp, &princ->policy);
312	else
313	    princ->policy = NULL;
314    }
315    if (mask & KADM5_AUX_ATTRIBUTES) {
316	krb5_ret_int32(sp, &tmp);
317	princ->aux_attributes = tmp;
318    }
319    if (mask & KADM5_MAX_RLIFE) {
320	krb5_ret_int32(sp, &tmp);
321	princ->max_renewable_life = tmp;
322    }
323    if (mask & KADM5_LAST_SUCCESS) {
324	krb5_ret_int32(sp, &tmp);
325	princ->last_success = tmp;
326    }
327    if (mask & KADM5_LAST_FAILED) {
328	krb5_ret_int32(sp, &tmp);
329	princ->last_failed = tmp;
330    }
331    if (mask & KADM5_FAIL_AUTH_COUNT) {
332	krb5_ret_int32(sp, &tmp);
333	princ->fail_auth_count = tmp;
334    }
335    if (mask & KADM5_KEY_DATA) {
336	krb5_ret_int32(sp, &tmp);
337	princ->n_key_data = tmp;
338	princ->key_data = malloc(princ->n_key_data * sizeof(*princ->key_data));
339	if (princ->key_data == NULL && princ->n_key_data != 0)
340	    return ENOMEM;
341	for(i = 0; i < princ->n_key_data; i++)
342	    kadm5_ret_key_data(sp, &princ->key_data[i]);
343    }
344    if (mask & KADM5_TL_DATA) {
345	krb5_ret_int32(sp, &tmp);
346	princ->n_tl_data = tmp;
347	princ->tl_data = NULL;
348	for(i = 0; i < princ->n_tl_data; i++){
349	    krb5_tl_data *tp = malloc(sizeof(*tp));
350	    if (tp == NULL)
351		return ENOMEM;
352	    kadm5_ret_tl_data(sp, tp);
353	    tp->tl_data_next = princ->tl_data;
354	    princ->tl_data = tp;
355	}
356    }
357    return 0;
358}
359
360kadm5_ret_t
361kadm5_ret_principal_ent(krb5_storage *sp,
362			kadm5_principal_ent_t princ)
363{
364    return ret_principal_ent (sp, princ, ~0);
365}
366
367kadm5_ret_t
368kadm5_ret_principal_ent_mask(krb5_storage *sp,
369			     kadm5_principal_ent_t princ,
370			     uint32_t *mask)
371{
372    int32_t tmp;
373
374    krb5_ret_int32 (sp, &tmp);
375    *mask = tmp;
376    return ret_principal_ent (sp, princ, *mask);
377}
378
379kadm5_ret_t
380_kadm5_marshal_params(krb5_context context,
381		      kadm5_config_params *params,
382		      krb5_data *out)
383{
384    krb5_storage *sp = krb5_storage_emem();
385
386    krb5_store_int32(sp, params->mask & (KADM5_CONFIG_REALM));
387
388    if(params->mask & KADM5_CONFIG_REALM)
389	krb5_store_string(sp, params->realm);
390    krb5_storage_to_data(sp, out);
391    krb5_storage_free(sp);
392
393    return 0;
394}
395
396kadm5_ret_t
397_kadm5_unmarshal_params(krb5_context context,
398			krb5_data *in,
399			kadm5_config_params *params)
400{
401    krb5_error_code ret;
402    krb5_storage *sp;
403    int32_t mask;
404
405    sp = krb5_storage_from_data(in);
406    if (sp == NULL)
407	return ENOMEM;
408
409    ret = krb5_ret_int32(sp, &mask);
410    if (ret)
411	goto out;
412    params->mask = mask;
413
414    if(params->mask & KADM5_CONFIG_REALM)
415	ret = krb5_ret_string(sp, &params->realm);
416 out:
417    krb5_storage_free(sp);
418
419    return ret;
420}
421