xref: /freebsd/crypto/heimdal/lib/kadm5/marshall.c (revision af23369a6deaaeb612ab266eb88b8bb8d560c322)
1 /*
2  * Copyright (c) 1997 - 1999 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the Institute nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #include "kadm5_locl.h"
35 
36 RCSID("$Id$");
37 #define CHECK(e) do { if (e) return EINVAL; } while (0)
38 
39 kadm5_ret_t
40 kadm5_store_key_data(krb5_storage *sp,
41 		     krb5_key_data *key)
42 {
43     krb5_data c;
44     CHECK(krb5_store_int32(sp, key->key_data_ver));
45     CHECK(krb5_store_int32(sp, key->key_data_kvno));
46     CHECK(krb5_store_int32(sp, key->key_data_type[0]));
47     c.length = key->key_data_length[0];
48     c.data = key->key_data_contents[0];
49     CHECK(krb5_store_data(sp, c));
50     CHECK(krb5_store_int32(sp, key->key_data_type[1]));
51     c.length = key->key_data_length[1];
52     c.data = key->key_data_contents[1];
53     CHECK(krb5_store_data(sp, c));
54     return 0;
55 }
56 
57 kadm5_ret_t
58 kadm5_ret_key_data(krb5_storage *sp,
59 		   krb5_key_data *key)
60 {
61     kadm5_ret_t ret;
62     krb5_data c;
63     int32_t tmp;
64     ret = krb5_ret_int32(sp, &tmp);
65     if (ret == 0) {
66 	key->key_data_ver = tmp;
67 	ret = krb5_ret_int32(sp, &tmp);
68     }
69     if (ret == 0) {
70 	key->key_data_kvno = tmp;
71 	ret = krb5_ret_int32(sp, &tmp);
72     }
73     if (ret == 0) {
74 	key->key_data_type[0] = tmp;
75 	ret = krb5_ret_data(sp, &c);
76     }
77     if (ret == 0) {
78 	key->key_data_length[0] = c.length;
79 	key->key_data_contents[0] = c.data;
80 	ret = krb5_ret_int32(sp, &tmp);
81     }
82     if (ret == 0) {
83 	key->key_data_type[1] = tmp;
84 	ret = krb5_ret_data(sp, &c);
85     }
86     if (ret == 0) {
87 	key->key_data_length[1] = c.length;
88 	key->key_data_contents[1] = c.data;
89 	return 0;
90     }
91     return KADM5_FAILURE;
92 }
93 
94 kadm5_ret_t
95 kadm5_store_tl_data(krb5_storage *sp,
96 		    krb5_tl_data *tl)
97 {
98     krb5_data c;
99     CHECK(krb5_store_int32(sp, tl->tl_data_type));
100     c.length = tl->tl_data_length;
101     c.data = tl->tl_data_contents;
102     CHECK(krb5_store_data(sp, c));
103     return 0;
104 }
105 
106 kadm5_ret_t
107 kadm5_ret_tl_data(krb5_storage *sp,
108 		  krb5_tl_data *tl)
109 {
110     krb5_data c;
111     int32_t tmp;
112     krb5_ret_int32(sp, &tmp);
113     tl->tl_data_type = tmp;
114     CHECK(krb5_ret_data(sp, &c));
115     tl->tl_data_length = c.length;
116     tl->tl_data_contents = c.data;
117     return 0;
118 }
119 
120 static kadm5_ret_t
121 store_principal_ent(krb5_storage *sp,
122 		    kadm5_principal_ent_t princ,
123 		    uint32_t mask)
124 {
125     int i;
126 
127     if (mask & KADM5_PRINCIPAL)
128 	CHECK(krb5_store_principal(sp, princ->principal));
129     if (mask & KADM5_PRINC_EXPIRE_TIME)
130 	CHECK(krb5_store_int32(sp, princ->princ_expire_time));
131     if (mask & KADM5_PW_EXPIRATION)
132 	CHECK(krb5_store_int32(sp, princ->pw_expiration));
133     if (mask & KADM5_LAST_PWD_CHANGE)
134 	CHECK(krb5_store_int32(sp, princ->last_pwd_change));
135     if (mask & KADM5_MAX_LIFE)
136 	CHECK(krb5_store_int32(sp, princ->max_life));
137     if (mask & KADM5_MOD_NAME) {
138 	CHECK(krb5_store_int32(sp, princ->mod_name != NULL));
139 	if(princ->mod_name)
140 	    CHECK(krb5_store_principal(sp, princ->mod_name));
141     }
142     if (mask & KADM5_MOD_TIME)
143 	CHECK(krb5_store_int32(sp, princ->mod_date));
144     if (mask & KADM5_ATTRIBUTES)
145 	CHECK(krb5_store_int32(sp, princ->attributes));
146     if (mask & KADM5_KVNO)
147 	CHECK(krb5_store_int32(sp, princ->kvno));
148     if (mask & KADM5_MKVNO)
149 	CHECK(krb5_store_int32(sp, princ->mkvno));
150     if (mask & KADM5_POLICY) {
151 	CHECK(krb5_store_int32(sp, princ->policy != NULL));
152 	if(princ->policy)
153 	    CHECK(krb5_store_string(sp, princ->policy));
154     }
155     if (mask & KADM5_AUX_ATTRIBUTES)
156 	CHECK(krb5_store_int32(sp, princ->aux_attributes));
157     if (mask & KADM5_MAX_RLIFE)
158 	CHECK(krb5_store_int32(sp, princ->max_renewable_life));
159     if (mask & KADM5_LAST_SUCCESS)
160 	CHECK(krb5_store_int32(sp, princ->last_success));
161     if (mask & KADM5_LAST_FAILED)
162 	CHECK(krb5_store_int32(sp, princ->last_failed));
163     if (mask & KADM5_FAIL_AUTH_COUNT)
164 	CHECK(krb5_store_int32(sp, princ->fail_auth_count));
165     if (mask & KADM5_KEY_DATA) {
166 	CHECK(krb5_store_int32(sp, princ->n_key_data));
167 	for(i = 0; i < princ->n_key_data; i++)
168 	    CHECK(kadm5_store_key_data(sp, &princ->key_data[i]));
169     }
170     if (mask & KADM5_TL_DATA) {
171 	krb5_tl_data *tp;
172 
173 	CHECK(krb5_store_int32(sp, princ->n_tl_data));
174 	for(tp = princ->tl_data; tp; tp = tp->tl_data_next)
175 	    CHECK(kadm5_store_tl_data(sp, tp));
176     }
177     return 0;
178 }
179 
180 
181 kadm5_ret_t
182 kadm5_store_principal_ent(krb5_storage *sp,
183 			  kadm5_principal_ent_t princ)
184 {
185     return store_principal_ent (sp, princ, ~0);
186 }
187 
188 kadm5_ret_t
189 kadm5_store_principal_ent_mask(krb5_storage *sp,
190 			       kadm5_principal_ent_t princ,
191 			       uint32_t mask)
192 {
193     kadm5_ret_t ret;
194 
195     ret = krb5_store_int32(sp, mask);
196     if (ret == 0)
197 	ret = store_principal_ent (sp, princ, mask);
198     return (ret);
199 }
200 
201 static kadm5_ret_t
202 ret_principal_ent(krb5_storage *sp,
203 		  kadm5_principal_ent_t princ,
204 		  uint32_t mask)
205 {
206     int i;
207     int32_t tmp;
208 
209     if (mask & KADM5_PRINCIPAL)
210 	CHECK(krb5_ret_principal(sp, &princ->principal));
211     if (mask & KADM5_PRINC_EXPIRE_TIME) {
212 	CHECK(krb5_ret_int32(sp, &tmp));
213 	princ->princ_expire_time = tmp;
214     }
215     if (mask & KADM5_PW_EXPIRATION) {
216 	CHECK(krb5_ret_int32(sp, &tmp));
217 	princ->pw_expiration = tmp;
218     }
219     if (mask & KADM5_LAST_PWD_CHANGE) {
220 	CHECK(krb5_ret_int32(sp, &tmp));
221 	princ->last_pwd_change = tmp;
222     }
223     if (mask & KADM5_MAX_LIFE) {
224 	CHECK(krb5_ret_int32(sp, &tmp));
225 	princ->max_life = tmp;
226     }
227     if (mask & KADM5_MOD_NAME) {
228 	CHECK(krb5_ret_int32(sp, &tmp));
229 	if(tmp)
230 	    CHECK(krb5_ret_principal(sp, &princ->mod_name));
231 	else
232 	    princ->mod_name = NULL;
233     }
234     if (mask & KADM5_MOD_TIME) {
235 	CHECK(krb5_ret_int32(sp, &tmp));
236 	princ->mod_date = tmp;
237     }
238     if (mask & KADM5_ATTRIBUTES) {
239 	CHECK(krb5_ret_int32(sp, &tmp));
240 	princ->attributes = tmp;
241     }
242     if (mask & KADM5_KVNO) {
243 	CHECK(krb5_ret_int32(sp, &tmp));
244 	princ->kvno = tmp;
245     }
246     if (mask & KADM5_MKVNO) {
247 	CHECK(krb5_ret_int32(sp, &tmp));
248 	princ->mkvno = tmp;
249     }
250     if (mask & KADM5_POLICY) {
251 	CHECK(krb5_ret_int32(sp, &tmp));
252 	if(tmp)
253 	    CHECK(krb5_ret_string(sp, &princ->policy));
254 	else
255 	    princ->policy = NULL;
256     }
257     if (mask & KADM5_AUX_ATTRIBUTES) {
258 	CHECK(krb5_ret_int32(sp, &tmp));
259 	princ->aux_attributes = tmp;
260     }
261     if (mask & KADM5_MAX_RLIFE) {
262 	CHECK(krb5_ret_int32(sp, &tmp));
263 	princ->max_renewable_life = tmp;
264     }
265     if (mask & KADM5_LAST_SUCCESS) {
266 	CHECK(krb5_ret_int32(sp, &tmp));
267 	princ->last_success = tmp;
268     }
269     if (mask & KADM5_LAST_FAILED) {
270 	CHECK(krb5_ret_int32(sp, &tmp));
271 	princ->last_failed = tmp;
272     }
273     if (mask & KADM5_FAIL_AUTH_COUNT) {
274 	CHECK(krb5_ret_int32(sp, &tmp));
275 	princ->fail_auth_count = tmp;
276     }
277     if (mask & KADM5_KEY_DATA) {
278 	CHECK(krb5_ret_int32(sp, &tmp));
279 	princ->n_key_data = tmp;
280 	princ->key_data = malloc(princ->n_key_data * sizeof(*princ->key_data));
281 	if (princ->key_data == NULL && princ->n_key_data != 0)
282 	    return ENOMEM;
283 	for(i = 0; i < princ->n_key_data; i++)
284 	    CHECK(kadm5_ret_key_data(sp, &princ->key_data[i]));
285     }
286     if (mask & KADM5_TL_DATA) {
287 	CHECK(krb5_ret_int32(sp, &tmp));
288 	princ->n_tl_data = tmp;
289 	princ->tl_data = NULL;
290 	for(i = 0; i < princ->n_tl_data; i++){
291 	    krb5_tl_data *tp = malloc(sizeof(*tp));
292 	    if (tp == NULL)
293 		return ENOMEM;
294 	    CHECK(kadm5_ret_tl_data(sp, tp));
295 	    tp->tl_data_next = princ->tl_data;
296 	    princ->tl_data = tp;
297 	}
298     }
299     return 0;
300 }
301 
302 kadm5_ret_t
303 kadm5_ret_principal_ent(krb5_storage *sp,
304 			kadm5_principal_ent_t princ)
305 {
306     return ret_principal_ent (sp, princ, ~0);
307 }
308 
309 kadm5_ret_t
310 kadm5_ret_principal_ent_mask(krb5_storage *sp,
311 			     kadm5_principal_ent_t princ,
312 			     uint32_t *mask)
313 {
314     kadm5_ret_t ret;
315     int32_t tmp;
316 
317     ret = krb5_ret_int32 (sp, &tmp);
318     if (ret) {
319 	*mask = 0;
320 	return (ret);
321     }
322     *mask = tmp;
323     return ret_principal_ent (sp, princ, *mask);
324 }
325 
326 kadm5_ret_t
327 _kadm5_marshal_params(krb5_context context,
328 		      kadm5_config_params *params,
329 		      krb5_data *out)
330 {
331     kadm5_ret_t ret;
332 
333     krb5_storage *sp = krb5_storage_emem();
334 
335     ret = krb5_store_int32(sp, params->mask & (KADM5_CONFIG_REALM));
336 
337     if (ret == 0 && params->mask & KADM5_CONFIG_REALM)
338 	ret = krb5_store_string(sp, params->realm);
339     if (ret == 0)
340 	krb5_storage_to_data(sp, out);
341     krb5_storage_free(sp);
342 
343     return (ret);
344 }
345 
346 kadm5_ret_t
347 _kadm5_unmarshal_params(krb5_context context,
348 			krb5_data *in,
349 			kadm5_config_params *params)
350 {
351     krb5_error_code ret;
352     krb5_storage *sp;
353     int32_t mask;
354 
355     sp = krb5_storage_from_data(in);
356     if (sp == NULL)
357 	return ENOMEM;
358 
359     ret = krb5_ret_int32(sp, &mask);
360     if (ret)
361 	goto out;
362     if (mask & KADM5_CONFIG_REALM & KADM5_CONFIG_DBNAME
363 	& KADM5_CONFIG_ACL_FILE & KADM5_CONFIG_STASH_FILE) {
364 	    ret = EINVAL;
365 	    goto out;
366     }
367     params->mask = mask;
368 
369     if (params->mask & KADM5_CONFIG_REALM) {
370 	ret = krb5_ret_string(sp, &params->realm);
371 	if (params->realm == NULL) {
372 	    ret = EINVAL;
373 	    goto out;
374 	}
375     }
376     if (params->mask & KADM5_CONFIG_DBNAME) {
377 	ret = krb5_ret_string(sp, &params->dbname);
378 	if (params->dbname == NULL) {
379 	    ret = EINVAL;
380 	    goto out;
381 	}
382     }
383     if (params->mask & KADM5_CONFIG_ACL_FILE) {
384 	ret = krb5_ret_string(sp, &params->acl_file);
385 	if (params->acl_file == NULL) {
386 	    ret = EINVAL;
387 	    goto out;
388 	}
389     }
390     if (params->mask & KADM5_CONFIG_STASH_FILE) {
391 	ret = krb5_ret_string(sp, &params->stash_file);
392 	if (params->stash_file == NULL) {
393 	    ret = EINVAL;
394 	}
395     }
396  out:
397     krb5_storage_free(sp);
398 
399     return ret;
400 }
401