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, "%u", (unsigned int)princ->princ_expire_time);
701 Tcl_DStringAppendElement(str, buf);
703 sprintf(buf, "%u", (unsigned int)princ->last_pwd_change);
704 Tcl_DStringAppendElement(str, buf);
706 sprintf(buf, "%u", (unsigned int)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, "%u", (unsigned int)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, "%u", (unsigned int)princ->last_success);
762 Tcl_DStringAppendElement(str, buf);
764 sprintf(buf, "%u", (unsigned int)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 Tcl_SetResult(interp, "wrong number of keysalts", TCL_STATIC);
808 *keysalts = (krb5_key_salt_tuple *)
809 malloc(sizeof(krb5_key_salt_tuple)*num_keysalts);
810 for (i = 0; i < num_keysalts; i++) {
811 if ((retcode = Tcl_SplitList(interp, argv[i], &argc1, &argv1)) !=
816 Tcl_SetResult(interp, "wrong # of fields in keysalt", TCL_STATIC);
820 /* XXX this used to be argv1[1] too! */
821 if ((retcode = Tcl_GetInt(interp, argv1[0], &tmp))
823 Tcl_AppendElement(interp, "while parsing ks_enctype");
827 (*keysalts)[i].ks_enctype = tmp;
828 if ((retcode = Tcl_GetInt(interp, argv1[1], &tmp))
830 Tcl_AppendElement(interp, "while parsing ks_salttype");
833 (*keysalts)[i].ks_salttype = tmp;
835 Tcl_Free((char *) argv1);
841 Tcl_Free((char *) argv1);
843 Tcl_Free((char *) argv);
847 static int parse_key_data(Tcl_Interp *interp, const char *list,
848 krb5_key_data **key_data,
851 const char **argv = NULL;
856 if (n_key_data != 0) {
857 Tcl_SetResult(interp, "wrong number of key_datas", TCL_STATIC);
864 if ((retcode = Tcl_SplitList(interp, list, &argc, &argv)) != TCL_OK) {
867 if (argc != n_key_data) {
868 Tcl_SetResult(interp, "wrong number of key_datas", TCL_STATIC);
874 Tcl_SetResult(interp, "cannot parse key_data yet", TCL_STATIC);
880 Tcl_Free((char *) argv);
884 static int parse_tl_data(Tcl_Interp *interp, const char *list,
888 krb5_tl_data *tl, *tl2;
889 const char **argv = NULL, **argv1 = NULL;
890 int i, tmp, argc, argc1, retcode;
894 if (n_tl_data != 0) {
895 Tcl_SetResult(interp, "wrong number of tl_datas", TCL_STATIC);
902 if ((retcode = Tcl_SplitList(interp, list, &argc, &argv)) != TCL_OK) {
905 if (argc != n_tl_data) {
906 Tcl_SetResult(interp, "wrong number of tl_datas", TCL_STATIC);
912 for (i = 0; i < n_tl_data; i++) {
913 tl2 = (krb5_tl_data *) malloc(sizeof(krb5_tl_data));
914 memset(tl2, 0, sizeof(krb5_tl_data));
915 tl2->tl_data_next = tl;
920 for (i = 0; i < n_tl_data; i++) {
921 if ((retcode = Tcl_SplitList(interp, argv[i], &argc1, &argv1)) !=
926 Tcl_SetResult(interp, "wrong # of fields in tl_data", TCL_STATIC);
930 if ((retcode = Tcl_GetInt(interp, argv1[0], &tmp))
932 Tcl_AppendElement(interp, "while parsing tl_data_type");
936 tl->tl_data_type = tmp;
937 if ((retcode = Tcl_GetInt(interp, argv1[1], &tmp))
939 Tcl_AppendElement(interp, "while parsing tl_data_length");
943 tl->tl_data_length = tmp;
944 if (tl->tl_data_length != strlen(argv1[2])) {
945 Tcl_SetResult(interp, "length != string length", TCL_STATIC);
949 tl->tl_data_contents = (krb5_octet *) strdup(argv1[2]);
951 Tcl_Free((char *) argv1);
953 tl = tl->tl_data_next;
956 Tcl_SetResult(interp, "tl is not NULL!", TCL_STATIC);
964 Tcl_Free((char *) argv1);
966 Tcl_Free((char *) argv);
970 static int parse_config_params(Tcl_Interp *interp, char *list,
971 kadm5_config_params *params)
973 static Tcl_HashTable *table = 0;
974 const char **argv = NULL;
975 int tmp, argc, retcode;
977 memset(params, 0, sizeof(kadm5_config_params));
981 if ((retcode = Tcl_SplitList(interp, list, &argc, &argv)) != TCL_OK) {
986 Tcl_SetResult(interp, "wrong # args in config params structure",
992 if ((retcode = parse_flags(interp, table, config_mask_flags,
993 sizeof(config_mask_flags) /
994 sizeof(struct flagval),
995 argv[0], &tmp)) != TCL_OK) {
1000 if ((retcode = parse_str(interp, argv[1], ¶ms->realm)) != TCL_OK) {
1001 Tcl_AppendElement(interp, "while parsing realm name");
1002 retcode = TCL_ERROR;
1005 if ((retcode = Tcl_GetInt(interp, argv[2], &tmp))
1007 Tcl_AppendElement(interp, "while parsing kadmind_port");
1008 retcode = TCL_ERROR;
1011 params->kadmind_port = tmp;
1012 if ((retcode = parse_str(interp, argv[3], ¶ms->admin_server))
1014 Tcl_AppendElement(interp, "while parsing profile name");
1015 retcode = TCL_ERROR;
1018 if ((retcode = parse_str(interp, argv[4], ¶ms->dbname)) != TCL_OK) {
1019 Tcl_AppendElement(interp, "while parsing profile name");
1020 retcode = TCL_ERROR;
1023 /* Ignore argv[5], which used to set the admin_dbname field. */
1024 /* Ignore argv[6], which used to set the admin_lockfile field. */
1025 /* Ignore argv[7], which used to set the admin_keytab field. */
1026 if ((retcode = parse_str(interp, argv[8], ¶ms->acl_file)) != TCL_OK) {
1027 Tcl_AppendElement(interp, "while parsing acl_file name");
1028 retcode = TCL_ERROR;
1031 if ((retcode = parse_str(interp, argv[9], ¶ms->dict_file)) != TCL_OK) {
1032 Tcl_AppendElement(interp, "while parsing dict_file name");
1033 retcode = TCL_ERROR;
1036 if ((retcode = Tcl_GetInt(interp, argv[10], &tmp))
1038 Tcl_AppendElement(interp, "while parsing mkey_from_kbd");
1039 retcode = TCL_ERROR;
1042 params->mkey_from_kbd = tmp;
1043 if ((retcode = parse_str(interp, argv[11], ¶ms->stash_file)) != TCL_OK) {
1044 Tcl_AppendElement(interp, "while parsing stash_file name");
1045 retcode = TCL_ERROR;
1048 if ((retcode = parse_str(interp, argv[12], ¶ms->mkey_name)) != TCL_OK) {
1049 Tcl_AppendElement(interp, "while parsing mkey_name name");
1050 retcode = TCL_ERROR;
1053 if ((retcode = Tcl_GetInt(interp, argv[13], &tmp))
1055 Tcl_AppendElement(interp, "while parsing enctype");
1056 retcode = TCL_ERROR;
1059 params->enctype = tmp;
1060 if ((retcode = Tcl_GetInt(interp, argv[14], &tmp))
1062 Tcl_AppendElement(interp, "while parsing max_life");
1063 retcode = TCL_ERROR;
1066 params->max_life = tmp;
1067 if ((retcode = Tcl_GetInt(interp, argv[15], &tmp))
1069 Tcl_AppendElement(interp, "while parsing max_rlife");
1070 retcode = TCL_ERROR;
1073 params->max_rlife = tmp;
1074 if ((retcode = Tcl_GetInt(interp, argv[16], &tmp))
1076 Tcl_AppendElement(interp, "while parsing expiration");
1077 retcode = TCL_ERROR;
1080 params->expiration = tmp;
1081 if ((retcode = parse_krb5_flags(interp, argv[17], &tmp))
1083 Tcl_AppendElement(interp, "while parsing flags");
1084 retcode = TCL_ERROR;
1087 params->flags = tmp;
1088 if ((retcode = Tcl_GetInt(interp, argv[18], &tmp))
1090 Tcl_AppendElement(interp, "while parsing num_keysalts");
1091 retcode = TCL_ERROR;
1094 params->num_keysalts = tmp;
1095 if ((retcode = parse_keysalts(interp, argv[19], ¶ms->keysalts,
1096 params->num_keysalts)) != TCL_OK) {
1097 Tcl_AppendElement(interp, "while parsing keysalts");
1098 retcode = TCL_ERROR;
1106 static int parse_principal_ent(Tcl_Interp *interp, char *list,
1107 kadm5_principal_ent_t *out_princ)
1109 kadm5_principal_ent_t princ = 0;
1110 krb5_error_code krb5_ret;
1115 int retcode = TCL_OK;
1117 if ((tcl_ret = Tcl_SplitList(interp, list, &argc, &argv)) != TCL_OK) {
1121 if (argc != 12 && argc != 20) {
1122 Tcl_SetResult(interp, "wrong # args in principal structure",
1124 retcode = TCL_ERROR;
1128 if (! (princ = malloc(sizeof *princ))) {
1129 fprintf(stderr, "Out of memory!\n");
1132 memset(princ, 0, sizeof(*princ));
1134 if ((krb5_ret = krb5_parse_name(context, argv[0], &princ->principal)) != 0) {
1135 stash_error(interp, krb5_ret);
1136 Tcl_AppendElement(interp, "while parsing principal");
1137 retcode = TCL_ERROR;
1142 * All of the numerical values parsed here are parsed into an
1143 * "int" and then assigned into the structure in case the actual
1144 * width of the field in the Kerberos structure is different from
1145 * the width of an integer.
1148 if ((tcl_ret = Tcl_GetInt(interp, argv[1], &tmp))
1150 Tcl_AppendElement(interp, "while parsing princ_expire_time");
1151 retcode = TCL_ERROR;
1154 princ->princ_expire_time = tmp;
1156 if ((tcl_ret = Tcl_GetInt(interp, argv[2], &tmp))
1158 Tcl_AppendElement(interp, "while parsing last_pwd_change");
1159 retcode = TCL_ERROR;
1162 princ->last_pwd_change = tmp;
1164 if ((tcl_ret = Tcl_GetInt(interp, argv[3], &tmp))
1166 Tcl_AppendElement(interp, "while parsing pw_expiration");
1167 retcode = TCL_ERROR;
1170 princ->pw_expiration = tmp;
1172 if ((tcl_ret = Tcl_GetInt(interp, argv[4], &tmp))
1174 Tcl_AppendElement(interp, "while parsing max_life");
1175 retcode = TCL_ERROR;
1178 princ->max_life = tmp;
1180 if ((krb5_ret = krb5_parse_name(context, argv[5], &princ->mod_name)) != 0) {
1181 stash_error(interp, krb5_ret);
1182 Tcl_AppendElement(interp, "while parsing mod_name");
1183 retcode = TCL_ERROR;
1187 if ((tcl_ret = Tcl_GetInt(interp, argv[6], &tmp))
1189 Tcl_AppendElement(interp, "while parsing mod_date");
1190 retcode = TCL_ERROR;
1193 princ->mod_date = tmp;
1195 if ((tcl_ret = parse_krb5_flags(interp, argv[7], &princ->attributes))
1197 Tcl_AppendElement(interp, "while parsing attributes");
1198 retcode = TCL_ERROR;
1202 if ((tcl_ret = Tcl_GetInt(interp, argv[8], &tmp))
1204 Tcl_AppendElement(interp, "while parsing kvno");
1205 retcode = TCL_ERROR;
1210 if ((tcl_ret = Tcl_GetInt(interp, argv[9], &tmp))
1212 Tcl_AppendElement(interp, "while parsing mkvno");
1213 retcode = TCL_ERROR;
1218 if ((tcl_ret = parse_str(interp, argv[10], &princ->policy)) != TCL_OK) {
1219 Tcl_AppendElement(interp, "while parsing policy");
1220 retcode = TCL_ERROR;
1223 if(princ->policy != NULL) {
1224 if(!(princ->policy = strdup(princ->policy))) {
1225 fprintf(stderr, "Out of memory!\n");
1230 if ((tcl_ret = parse_aux_attributes(interp, argv[11],
1231 &princ->aux_attributes)) != TCL_OK) {
1232 Tcl_AppendElement(interp, "while parsing aux_attributes");
1233 retcode = TCL_ERROR;
1237 if (argc == 12) goto finished;
1239 if ((tcl_ret = Tcl_GetInt(interp, argv[12], &tmp))
1241 Tcl_AppendElement(interp, "while parsing max_renewable_life");
1242 retcode = TCL_ERROR;
1245 princ->max_renewable_life = tmp;
1247 if ((tcl_ret = Tcl_GetInt(interp, argv[13], &tmp))
1249 Tcl_AppendElement(interp, "while parsing last_success");
1250 retcode = TCL_ERROR;
1253 princ->last_success = tmp;
1255 if ((tcl_ret = Tcl_GetInt(interp, argv[14], &tmp))
1257 Tcl_AppendElement(interp, "while parsing last_failed");
1258 retcode = TCL_ERROR;
1261 princ->last_failed = tmp;
1263 if ((tcl_ret = Tcl_GetInt(interp, argv[15], &tmp))
1265 Tcl_AppendElement(interp, "while parsing fail_auth_count");
1266 retcode = TCL_ERROR;
1269 princ->fail_auth_count = tmp;
1271 if ((tcl_ret = Tcl_GetInt(interp, argv[16], &tmp))
1273 Tcl_AppendElement(interp, "while parsing n_key_data");
1274 retcode = TCL_ERROR;
1277 princ->n_key_data = tmp;
1279 if ((tcl_ret = Tcl_GetInt(interp, argv[17], &tmp))
1281 Tcl_AppendElement(interp, "while parsing n_tl_data");
1282 retcode = TCL_ERROR;
1285 princ->n_tl_data = tmp;
1287 if ((tcl_ret = parse_key_data(interp, argv[18],
1289 princ->n_key_data)) != TCL_OK) {
1290 Tcl_AppendElement(interp, "while parsing key_data");
1291 retcode = TCL_ERROR;
1295 if ((tcl_ret = parse_tl_data(interp, argv[19],
1297 princ->n_tl_data)) != TCL_OK) {
1298 Tcl_AppendElement(interp, "while parsing tl_data");
1299 retcode = TCL_ERROR;
1302 princ->n_tl_data = tmp;
1305 Tcl_Free((char *) argv);
1311 static void free_principal_ent(kadm5_principal_ent_t *princ)
1313 krb5_free_principal(context, (*princ)->principal);
1314 krb5_free_principal(context, (*princ)->mod_name);
1315 free((*princ)->policy);
1320 static Tcl_DString *unparse_policy_ent(kadm5_policy_ent_t policy)
1322 Tcl_DString *str, *tmp_dstring;
1325 if (! (str = malloc(sizeof(*str)))) {
1326 fprintf(stderr, "Out of memory!\n");
1330 Tcl_DStringInit(str);
1332 tmp_dstring = unparse_str(policy->policy);
1333 Tcl_DStringAppendElement(str, tmp_dstring->string);
1334 Tcl_DStringFree(tmp_dstring);
1337 sprintf(buf, "%ld", policy->pw_min_life);
1338 Tcl_DStringAppendElement(str, buf);
1340 sprintf(buf, "%ld", policy->pw_max_life);
1341 Tcl_DStringAppendElement(str, buf);
1343 sprintf(buf, "%ld", policy->pw_min_length);
1344 Tcl_DStringAppendElement(str, buf);
1346 sprintf(buf, "%ld", policy->pw_min_classes);
1347 Tcl_DStringAppendElement(str, buf);
1349 sprintf(buf, "%ld", policy->pw_history_num);
1350 Tcl_DStringAppendElement(str, buf);
1352 sprintf(buf, "%ld", policy->policy_refcnt);
1353 Tcl_DStringAppendElement(str, buf);
1355 sprintf(buf, "%d", policy->pw_max_fail);
1356 Tcl_DStringAppendElement(str, buf);
1358 sprintf(buf, "%d", policy->pw_failcnt_interval);
1359 Tcl_DStringAppendElement(str, buf);
1361 sprintf(buf, "%d", policy->pw_lockout_duration);
1362 Tcl_DStringAppendElement(str, buf);
1369 static int parse_policy_ent(Tcl_Interp *interp, char *list,
1370 kadm5_policy_ent_t *out_policy)
1372 kadm5_policy_ent_t policy = 0;
1377 int retcode = TCL_OK;
1379 if ((tcl_ret = Tcl_SplitList(interp, list, &argc, &argv)) != TCL_OK) {
1383 if (argc != 7 && argc != 10) {
1384 Tcl_SetResult(interp, "wrong # args in policy structure", TCL_STATIC);
1385 retcode = TCL_ERROR;
1389 if (! (policy = malloc(sizeof *policy))) {
1390 fprintf(stderr, "Out of memory!\n");
1394 if ((tcl_ret = parse_str(interp, argv[0], &policy->policy)) != TCL_OK) {
1395 Tcl_AppendElement(interp, "while parsing policy name");
1396 retcode = TCL_ERROR;
1400 if(policy->policy != NULL) {
1401 if (! (policy->policy = strdup(policy->policy))) {
1402 fprintf(stderr, "Out of memory!\n");
1408 * All of the numerical values parsed here are parsed into an
1409 * "int" and then assigned into the structure in case the actual
1410 * width of the field in the Kerberos structure is different from
1411 * the width of an integer.
1414 if ((tcl_ret = Tcl_GetInt(interp, argv[1], &tmp))
1416 Tcl_AppendElement(interp, "while parsing pw_min_life");
1417 retcode = TCL_ERROR;
1420 policy->pw_min_life = tmp;
1422 if ((tcl_ret = Tcl_GetInt(interp, argv[2], &tmp))
1424 Tcl_AppendElement(interp, "while parsing pw_max_life");
1425 retcode = TCL_ERROR;
1428 policy->pw_max_life = tmp;
1430 if ((tcl_ret = Tcl_GetInt(interp, argv[3], &tmp))
1432 Tcl_AppendElement(interp, "while parsing pw_min_length");
1433 retcode = TCL_ERROR;
1436 policy->pw_min_length = tmp;
1438 if ((tcl_ret = Tcl_GetInt(interp, argv[4], &tmp))
1440 Tcl_AppendElement(interp, "while parsing pw_min_classes");
1441 retcode = TCL_ERROR;
1444 policy->pw_min_classes = tmp;
1446 if ((tcl_ret = Tcl_GetInt(interp, argv[5], &tmp))
1448 Tcl_AppendElement(interp, "while parsing pw_history_num");
1449 retcode = TCL_ERROR;
1452 policy->pw_history_num = tmp;
1454 if ((tcl_ret = Tcl_GetInt(interp, argv[6], &tmp))
1456 Tcl_AppendElement(interp, "while parsing policy_refcnt");
1457 retcode = TCL_ERROR;
1460 policy->policy_refcnt = tmp;
1462 if (argc == 7) goto finished;
1464 if ((tcl_ret = Tcl_GetInt(interp, argv[7], &tmp))
1466 Tcl_AppendElement(interp, "while parsing pw_max_fail");
1467 retcode = TCL_ERROR;
1470 policy->pw_max_fail = tmp;
1472 if ((tcl_ret = Tcl_GetInt(interp, argv[8], &tmp))
1474 Tcl_AppendElement(interp, "while parsing pw_failcnt_interval");
1475 retcode = TCL_ERROR;
1478 policy->pw_failcnt_interval = tmp;
1480 if ((tcl_ret = Tcl_GetInt(interp, argv[9], &tmp))
1482 Tcl_AppendElement(interp, "while parsing pw_lockout_duration");
1483 retcode = TCL_ERROR;
1486 policy->pw_lockout_duration = tmp;
1489 Tcl_Free((char *) argv);
1490 *out_policy = policy;
1495 static void free_policy_ent(kadm5_policy_ent_t *policy)
1497 free((*policy)->policy);
1502 static Tcl_DString *unparse_keytype(krb5_enctype enctype)
1507 if (! (str = malloc(sizeof(*str)))) {
1508 fprintf(stderr, "Out of memory!\n");
1512 Tcl_DStringInit(str);
1515 /* XXX is this right? */
1516 case ENCTYPE_NULL: Tcl_DStringAppend(str, "ENCTYPE_NULL", -1); break;
1517 case ENCTYPE_DES_CBC_CRC:
1518 Tcl_DStringAppend(str, "ENCTYPE_DES_CBC_CRC", -1); break;
1520 sprintf(buf, "UNKNOWN KEYTYPE (0x%x)", enctype);
1521 Tcl_DStringAppend(str, buf, -1);
1529 static Tcl_DString *unparse_keyblocks(krb5_keyblock *keyblocks, int num_keys)
1532 Tcl_DString *keytype;
1536 if (! (str = malloc(sizeof(*str)))) {
1537 fprintf(stderr, "Out of memory!\n");
1541 Tcl_DStringInit(str);
1543 for (j = 0; j < num_keys; j++) {
1544 krb5_keyblock *keyblock = &keyblocks[j];
1546 Tcl_DStringStartSublist(str);
1548 keytype = unparse_keytype(keyblock->enctype);
1549 Tcl_DStringAppendElement(str, keytype->string);
1550 Tcl_DStringFree(keytype);
1552 if (keyblock->length == 0) {
1553 Tcl_DStringAppendElement(str, "0x00");
1556 Tcl_DStringAppendElement(str, "0x");
1557 for (i = 0; i < keyblock->length; i++) {
1559 sprintf(buf, "%02x", (int) keyblock->contents[i]);
1560 Tcl_DStringAppend(str, buf, -1);
1564 Tcl_DStringEndSublist(str);
1571 enum init_type { INIT_NONE, INIT_PASS, INIT_CREDS };
1573 static int _tcl_kadm5_init_any(enum init_type init_type, ClientData clientData,
1574 Tcl_Interp *interp, int argc, const char *argv[])
1577 char *client_name, *pass, *service_name;
1579 krb5_ui_4 struct_version, api_version;
1580 const char *handle_var;
1581 void *server_handle;
1582 char *handle_name, *params_str;
1583 const char *whoami = argv[0];
1584 kadm5_config_params params;
1588 kadm5_init_krb5_context(&context);
1591 Tcl_AppendResult(interp, whoami, ": ", arg_error, 0);
1595 if (((tcl_ret = parse_str(interp, argv[0], &client_name)) != TCL_OK) ||
1596 ((tcl_ret = parse_str(interp, argv[1], &pass)) != TCL_OK) ||
1597 ((tcl_ret = parse_str(interp, argv[2], &service_name)) != TCL_OK) ||
1598 ((tcl_ret = parse_str(interp, argv[3], ¶ms_str)) != TCL_OK) ||
1599 ((tcl_ret = parse_config_params(interp, params_str, ¶ms))
1601 ((tcl_ret = Tcl_GetInt(interp, argv[4], (int *) &struct_version)) !=
1603 ((tcl_ret = Tcl_GetInt(interp, argv[5], (int *) &api_version)) !=
1608 handle_var = argv[6];
1610 if (! (handle_var && *handle_var)) {
1611 Tcl_SetResult(interp, "must specify server handle variable name",
1616 if (init_type == INIT_CREDS) {
1620 if ((ret = krb5_cc_default(context, &cc))) {
1621 stash_error(interp, ret);
1625 if ((ret = krb5_cc_resolve(context, pass, &cc))) {
1626 stash_error(interp, ret);
1631 ret = kadm5_init_with_creds(context, client_name, cc, service_name,
1632 ¶ms, struct_version,
1633 api_version, NULL, &server_handle);
1635 (void) krb5_cc_close(context, cc);
1637 ret = kadm5_init(context, client_name, pass, service_name, ¶ms,
1638 struct_version, api_version, NULL, &server_handle);
1640 /* The string fields of params are aliases into argv[3], but
1641 * params.keysalts is allocated, so clean it up. */
1642 free(params.keysalts);
1644 if (ret != KADM5_OK) {
1645 stash_error(interp, ret);
1649 if ((tcl_ret = put_server_handle(interp, server_handle, &handle_name))
1654 if (! Tcl_SetVar(interp, handle_var, handle_name, TCL_LEAVE_ERR_MSG)) {
1658 set_ok(interp, "KADM5 API initialized.");
1662 static int tcl_kadm5_init(ClientData clientData, Tcl_Interp *interp,
1663 int argc, const char *argv[])
1665 return _tcl_kadm5_init_any(INIT_PASS, clientData, interp, argc, argv);
1668 static int tcl_kadm5_init_with_creds(ClientData clientData, Tcl_Interp *interp,
1669 int argc, const char *argv[])
1671 return _tcl_kadm5_init_any(INIT_CREDS, clientData, interp, argc, argv);
1674 static int tcl_kadm5_destroy(ClientData clientData, Tcl_Interp *interp,
1675 int argc, const char *argv[])
1682 ret = kadm5_destroy(server_handle);
1684 if (ret != KADM5_OK) {
1685 stash_error(interp, ret);
1689 if ((tcl_ret = remove_server_handle(interp, argv[-1])) != TCL_OK) {
1693 set_ok(interp, "KADM5 API deinitialized.");
1697 static int tcl_kadm5_create_principal(ClientData clientData,
1699 int argc, const char *argv[])
1703 int retcode = TCL_OK;
1705 kadm5_principal_ent_t princ = 0;
1714 if ((tcl_ret = parse_str(interp, argv[0], &princ_string)) != TCL_OK) {
1715 Tcl_AppendElement(interp, "while parsing principal");
1720 ((tcl_ret = parse_principal_ent(interp, princ_string, &princ))
1725 if ((tcl_ret = parse_principal_mask(interp, argv[1], &mask)) != TCL_OK) {
1730 if ((tcl_ret = parse_str(interp, argv[2], &pw)) != TCL_OK) {
1735 if ((tcl_ret = Tcl_GetBoolean(interp, argv[3], &override_qual)) !=
1743 ret = kadm5_create_principal(server_handle, princ, mask, pw,
1746 ret = kadm5_create_principal(server_handle, princ, mask, pw);
1749 if (ret != KADM5_OK) {
1750 stash_error(interp, ret);
1751 retcode = TCL_ERROR;
1755 set_ok(interp, "Principal created.");
1760 free_principal_ent(&princ);
1767 static int tcl_kadm5_delete_principal(ClientData clientData,
1769 int argc, const char *argv[])
1771 krb5_principal princ;
1772 krb5_error_code krb5_ret;
1779 if((tcl_ret = parse_str(interp, argv[0], &name)) != TCL_OK)
1782 if ((krb5_ret = krb5_parse_name(context, name, &princ))) {
1783 stash_error(interp, krb5_ret);
1784 Tcl_AppendElement(interp, "while parsing principal");
1787 } else princ = NULL;
1788 ret = kadm5_delete_principal(server_handle, princ);
1791 krb5_free_principal(context, princ);
1793 if (ret != KADM5_OK) {
1794 stash_error(interp, ret);
1798 set_ok(interp, "Principal deleted.");
1805 static int tcl_kadm5_modify_principal(ClientData clientData,
1807 int argc, const char *argv[])
1810 kadm5_principal_ent_t princ = 0;
1813 int retcode = TCL_OK;
1818 if ((tcl_ret = parse_str(interp, argv[0], &princ_string)) != TCL_OK) {
1819 Tcl_AppendElement(interp, "while parsing principal");
1824 ((tcl_ret = parse_principal_ent(interp, princ_string, &princ))
1829 if ((tcl_ret = parse_principal_mask(interp, argv[1], &mask)) != TCL_OK) {
1830 retcode = TCL_ERROR;
1834 ret = kadm5_modify_principal(server_handle, princ, mask);
1836 if (ret != KADM5_OK) {
1837 stash_error(interp, ret);
1838 retcode = TCL_ERROR;
1841 set_ok(interp, "Principal modified.");
1846 free_principal_ent(&princ);
1852 static int tcl_kadm5_rename_principal(ClientData clientData,
1854 int argc, const char *argv[])
1856 krb5_principal source, target;
1857 krb5_error_code krb5_ret;
1859 int retcode = TCL_OK;
1863 if ((krb5_ret = krb5_parse_name(context, argv[0], &source)) != 0) {
1864 stash_error(interp, krb5_ret);
1865 Tcl_AppendElement(interp, "while parsing source");
1869 if ((krb5_ret = krb5_parse_name(context, argv[1], &target)) != 0) {
1870 stash_error(interp, krb5_ret);
1871 Tcl_AppendElement(interp, "while parsing target");
1872 krb5_free_principal(context, source);
1876 ret = kadm5_rename_principal(server_handle, source, target);
1878 if (ret == KADM5_OK) {
1879 set_ok(interp, "Principal renamed.");
1882 stash_error(interp, ret);
1883 retcode = TCL_ERROR;
1886 krb5_free_principal(context, source);
1887 krb5_free_principal(context, target);
1893 static int tcl_kadm5_chpass_principal(ClientData clientData,
1895 int argc, const char *argv[])
1897 krb5_principal princ;
1902 krb5_error_code krb5_ret;
1903 int retcode = TCL_OK;
1908 if ((krb5_ret = krb5_parse_name(context, argv[0], &princ)) != 0) {
1909 stash_error(interp, krb5_ret);
1910 Tcl_AppendElement(interp, "while parsing principal name");
1914 if (parse_str(interp, argv[1], &pw) != TCL_OK) {
1915 Tcl_AppendElement(interp, "while parsing password");
1916 retcode = TCL_ERROR;
1921 if (Tcl_GetBoolean(interp, argv[2], &override_qual) != TCL_OK) {
1922 Tcl_AppendElement(interp, "while parsing override_qual");
1923 retcode = TCL_ERROR;
1927 ret = kadm5_chpass_principal(server_handle,
1928 princ, pw, override_qual);
1930 ret = kadm5_chpass_principal(server_handle, princ, pw);
1933 if (ret == KADM5_OK) {
1934 set_ok(interp, "Password changed.");
1938 stash_error(interp, ret);
1939 retcode = TCL_ERROR;
1943 krb5_free_principal(context, princ);
1949 static int tcl_kadm5_chpass_principal_util(ClientData clientData,
1951 int argc, const char *argv[])
1953 krb5_principal princ;
1958 char *pw_ret, *pw_ret_var;
1959 char msg_ret[1024], *msg_ret_var;
1960 krb5_error_code krb5_ret;
1962 int retcode = TCL_OK;
1966 if ((krb5_ret = krb5_parse_name(context, argv[0], &princ)) != 0) {
1967 stash_error(interp, krb5_ret);
1968 Tcl_AppendElement(interp, "while parsing principal name");
1972 if (parse_str(interp, argv[1], &new_pw) != TCL_OK) {
1973 Tcl_AppendElement(interp, "while parsing new password");
1974 retcode = TCL_ERROR;
1978 if (Tcl_GetBoolean(interp, argv[2], &override_qual) != TCL_OK) {
1979 Tcl_AppendElement(interp, "while parsing override_qual");
1980 retcode = TCL_ERROR;
1984 if (parse_str(interp, argv[3], &pw_ret_var) != TCL_OK) {
1985 Tcl_AppendElement(interp, "while parsing pw_ret variable name");
1986 retcode = TCL_ERROR;
1990 if (parse_str(interp, argv[4], &msg_ret_var) != TCL_OK) {
1991 Tcl_AppendElement(interp, "while parsing msg_ret variable name");
1992 retcode = TCL_ERROR;
1996 ret = kadm5_chpass_principal_util(server_handle, princ, new_pw,
2000 pw_ret_var ? &pw_ret : 0,
2001 msg_ret_var ? msg_ret : 0,
2002 msg_ret_var ? sizeof(msg_ret) : 0);
2004 if (ret == KADM5_OK) {
2006 (! Tcl_SetVar(interp, pw_ret_var, pw_ret,
2007 TCL_LEAVE_ERR_MSG))) {
2008 Tcl_AppendElement(interp, "while setting pw_ret variable");
2009 retcode = TCL_ERROR;
2013 (! Tcl_SetVar(interp, msg_ret_var, msg_ret,
2014 TCL_LEAVE_ERR_MSG))) {
2015 Tcl_AppendElement(interp,
2016 "while setting msg_ret variable");
2017 retcode = TCL_ERROR;
2020 set_ok(interp, "Password changed.");
2023 stash_error(interp, ret);
2024 retcode = TCL_ERROR;
2028 krb5_free_principal(context, princ);
2034 static int tcl_kadm5_randkey_principal(ClientData clientData,
2036 int argc, const char *argv[])
2038 krb5_principal princ;
2039 krb5_keyblock *keyblocks;
2041 char *keyblock_var, *num_var, buf[50];
2042 Tcl_DString *keyblock_dstring = 0;
2043 krb5_error_code krb5_ret;
2045 int retcode = TCL_OK;
2049 if ((krb5_ret = krb5_parse_name(context, argv[0], &princ)) != 0) {
2050 stash_error(interp, krb5_ret);
2051 Tcl_AppendElement(interp, "while parsing principal name");
2055 if (parse_str(interp, argv[1], &keyblock_var) != TCL_OK) {
2056 Tcl_AppendElement(interp, "while parsing keyblock variable name");
2057 retcode = TCL_ERROR;
2060 if (parse_str(interp, argv[2], &num_var) != TCL_OK) {
2061 Tcl_AppendElement(interp, "while parsing keyblock variable name");
2062 retcode = TCL_ERROR;
2066 ret = kadm5_randkey_principal(server_handle,
2067 princ, keyblock_var ? &keyblocks : 0,
2070 if (ret == KADM5_OK) {
2072 keyblock_dstring = unparse_keyblocks(keyblocks, num_keys);
2073 if (! Tcl_SetVar(interp, keyblock_var,
2074 keyblock_dstring->string,
2075 TCL_LEAVE_ERR_MSG)) {
2076 Tcl_AppendElement(interp,
2077 "while setting keyblock variable");
2078 retcode = TCL_ERROR;
2083 sprintf(buf, "%d", num_keys);
2084 if (! Tcl_SetVar(interp, num_var, buf,
2085 TCL_LEAVE_ERR_MSG)) {
2086 Tcl_AppendElement(interp,
2087 "while setting num_keys variable");
2090 set_ok(interp, "Key randomized.");
2093 stash_error(interp, ret);
2094 retcode = TCL_ERROR;
2098 krb5_free_principal(context, princ);
2099 if (keyblock_dstring) {
2100 Tcl_DStringFree(keyblock_dstring);
2101 free(keyblock_dstring);
2108 static int tcl_kadm5_get_principal(ClientData clientData, Tcl_Interp *interp,
2109 int argc, const char *argv[])
2111 krb5_principal princ;
2112 kadm5_principal_ent_rec ent;
2113 Tcl_DString *ent_dstring = 0;
2116 krb5_error_code krb5_ret;
2118 kadm5_ret_t ret = -1;
2120 int retcode = TCL_OK;
2124 if((tcl_ret = parse_str(interp, argv[0], &name)) != TCL_OK)
2127 if ((krb5_ret = krb5_parse_name(context, name, &princ)) != 0) {
2128 stash_error(interp, krb5_ret);
2129 Tcl_AppendElement(interp, "while parsing principal name");
2132 } else princ = NULL;
2134 if ((tcl_ret = parse_str(interp, argv[1], &ent_var)) != TCL_OK) {
2135 Tcl_AppendElement(interp, "while parsing entry variable name");
2136 retcode = TCL_ERROR;
2139 if ((tcl_ret = parse_principal_mask(interp, argv[2], &mask)) != TCL_OK) {
2140 Tcl_AppendElement(interp, "while parsing principal mask");
2141 retcode = TCL_ERROR;
2145 ret = kadm5_get_principal(server_handle, princ, ent_var ? &ent : 0,
2148 if (ret == KADM5_OK) {
2150 ent_dstring = unparse_principal_ent(&ent, mask);
2151 if (! Tcl_SetVar(interp, ent_var, ent_dstring->string,
2152 TCL_LEAVE_ERR_MSG)) {
2153 Tcl_AppendElement(interp,
2154 "while setting entry variable");
2155 retcode = TCL_ERROR;
2158 set_ok(interp, "Principal retrieved.");
2162 stash_error(interp, ret);
2163 retcode = TCL_ERROR;
2168 Tcl_DStringFree(ent_dstring);
2172 krb5_free_principal(context, princ);
2173 if (ret == KADM5_OK && ent_var &&
2174 (ret = kadm5_free_principal_ent(server_handle, &ent)) &&
2175 (retcode == TCL_OK)) {
2176 stash_error(interp, ret);
2177 retcode = TCL_ERROR;
2182 static int tcl_kadm5_create_policy(ClientData clientData, Tcl_Interp *interp,
2183 int argc, const char *argv[])
2187 int retcode = TCL_OK;
2188 char *policy_string;
2189 kadm5_policy_ent_t policy = 0;
2194 if ((tcl_ret = parse_str(interp, argv[0], &policy_string)) != TCL_OK) {
2195 Tcl_AppendElement(interp, "while parsing policy");
2199 if (policy_string &&
2200 ((tcl_ret = parse_policy_ent(interp, policy_string, &policy))
2205 if ((tcl_ret = parse_policy_mask(interp, argv[1], &mask)) != TCL_OK) {
2210 ret = kadm5_create_policy(server_handle, policy, mask);
2212 if (ret != KADM5_OK) {
2213 stash_error(interp, ret);
2214 retcode = TCL_ERROR;
2218 set_ok(interp, "Policy created.");
2223 free_policy_ent(&policy);
2230 static int tcl_kadm5_delete_policy(ClientData clientData, Tcl_Interp *interp,
2231 int argc, const char *argv[])
2238 if (parse_str(interp, argv[0], &policy) != TCL_OK) {
2239 Tcl_AppendElement(interp, "while parsing policy name");
2243 ret = kadm5_delete_policy(server_handle, policy);
2245 if (ret != KADM5_OK) {
2246 stash_error(interp, ret);
2250 set_ok(interp, "Policy deleted.");
2257 static int tcl_kadm5_modify_policy(ClientData clientData, Tcl_Interp *interp,
2258 int argc, const char *argv[])
2260 char *policy_string;
2261 kadm5_policy_ent_t policy = 0;
2264 int retcode = TCL_OK;
2269 if ((tcl_ret = parse_str(interp, argv[0], &policy_string)) != TCL_OK) {
2270 Tcl_AppendElement(interp, "while parsing policy");
2274 if (policy_string &&
2275 ((tcl_ret = parse_policy_ent(interp, policy_string, &policy))
2280 if ((tcl_ret = parse_policy_mask(interp, argv[1], &mask)) != TCL_OK) {
2281 retcode = TCL_ERROR;
2285 ret = kadm5_modify_policy(server_handle, policy, mask);
2287 if (ret != KADM5_OK) {
2288 stash_error(interp, ret);
2289 retcode = TCL_ERROR;
2292 set_ok(interp, "Policy modified.");
2297 free_policy_ent(&policy);
2303 static int tcl_kadm5_get_policy(ClientData clientData, Tcl_Interp *interp,
2304 int argc, const char *argv[])
2306 kadm5_policy_ent_rec ent;
2307 Tcl_DString *ent_dstring = 0;
2311 int retcode = TCL_OK;
2315 if (parse_str(interp, argv[0], &policy) != TCL_OK) {
2316 Tcl_AppendElement(interp, "while parsing policy name");
2320 if (parse_str(interp, argv[1], &ent_var) != TCL_OK) {
2321 Tcl_AppendElement(interp, "while parsing entry variable name");
2325 ret = kadm5_get_policy(server_handle, policy, ent_var ? &ent : 0);
2327 if (ret == KADM5_OK) {
2329 ent_dstring = unparse_policy_ent(&ent);
2330 if (! Tcl_SetVar(interp, ent_var, ent_dstring->string,
2331 TCL_LEAVE_ERR_MSG)) {
2332 Tcl_AppendElement(interp,
2333 "while setting entry variable");
2334 retcode = TCL_ERROR;
2337 set_ok(interp, "Policy retrieved.");
2341 stash_error(interp, ret);
2342 retcode = TCL_ERROR;
2347 Tcl_DStringFree(ent_dstring);
2350 if (ent_var && ret == KADM5_OK &&
2351 (ret = kadm5_free_policy_ent(server_handle, &ent)) &&
2352 (retcode == TCL_OK)) {
2353 stash_error(interp, ret);
2354 retcode = TCL_ERROR;
2361 static int tcl_kadm5_free_principal_ent(ClientData clientData,
2363 int argc, const char *argv[])
2366 kadm5_principal_ent_t ent;
2371 if (parse_str(interp, argv[0], &ent_name) != TCL_OK) {
2372 Tcl_AppendElement(interp, "while parsing entry name");
2377 (ret = kadm5_free_principal_ent(server_handle, 0))) {
2378 stash_error(interp, ret);
2382 Tcl_HashEntry *entry;
2384 if (strncmp(ent_name, "principal", sizeof("principal")-1)) {
2385 Tcl_AppendResult(interp, "invalid principal handle \"",
2389 if (! struct_table) {
2390 if (! (struct_table = malloc(sizeof(*struct_table)))) {
2391 fprintf(stderr, "Out of memory!\n");
2394 Tcl_InitHashTable(struct_table, TCL_STRING_KEYS);
2397 if (! (entry = Tcl_FindHashEntry(struct_table, ent_name))) {
2398 Tcl_AppendResult(interp, "principal handle \"", ent_name,
2403 ent = (kadm5_principal_ent_t) Tcl_GetHashValue(entry);
2405 ret = kadm5_free_principal_ent(server_handle, ent);
2406 if (ret != KADM5_OK) {
2407 stash_error(interp, ret);
2410 Tcl_DeleteHashEntry(entry);
2412 set_ok(interp, "Principal freed.");
2417 static int tcl_kadm5_free_policy_ent(ClientData clientData,
2419 int argc, const char *argv[])
2422 kadm5_policy_ent_t ent;
2427 if (parse_str(interp, argv[0], &ent_name) != TCL_OK) {
2428 Tcl_AppendElement(interp, "while parsing entry name");
2433 (ret = kadm5_free_policy_ent(server_handle, 0))) {
2434 stash_error(interp, ret);
2438 Tcl_HashEntry *entry;
2440 if (strncmp(ent_name, "policy", sizeof("policy")-1)) {
2441 Tcl_AppendResult(interp, "invalid principal handle \"",
2445 if (! struct_table) {
2446 if (! (struct_table = malloc(sizeof(*struct_table)))) {
2447 fprintf(stderr, "Out of memory!\n");
2450 Tcl_InitHashTable(struct_table, TCL_STRING_KEYS);
2453 if (! (entry = Tcl_FindHashEntry(struct_table, ent_name))) {
2454 Tcl_AppendResult(interp, "policy handle \"", ent_name,
2459 ent = (kadm5_policy_ent_t) Tcl_GetHashValue(entry);
2461 if ((ret = kadm5_free_policy_ent(server_handle, ent)) != KADM5_OK) {
2462 stash_error(interp, ret);
2465 Tcl_DeleteHashEntry(entry);
2467 set_ok(interp, "Policy freed.");
2472 static int tcl_kadm5_get_privs(ClientData clientData, Tcl_Interp *interp,
2473 int argc, const char *argv[])
2475 const char *set_ret;
2482 if (parse_str(interp, argv[0], &priv_var) != TCL_OK) {
2483 Tcl_AppendElement(interp, "while parsing privs variable name");
2487 ret = kadm5_get_privs(server_handle, priv_var ? &privs : 0);
2489 if (ret == KADM5_OK) {
2491 Tcl_DString *str = unparse_privs(privs);
2492 set_ret = Tcl_SetVar(interp, priv_var, str->string,
2494 Tcl_DStringFree(str);
2497 Tcl_AppendElement(interp, "while setting priv variable");
2501 set_ok(interp, "Privileges retrieved.");
2505 stash_error(interp, ret);
2511 void Tcl_kadm5_init(Tcl_Interp *interp)
2515 Tcl_SetVar(interp, "KADM5_ADMIN_SERVICE",
2516 KADM5_ADMIN_SERVICE, TCL_GLOBAL_ONLY);
2517 Tcl_SetVar(interp, "KADM5_CHANGEPW_SERVICE",
2518 KADM5_CHANGEPW_SERVICE, TCL_GLOBAL_ONLY);
2519 (void) sprintf(buf, "%d", KADM5_STRUCT_VERSION);
2520 Tcl_SetVar(interp, "KADM5_STRUCT_VERSION", buf, TCL_GLOBAL_ONLY);
2521 (void) sprintf(buf, "%d", KADM5_API_VERSION_2);
2522 Tcl_SetVar(interp, "KADM5_API_VERSION_2", buf, TCL_GLOBAL_ONLY);
2523 (void) sprintf(buf, "%d", KADM5_API_VERSION_3);
2524 Tcl_SetVar(interp, "KADM5_API_VERSION_3", buf, TCL_GLOBAL_ONLY);
2525 (void) sprintf(buf, "%d", KADM5_API_VERSION_4);
2526 Tcl_SetVar(interp, "KADM5_API_VERSION_4", buf, TCL_GLOBAL_ONLY);
2527 (void) sprintf(buf, "%d", KADM5_API_VERSION_MASK);
2528 Tcl_SetVar(interp, "KADM5_API_VERSION_MASK", buf, TCL_GLOBAL_ONLY);
2529 (void) sprintf(buf, "%d", KADM5_STRUCT_VERSION_MASK);
2530 Tcl_SetVar(interp, "KADM5_STRUCT_VERSION_MASK", buf,
2533 Tcl_CreateCommand(interp, "kadm5_init", tcl_kadm5_init, 0, 0);
2534 Tcl_CreateCommand(interp, "kadm5_init_with_creds",
2535 tcl_kadm5_init_with_creds, 0, 0);
2536 Tcl_CreateCommand(interp, "kadm5_destroy", tcl_kadm5_destroy, 0,
2538 Tcl_CreateCommand(interp, "kadm5_create_principal",
2539 tcl_kadm5_create_principal, 0, 0);
2540 Tcl_CreateCommand(interp, "kadm5_delete_principal",
2541 tcl_kadm5_delete_principal, 0, 0);
2542 Tcl_CreateCommand(interp, "kadm5_modify_principal",
2543 tcl_kadm5_modify_principal, 0, 0);
2544 Tcl_CreateCommand(interp, "kadm5_rename_principal",
2545 tcl_kadm5_rename_principal, 0, 0);
2546 Tcl_CreateCommand(interp, "kadm5_chpass_principal",
2547 tcl_kadm5_chpass_principal, 0, 0);
2548 Tcl_CreateCommand(interp, "kadm5_chpass_principal_util",
2549 tcl_kadm5_chpass_principal_util, 0, 0);
2550 Tcl_CreateCommand(interp, "kadm5_randkey_principal",
2551 tcl_kadm5_randkey_principal, 0, 0);
2552 Tcl_CreateCommand(interp, "kadm5_get_principal",
2553 tcl_kadm5_get_principal, 0, 0);
2554 Tcl_CreateCommand(interp, "kadm5_create_policy",
2555 tcl_kadm5_create_policy, 0, 0);
2556 Tcl_CreateCommand(interp, "kadm5_delete_policy",
2557 tcl_kadm5_delete_policy, 0, 0);
2558 Tcl_CreateCommand(interp, "kadm5_modify_policy",
2559 tcl_kadm5_modify_policy, 0, 0);
2560 Tcl_CreateCommand(interp, "kadm5_get_policy",
2561 tcl_kadm5_get_policy, 0, 0);
2562 Tcl_CreateCommand(interp, "kadm5_free_principal_ent",
2563 tcl_kadm5_free_principal_ent, 0, 0);
2564 Tcl_CreateCommand(interp, "kadm5_free_policy_ent",
2565 tcl_kadm5_free_policy_ent, 0, 0);
2566 Tcl_CreateCommand(interp, "kadm5_get_privs",
2567 tcl_kadm5_get_privs, 0, 0);