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