xref: /titanic_50/usr/src/lib/krb5/kadm5/clnt/client_principal.c (revision fa9e4066f08beec538e775443c5be79dd423fcab)
1 /*
2  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 #pragma ident	"%Z%%M%	%I%	%E% SMI"
7 
8 /*
9  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
10  *
11  *	Openvision retains the copyright to derivative works of
12  *	this source code.  Do *NOT* create a derivative of this
13  *	source code before consulting with your legal department.
14  *	Do *NOT* integrate *ANY* of this source code into another
15  *	product before consulting with your legal department.
16  *
17  *	For further information, read the top-level Openvision
18  *	copyright which is contained in the top-level MIT Kerberos
19  *	copyright.
20  *
21  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
22  *
23  */
24 
25 
26 /*
27  * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
28  *
29  * $Header: /cvs/krbdev/krb5/src/lib/kadm5/clnt/client_principal.c,v 1.8 2000/02/27 22:18:15 tlyu Exp $
30  */
31 
32 #if !defined(lint) && !defined(__CODECENTER__)
33 static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/clnt/client_principal.c,v 1.8 2000/02/27 22:18:15 tlyu Exp $";
34 #endif
35 
36 #include    <rpc/rpc.h>  /* SUNWresync121 XXX */
37 #include    <kadm5/admin.h>
38 #include    <kadm5/kadm_rpc.h>
39 #include    <memory.h>
40 #include    "client_internal.h"
41 
42 kadm5_ret_t
43 kadm5_create_principal(void *server_handle,
44 			    kadm5_principal_ent_t princ, long mask,
45 			    char *pw)
46 {
47     generic_ret		*r;
48     cprinc_arg		arg;
49     kadm5_server_handle_t handle = server_handle;
50 
51     CHECK_HANDLE(server_handle);
52 
53     memset(&arg, 0, sizeof(arg));
54     arg.mask = mask;
55     arg.passwd = pw;
56     arg.api_version = handle->api_version;
57 
58     if(princ == NULL)
59 	return EINVAL;
60 
61     if (handle->api_version == KADM5_API_VERSION_1) {
62        memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec_v1));
63     } else {
64        memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec));
65     }
66     if (handle->api_version == KADM5_API_VERSION_1) {
67 	 /*
68 	  * hack hack cough cough.
69 	  * krb5_unparse name dumps core if we pass it in garbage
70 	  * or null. So, since the client is not allowed to set mod_name
71 	  * anyway, we just fill it in with a dummy principal. The server of
72 	  * course ignores this.
73 	  */
74 	/* krb5_parse_name(handle->context, "bogus/bogus", &arg.rec.mod_name); */
75 	 arg.rec.mod_name = NULL;
76     } else
77 	 arg.rec.mod_name = NULL;
78 
79     if(!(mask & KADM5_POLICY))
80 	arg.rec.policy = NULL;
81     if (! (mask & KADM5_KEY_DATA)) {
82 	 arg.rec.n_key_data = 0;
83 	 arg.rec.key_data = NULL;
84     }
85     if (! (mask & KADM5_TL_DATA)) {
86 	 arg.rec.n_tl_data = 0;
87 	 arg.rec.tl_data = NULL;
88     }
89 
90     r = create_principal_1(&arg, handle->clnt);
91 
92     if (handle->api_version == KADM5_API_VERSION_1)
93 	 krb5_free_principal(handle->context, arg.rec.mod_name);
94 
95     if(r == NULL)
96 	return KADM5_RPC_ERROR;
97     return r->code;
98 }
99 
100 kadm5_ret_t
101 kadm5_create_principal_3(void *server_handle,
102 			 kadm5_principal_ent_t princ, long mask,
103 			 int n_ks_tuple,
104 			 krb5_key_salt_tuple *ks_tuple,
105 			 char *pw)
106 {
107     generic_ret		*r;
108     cprinc3_arg		arg;
109     kadm5_server_handle_t handle = server_handle;
110 
111     CHECK_HANDLE(server_handle);
112 
113     memset(&arg, 0, sizeof(arg));
114     arg.mask = mask;
115     arg.passwd = pw;
116     arg.api_version = handle->api_version;
117     arg.n_ks_tuple = n_ks_tuple;
118     arg.ks_tuple = ks_tuple;
119 
120     if(princ == NULL)
121 	return EINVAL;
122 
123     if (handle->api_version == KADM5_API_VERSION_1) {
124        memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec_v1));
125     } else {
126        memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec));
127     }
128     if (handle->api_version == KADM5_API_VERSION_1) {
129 	 /*
130 	  * hack hack cough cough.
131 	  * krb5_unparse name dumps core if we pass it in garbage
132 	  * or null. So, since the client is not allowed to set mod_name
133 	  * anyway, we just fill it in with a dummy principal. The server of
134 	  * course ignores this.
135 	  */
136 	 krb5_parse_name(handle->context, "bogus/bogus", &arg.rec.mod_name);
137     } else
138 	 arg.rec.mod_name = NULL;
139 
140     if(!(mask & KADM5_POLICY))
141 	arg.rec.policy = NULL;
142     if (! (mask & KADM5_KEY_DATA)) {
143 	 arg.rec.n_key_data = 0;
144 	 arg.rec.key_data = NULL;
145     }
146     if (! (mask & KADM5_TL_DATA)) {
147 	 arg.rec.n_tl_data = 0;
148 	 arg.rec.tl_data = NULL;
149     }
150 
151     r = create_principal3_1(&arg, handle->clnt);
152 
153     if (handle->api_version == KADM5_API_VERSION_1)
154 	 krb5_free_principal(handle->context, arg.rec.mod_name);
155 
156     if(r == NULL)
157 	return KADM5_RPC_ERROR;
158     return r->code;
159 }
160 
161 kadm5_ret_t
162 kadm5_delete_principal(void *server_handle, krb5_principal principal)
163 {
164     dprinc_arg		arg;
165     generic_ret		*r;
166     kadm5_server_handle_t handle = server_handle;
167 
168     CHECK_HANDLE(server_handle);
169 
170     if(principal == NULL)
171 	return EINVAL;
172     arg.princ = principal;
173     arg.api_version = handle->api_version;
174     r = delete_principal_1(&arg, handle->clnt);
175     if(r == NULL)
176 	return KADM5_RPC_ERROR;
177     return r->code;
178 }
179 
180 kadm5_ret_t
181 kadm5_modify_principal(void *server_handle,
182 			    kadm5_principal_ent_t princ, long mask)
183 {
184     mprinc_arg		arg;
185     generic_ret		*r;
186     kadm5_server_handle_t handle = server_handle;
187 
188     CHECK_HANDLE(server_handle);
189 
190     memset(&arg, 0, sizeof(arg));
191     arg.mask = mask;
192     arg.api_version = handle->api_version;
193     /*
194      * cough cough gag gag
195      * see comment in create_principal.
196      */
197     if(princ == NULL)
198 	return EINVAL;
199     if (handle->api_version == KADM5_API_VERSION_1) {
200         memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec_v1));
201     } else {
202         memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec));
203     }
204     if(!(mask & KADM5_POLICY))
205 	arg.rec.policy = NULL;
206     if (! (mask & KADM5_KEY_DATA)) {
207 	 arg.rec.n_key_data = 0;
208 	 arg.rec.key_data = NULL;
209     }
210     if (! (mask & KADM5_TL_DATA)) {
211 	 arg.rec.n_tl_data = 0;
212 	 arg.rec.tl_data = NULL;
213     }
214 
215     if (handle->api_version == KADM5_API_VERSION_1) {
216 	 /*
217 	  * See comment in create_principal
218 	  */
219 	 krb5_parse_name(handle->context, "bogus/bogus", &arg.rec.mod_name);
220     } else
221 	 arg.rec.mod_name = NULL;
222 
223     r = modify_principal_1(&arg, handle->clnt);
224 
225     if (handle->api_version == KADM5_API_VERSION_1)
226 	 krb5_free_principal(handle->context, arg.rec.mod_name);
227 
228     if(r == NULL)
229 	return KADM5_RPC_ERROR;
230     return r->code;
231 }
232 
233 kadm5_ret_t
234 kadm5_get_principal(void *server_handle,
235 		    krb5_principal princ, kadm5_principal_ent_t ent,
236 		    long mask)
237 {
238     gprinc_arg	arg;
239     gprinc_ret	*r;
240     kadm5_server_handle_t handle = server_handle;
241 
242     CHECK_HANDLE(server_handle);
243 
244     if(princ == NULL)
245 	return EINVAL;
246     arg.princ = princ;
247     if (handle->api_version == KADM5_API_VERSION_1)
248        arg.mask = KADM5_PRINCIPAL_NORMAL_MASK;
249     else
250        arg.mask = mask;
251     arg.api_version = handle->api_version;
252     r = get_principal_1(&arg, handle->clnt);
253     if(r == NULL)
254 	return KADM5_RPC_ERROR;
255     if (handle->api_version == KADM5_API_VERSION_1) {
256 	 kadm5_principal_ent_t_v1 *entp;
257 
258 	 entp = (kadm5_principal_ent_t_v1 *) ent;
259 	 if (r->code == 0) {
260 	      if (!(*entp = (kadm5_principal_ent_t_v1)
261 		    malloc(sizeof(kadm5_principal_ent_rec_v1))))
262 		   return ENOMEM;
263 	      /* this memcpy works because the v1 structure is an initial
264 		 subset of the v2 struct.  C guarantees that this will
265 		 result in the same layout in memory */
266 	      memcpy(*entp, &r->rec, sizeof(**entp));
267 	 } else {
268 	    *entp = NULL;
269 	 }
270     } else {
271 	 if (r->code == 0)
272 	      memcpy(ent, &r->rec, sizeof(r->rec));
273     }
274 
275     return r->code;
276 }
277 
278 kadm5_ret_t
279 kadm5_get_principals(void *server_handle,
280 			  char *exp, char ***princs, int *count)
281 {
282     gprincs_arg	arg;
283     gprincs_ret	*r;
284     kadm5_server_handle_t handle = server_handle;
285 
286     CHECK_HANDLE(server_handle);
287 
288     if(princs == NULL || count == NULL)
289 	return EINVAL;
290     arg.exp = exp;
291     arg.api_version = handle->api_version;
292     r = get_princs_1(&arg, handle->clnt);
293     if(r == NULL)
294 	return KADM5_RPC_ERROR;
295     if(r->code == 0) {
296 	 *count = r->count;
297 	 *princs = r->princs;
298     } else {
299 	 *count = 0;
300 	 *princs = NULL;
301     }
302 
303     return r->code;
304 }
305 
306 kadm5_ret_t
307 kadm5_rename_principal(void *server_handle,
308 			    krb5_principal source, krb5_principal dest)
309 {
310     rprinc_arg		arg;
311     generic_ret		*r;
312     kadm5_server_handle_t handle = server_handle;
313 
314     CHECK_HANDLE(server_handle);
315 
316     arg.src = source;
317     arg.dest = dest;
318     arg.api_version = handle->api_version;
319     if (source == NULL || dest == NULL)
320 	return EINVAL;
321     r = rename_principal_1(&arg, handle->clnt);
322     if(r == NULL)
323 	return KADM5_RPC_ERROR;
324     return r->code;
325 }
326 
327 kadm5_ret_t
328 kadm5_chpass_principal(void *server_handle,
329 			    krb5_principal princ, char *password)
330 {
331     chpass_arg		arg;
332     generic_ret		*r;
333     kadm5_server_handle_t handle = server_handle;
334 
335     CHECK_HANDLE(server_handle);
336 
337     arg.princ = princ;
338     arg.pass = password;
339     arg.api_version = handle->api_version;
340 
341     if(princ == NULL)
342 	return EINVAL;
343     r = chpass_principal_1(&arg, handle->clnt);
344     if(r == NULL)
345 	return KADM5_RPC_ERROR;
346     return r->code;
347 }
348 
349 kadm5_ret_t
350 kadm5_chpass_principal_3(void *server_handle,
351 			 krb5_principal princ, krb5_boolean keepold,
352 			 int n_ks_tuple, krb5_key_salt_tuple *ks_tuple,
353 			 char *password)
354 {
355     chpass3_arg		arg;
356     generic_ret		*r;
357     kadm5_server_handle_t handle = server_handle;
358 
359     CHECK_HANDLE(server_handle);
360 
361     arg.princ = princ;
362     arg.pass = password;
363     arg.api_version = handle->api_version;
364     arg.keepold = keepold;
365     arg.n_ks_tuple = n_ks_tuple;
366     arg.ks_tuple = ks_tuple;
367 
368     if(princ == NULL)
369 	return EINVAL;
370     r = chpass_principal3_1(&arg, handle->clnt);
371     if(r == NULL)
372 	return KADM5_RPC_ERROR;
373     return r->code;
374 }
375 
376 kadm5_ret_t
377 kadm5_setv4key_principal(void *server_handle,
378 			 krb5_principal princ,
379 			 krb5_keyblock *keyblock)
380 {
381     setv4key_arg	arg;
382     generic_ret		*r;
383     kadm5_server_handle_t handle = server_handle;
384 
385     CHECK_HANDLE(server_handle);
386 
387     arg.princ = princ;
388     arg.keyblock = keyblock;
389     arg.api_version = handle->api_version;
390 
391     if(princ == NULL || keyblock == NULL)
392 	return EINVAL;
393     r = setv4key_principal_1(&arg, handle->clnt);
394     if(r == NULL)
395 	return KADM5_RPC_ERROR;
396     return r->code;
397 }
398 
399 kadm5_ret_t
400 kadm5_setkey_principal(void *server_handle,
401 		       krb5_principal princ,
402 		       krb5_keyblock *keyblocks,
403 		       int n_keys)
404 {
405 
406     setkey_arg		arg;
407     generic_ret		*r;
408     kadm5_server_handle_t handle = server_handle;
409 
410     CHECK_HANDLE(server_handle);
411 
412     arg.princ = princ;
413     arg.keyblocks = keyblocks;
414     arg.n_keys = n_keys;
415     arg.api_version = handle->api_version;
416 
417     if(princ == NULL || keyblocks == NULL)
418 	return EINVAL;
419     r = setkey_principal_1(&arg, handle->clnt);
420     if(r == NULL)
421 	return KADM5_RPC_ERROR;
422     return r->code;
423 }
424 
425 kadm5_ret_t
426 kadm5_setkey_principal_3(void *server_handle,
427 			 krb5_principal princ,
428 			 krb5_boolean keepold, int n_ks_tuple,
429 			 krb5_key_salt_tuple *ks_tuple,
430 			 krb5_keyblock *keyblocks,
431 			 int n_keys)
432 {
433     setkey3_arg		arg;
434     generic_ret		*r;
435     kadm5_server_handle_t handle = server_handle;
436 
437     CHECK_HANDLE(server_handle);
438 
439     arg.princ = princ;
440     arg.keyblocks = keyblocks;
441     arg.n_keys = n_keys;
442     arg.api_version = handle->api_version;
443     arg.keepold = keepold;
444     arg.n_ks_tuple = n_ks_tuple;
445     arg.ks_tuple = ks_tuple;
446 
447     if(princ == NULL || keyblocks == NULL)
448 	return EINVAL;
449     r = setkey_principal3_1(&arg, handle->clnt);
450     if(r == NULL)
451 	return KADM5_RPC_ERROR;
452     return r->code;
453 }
454 
455 /*
456  * Solaris Kerberos:
457  * This routine implements just the "old" randkey_principal code.
458  * The code in the kadmin client sometimes needs to call this
459  * directly when the kadm5_randkey_principal_3 call fails.
460  *
461  * The kadmin client utility uses a specific set of key/salt tuples,
462  * so the standard fallback in kadm5_randkey_principal (see below)
463  * will not work because it would result in kadm5_randkey_principal_3
464  * being called twice - once with the specific key/salts specified by
465  * kadmin and once with the NULL set (used to indicate that the server
466  * should use the full set of supported enctypes).  Making this
467  * routine separate makes the code simpler and avoids making the
468  * kadm5_randkey_principal_3 twice from kadmin.
469  */
470 kadm5_ret_t
471 kadm5_randkey_principal_old(void *server_handle,
472 			krb5_principal princ,
473 			krb5_keyblock **key,
474 			int *n_keys)
475 {
476 	chrand_arg		arg;
477 	chrand_ret		*r;
478 	kadm5_server_handle_t handle = server_handle;
479 	int		i, ret;
480 
481 	/* For safety */
482 	if (n_keys)
483 		*n_keys = 0;
484 	if (key)
485 		*key = NULL;
486 	CHECK_HANDLE(server_handle);
487 
488 	arg.princ = princ;
489 	arg.api_version = handle->api_version;
490 
491 	if(princ == NULL)
492 		return EINVAL;
493 	r = chrand_principal_1(&arg, handle->clnt);
494 	if (r == NULL)
495 		return KADM5_RPC_ERROR;
496 	if (handle->api_version == KADM5_API_VERSION_1) {
497 		if (key)
498 			krb5_copy_keyblock(handle->context, &r->key, key);
499 	} else if (key && (r->n_keys > 0)) {
500 		*key = (krb5_keyblock *) malloc(
501 			r->n_keys*sizeof(krb5_keyblock));
502 		if (*key == NULL)
503 			return ENOMEM;
504 		for (i = 0; i < r->n_keys; i++) {
505 			ret = krb5_copy_keyblock_contents(
506 				handle->context,
507 				&r->keys[i],
508 				&(*key)[i]);
509 			if (ret) {
510 				free(*key);
511 				*key = NULL;
512 				return ENOMEM;
513 			}
514 		}
515 		if (n_keys)
516 			*n_keys = r->n_keys;
517 	}
518 	return (r->code);
519 }
520 
521 kadm5_ret_t
522 kadm5_randkey_principal_3(void *server_handle,
523 			  krb5_principal princ,
524 			  krb5_boolean keepold, int n_ks_tuple,
525 			  krb5_key_salt_tuple *ks_tuple,
526 			  krb5_keyblock **key, int *n_keys)
527 {
528     chrand3_arg		arg;
529     chrand_ret		*r;
530     krb5_keyblock	new;
531     kadm5_server_handle_t handle = server_handle;
532     int			i, ret;
533 
534     /* For safety */
535     if (n_keys)
536 	*n_keys = 0;
537     if (key)
538 	*key = NULL;
539 
540     CHECK_HANDLE(server_handle);
541 
542     arg.princ = princ;
543     arg.api_version = handle->api_version;
544     arg.keepold = keepold;
545     arg.n_ks_tuple = n_ks_tuple;
546     arg.ks_tuple = ks_tuple;
547 
548     if(princ == NULL)
549 	return EINVAL;
550     r = chrand_principal3_1(&arg, handle->clnt);
551     if(r == NULL)
552 	return KADM5_RPC_ERROR;
553     if (handle->api_version == KADM5_API_VERSION_1) {
554 	 if (key)
555 	      krb5_copy_keyblock(handle->context, &r->key, key);
556     } else if (key && (r->n_keys > 0)) {
557 	*key = (krb5_keyblock *)
558 	    malloc(r->n_keys*sizeof(krb5_keyblock));
559 	if (*key == NULL)
560 	    return ENOMEM;
561 	for (i = 0; i < r->n_keys; i++) {
562 	    ret = krb5_copy_keyblock_contents(handle->context,
563 		&r->keys[i],
564 		&(*key)[i]);
565 	    if (ret) {
566 		free(*key);
567 		*key = NULL;
568 		return ENOMEM;
569 	    }
570 	}
571 	if (n_keys)
572 	    *n_keys = r->n_keys;
573     }
574 
575     return r->code;
576 }
577 
578 kadm5_ret_t
579 kadm5_randkey_principal(void *server_handle,
580 			krb5_principal princ,
581 			krb5_keyblock **key, int *n_keys)
582 {
583 
584 	kadm5_ret_t kret;
585 
586 	/*
587 	 * Default to trying the newest API to insure that the full
588 	 * set of enctypes is created.
589 	 */
590 	kret = kadm5_randkey_principal_3(server_handle, princ, FALSE,
591 		0, NULL, key, n_keys);
592 
593 	/*
594 	 * We will get an RPC error if the RPC call failed which
595 	 * will normally indicate that the remote procedure did not
596 	 * exist on the server, so try the older API.
597 	 */
598 	if (kret == KADM5_RPC_ERROR) {
599 		kret = kadm5_randkey_principal_old(server_handle, princ,
600 				key, n_keys);
601 	}
602 	return (kret);
603 }
604 
605 /* not supported on client side */
606 kadm5_ret_t kadm5_decrypt_key(void *server_handle,
607 			      kadm5_principal_ent_t entry, krb5_int32
608 			      ktype, krb5_int32 stype, krb5_int32
609 			      kvno, krb5_keyblock *keyblock,
610 			      krb5_keysalt *keysalt, int *kvnop)
611 {
612      return EINVAL;
613 }
614