1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
10 #define USE_KADM5_API_VERSION 2
11 #include <kadm5/admin.h>
16 #include "tcl_kadm5.h"
23 /* XXX This should probably be in the hash table like server_handle */
24 static krb5_context context;
26 static struct flagval krb5_flags_array[] = {
27 {"KRB5_KDB_DISALLOW_POSTDATED", KRB5_KDB_DISALLOW_POSTDATED},
28 {"KRB5_KDB_DISALLOW_FORWARDABLE", KRB5_KDB_DISALLOW_FORWARDABLE},
29 {"KRB5_KDB_DISALLOW_TGT_BASED", KRB5_KDB_DISALLOW_TGT_BASED},
30 {"KRB5_KDB_DISALLOW_RENEWABLE", KRB5_KDB_DISALLOW_RENEWABLE},
31 {"KRB5_KDB_DISALLOW_PROXIABLE", KRB5_KDB_DISALLOW_PROXIABLE},
32 {"KRB5_KDB_DISALLOW_DUP_SKEY", KRB5_KDB_DISALLOW_DUP_SKEY},
33 {"KRB5_KDB_DISALLOW_ALL_TIX", KRB5_KDB_DISALLOW_ALL_TIX},
34 {"KRB5_KDB_REQUIRES_PRE_AUTH", KRB5_KDB_REQUIRES_PRE_AUTH},
35 {"KRB5_KDB_REQUIRES_HW_AUTH", KRB5_KDB_REQUIRES_HW_AUTH},
36 {"KRB5_KDB_REQUIRES_PWCHANGE", KRB5_KDB_REQUIRES_PWCHANGE},
37 {"KRB5_KDB_DISALLOW_SVR", KRB5_KDB_DISALLOW_SVR},
38 {"KRB5_KDB_PWCHANGE_SERVICE", KRB5_KDB_PWCHANGE_SERVICE}
41 static struct flagval aux_attributes[] = {
42 {"KADM5_POLICY", KADM5_POLICY}
45 static struct flagval principal_mask_flags[] = {
46 {"KADM5_PRINCIPAL", KADM5_PRINCIPAL},
47 {"KADM5_PRINC_EXPIRE_TIME", KADM5_PRINC_EXPIRE_TIME},
48 {"KADM5_PW_EXPIRATION", KADM5_PW_EXPIRATION},
49 {"KADM5_LAST_PWD_CHANGE", KADM5_LAST_PWD_CHANGE},
50 {"KADM5_ATTRIBUTES", KADM5_ATTRIBUTES},
51 {"KADM5_MAX_LIFE", KADM5_MAX_LIFE},
52 {"KADM5_MOD_TIME", KADM5_MOD_TIME},
53 {"KADM5_MOD_NAME", KADM5_MOD_NAME},
54 {"KADM5_KVNO", KADM5_KVNO},
55 {"KADM5_MKVNO", KADM5_MKVNO},
56 {"KADM5_AUX_ATTRIBUTES", KADM5_AUX_ATTRIBUTES},
57 {"KADM5_POLICY", KADM5_POLICY},
58 {"KADM5_POLICY_CLR", KADM5_POLICY_CLR},
59 {"KADM5_MAX_RLIFE", KADM5_MAX_RLIFE},
60 {"KADM5_LAST_SUCCESS", KADM5_LAST_SUCCESS},
61 {"KADM5_LAST_FAILED", KADM5_LAST_FAILED},
62 {"KADM5_FAIL_AUTH_COUNT", KADM5_FAIL_AUTH_COUNT},
63 {"KADM5_KEY_DATA", KADM5_KEY_DATA},
64 {"KADM5_TL_DATA", KADM5_TL_DATA},
65 {"KADM5_PRINCIPAL_NORMAL_MASK", KADM5_PRINCIPAL_NORMAL_MASK}
68 static struct flagval policy_mask_flags[] = {
69 {"KADM5_POLICY", KADM5_POLICY},
70 {"KADM5_PW_MAX_LIFE", KADM5_PW_MAX_LIFE},
71 {"KADM5_PW_MIN_LIFE", KADM5_PW_MIN_LIFE},
72 {"KADM5_PW_MIN_LENGTH", KADM5_PW_MIN_LENGTH},
73 {"KADM5_PW_MIN_CLASSES", KADM5_PW_MIN_CLASSES},
74 {"KADM5_PW_HISTORY_NUM", KADM5_PW_HISTORY_NUM},
75 {"KADM5_REF_COUNT", KADM5_REF_COUNT},
76 {"KADM5_PW_MAX_FAILURE", KADM5_PW_MAX_FAILURE},
77 {"KADM5_PW_FAILURE_COUNT_INTERVAL", KADM5_PW_FAILURE_COUNT_INTERVAL},
78 {"KADM5_PW_LOCKOUT_DURATION", KADM5_PW_LOCKOUT_DURATION},
81 static struct flagval config_mask_flags[] = {
82 {"KADM5_CONFIG_REALM", KADM5_CONFIG_REALM},
83 {"KADM5_CONFIG_DBNAME", KADM5_CONFIG_DBNAME},
84 {"KADM5_CONFIG_MKEY_NAME", KADM5_CONFIG_MKEY_NAME},
85 {"KADM5_CONFIG_MAX_LIFE", KADM5_CONFIG_MAX_LIFE},
86 {"KADM5_CONFIG_MAX_RLIFE", KADM5_CONFIG_MAX_RLIFE},
87 {"KADM5_CONFIG_EXPIRATION", KADM5_CONFIG_EXPIRATION},
88 {"KADM5_CONFIG_FLAGS", KADM5_CONFIG_FLAGS},
89 {"KADM5_CONFIG_STASH_FILE", KADM5_CONFIG_STASH_FILE},
90 {"KADM5_CONFIG_ENCTYPE", KADM5_CONFIG_ENCTYPE},
91 {"KADM5_CONFIG_ADBNAME", KADM5_CONFIG_ADBNAME},
92 {"KADM5_CONFIG_ADB_LOCKFILE", KADM5_CONFIG_ADB_LOCKFILE},
93 {"KADM5_CONFIG_ACL_FILE", KADM5_CONFIG_ACL_FILE},
94 {"KADM5_CONFIG_KADMIND_PORT", KADM5_CONFIG_KADMIND_PORT},
95 {"KADM5_CONFIG_ENCTYPES", KADM5_CONFIG_ENCTYPES},
96 {"KADM5_CONFIG_ADMIN_SERVER", KADM5_CONFIG_ADMIN_SERVER},
97 {"KADM5_CONFIG_DICT_FILE", KADM5_CONFIG_DICT_FILE},
98 {"KADM5_CONFIG_MKEY_FROM_KBD", KADM5_CONFIG_MKEY_FROM_KBD},
101 static struct flagval priv_flags[] = {
102 {"KADM5_PRIV_GET", KADM5_PRIV_GET},
103 {"KADM5_PRIV_ADD", KADM5_PRIV_ADD},
104 {"KADM5_PRIV_MODIFY", KADM5_PRIV_MODIFY},
105 {"KADM5_PRIV_DELETE", KADM5_PRIV_DELETE}
109 static char *arg_error = "wrong # args";
111 static Tcl_HashTable *struct_table = 0;
113 static int put_server_handle(Tcl_Interp *interp, void *handle, char **name)
115 int i = 1, newPtr = 0;
117 Tcl_HashEntry *entry;
119 if (! struct_table) {
120 if (! (struct_table =
121 malloc(sizeof(*struct_table)))) {
122 fprintf(stderr, "Out of memory!\n");
125 Tcl_InitHashTable(struct_table, TCL_STRING_KEYS);
129 sprintf(buf, "kadm5_handle%d", i);
130 entry = Tcl_CreateHashEntry(struct_table, buf, &newPtr);
134 Tcl_SetHashValue(entry, handle);
141 static int get_server_handle(Tcl_Interp *interp, const char *name,
144 Tcl_HashEntry *entry;
146 if(!strcasecmp(name, "null"))
149 if (! (struct_table &&
150 (entry = Tcl_FindHashEntry(struct_table, name)))) {
151 Tcl_AppendResult(interp, "unknown server handle ", name, 0);
154 *handle = (void *) Tcl_GetHashValue(entry);
159 static int remove_server_handle(Tcl_Interp *interp, const char *name)
161 Tcl_HashEntry *entry;
163 if (! (struct_table &&
164 (entry = Tcl_FindHashEntry(struct_table, name)))) {
165 Tcl_AppendResult(interp, "unknown server handle ", name, 0);
169 Tcl_SetHashValue(entry, NULL);
173 #define GET_HANDLE(num_args, ignored) \
174 void *server_handle; \
175 const char *whoami = argv[0]; \
177 if (argc != num_args + 1) { \
178 Tcl_AppendResult(interp, whoami, ": ", arg_error, 0); \
183 if ((ltcl_ret = get_server_handle(interp, argv[0], &server_handle)) \
190 static Tcl_HashTable *create_flag_table(struct flagval *flags, int size)
192 Tcl_HashTable *table;
193 Tcl_HashEntry *entry;
196 if (! (table = (Tcl_HashTable *) malloc(sizeof(Tcl_HashTable)))) {
197 fprintf(stderr, "Out of memory!\n");
201 Tcl_InitHashTable(table, TCL_STRING_KEYS);
203 for (i = 0; i < size; i++) {
206 if (! (entry = Tcl_CreateHashEntry(table, flags[i].name, &newPtr))) {
207 fprintf(stderr, "Out of memory!\n");
211 Tcl_SetHashValue(entry, &flags[i].val);
218 static Tcl_DString *unparse_str(char *in_str)
222 if (! (str = malloc(sizeof(*str)))) {
223 fprintf(stderr, "Out of memory!\n");
227 Tcl_DStringInit(str);
230 Tcl_DStringAppend(str, "null", -1);
233 Tcl_DStringAppend(str, in_str, -1);
241 static int parse_str(Tcl_Interp *interp, const char *in_str, char **out_str)
246 else if (! strcasecmp(in_str, "null")) {
250 *out_str = (char *) in_str;
256 static void set_ok(Tcl_Interp *interp, char *string)
258 Tcl_SetResult(interp, "OK", TCL_STATIC);
259 Tcl_AppendElement(interp, "KADM5_OK");
260 Tcl_AppendElement(interp, string);
265 static Tcl_DString *unparse_err(kadm5_ret_t code)
268 const char *error_string;
269 Tcl_DString *dstring;
272 case KADM5_FAILURE: code_string = "KADM5_FAILURE"; break;
273 case KADM5_AUTH_GET: code_string = "KADM5_AUTH_GET"; break;
274 case KADM5_AUTH_ADD: code_string = "KADM5_AUTH_ADD"; break;
275 case KADM5_AUTH_MODIFY:
276 code_string = "KADM5_AUTH_MODIFY"; break;
277 case KADM5_AUTH_DELETE:
278 code_string = "KADM5_AUTH_DELETE"; break;
279 case KADM5_AUTH_INSUFFICIENT:
280 code_string = "KADM5_AUTH_INSUFFICIENT"; break;
281 case KADM5_BAD_DB: code_string = "KADM5_BAD_DB"; break;
282 case KADM5_DUP: code_string = "KADM5_DUP"; break;
283 case KADM5_RPC_ERROR: code_string = "KADM5_RPC_ERROR"; break;
284 case KADM5_NO_SRV: code_string = "KADM5_NO_SRV"; break;
285 case KADM5_BAD_HIST_KEY:
286 code_string = "KADM5_BAD_HIST_KEY"; break;
287 case KADM5_NOT_INIT: code_string = "KADM5_NOT_INIT"; break;
288 case KADM5_INIT: code_string = "KADM5_INIT"; break;
289 case KADM5_BAD_PASSWORD:
290 code_string = "KADM5_BAD_PASSWORD"; break;
291 case KADM5_UNK_PRINC: code_string = "KADM5_UNK_PRINC"; break;
292 case KADM5_UNK_POLICY: code_string = "KADM5_UNK_POLICY"; break;
293 case KADM5_BAD_MASK: code_string = "KADM5_BAD_MASK"; break;
294 case KADM5_BAD_CLASS: code_string = "KADM5_BAD_CLASS"; break;
295 case KADM5_BAD_LENGTH: code_string = "KADM5_BAD_LENGTH"; break;
296 case KADM5_BAD_POLICY: code_string = "KADM5_BAD_POLICY"; break;
297 case KADM5_BAD_HISTORY: code_string = "KADM5_BAD_HISTORY"; break;
298 case KADM5_BAD_PRINCIPAL:
299 code_string = "KADM5_BAD_PRINCIPAL"; break;
300 case KADM5_BAD_AUX_ATTR:
301 code_string = "KADM5_BAD_AUX_ATTR"; break;
302 case KADM5_PASS_Q_TOOSHORT:
303 code_string = "KADM5_PASS_Q_TOOSHORT"; break;
304 case KADM5_PASS_Q_CLASS:
305 code_string = "KADM5_PASS_Q_CLASS"; break;
306 case KADM5_PASS_Q_DICT:
307 code_string = "KADM5_PASS_Q_DICT"; break;
308 case KADM5_PASS_REUSE: code_string = "KADM5_PASS_REUSE"; break;
309 case KADM5_PASS_TOOSOON:
310 code_string = "KADM5_PASS_TOOSOON"; break;
311 case KADM5_POLICY_REF:
312 code_string = "KADM5_POLICY_REF"; break;
313 case KADM5_PROTECT_PRINCIPAL:
314 code_string = "KADM5_PROTECT_PRINCIPAL"; break;
315 case KADM5_BAD_SERVER_HANDLE:
316 code_string = "KADM5_BAD_SERVER_HANDLE"; break;
317 case KADM5_BAD_STRUCT_VERSION:
318 code_string = "KADM5_BAD_STRUCT_VERSION"; break;
319 case KADM5_OLD_STRUCT_VERSION:
320 code_string = "KADM5_OLD_STRUCT_VERSION"; break;
321 case KADM5_NEW_STRUCT_VERSION:
322 code_string = "KADM5_NEW_STRUCT_VERSION"; break;
323 case KADM5_BAD_API_VERSION:
324 code_string = "KADM5_BAD_API_VERSION"; break;
325 case KADM5_OLD_LIB_API_VERSION:
326 code_string = "KADM5_OLD_LIB_API_VERSION"; break;
327 case KADM5_OLD_SERVER_API_VERSION:
328 code_string = "KADM5_OLD_SERVER_API_VERSION"; break;
329 case KADM5_NEW_LIB_API_VERSION:
330 code_string = "KADM5_NEW_LIB_API_VERSION"; break;
331 case KADM5_NEW_SERVER_API_VERSION:
332 code_string = "KADM5_NEW_SERVER_API_VERSION"; break;
333 case KADM5_SECURE_PRINC_MISSING:
334 code_string = "KADM5_SECURE_PRINC_MISSING"; break;
335 case KADM5_NO_RENAME_SALT:
336 code_string = "KADM5_NO_RENAME_SALT"; break;
337 case KADM5_BAD_CLIENT_PARAMS:
338 code_string = "KADM5_BAD_CLIENT_PARAMS"; break;
339 case KADM5_BAD_SERVER_PARAMS:
340 code_string = "KADM5_BAD_SERVER_PARAMS"; break;
341 case KADM5_AUTH_LIST:
342 code_string = "KADM5_AUTH_LIST"; break;
343 case KADM5_AUTH_CHANGEPW:
344 code_string = "KADM5_AUTH_CHANGEPW"; break;
345 case KADM5_GSS_ERROR: code_string = "KADM5_GSS_ERROR"; break;
346 case KADM5_BAD_TL_TYPE: code_string = "KADM5_BAD_TL_TYPE"; break;
347 case KADM5_MISSING_CONF_PARAMS:
348 code_string = "KADM5_MISSING_CONF_PARAMS"; break;
349 case KADM5_BAD_SERVER_NAME:
350 code_string = "KADM5_BAD_SERVER_NAME"; break;
351 case KADM5_MISSING_KRB5_CONF_PARAMS:
352 code_string = "KADM5_MISSING_KRB5_CONF_PARAMS"; break;
353 case KADM5_XDR_FAILURE: code_string = "KADM5_XDR_FAILURE"; break;
354 case KADM5_CANT_RESOLVE: code_string = "KADM5_CANT_RESOLVE"; break;
357 case OSA_ADB_DUP: code_string = "OSA_ADB_DUP"; break;
358 case OSA_ADB_NOENT: code_string = "ENOENT"; break;
359 case OSA_ADB_DBINIT: code_string = "OSA_ADB_DBINIT"; break;
360 case OSA_ADB_BAD_POLICY: code_string = "Bad policy name"; break;
361 case OSA_ADB_BAD_PRINC: code_string = "Bad principal name"; break;
362 case OSA_ADB_BAD_DB: code_string = "Invalid database."; break;
363 case OSA_ADB_XDR_FAILURE: code_string = "OSA_ADB_XDR_FAILURE"; break;
364 case OSA_ADB_BADLOCKMODE: code_string = "OSA_ADB_BADLOCKMODE"; break;
365 case OSA_ADB_CANTLOCK_DB: code_string = "OSA_ADB_CANTLOCK_DB"; break;
366 case OSA_ADB_NOTLOCKED: code_string = "OSA_ADB_NOTLOCKED"; break;
367 case OSA_ADB_NOLOCKFILE: code_string = "OSA_ADB_NOLOCKFILE"; break;
368 case OSA_ADB_NOEXCL_PERM: code_string = "OSA_ADB_NOEXCL_PERM"; break;
370 case KRB5_KDB_INUSE: code_string = "KRB5_KDB_INUSE"; break;
371 case KRB5_KDB_UK_SERROR: code_string = "KRB5_KDB_UK_SERROR"; break;
372 case KRB5_KDB_UK_RERROR: code_string = "KRB5_KDB_UK_RERROR"; break;
373 case KRB5_KDB_UNAUTH: code_string = "KRB5_KDB_UNAUTH"; break;
374 case KRB5_KDB_NOENTRY: code_string = "KRB5_KDB_NOENTRY"; break;
375 case KRB5_KDB_ILL_WILDCARD: code_string = "KRB5_KDB_ILL_WILDCARD"; break;
376 case KRB5_KDB_DB_INUSE: code_string = "KRB5_KDB_DB_INUSE"; break;
377 case KRB5_KDB_DB_CHANGED: code_string = "KRB5_KDB_DB_CHANGED"; break;
378 case KRB5_KDB_TRUNCATED_RECORD:
379 code_string = "KRB5_KDB_TRUNCATED_RECORD"; break;
380 case KRB5_KDB_RECURSIVELOCK:
381 code_string = "KRB5_KDB_RECURSIVELOCK"; break;
382 case KRB5_KDB_NOTLOCKED: code_string = "KRB5_KDB_NOTLOCKED"; break;
383 case KRB5_KDB_BADLOCKMODE: code_string = "KRB5_KDB_BADLOCKMODE"; break;
384 case KRB5_KDB_DBNOTINITED: code_string = "KRB5_KDB_DBNOTINITED"; break;
385 case KRB5_KDB_DBINITED: code_string = "KRB5_KDB_DBINITED"; break;
386 case KRB5_KDB_ILLDIRECTION: code_string = "KRB5_KDB_ILLDIRECTION"; break;
387 case KRB5_KDB_NOMASTERKEY: code_string = "KRB5_KDB_NOMASTERKEY"; break;
388 case KRB5_KDB_BADMASTERKEY: code_string = "KRB5_KDB_BADMASTERKEY"; break;
389 case KRB5_KDB_INVALIDKEYSIZE:
390 code_string = "KRB5_KDB_INVALIDKEYSIZE"; break;
391 case KRB5_KDB_CANTREAD_STORED:
392 code_string = "KRB5_KDB_CANTREAD_STORED"; break;
393 case KRB5_KDB_BADSTORED_MKEY:
394 code_string = "KRB5_KDB_BADSTORED_MKEY"; break;
395 case KRB5_KDB_CANTLOCK_DB: code_string = "KRB5_KDB_CANTLOCK_DB"; break;
396 case KRB5_KDB_DB_CORRUPT: code_string = "KRB5_KDB_DB_CORRUPT"; break;
398 case KRB5_PARSE_ILLCHAR: code_string = "KRB5_PARSE_ILLCHAR"; break;
399 case KRB5_PARSE_MALFORMED: code_string = "KRB5_PARSE_MALFORMED"; break;
400 case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN: code_string = "KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN"; break;
401 case KRB5_REALM_UNKNOWN: code_string = "KRB5_REALM_UNKNOWN"; break;
402 case KRB5_KDC_UNREACH: code_string = "KRB5_KDC_UNREACH"; break;
403 case KRB5_KDCREP_MODIFIED: code_string = "KRB5_KDCREP_MODIFIED"; break;
404 case KRB5KRB_AP_ERR_BAD_INTEGRITY: code_string = "KRB5KRB_AP_ERR_BAD_INTEGRITY"; break;
405 case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN: code_string = "KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN"; break;
406 case KRB5_CONFIG_BADFORMAT: code_string = "KRB5_CONFIG_BADFORMAT"; break;
408 case KRB5_CC_NOTFOUND: code_string = "KRB5_CC_NOTFOUND"; break;
409 case KRB5_FCC_NOFILE: code_string = "KRB5_FCC_NOFILE"; break;
411 case EINVAL: code_string = "EINVAL"; break;
412 case ENOENT: code_string = "ENOENT"; break;
415 fprintf(stderr, "**** CODE %ld (%s) ***\n", (long) code,
416 error_message (code));
417 code_string = "UNKNOWN";
421 error_string = error_message(code);
423 if (! (dstring = (Tcl_DString *) malloc(sizeof(Tcl_DString)))) {
424 fprintf(stderr, "Out of memory!\n");
425 exit(1); /* XXX Do we really want to exit? Ok if this is */
426 /* just a test program, but what about if it gets */
427 /* used for other things later? */
430 Tcl_DStringInit(dstring);
432 if (! (Tcl_DStringAppendElement(dstring, "ERROR") &&
433 Tcl_DStringAppendElement(dstring, code_string) &&
434 Tcl_DStringAppendElement(dstring, error_string))) {
435 fprintf(stderr, "Out of memory!\n");
444 static void stash_error(Tcl_Interp *interp, krb5_error_code code)
446 Tcl_DString *dstring = unparse_err(code);
447 Tcl_DStringResult(interp, dstring);
448 Tcl_DStringFree(dstring);
452 static Tcl_DString *unparse_key_data(krb5_key_data *key_data, int n_key_data)
458 if (! (str = malloc(sizeof(*str)))) {
459 fprintf(stderr, "Out of memory!\n");
463 Tcl_DStringInit(str);
464 for (i = 0; i < n_key_data; i++) {
465 krb5_key_data *key = &key_data[i];
467 Tcl_DStringStartSublist(str);
468 sprintf(buf, "%d", key->key_data_type[0]);
469 Tcl_DStringAppendElement(str, buf);
470 sprintf(buf, "%d", key->key_data_ver > 1 ?
471 key->key_data_type[1] : -1);
472 Tcl_DStringAppendElement(str, buf);
473 if (key->key_data_contents[0]) {
475 for (j = 0; j < key->key_data_length[0]; j++) {
476 sprintf(buf + 2*(j+1), "%02x",
477 key->key_data_contents[0][j]);
480 Tcl_DStringAppendElement(str, buf);
481 Tcl_DStringEndSublist(str);
487 static Tcl_DString *unparse_tl_data(krb5_tl_data *tl_data, int n_tl_data)
492 if (! (str = malloc(sizeof(*str)))) {
493 fprintf(stderr, "Out of memory!\n");
497 Tcl_DStringInit(str);
498 Tcl_DStringStartSublist(str);
499 for (; tl_data; tl_data = tl_data->tl_data_next) {
500 Tcl_DStringStartSublist(str);
501 sprintf(buf, "%d", tl_data->tl_data_type);
502 Tcl_DStringAppendElement(str, buf);
503 sprintf(buf, "%d", tl_data->tl_data_length);
504 Tcl_DStringAppendElement(str, buf);
505 Tcl_DStringAppend(str, " ", 1);
506 Tcl_DStringAppend(str, (char *) tl_data->tl_data_contents,
507 tl_data->tl_data_length);
508 Tcl_DStringEndSublist(str);
510 Tcl_DStringEndSublist(str);
515 static Tcl_DString *unparse_flags(struct flagval *array, int size,
521 if (! (str = malloc(sizeof(*str)))) {
522 fprintf(stderr, "Out of memory!\n");
526 Tcl_DStringInit(str);
528 for (i = 0; i < size; i++) {
529 if (flags & array[i].val) {
530 Tcl_DStringAppendElement(str, array[i].name);
538 static int parse_flags(Tcl_Interp *interp, Tcl_HashTable *table,
539 struct flagval *array, int size, const char *str,
542 int tmp, argc, i, retcode = TCL_OK;
544 Tcl_HashEntry *entry;
546 if (Tcl_GetInt(interp, str, &tmp) == TCL_OK) {
550 Tcl_ResetResult(interp);
552 if (Tcl_SplitList(interp, str, &argc, &argv) != TCL_OK) {
557 table = create_flag_table(array, size);
562 for (i = 0; i < argc; i++) {
563 if (! (entry = Tcl_FindHashEntry(table, argv[i]))) {
564 Tcl_AppendResult(interp, "unknown krb5 flag ", argv[i], 0);
568 *flags |= *(krb5_flags *) Tcl_GetHashValue(entry);
571 Tcl_Free((char *) argv);
575 static Tcl_DString *unparse_privs(krb5_flags flags)
577 return unparse_flags(priv_flags, sizeof(priv_flags) /
578 sizeof(struct flagval), flags);
582 static Tcl_DString *unparse_krb5_flags(krb5_flags flags)
584 return unparse_flags(krb5_flags_array, sizeof(krb5_flags_array) /
585 sizeof(struct flagval), flags);
588 static int parse_krb5_flags(Tcl_Interp *interp, const char *str,
592 static Tcl_HashTable *table = 0;
595 if ((tcl_ret = parse_flags(interp, table, krb5_flags_array,
596 sizeof(krb5_flags_array) /
597 sizeof(struct flagval),
598 str, &tmp)) != TCL_OK) {
606 static Tcl_DString *unparse_aux_attributes(krb5_int32 flags)
608 return unparse_flags(aux_attributes, sizeof(aux_attributes) /
609 sizeof(struct flagval), flags);
613 static int parse_aux_attributes(Tcl_Interp *interp, const char *str,
617 static Tcl_HashTable *table = 0;
620 if ((tcl_ret = parse_flags(interp, table, aux_attributes,
621 sizeof(aux_attributes) /
622 sizeof(struct flagval),
623 str, &tmp)) != TCL_OK) {
631 static int parse_principal_mask(Tcl_Interp *interp, const char *str,
635 static Tcl_HashTable *table = 0;
638 if ((tcl_ret = parse_flags(interp, table, principal_mask_flags,
639 sizeof(principal_mask_flags) /
640 sizeof(struct flagval),
641 str, &tmp)) != TCL_OK) {
649 static int parse_policy_mask(Tcl_Interp *interp, const char *str,
653 static Tcl_HashTable *table = 0;
656 if ((tcl_ret = parse_flags(interp, table, policy_mask_flags,
657 sizeof(policy_mask_flags) /
658 sizeof(struct flagval),
659 str, &tmp)) != TCL_OK) {
668 static Tcl_DString *unparse_principal_ent(kadm5_principal_ent_t princ,
671 Tcl_DString *str, *tmp_dstring;
674 krb5_error_code krb5_ret;
676 if (! (str = malloc(sizeof(*str)))) {
677 fprintf(stderr, "Out of memory!\n");
681 Tcl_DStringInit(str);
683 tmp = 0; /* It looks to me from looking at the library source */
684 /* code for krb5_parse_name that the pointer passed into */
685 /* it should be initialized to 0 if I want it do be */
686 /* allocated automatically. */
687 if (mask & KADM5_PRINCIPAL) {
688 krb5_ret = krb5_unparse_name(context, princ->principal, &tmp);
690 /* XXX Do we want to return an error? Not sure. */
691 Tcl_DStringAppendElement(str, "[unparseable principal]");
694 Tcl_DStringAppendElement(str, tmp);
698 Tcl_DStringAppendElement(str, "null");
700 sprintf(buf, "%d", princ->princ_expire_time);
701 Tcl_DStringAppendElement(str, buf);
703 sprintf(buf, "%d", princ->last_pwd_change);
704 Tcl_DStringAppendElement(str, buf);
706 sprintf(buf, "%d", princ->pw_expiration);
707 Tcl_DStringAppendElement(str, buf);
709 sprintf(buf, "%d", princ->max_life);
710 Tcl_DStringAppendElement(str, buf);
713 if (mask & KADM5_MOD_NAME) {
714 if ((krb5_ret = krb5_unparse_name(context, princ->mod_name, &tmp))) {
716 Tcl_DStringAppendElement(str, "[unparseable principal]");
719 Tcl_DStringAppendElement(str, tmp);
723 Tcl_DStringAppendElement(str, "null");
725 sprintf(buf, "%d", princ->mod_date);
726 Tcl_DStringAppendElement(str, buf);
728 if (mask & KADM5_ATTRIBUTES) {
729 tmp_dstring = unparse_krb5_flags(princ->attributes);
730 Tcl_DStringAppendElement(str, tmp_dstring->string);
731 Tcl_DStringFree(tmp_dstring);
734 Tcl_DStringAppendElement(str, "null");
736 sprintf(buf, "%d", princ->kvno);
737 Tcl_DStringAppendElement(str, buf);
739 sprintf(buf, "%d", princ->mkvno);
740 Tcl_DStringAppendElement(str, buf);
742 /* XXX This may be dangerous, because the contents of the policy */
743 /* field are undefined if the POLICY bit isn't set. However, I */
744 /* think it's a bug for the field not to be null in that case */
745 /* anyway, so we should assume that it will be null so that we'll */
746 /* catch it if it isn't. */
748 tmp_dstring = unparse_str(princ->policy);
749 Tcl_DStringAppendElement(str, tmp_dstring->string);
750 Tcl_DStringFree(tmp_dstring);
753 tmp_dstring = unparse_aux_attributes(princ->aux_attributes);
754 Tcl_DStringAppendElement(str, tmp_dstring->string);
755 Tcl_DStringFree(tmp_dstring);
758 sprintf(buf, "%d", princ->max_renewable_life);
759 Tcl_DStringAppendElement(str, buf);
761 sprintf(buf, "%d", princ->last_success);
762 Tcl_DStringAppendElement(str, buf);
764 sprintf(buf, "%d", princ->last_failed);
765 Tcl_DStringAppendElement(str, buf);
767 sprintf(buf, "%d", princ->fail_auth_count);
768 Tcl_DStringAppendElement(str, buf);
770 sprintf(buf, "%d", princ->n_key_data);
771 Tcl_DStringAppendElement(str, buf);
773 sprintf(buf, "%d", princ->n_tl_data);
774 Tcl_DStringAppendElement(str, buf);
776 tmp_dstring = unparse_key_data(princ->key_data, princ->n_key_data);
777 Tcl_DStringAppendElement(str, tmp_dstring->string);
778 Tcl_DStringFree(tmp_dstring);
781 tmp_dstring = unparse_tl_data(princ->tl_data, princ->n_tl_data);
782 Tcl_DStringAppendElement(str, tmp_dstring->string);
783 Tcl_DStringFree(tmp_dstring);
789 static int parse_keysalts(Tcl_Interp *interp, const char *list,
790 krb5_key_salt_tuple **keysalts,
793 const char **argv, **argv1 = NULL;
794 int i, tmp, argc, argc1, retcode;
800 if ((retcode = Tcl_SplitList(interp, list, &argc, &argv)) != TCL_OK) {
803 if (argc != num_keysalts) {
804 sprintf(interp->result, "%d keysalts specified, "
805 "but num_keysalts is %d", argc, num_keysalts);
809 *keysalts = (krb5_key_salt_tuple *)
810 malloc(sizeof(krb5_key_salt_tuple)*num_keysalts);
811 for (i = 0; i < num_keysalts; i++) {
812 if ((retcode = Tcl_SplitList(interp, argv[i], &argc1, &argv1)) !=
817 sprintf(interp->result, "wrong # fields in keysalt "
818 "(%d should be 2)", argc1);
822 /* XXX this used to be argv1[1] too! */
823 if ((retcode = Tcl_GetInt(interp, argv1[0], &tmp))
825 Tcl_AppendElement(interp, "while parsing ks_enctype");
829 (*keysalts)[i].ks_enctype = tmp;
830 if ((retcode = Tcl_GetInt(interp, argv1[1], &tmp))
832 Tcl_AppendElement(interp, "while parsing ks_salttype");
835 (*keysalts)[i].ks_salttype = tmp;
837 Tcl_Free((char *) argv1);
843 Tcl_Free((char *) argv1);
845 Tcl_Free((char *) argv);
849 static int parse_key_data(Tcl_Interp *interp, const char *list,
850 krb5_key_data **key_data,
853 const char **argv = NULL;
858 if (n_key_data != 0) {
859 sprintf(interp->result, "0 key_datas specified, "
860 "but n_key_data is %d", n_key_data);
867 if ((retcode = Tcl_SplitList(interp, list, &argc, &argv)) != TCL_OK) {
870 if (argc != n_key_data) {
871 sprintf(interp->result, "%d key_datas specified, "
872 "but n_key_data is %d", argc, n_key_data);
878 sprintf(interp->result, "cannot parse key_data yet");
884 Tcl_Free((char *) argv);
888 static int parse_tl_data(Tcl_Interp *interp, const char *list,
892 krb5_tl_data *tl, *tl2;
893 const char **argv = NULL, **argv1 = NULL;
894 int i, tmp, argc, argc1, retcode;
898 if (n_tl_data != 0) {
899 sprintf(interp->result, "0 tl_datas specified, "
900 "but n_tl_data is %d", n_tl_data);
907 if ((retcode = Tcl_SplitList(interp, list, &argc, &argv)) != TCL_OK) {
910 if (argc != n_tl_data) {
911 sprintf(interp->result, "%d tl_datas specified, "
912 "but n_tl_data is %d", argc, n_tl_data);
918 for (i = 0; i < n_tl_data; i++) {
919 tl2 = (krb5_tl_data *) malloc(sizeof(krb5_tl_data));
920 memset(tl2, 0, sizeof(krb5_tl_data));
921 tl2->tl_data_next = tl;
926 for (i = 0; i < n_tl_data; i++) {
927 if ((retcode = Tcl_SplitList(interp, argv[i], &argc1, &argv1)) !=
932 sprintf(interp->result, "wrong # fields in tl_data "
933 "(%d should be 3)", argc1);
937 if ((retcode = Tcl_GetInt(interp, argv1[0], &tmp))
939 Tcl_AppendElement(interp, "while parsing tl_data_type");
943 tl->tl_data_type = tmp;
944 if ((retcode = Tcl_GetInt(interp, argv1[1], &tmp))
946 Tcl_AppendElement(interp, "while parsing tl_data_length");
950 tl->tl_data_length = tmp;
951 if (tl->tl_data_length != strlen(argv1[2])) {
952 sprintf(interp->result, "specified length %d does not "
953 "match length %lu of string \"%s\"", tmp,
954 (unsigned long) strlen(argv1[2]), argv1[2]);
958 tl->tl_data_contents = (krb5_octet *) strdup(argv1[2]);
960 Tcl_Free((char *) argv1);
962 tl = tl->tl_data_next;
965 sprintf(interp->result, "tl is not NULL!");
973 Tcl_Free((char *) argv1);
975 Tcl_Free((char *) argv);
979 static int parse_config_params(Tcl_Interp *interp, char *list,
980 kadm5_config_params *params)
982 static Tcl_HashTable *table = 0;
983 const char **argv = NULL;
984 int tmp, argc, retcode;
986 memset(params, 0, sizeof(kadm5_config_params));
990 if ((retcode = Tcl_SplitList(interp, list, &argc, &argv)) != TCL_OK) {
995 sprintf(interp->result,
996 "wrong # args in config params structure (%d should be 20)",
1002 if ((retcode = parse_flags(interp, table, config_mask_flags,
1003 sizeof(config_mask_flags) /
1004 sizeof(struct flagval),
1005 argv[0], &tmp)) != TCL_OK) {
1010 if ((retcode = parse_str(interp, argv[1], ¶ms->realm)) != TCL_OK) {
1011 Tcl_AppendElement(interp, "while parsing realm name");
1012 retcode = TCL_ERROR;
1015 if ((retcode = Tcl_GetInt(interp, argv[2], &tmp))
1017 Tcl_AppendElement(interp, "while parsing kadmind_port");
1018 retcode = TCL_ERROR;
1021 params->kadmind_port = tmp;
1022 if ((retcode = parse_str(interp, argv[3], ¶ms->admin_server))
1024 Tcl_AppendElement(interp, "while parsing profile name");
1025 retcode = TCL_ERROR;
1028 if ((retcode = parse_str(interp, argv[4], ¶ms->dbname)) != TCL_OK) {
1029 Tcl_AppendElement(interp, "while parsing profile name");
1030 retcode = TCL_ERROR;
1033 /* Ignore argv[5], which used to set the admin_dbname field. */
1034 /* Ignore argv[6], which used to set the admin_lockfile field. */
1035 /* Ignore argv[7], which used to set the admin_keytab field. */
1036 if ((retcode = parse_str(interp, argv[8], ¶ms->acl_file)) != TCL_OK) {
1037 Tcl_AppendElement(interp, "while parsing acl_file name");
1038 retcode = TCL_ERROR;
1041 if ((retcode = parse_str(interp, argv[9], ¶ms->dict_file)) != TCL_OK) {
1042 Tcl_AppendElement(interp, "while parsing dict_file name");
1043 retcode = TCL_ERROR;
1046 if ((retcode = Tcl_GetInt(interp, argv[10], &tmp))
1048 Tcl_AppendElement(interp, "while parsing mkey_from_kbd");
1049 retcode = TCL_ERROR;
1052 params->mkey_from_kbd = tmp;
1053 if ((retcode = parse_str(interp, argv[11], ¶ms->stash_file)) != TCL_OK) {
1054 Tcl_AppendElement(interp, "while parsing stash_file name");
1055 retcode = TCL_ERROR;
1058 if ((retcode = parse_str(interp, argv[12], ¶ms->mkey_name)) != TCL_OK) {
1059 Tcl_AppendElement(interp, "while parsing mkey_name name");
1060 retcode = TCL_ERROR;
1063 if ((retcode = Tcl_GetInt(interp, argv[13], &tmp))
1065 Tcl_AppendElement(interp, "while parsing enctype");
1066 retcode = TCL_ERROR;
1069 params->enctype = tmp;
1070 if ((retcode = Tcl_GetInt(interp, argv[14], &tmp))
1072 Tcl_AppendElement(interp, "while parsing max_life");
1073 retcode = TCL_ERROR;
1076 params->max_life = tmp;
1077 if ((retcode = Tcl_GetInt(interp, argv[15], &tmp))
1079 Tcl_AppendElement(interp, "while parsing max_rlife");
1080 retcode = TCL_ERROR;
1083 params->max_rlife = tmp;
1084 if ((retcode = Tcl_GetInt(interp, argv[16], &tmp))
1086 Tcl_AppendElement(interp, "while parsing expiration");
1087 retcode = TCL_ERROR;
1090 params->expiration = tmp;
1091 if ((retcode = parse_krb5_flags(interp, argv[17], &tmp))
1093 Tcl_AppendElement(interp, "while parsing flags");
1094 retcode = TCL_ERROR;
1097 params->flags = tmp;
1098 if ((retcode = Tcl_GetInt(interp, argv[18], &tmp))
1100 Tcl_AppendElement(interp, "while parsing num_keysalts");
1101 retcode = TCL_ERROR;
1104 params->num_keysalts = tmp;
1105 if ((retcode = parse_keysalts(interp, argv[19], ¶ms->keysalts,
1106 params->num_keysalts)) != TCL_OK) {
1107 Tcl_AppendElement(interp, "while parsing keysalts");
1108 retcode = TCL_ERROR;
1116 static int parse_principal_ent(Tcl_Interp *interp, char *list,
1117 kadm5_principal_ent_t *out_princ)
1119 kadm5_principal_ent_t princ = 0;
1120 krb5_error_code krb5_ret;
1125 int retcode = TCL_OK;
1127 if ((tcl_ret = Tcl_SplitList(interp, list, &argc, &argv)) != TCL_OK) {
1131 if (argc != 12 && argc != 20) {
1132 sprintf(interp->result,
1133 "wrong # args in principal structure (%d should be 12 or 20)",
1135 retcode = TCL_ERROR;
1139 if (! (princ = malloc(sizeof *princ))) {
1140 fprintf(stderr, "Out of memory!\n");
1143 memset(princ, 0, sizeof(*princ));
1145 if ((krb5_ret = krb5_parse_name(context, argv[0], &princ->principal)) != 0) {
1146 stash_error(interp, krb5_ret);
1147 Tcl_AppendElement(interp, "while parsing principal");
1148 retcode = TCL_ERROR;
1153 * All of the numerical values parsed here are parsed into an
1154 * "int" and then assigned into the structure in case the actual
1155 * width of the field in the Kerberos structure is different from
1156 * the width of an integer.
1159 if ((tcl_ret = Tcl_GetInt(interp, argv[1], &tmp))
1161 Tcl_AppendElement(interp, "while parsing princ_expire_time");
1162 retcode = TCL_ERROR;
1165 princ->princ_expire_time = tmp;
1167 if ((tcl_ret = Tcl_GetInt(interp, argv[2], &tmp))
1169 Tcl_AppendElement(interp, "while parsing last_pwd_change");
1170 retcode = TCL_ERROR;
1173 princ->last_pwd_change = tmp;
1175 if ((tcl_ret = Tcl_GetInt(interp, argv[3], &tmp))
1177 Tcl_AppendElement(interp, "while parsing pw_expiration");
1178 retcode = TCL_ERROR;
1181 princ->pw_expiration = tmp;
1183 if ((tcl_ret = Tcl_GetInt(interp, argv[4], &tmp))
1185 Tcl_AppendElement(interp, "while parsing max_life");
1186 retcode = TCL_ERROR;
1189 princ->max_life = tmp;
1191 if ((krb5_ret = krb5_parse_name(context, argv[5], &princ->mod_name)) != 0) {
1192 stash_error(interp, krb5_ret);
1193 Tcl_AppendElement(interp, "while parsing mod_name");
1194 retcode = TCL_ERROR;
1198 if ((tcl_ret = Tcl_GetInt(interp, argv[6], &tmp))
1200 Tcl_AppendElement(interp, "while parsing mod_date");
1201 retcode = TCL_ERROR;
1204 princ->mod_date = tmp;
1206 if ((tcl_ret = parse_krb5_flags(interp, argv[7], &princ->attributes))
1208 Tcl_AppendElement(interp, "while parsing attributes");
1209 retcode = TCL_ERROR;
1213 if ((tcl_ret = Tcl_GetInt(interp, argv[8], &tmp))
1215 Tcl_AppendElement(interp, "while parsing kvno");
1216 retcode = TCL_ERROR;
1221 if ((tcl_ret = Tcl_GetInt(interp, argv[9], &tmp))
1223 Tcl_AppendElement(interp, "while parsing mkvno");
1224 retcode = TCL_ERROR;
1229 if ((tcl_ret = parse_str(interp, argv[10], &princ->policy)) != TCL_OK) {
1230 Tcl_AppendElement(interp, "while parsing policy");
1231 retcode = TCL_ERROR;
1234 if(princ->policy != NULL) {
1235 if(!(princ->policy = strdup(princ->policy))) {
1236 fprintf(stderr, "Out of memory!\n");
1241 if ((tcl_ret = parse_aux_attributes(interp, argv[11],
1242 &princ->aux_attributes)) != TCL_OK) {
1243 Tcl_AppendElement(interp, "while parsing aux_attributes");
1244 retcode = TCL_ERROR;
1248 if (argc == 12) goto finished;
1250 if ((tcl_ret = Tcl_GetInt(interp, argv[12], &tmp))
1252 Tcl_AppendElement(interp, "while parsing max_renewable_life");
1253 retcode = TCL_ERROR;
1256 princ->max_renewable_life = tmp;
1258 if ((tcl_ret = Tcl_GetInt(interp, argv[13], &tmp))
1260 Tcl_AppendElement(interp, "while parsing last_success");
1261 retcode = TCL_ERROR;
1264 princ->last_success = tmp;
1266 if ((tcl_ret = Tcl_GetInt(interp, argv[14], &tmp))
1268 Tcl_AppendElement(interp, "while parsing last_failed");
1269 retcode = TCL_ERROR;
1272 princ->last_failed = tmp;
1274 if ((tcl_ret = Tcl_GetInt(interp, argv[15], &tmp))
1276 Tcl_AppendElement(interp, "while parsing fail_auth_count");
1277 retcode = TCL_ERROR;
1280 princ->fail_auth_count = tmp;
1282 if ((tcl_ret = Tcl_GetInt(interp, argv[16], &tmp))
1284 Tcl_AppendElement(interp, "while parsing n_key_data");
1285 retcode = TCL_ERROR;
1288 princ->n_key_data = tmp;
1290 if ((tcl_ret = Tcl_GetInt(interp, argv[17], &tmp))
1292 Tcl_AppendElement(interp, "while parsing n_tl_data");
1293 retcode = TCL_ERROR;
1296 princ->n_tl_data = tmp;
1298 if ((tcl_ret = parse_key_data(interp, argv[18],
1300 princ->n_key_data)) != TCL_OK) {
1301 Tcl_AppendElement(interp, "while parsing key_data");
1302 retcode = TCL_ERROR;
1306 if ((tcl_ret = parse_tl_data(interp, argv[19],
1308 princ->n_tl_data)) != TCL_OK) {
1309 Tcl_AppendElement(interp, "while parsing tl_data");
1310 retcode = TCL_ERROR;
1313 princ->n_tl_data = tmp;
1316 Tcl_Free((char *) argv);
1322 static void free_principal_ent(kadm5_principal_ent_t *princ)
1324 krb5_free_principal(context, (*princ)->principal);
1325 krb5_free_principal(context, (*princ)->mod_name);
1330 static Tcl_DString *unparse_policy_ent(kadm5_policy_ent_t policy)
1332 Tcl_DString *str, *tmp_dstring;
1335 if (! (str = malloc(sizeof(*str)))) {
1336 fprintf(stderr, "Out of memory!\n");
1340 Tcl_DStringInit(str);
1342 tmp_dstring = unparse_str(policy->policy);
1343 Tcl_DStringAppendElement(str, tmp_dstring->string);
1344 Tcl_DStringFree(tmp_dstring);
1347 sprintf(buf, "%ld", policy->pw_min_life);
1348 Tcl_DStringAppendElement(str, buf);
1350 sprintf(buf, "%ld", policy->pw_max_life);
1351 Tcl_DStringAppendElement(str, buf);
1353 sprintf(buf, "%ld", policy->pw_min_length);
1354 Tcl_DStringAppendElement(str, buf);
1356 sprintf(buf, "%ld", policy->pw_min_classes);
1357 Tcl_DStringAppendElement(str, buf);
1359 sprintf(buf, "%ld", policy->pw_history_num);
1360 Tcl_DStringAppendElement(str, buf);
1362 sprintf(buf, "%ld", policy->policy_refcnt);
1363 Tcl_DStringAppendElement(str, buf);
1365 sprintf(buf, "%d", policy->pw_max_fail);
1366 Tcl_DStringAppendElement(str, buf);
1368 sprintf(buf, "%d", policy->pw_failcnt_interval);
1369 Tcl_DStringAppendElement(str, buf);
1371 sprintf(buf, "%d", policy->pw_lockout_duration);
1372 Tcl_DStringAppendElement(str, buf);
1379 static int parse_policy_ent(Tcl_Interp *interp, char *list,
1380 kadm5_policy_ent_t *out_policy)
1382 kadm5_policy_ent_t policy = 0;
1387 int retcode = TCL_OK;
1389 if ((tcl_ret = Tcl_SplitList(interp, list, &argc, &argv)) != TCL_OK) {
1393 if (argc != 7 && argc != 10) {
1394 sprintf(interp->result, "wrong # args in policy structure (%d should be 7 or 10)",
1396 retcode = TCL_ERROR;
1400 if (! (policy = malloc(sizeof *policy))) {
1401 fprintf(stderr, "Out of memory!\n");
1405 if ((tcl_ret = parse_str(interp, argv[0], &policy->policy)) != TCL_OK) {
1406 Tcl_AppendElement(interp, "while parsing policy name");
1407 retcode = TCL_ERROR;
1411 if(policy->policy != NULL) {
1412 if (! (policy->policy = strdup(policy->policy))) {
1413 fprintf(stderr, "Out of memory!\n");
1419 * All of the numerical values parsed here are parsed into an
1420 * "int" and then assigned into the structure in case the actual
1421 * width of the field in the Kerberos structure is different from
1422 * the width of an integer.
1425 if ((tcl_ret = Tcl_GetInt(interp, argv[1], &tmp))
1427 Tcl_AppendElement(interp, "while parsing pw_min_life");
1428 retcode = TCL_ERROR;
1431 policy->pw_min_life = tmp;
1433 if ((tcl_ret = Tcl_GetInt(interp, argv[2], &tmp))
1435 Tcl_AppendElement(interp, "while parsing pw_max_life");
1436 retcode = TCL_ERROR;
1439 policy->pw_max_life = tmp;
1441 if ((tcl_ret = Tcl_GetInt(interp, argv[3], &tmp))
1443 Tcl_AppendElement(interp, "while parsing pw_min_length");
1444 retcode = TCL_ERROR;
1447 policy->pw_min_length = tmp;
1449 if ((tcl_ret = Tcl_GetInt(interp, argv[4], &tmp))
1451 Tcl_AppendElement(interp, "while parsing pw_min_classes");
1452 retcode = TCL_ERROR;
1455 policy->pw_min_classes = tmp;
1457 if ((tcl_ret = Tcl_GetInt(interp, argv[5], &tmp))
1459 Tcl_AppendElement(interp, "while parsing pw_history_num");
1460 retcode = TCL_ERROR;
1463 policy->pw_history_num = tmp;
1465 if ((tcl_ret = Tcl_GetInt(interp, argv[6], &tmp))
1467 Tcl_AppendElement(interp, "while parsing policy_refcnt");
1468 retcode = TCL_ERROR;
1471 policy->policy_refcnt = tmp;
1473 if (argc == 7) goto finished;
1475 if ((tcl_ret = Tcl_GetInt(interp, argv[7], &tmp))
1477 Tcl_AppendElement(interp, "while parsing pw_max_fail");
1478 retcode = TCL_ERROR;
1481 policy->pw_max_fail = tmp;
1483 if ((tcl_ret = Tcl_GetInt(interp, argv[8], &tmp))
1485 Tcl_AppendElement(interp, "while parsing pw_failcnt_interval");
1486 retcode = TCL_ERROR;
1489 policy->pw_failcnt_interval = tmp;
1491 if ((tcl_ret = Tcl_GetInt(interp, argv[9], &tmp))
1493 Tcl_AppendElement(interp, "while parsing pw_lockout_duration");
1494 retcode = TCL_ERROR;
1497 policy->pw_lockout_duration = tmp;
1500 Tcl_Free((char *) argv);
1501 *out_policy = policy;
1506 static void free_policy_ent(kadm5_policy_ent_t *policy)
1512 static Tcl_DString *unparse_keytype(krb5_enctype enctype)
1517 if (! (str = malloc(sizeof(*str)))) {
1518 fprintf(stderr, "Out of memory!\n");
1522 Tcl_DStringInit(str);
1525 /* XXX is this right? */
1526 case ENCTYPE_NULL: Tcl_DStringAppend(str, "ENCTYPE_NULL", -1); break;
1527 case ENCTYPE_DES_CBC_CRC:
1528 Tcl_DStringAppend(str, "ENCTYPE_DES_CBC_CRC", -1); break;
1530 sprintf(buf, "UNKNOWN KEYTYPE (0x%x)", enctype);
1531 Tcl_DStringAppend(str, buf, -1);
1539 static Tcl_DString *unparse_keyblocks(krb5_keyblock *keyblocks, int num_keys)
1542 Tcl_DString *keytype;
1546 if (! (str = malloc(sizeof(*str)))) {
1547 fprintf(stderr, "Out of memory!\n");
1551 Tcl_DStringInit(str);
1553 for (j = 0; j < num_keys; j++) {
1554 krb5_keyblock *keyblock = &keyblocks[j];
1556 Tcl_DStringStartSublist(str);
1558 keytype = unparse_keytype(keyblock->enctype);
1559 Tcl_DStringAppendElement(str, keytype->string);
1560 Tcl_DStringFree(keytype);
1562 if (keyblock->length == 0) {
1563 Tcl_DStringAppendElement(str, "0x00");
1566 Tcl_DStringAppendElement(str, "0x");
1567 for (i = 0; i < keyblock->length; i++) {
1569 sprintf(buf, "%02x", (int) keyblock->contents[i]);
1570 Tcl_DStringAppend(str, buf, -1);
1574 Tcl_DStringEndSublist(str);
1581 enum init_type { INIT_NONE, INIT_PASS, INIT_CREDS };
1583 static int _tcl_kadm5_init_any(enum init_type init_type, ClientData clientData,
1584 Tcl_Interp *interp, int argc, const char *argv[])
1587 char *client_name, *pass, *service_name;
1589 krb5_ui_4 struct_version, api_version;
1590 const char *handle_var;
1591 void *server_handle;
1592 char *handle_name, *params_str;
1593 const char *whoami = argv[0];
1594 kadm5_config_params params;
1598 kadm5_init_krb5_context(&context);
1601 Tcl_AppendResult(interp, whoami, ": ", arg_error, 0);
1605 if (((tcl_ret = parse_str(interp, argv[0], &client_name)) != TCL_OK) ||
1606 ((tcl_ret = parse_str(interp, argv[1], &pass)) != TCL_OK) ||
1607 ((tcl_ret = parse_str(interp, argv[2], &service_name)) != TCL_OK) ||
1608 ((tcl_ret = parse_str(interp, argv[3], ¶ms_str)) != TCL_OK) ||
1609 ((tcl_ret = parse_config_params(interp, params_str, ¶ms))
1611 ((tcl_ret = Tcl_GetInt(interp, argv[4], (int *) &struct_version)) !=
1613 ((tcl_ret = Tcl_GetInt(interp, argv[5], (int *) &api_version)) !=
1618 handle_var = argv[6];
1620 if (! (handle_var && *handle_var)) {
1621 Tcl_SetResult(interp, "must specify server handle variable name",
1626 if (init_type == INIT_CREDS) {
1630 if ((ret = krb5_cc_default(context, &cc))) {
1631 stash_error(interp, ret);
1635 if ((ret = krb5_cc_resolve(context, pass, &cc))) {
1636 stash_error(interp, ret);
1641 ret = kadm5_init_with_creds(context, client_name, cc, service_name,
1642 ¶ms, struct_version,
1643 api_version, NULL, &server_handle);
1645 (void) krb5_cc_close(context, cc);
1647 ret = kadm5_init(context, client_name, pass, service_name, ¶ms,
1648 struct_version, api_version, NULL, &server_handle);
1650 if (ret != KADM5_OK) {
1651 stash_error(interp, ret);
1655 if ((tcl_ret = put_server_handle(interp, server_handle, &handle_name))
1660 if (! Tcl_SetVar(interp, handle_var, handle_name, TCL_LEAVE_ERR_MSG)) {
1664 set_ok(interp, "KADM5 API initialized.");
1668 static int tcl_kadm5_init(ClientData clientData, Tcl_Interp *interp,
1669 int argc, const char *argv[])
1671 return _tcl_kadm5_init_any(INIT_PASS, clientData, interp, argc, argv);
1674 static int tcl_kadm5_init_with_creds(ClientData clientData, Tcl_Interp *interp,
1675 int argc, const char *argv[])
1677 return _tcl_kadm5_init_any(INIT_CREDS, clientData, interp, argc, argv);
1680 static int tcl_kadm5_destroy(ClientData clientData, Tcl_Interp *interp,
1681 int argc, const char *argv[])
1688 ret = kadm5_destroy(server_handle);
1690 if (ret != KADM5_OK) {
1691 stash_error(interp, ret);
1695 if ((tcl_ret = remove_server_handle(interp, argv[-1])) != TCL_OK) {
1699 set_ok(interp, "KADM5 API deinitialized.");
1703 static int tcl_kadm5_create_principal(ClientData clientData,
1705 int argc, const char *argv[])
1709 int retcode = TCL_OK;
1711 kadm5_principal_ent_t princ = 0;
1720 if ((tcl_ret = parse_str(interp, argv[0], &princ_string)) != TCL_OK) {
1721 Tcl_AppendElement(interp, "while parsing principal");
1726 ((tcl_ret = parse_principal_ent(interp, princ_string, &princ))
1731 if ((tcl_ret = parse_principal_mask(interp, argv[1], &mask)) != TCL_OK) {
1736 if ((tcl_ret = parse_str(interp, argv[2], &pw)) != TCL_OK) {
1741 if ((tcl_ret = Tcl_GetBoolean(interp, argv[3], &override_qual)) !=
1749 ret = kadm5_create_principal(server_handle, princ, mask, pw,
1752 ret = kadm5_create_principal(server_handle, princ, mask, pw);
1755 if (ret != KADM5_OK) {
1756 stash_error(interp, ret);
1757 retcode = TCL_ERROR;
1761 set_ok(interp, "Principal created.");
1766 free_principal_ent(&princ);
1773 static int tcl_kadm5_delete_principal(ClientData clientData,
1775 int argc, const char *argv[])
1777 krb5_principal princ;
1778 krb5_error_code krb5_ret;
1785 if((tcl_ret = parse_str(interp, argv[0], &name)) != TCL_OK)
1788 if ((krb5_ret = krb5_parse_name(context, name, &princ))) {
1789 stash_error(interp, krb5_ret);
1790 Tcl_AppendElement(interp, "while parsing principal");
1793 } else princ = NULL;
1794 ret = kadm5_delete_principal(server_handle, princ);
1797 krb5_free_principal(context, princ);
1799 if (ret != KADM5_OK) {
1800 stash_error(interp, ret);
1804 set_ok(interp, "Principal deleted.");
1811 static int tcl_kadm5_modify_principal(ClientData clientData,
1813 int argc, const char *argv[])
1816 kadm5_principal_ent_t princ = 0;
1819 int retcode = TCL_OK;
1824 if ((tcl_ret = parse_str(interp, argv[0], &princ_string)) != TCL_OK) {
1825 Tcl_AppendElement(interp, "while parsing principal");
1830 ((tcl_ret = parse_principal_ent(interp, princ_string, &princ))
1835 if ((tcl_ret = parse_principal_mask(interp, argv[1], &mask)) != TCL_OK) {
1836 retcode = TCL_ERROR;
1840 ret = kadm5_modify_principal(server_handle, princ, mask);
1842 if (ret != KADM5_OK) {
1843 stash_error(interp, ret);
1844 retcode = TCL_ERROR;
1847 set_ok(interp, "Principal modified.");
1852 free_principal_ent(&princ);
1858 static int tcl_kadm5_rename_principal(ClientData clientData,
1860 int argc, const char *argv[])
1862 krb5_principal source, target;
1863 krb5_error_code krb5_ret;
1865 int retcode = TCL_OK;
1869 if ((krb5_ret = krb5_parse_name(context, argv[0], &source)) != 0) {
1870 stash_error(interp, krb5_ret);
1871 Tcl_AppendElement(interp, "while parsing source");
1875 if ((krb5_ret = krb5_parse_name(context, argv[1], &target)) != 0) {
1876 stash_error(interp, krb5_ret);
1877 Tcl_AppendElement(interp, "while parsing target");
1878 krb5_free_principal(context, source);
1882 ret = kadm5_rename_principal(server_handle, source, target);
1884 if (ret == KADM5_OK) {
1885 set_ok(interp, "Principal renamed.");
1888 stash_error(interp, ret);
1889 retcode = TCL_ERROR;
1892 krb5_free_principal(context, source);
1893 krb5_free_principal(context, target);
1899 static int tcl_kadm5_chpass_principal(ClientData clientData,
1901 int argc, const char *argv[])
1903 krb5_principal princ;
1908 krb5_error_code krb5_ret;
1909 int retcode = TCL_OK;
1914 if ((krb5_ret = krb5_parse_name(context, argv[0], &princ)) != 0) {
1915 stash_error(interp, krb5_ret);
1916 Tcl_AppendElement(interp, "while parsing principal name");
1920 if (parse_str(interp, argv[1], &pw) != TCL_OK) {
1921 Tcl_AppendElement(interp, "while parsing password");
1922 retcode = TCL_ERROR;
1927 if (Tcl_GetBoolean(interp, argv[2], &override_qual) != TCL_OK) {
1928 Tcl_AppendElement(interp, "while parsing override_qual");
1929 retcode = TCL_ERROR;
1933 ret = kadm5_chpass_principal(server_handle,
1934 princ, pw, override_qual);
1936 ret = kadm5_chpass_principal(server_handle, princ, pw);
1939 if (ret == KADM5_OK) {
1940 set_ok(interp, "Password changed.");
1944 stash_error(interp, ret);
1945 retcode = TCL_ERROR;
1949 krb5_free_principal(context, princ);
1955 static int tcl_kadm5_chpass_principal_util(ClientData clientData,
1957 int argc, const char *argv[])
1959 krb5_principal princ;
1964 char *pw_ret, *pw_ret_var;
1965 char msg_ret[1024], *msg_ret_var;
1966 krb5_error_code krb5_ret;
1968 int retcode = TCL_OK;
1972 if ((krb5_ret = krb5_parse_name(context, argv[0], &princ)) != 0) {
1973 stash_error(interp, krb5_ret);
1974 Tcl_AppendElement(interp, "while parsing principal name");
1978 if (parse_str(interp, argv[1], &new_pw) != TCL_OK) {
1979 Tcl_AppendElement(interp, "while parsing new password");
1980 retcode = TCL_ERROR;
1984 if (Tcl_GetBoolean(interp, argv[2], &override_qual) != TCL_OK) {
1985 Tcl_AppendElement(interp, "while parsing override_qual");
1986 retcode = TCL_ERROR;
1990 if (parse_str(interp, argv[3], &pw_ret_var) != TCL_OK) {
1991 Tcl_AppendElement(interp, "while parsing pw_ret variable name");
1992 retcode = TCL_ERROR;
1996 if (parse_str(interp, argv[4], &msg_ret_var) != TCL_OK) {
1997 Tcl_AppendElement(interp, "while parsing msg_ret variable name");
1998 retcode = TCL_ERROR;
2002 ret = kadm5_chpass_principal_util(server_handle, princ, new_pw,
2006 pw_ret_var ? &pw_ret : 0,
2007 msg_ret_var ? msg_ret : 0,
2008 msg_ret_var ? sizeof(msg_ret) : 0);
2010 if (ret == KADM5_OK) {
2012 (! Tcl_SetVar(interp, pw_ret_var, pw_ret,
2013 TCL_LEAVE_ERR_MSG))) {
2014 Tcl_AppendElement(interp, "while setting pw_ret variable");
2015 retcode = TCL_ERROR;
2019 (! Tcl_SetVar(interp, msg_ret_var, msg_ret,
2020 TCL_LEAVE_ERR_MSG))) {
2021 Tcl_AppendElement(interp,
2022 "while setting msg_ret variable");
2023 retcode = TCL_ERROR;
2026 set_ok(interp, "Password changed.");
2029 stash_error(interp, ret);
2030 retcode = TCL_ERROR;
2034 krb5_free_principal(context, princ);
2040 static int tcl_kadm5_randkey_principal(ClientData clientData,
2042 int argc, const char *argv[])
2044 krb5_principal princ;
2045 krb5_keyblock *keyblocks;
2047 char *keyblock_var, *num_var, buf[50];
2048 Tcl_DString *keyblock_dstring = 0;
2049 krb5_error_code krb5_ret;
2051 int retcode = TCL_OK;
2055 if ((krb5_ret = krb5_parse_name(context, argv[0], &princ)) != 0) {
2056 stash_error(interp, krb5_ret);
2057 Tcl_AppendElement(interp, "while parsing principal name");
2061 if (parse_str(interp, argv[1], &keyblock_var) != TCL_OK) {
2062 Tcl_AppendElement(interp, "while parsing keyblock variable name");
2063 retcode = TCL_ERROR;
2066 if (parse_str(interp, argv[2], &num_var) != TCL_OK) {
2067 Tcl_AppendElement(interp, "while parsing keyblock variable name");
2068 retcode = TCL_ERROR;
2072 ret = kadm5_randkey_principal(server_handle,
2073 princ, keyblock_var ? &keyblocks : 0,
2076 if (ret == KADM5_OK) {
2078 keyblock_dstring = unparse_keyblocks(keyblocks, num_keys);
2079 if (! Tcl_SetVar(interp, keyblock_var,
2080 keyblock_dstring->string,
2081 TCL_LEAVE_ERR_MSG)) {
2082 Tcl_AppendElement(interp,
2083 "while setting keyblock variable");
2084 retcode = TCL_ERROR;
2089 sprintf(buf, "%d", num_keys);
2090 if (! Tcl_SetVar(interp, num_var, buf,
2091 TCL_LEAVE_ERR_MSG)) {
2092 Tcl_AppendElement(interp,
2093 "while setting num_keys variable");
2096 set_ok(interp, "Key randomized.");
2099 stash_error(interp, ret);
2100 retcode = TCL_ERROR;
2104 krb5_free_principal(context, princ);
2105 if (keyblock_dstring) {
2106 Tcl_DStringFree(keyblock_dstring);
2107 free(keyblock_dstring);
2114 static int tcl_kadm5_get_principal(ClientData clientData, Tcl_Interp *interp,
2115 int argc, const char *argv[])
2117 krb5_principal princ;
2118 kadm5_principal_ent_rec ent;
2119 Tcl_DString *ent_dstring = 0;
2122 krb5_error_code krb5_ret;
2124 kadm5_ret_t ret = -1;
2126 int retcode = TCL_OK;
2130 if((tcl_ret = parse_str(interp, argv[0], &name)) != TCL_OK)
2133 if ((krb5_ret = krb5_parse_name(context, name, &princ)) != 0) {
2134 stash_error(interp, krb5_ret);
2135 Tcl_AppendElement(interp, "while parsing principal name");
2138 } else princ = NULL;
2140 if ((tcl_ret = parse_str(interp, argv[1], &ent_var)) != TCL_OK) {
2141 Tcl_AppendElement(interp, "while parsing entry variable name");
2142 retcode = TCL_ERROR;
2145 if ((tcl_ret = parse_principal_mask(interp, argv[2], &mask)) != TCL_OK) {
2146 Tcl_AppendElement(interp, "while parsing principal mask");
2147 retcode = TCL_ERROR;
2151 ret = kadm5_get_principal(server_handle, princ, ent_var ? &ent : 0,
2154 if (ret == KADM5_OK) {
2156 ent_dstring = unparse_principal_ent(&ent, mask);
2157 if (! Tcl_SetVar(interp, ent_var, ent_dstring->string,
2158 TCL_LEAVE_ERR_MSG)) {
2159 Tcl_AppendElement(interp,
2160 "while setting entry variable");
2161 retcode = TCL_ERROR;
2164 set_ok(interp, "Principal retrieved.");
2168 stash_error(interp, ret);
2169 retcode = TCL_ERROR;
2174 Tcl_DStringFree(ent_dstring);
2178 krb5_free_principal(context, princ);
2179 if (ret == KADM5_OK && ent_var &&
2180 (ret = kadm5_free_principal_ent(server_handle, &ent)) &&
2181 (retcode == TCL_OK)) {
2182 stash_error(interp, ret);
2183 retcode = TCL_ERROR;
2188 static int tcl_kadm5_create_policy(ClientData clientData, Tcl_Interp *interp,
2189 int argc, const char *argv[])
2193 int retcode = TCL_OK;
2194 char *policy_string;
2195 kadm5_policy_ent_t policy = 0;
2200 if ((tcl_ret = parse_str(interp, argv[0], &policy_string)) != TCL_OK) {
2201 Tcl_AppendElement(interp, "while parsing policy");
2205 if (policy_string &&
2206 ((tcl_ret = parse_policy_ent(interp, policy_string, &policy))
2211 if ((tcl_ret = parse_policy_mask(interp, argv[1], &mask)) != TCL_OK) {
2216 ret = kadm5_create_policy(server_handle, policy, mask);
2218 if (ret != KADM5_OK) {
2219 stash_error(interp, ret);
2220 retcode = TCL_ERROR;
2224 set_ok(interp, "Policy created.");
2229 free_policy_ent(&policy);
2236 static int tcl_kadm5_delete_policy(ClientData clientData, Tcl_Interp *interp,
2237 int argc, const char *argv[])
2244 if (parse_str(interp, argv[0], &policy) != TCL_OK) {
2245 Tcl_AppendElement(interp, "while parsing policy name");
2249 ret = kadm5_delete_policy(server_handle, policy);
2251 if (ret != KADM5_OK) {
2252 stash_error(interp, ret);
2256 set_ok(interp, "Policy deleted.");
2263 static int tcl_kadm5_modify_policy(ClientData clientData, Tcl_Interp *interp,
2264 int argc, const char *argv[])
2266 char *policy_string;
2267 kadm5_policy_ent_t policy = 0;
2270 int retcode = TCL_OK;
2275 if ((tcl_ret = parse_str(interp, argv[0], &policy_string)) != TCL_OK) {
2276 Tcl_AppendElement(interp, "while parsing policy");
2280 if (policy_string &&
2281 ((tcl_ret = parse_policy_ent(interp, policy_string, &policy))
2286 if ((tcl_ret = parse_policy_mask(interp, argv[1], &mask)) != TCL_OK) {
2287 retcode = TCL_ERROR;
2291 ret = kadm5_modify_policy(server_handle, policy, mask);
2293 if (ret != KADM5_OK) {
2294 stash_error(interp, ret);
2295 retcode = TCL_ERROR;
2298 set_ok(interp, "Policy modified.");
2303 free_policy_ent(&policy);
2309 static int tcl_kadm5_get_policy(ClientData clientData, Tcl_Interp *interp,
2310 int argc, const char *argv[])
2312 kadm5_policy_ent_rec ent;
2313 Tcl_DString *ent_dstring = 0;
2317 int retcode = TCL_OK;
2321 if (parse_str(interp, argv[0], &policy) != TCL_OK) {
2322 Tcl_AppendElement(interp, "while parsing policy name");
2326 if (parse_str(interp, argv[1], &ent_var) != TCL_OK) {
2327 Tcl_AppendElement(interp, "while parsing entry variable name");
2331 ret = kadm5_get_policy(server_handle, policy, ent_var ? &ent : 0);
2333 if (ret == KADM5_OK) {
2335 ent_dstring = unparse_policy_ent(&ent);
2336 if (! Tcl_SetVar(interp, ent_var, ent_dstring->string,
2337 TCL_LEAVE_ERR_MSG)) {
2338 Tcl_AppendElement(interp,
2339 "while setting entry variable");
2340 retcode = TCL_ERROR;
2343 set_ok(interp, "Policy retrieved.");
2347 stash_error(interp, ret);
2348 retcode = TCL_ERROR;
2353 Tcl_DStringFree(ent_dstring);
2356 if (ent_var && ret == KADM5_OK &&
2357 (ret = kadm5_free_policy_ent(server_handle, &ent)) &&
2358 (retcode == TCL_OK)) {
2359 stash_error(interp, ret);
2360 retcode = TCL_ERROR;
2367 static int tcl_kadm5_free_principal_ent(ClientData clientData,
2369 int argc, const char *argv[])
2372 kadm5_principal_ent_t ent;
2377 if (parse_str(interp, argv[0], &ent_name) != TCL_OK) {
2378 Tcl_AppendElement(interp, "while parsing entry name");
2383 (ret = kadm5_free_principal_ent(server_handle, 0))) {
2384 stash_error(interp, ret);
2388 Tcl_HashEntry *entry;
2390 if (strncmp(ent_name, "principal", sizeof("principal")-1)) {
2391 Tcl_AppendResult(interp, "invalid principal handle \"",
2395 if (! struct_table) {
2396 if (! (struct_table = malloc(sizeof(*struct_table)))) {
2397 fprintf(stderr, "Out of memory!\n");
2400 Tcl_InitHashTable(struct_table, TCL_STRING_KEYS);
2403 if (! (entry = Tcl_FindHashEntry(struct_table, ent_name))) {
2404 Tcl_AppendResult(interp, "principal handle \"", ent_name,
2409 ent = (kadm5_principal_ent_t) Tcl_GetHashValue(entry);
2411 ret = kadm5_free_principal_ent(server_handle, ent);
2412 if (ret != KADM5_OK) {
2413 stash_error(interp, ret);
2416 Tcl_DeleteHashEntry(entry);
2418 set_ok(interp, "Principal freed.");
2423 static int tcl_kadm5_free_policy_ent(ClientData clientData,
2425 int argc, const char *argv[])
2428 kadm5_policy_ent_t ent;
2433 if (parse_str(interp, argv[0], &ent_name) != TCL_OK) {
2434 Tcl_AppendElement(interp, "while parsing entry name");
2439 (ret = kadm5_free_policy_ent(server_handle, 0))) {
2440 stash_error(interp, ret);
2444 Tcl_HashEntry *entry;
2446 if (strncmp(ent_name, "policy", sizeof("policy")-1)) {
2447 Tcl_AppendResult(interp, "invalid principal handle \"",
2451 if (! struct_table) {
2452 if (! (struct_table = malloc(sizeof(*struct_table)))) {
2453 fprintf(stderr, "Out of memory!\n");
2456 Tcl_InitHashTable(struct_table, TCL_STRING_KEYS);
2459 if (! (entry = Tcl_FindHashEntry(struct_table, ent_name))) {
2460 Tcl_AppendResult(interp, "policy handle \"", ent_name,
2465 ent = (kadm5_policy_ent_t) Tcl_GetHashValue(entry);
2467 if ((ret = kadm5_free_policy_ent(server_handle, ent)) != KADM5_OK) {
2468 stash_error(interp, ret);
2471 Tcl_DeleteHashEntry(entry);
2473 set_ok(interp, "Policy freed.");
2478 static int tcl_kadm5_get_privs(ClientData clientData, Tcl_Interp *interp,
2479 int argc, const char *argv[])
2481 const char *set_ret;
2488 if (parse_str(interp, argv[0], &priv_var) != TCL_OK) {
2489 Tcl_AppendElement(interp, "while parsing privs variable name");
2493 ret = kadm5_get_privs(server_handle, priv_var ? &privs : 0);
2495 if (ret == KADM5_OK) {
2497 Tcl_DString *str = unparse_privs(privs);
2498 set_ret = Tcl_SetVar(interp, priv_var, str->string,
2500 Tcl_DStringFree(str);
2503 Tcl_AppendElement(interp, "while setting priv variable");
2507 set_ok(interp, "Privileges retrieved.");
2511 stash_error(interp, ret);
2517 void Tcl_kadm5_init(Tcl_Interp *interp)
2521 Tcl_SetVar(interp, "KADM5_ADMIN_SERVICE",
2522 KADM5_ADMIN_SERVICE, TCL_GLOBAL_ONLY);
2523 Tcl_SetVar(interp, "KADM5_CHANGEPW_SERVICE",
2524 KADM5_CHANGEPW_SERVICE, TCL_GLOBAL_ONLY);
2525 (void) sprintf(buf, "%d", KADM5_STRUCT_VERSION);
2526 Tcl_SetVar(interp, "KADM5_STRUCT_VERSION", buf, TCL_GLOBAL_ONLY);
2527 (void) sprintf(buf, "%d", KADM5_API_VERSION_2);
2528 Tcl_SetVar(interp, "KADM5_API_VERSION_2", buf, TCL_GLOBAL_ONLY);
2529 (void) sprintf(buf, "%d", KADM5_API_VERSION_3);
2530 Tcl_SetVar(interp, "KADM5_API_VERSION_3", buf, TCL_GLOBAL_ONLY);
2531 (void) sprintf(buf, "%d", KADM5_API_VERSION_MASK);
2532 Tcl_SetVar(interp, "KADM5_API_VERSION_MASK", buf, TCL_GLOBAL_ONLY);
2533 (void) sprintf(buf, "%d", KADM5_STRUCT_VERSION_MASK);
2534 Tcl_SetVar(interp, "KADM5_STRUCT_VERSION_MASK", buf,
2537 Tcl_CreateCommand(interp, "kadm5_init", tcl_kadm5_init, 0, 0);
2538 Tcl_CreateCommand(interp, "kadm5_init_with_creds",
2539 tcl_kadm5_init_with_creds, 0, 0);
2540 Tcl_CreateCommand(interp, "kadm5_destroy", tcl_kadm5_destroy, 0,
2542 Tcl_CreateCommand(interp, "kadm5_create_principal",
2543 tcl_kadm5_create_principal, 0, 0);
2544 Tcl_CreateCommand(interp, "kadm5_delete_principal",
2545 tcl_kadm5_delete_principal, 0, 0);
2546 Tcl_CreateCommand(interp, "kadm5_modify_principal",
2547 tcl_kadm5_modify_principal, 0, 0);
2548 Tcl_CreateCommand(interp, "kadm5_rename_principal",
2549 tcl_kadm5_rename_principal, 0, 0);
2550 Tcl_CreateCommand(interp, "kadm5_chpass_principal",
2551 tcl_kadm5_chpass_principal, 0, 0);
2552 Tcl_CreateCommand(interp, "kadm5_chpass_principal_util",
2553 tcl_kadm5_chpass_principal_util, 0, 0);
2554 Tcl_CreateCommand(interp, "kadm5_randkey_principal",
2555 tcl_kadm5_randkey_principal, 0, 0);
2556 Tcl_CreateCommand(interp, "kadm5_get_principal",
2557 tcl_kadm5_get_principal, 0, 0);
2558 Tcl_CreateCommand(interp, "kadm5_create_policy",
2559 tcl_kadm5_create_policy, 0, 0);
2560 Tcl_CreateCommand(interp, "kadm5_delete_policy",
2561 tcl_kadm5_delete_policy, 0, 0);
2562 Tcl_CreateCommand(interp, "kadm5_modify_policy",
2563 tcl_kadm5_modify_policy, 0, 0);
2564 Tcl_CreateCommand(interp, "kadm5_get_policy",
2565 tcl_kadm5_get_policy, 0, 0);
2566 Tcl_CreateCommand(interp, "kadm5_free_principal_ent",
2567 tcl_kadm5_free_principal_ent, 0, 0);
2568 Tcl_CreateCommand(interp, "kadm5_free_policy_ent",
2569 tcl_kadm5_free_policy_ent, 0, 0);
2570 Tcl_CreateCommand(interp, "kadm5_get_privs",
2571 tcl_kadm5_get_privs, 0, 0);