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