void kadm5_free_principal_ent(void *server_handle, kadm5_principal_ent_t princ) { kadm5_server_context *context = server_handle; if (princ->principal) krb5_free_principal(context->context, princ->principal); if (princ->mod_name) krb5_free_principal(context->context, princ->mod_name); kadm5_free_key_data(server_handle, &princ->n_key_data, princ->key_data); while (princ->n_tl_data && princ->tl_data) { krb5_tl_data *tp; tp = princ->tl_data; princ->tl_data = tp->tl_data_next; princ->n_tl_data--; memset(tp->tl_data_contents, 0, tp->tl_data_length); free(tp->tl_data_contents); free(tp); } if (princ->key_data != NULL) free(princ->key_data); if (princ->policy) free(princ->policy); }
int add_new_key(struct add_options *opt, int argc, char **argv) { krb5_error_code ret = 0; int i; int num; krb5_key_data key_data[3]; krb5_key_data *kdp = NULL; num = 0; if (opt->random_key_flag) ++num; if (opt->random_password_flag) ++num; if (opt->password_string) ++num; if (opt->key_string) ++num; if (num > 1) { fprintf (stderr, "give only one of " "--random-key, --random-password, --password, --key\n"); return 1; } if (opt->key_string) { const char *error; if (parse_des_key (opt->key_string, key_data, &error)) { fprintf (stderr, "failed parsing key \"%s\": %s\n", opt->key_string, error); return 1; } kdp = key_data; } for(i = 0; i < argc; i++) { ret = add_one_principal (argv[i], opt->random_key_flag, opt->random_password_flag, opt->use_defaults_flag, opt->password_string, opt->policy_string, kdp, opt->max_ticket_life_string, opt->max_renewable_life_string, opt->attributes_string, opt->expiration_time_string, opt->pw_expiration_time_string); if (ret) { krb5_warn (context, ret, "adding %s", argv[i]); break; } } if (kdp) { int16_t dummy = 3; kadm5_free_key_data (kadm_handle, &dummy, key_data); } return ret != 0; }
int cpw_entry(struct passwd_options *opt, int argc, char **argv) { krb5_error_code ret = 0; int i; struct cpw_entry_data data; int num; krb5_key_data key_data[3]; data.keepold = opt->keepold_flag; data.random_key = opt->random_key_flag; data.random_password = opt->random_password_flag; data.password = opt->password_string; data.key_data = NULL; num = 0; if (data.random_key) ++num; if (data.random_password) ++num; if (data.password) ++num; if (opt->key_string) ++num; if (num > 1) { fprintf (stderr, "give only one of " "--random-key, --random-password, --password, --key\n"); return 1; } if (opt->key_string) { const char *error; if (parse_des_key (opt->key_string, key_data, &error)) { fprintf (stderr, "failed parsing key \"%s\": %s\n", opt->key_string, error); return 1; } data.key_data = key_data; } for(i = 0; i < argc; i++) ret = foreach_principal(argv[i], do_cpw_entry, "cpw", &data); if (data.key_data) { int16_t dummy; kadm5_free_key_data (kadm_handle, &dummy, key_data); } return ret != 0; }
static kadm5_ret_t kadmind_dispatch(void *kadm_handle, krb5_boolean initial, krb5_data *in, krb5_data *out) { kadm5_ret_t ret; int32_t cmd, mask, tmp; kadm5_server_context *context = kadm_handle; char client[128], name[128], name2[128]; char *op = ""; krb5_principal princ, princ2; kadm5_principal_ent_rec ent; char *password, *expression; krb5_keyblock *new_keys; int n_keys; char **princs; int n_princs; krb5_storage *sp; krb5_unparse_name_fixed(context->context, context->caller, client, sizeof(client)); sp = krb5_storage_from_data(in); if (sp == NULL) krb5_errx(context->context, 1, "out of memory"); krb5_ret_int32(sp, &cmd); switch(cmd){ case kadm_get:{ op = "GET"; ret = krb5_ret_principal(sp, &princ); if(ret) goto fail; ret = krb5_ret_int32(sp, &mask); if(ret){ krb5_free_principal(context->context, princ); goto fail; } mask |= KADM5_PRINCIPAL; krb5_unparse_name_fixed(context->context, princ, name, sizeof(name)); krb5_warnx(context->context, "%s: %s %s", client, op, name); ret = _kadm5_acl_check_permission(context, KADM5_PRIV_GET, princ); if(ret){ krb5_free_principal(context->context, princ); goto fail; } ret = kadm5_get_principal(kadm_handle, princ, &ent, mask); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); if(ret == 0){ kadm5_store_principal_ent(sp, &ent); kadm5_free_principal_ent(kadm_handle, &ent); } krb5_free_principal(context->context, princ); break; } case kadm_delete:{ op = "DELETE"; ret = krb5_ret_principal(sp, &princ); if(ret) goto fail; krb5_unparse_name_fixed(context->context, princ, name, sizeof(name)); krb5_warnx(context->context, "%s: %s %s", client, op, name); ret = _kadm5_acl_check_permission(context, KADM5_PRIV_DELETE, princ); if(ret){ krb5_free_principal(context->context, princ); goto fail; } ret = kadm5_delete_principal(kadm_handle, princ); krb5_free_principal(context->context, princ); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); break; } case kadm_create:{ op = "CREATE"; ret = kadm5_ret_principal_ent(sp, &ent); if(ret) goto fail; ret = krb5_ret_int32(sp, &mask); if(ret){ kadm5_free_principal_ent(context->context, &ent); goto fail; } ret = krb5_ret_string(sp, &password); if(ret){ kadm5_free_principal_ent(context->context, &ent); goto fail; } krb5_unparse_name_fixed(context->context, ent.principal, name, sizeof(name)); krb5_warnx(context->context, "%s: %s %s", client, op, name); ret = _kadm5_acl_check_permission(context, KADM5_PRIV_ADD, ent.principal); if(ret){ kadm5_free_principal_ent(context->context, &ent); memset(password, 0, strlen(password)); free(password); goto fail; } ret = kadm5_create_principal(kadm_handle, &ent, mask, password); kadm5_free_principal_ent(kadm_handle, &ent); memset(password, 0, strlen(password)); free(password); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); break; } case kadm_modify:{ op = "MODIFY"; ret = kadm5_ret_principal_ent(sp, &ent); if(ret) goto fail; ret = krb5_ret_int32(sp, &mask); if(ret){ kadm5_free_principal_ent(context, &ent); goto fail; } krb5_unparse_name_fixed(context->context, ent.principal, name, sizeof(name)); krb5_warnx(context->context, "%s: %s %s", client, op, name); ret = _kadm5_acl_check_permission(context, KADM5_PRIV_MODIFY, ent.principal); if(ret){ kadm5_free_principal_ent(context, &ent); goto fail; } ret = kadm5_modify_principal(kadm_handle, &ent, mask); kadm5_free_principal_ent(kadm_handle, &ent); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); break; } case kadm_rename:{ op = "RENAME"; ret = krb5_ret_principal(sp, &princ); if(ret) goto fail; ret = krb5_ret_principal(sp, &princ2); if(ret){ krb5_free_principal(context->context, princ); goto fail; } krb5_unparse_name_fixed(context->context, princ, name, sizeof(name)); krb5_unparse_name_fixed(context->context, princ2, name2, sizeof(name2)); krb5_warnx(context->context, "%s: %s %s -> %s", client, op, name, name2); ret = _kadm5_acl_check_permission(context, KADM5_PRIV_ADD, princ2) || _kadm5_acl_check_permission(context, KADM5_PRIV_DELETE, princ); if(ret){ krb5_free_principal(context->context, princ); krb5_free_principal(context->context, princ2); goto fail; } ret = kadm5_rename_principal(kadm_handle, princ, princ2); krb5_free_principal(context->context, princ); krb5_free_principal(context->context, princ2); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); break; } case kadm_chpass:{ op = "CHPASS"; ret = krb5_ret_principal(sp, &princ); if(ret) goto fail; ret = krb5_ret_string(sp, &password); if(ret){ krb5_free_principal(context->context, princ); goto fail; } krb5_unparse_name_fixed(context->context, princ, name, sizeof(name)); krb5_warnx(context->context, "%s: %s %s", client, op, name); /* * The change is allowed if at least one of: * a) it's for the principal him/herself and this was an * initial ticket, but then, check with the password quality * function. * b) the user is on the CPW ACL. */ if (initial && krb5_principal_compare (context->context, context->caller, princ)) { krb5_data pwd_data; const char *pwd_reason; pwd_data.data = password; pwd_data.length = strlen(password); pwd_reason = kadm5_check_password_quality (context->context, princ, &pwd_data); if (pwd_reason != NULL) ret = KADM5_PASS_Q_DICT; else ret = 0; } else ret = _kadm5_acl_check_permission(context, KADM5_PRIV_CPW, princ); if(ret) { krb5_free_principal(context->context, princ); memset(password, 0, strlen(password)); free(password); goto fail; } ret = kadm5_chpass_principal(kadm_handle, princ, password); krb5_free_principal(context->context, princ); memset(password, 0, strlen(password)); free(password); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); break; } case kadm_chpass_with_key:{ int i; krb5_key_data *key_data; int n_key_data; op = "CHPASS_WITH_KEY"; ret = krb5_ret_principal(sp, &princ); if(ret) goto fail; ret = krb5_ret_int32(sp, &n_key_data); if (ret) { krb5_free_principal(context->context, princ); goto fail; } /* n_key_data will be squeezed into an int16_t below. */ if (n_key_data < 0 || n_key_data >= 1 << 16 || n_key_data > UINT_MAX/sizeof(*key_data)) { ret = ERANGE; krb5_free_principal(context->context, princ); goto fail; } key_data = malloc (n_key_data * sizeof(*key_data)); if (key_data == NULL && n_key_data != 0) { ret = ENOMEM; krb5_free_principal(context->context, princ); goto fail; } for (i = 0; i < n_key_data; ++i) { ret = kadm5_ret_key_data (sp, &key_data[i]); if (ret) { int16_t dummy = i; kadm5_free_key_data (context, &dummy, key_data); free (key_data); krb5_free_principal(context->context, princ); goto fail; } } krb5_unparse_name_fixed(context->context, princ, name, sizeof(name)); krb5_warnx(context->context, "%s: %s %s", client, op, name); /* * The change is only allowed if the user is on the CPW ACL, * this it to force password quality check on the user. */ ret = _kadm5_acl_check_permission(context, KADM5_PRIV_CPW, princ); if(ret) { int16_t dummy = n_key_data; kadm5_free_key_data (context, &dummy, key_data); free (key_data); krb5_free_principal(context->context, princ); goto fail; } ret = kadm5_chpass_principal_with_key(kadm_handle, princ, n_key_data, key_data); { int16_t dummy = n_key_data; kadm5_free_key_data (context, &dummy, key_data); } free (key_data); krb5_free_principal(context->context, princ); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); break; } case kadm_randkey:{ op = "RANDKEY"; ret = krb5_ret_principal(sp, &princ); if(ret) goto fail; krb5_unparse_name_fixed(context->context, princ, name, sizeof(name)); krb5_warnx(context->context, "%s: %s %s", client, op, name); /* * The change is allowed if at least one of: * a) it's for the principal him/herself and this was an initial ticket * b) the user is on the CPW ACL. */ if (initial && krb5_principal_compare (context->context, context->caller, princ)) ret = 0; else ret = _kadm5_acl_check_permission(context, KADM5_PRIV_CPW, princ); if(ret) { krb5_free_principal(context->context, princ); goto fail; } ret = kadm5_randkey_principal(kadm_handle, princ, &new_keys, &n_keys); krb5_free_principal(context->context, princ); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); if(ret == 0){ int i; krb5_store_int32(sp, n_keys); for(i = 0; i < n_keys; i++){ krb5_store_keyblock(sp, new_keys[i]); krb5_free_keyblock_contents(context->context, &new_keys[i]); } free(new_keys); } break; } case kadm_get_privs:{ uint32_t privs; ret = kadm5_get_privs(kadm_handle, &privs); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); if(ret == 0) krb5_store_uint32(sp, privs); break; } case kadm_get_princs:{ op = "LIST"; ret = krb5_ret_int32(sp, &tmp); if(ret) goto fail; if(tmp){ ret = krb5_ret_string(sp, &expression); if(ret) goto fail; }else expression = NULL; krb5_warnx(context->context, "%s: %s %s", client, op, expression ? expression : "*"); ret = _kadm5_acl_check_permission(context, KADM5_PRIV_LIST, NULL); if(ret){ free(expression); goto fail; } ret = kadm5_get_principals(kadm_handle, expression, &princs, &n_princs); free(expression); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); if(ret == 0){ int i; krb5_store_int32(sp, n_princs); for(i = 0; i < n_princs; i++) krb5_store_string(sp, princs[i]); kadm5_free_name_list(kadm_handle, princs, &n_princs); } break; } default: krb5_warnx(context->context, "%s: UNKNOWN OP %d", client, cmd); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, KADM5_FAILURE); break; } krb5_storage_to_data(sp, out); krb5_storage_free(sp); return 0; fail: krb5_warn(context->context, ret, "%s", op); krb5_storage_seek(sp, 0, SEEK_SET); krb5_store_int32(sp, ret); krb5_storage_to_data(sp, out); krb5_storage_free(sp); return 0; }
static kadm5_ret_t kadmind_dispatch(void *kadm_handlep, krb5_boolean initial, krb5_data *in, krb5_data *out) { kadm5_ret_t ret; int32_t cmd, mask, tmp; kadm5_server_context *contextp = kadm_handlep; char client[128], name[128], name2[128]; const char *op = ""; krb5_principal princ, princ2; kadm5_principal_ent_rec ent; char *password, *expression; krb5_keyblock *new_keys; krb5_key_salt_tuple *ks_tuple = NULL; krb5_boolean keepold = FALSE; int n_ks_tuple = 0; int n_keys; char **princs; int n_princs; int keys_ok = 0; krb5_storage *sp; krb5_unparse_name_fixed(contextp->context, contextp->caller, client, sizeof(client)); sp = krb5_storage_from_data(in); if (sp == NULL) krb5_errx(contextp->context, 1, "out of memory"); krb5_ret_int32(sp, &cmd); switch(cmd){ case kadm_get:{ op = "GET"; ret = krb5_ret_principal(sp, &princ); if(ret) goto fail; ret = krb5_ret_int32(sp, &mask); if(ret){ krb5_free_principal(contextp->context, princ); goto fail; } mask |= KADM5_PRINCIPAL; krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name)); krb5_warnx(contextp->context, "%s: %s %s", client, op, name); /* If the caller doesn't have KADM5_PRIV_GET, we're done. */ ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_GET, princ); if (ret) { krb5_free_principal(contextp->context, princ); goto fail; } /* Then check to see if it is ok to return keys */ if ((mask & KADM5_KEY_DATA) != 0) { ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_GET_KEYS, princ); if (ret == 0) { keys_ok = 1; } else if ((mask == (KADM5_PRINCIPAL|KADM5_KEY_DATA)) || (mask == (KADM5_PRINCIPAL|KADM5_KVNO|KADM5_KEY_DATA))) { /* * Requests for keys will get bogus keys, which is useful if * the client just wants to see what (kvno, enctype)s the * principal has keys for, but terrible if the client wants to * write the keys into a keytab or modify the principal and * write the bogus keys back to the server. * * We use a heuristic to detect which case we're handling here. * If the client only asks for the flags in the above * condition, then it's very likely a kadmin ext_keytab, * add_enctype, or other request that should not see bogus * keys. We deny them. * * The kadmin get command can be coaxed into making a request * with the same mask. But the default long and terse output * modes request other things too, so in all likelihood this * heuristic will not hurt any kadmin get uses. */ krb5_free_principal(contextp->context, princ); goto fail; } } ret = kadm5_get_principal(kadm_handlep, princ, &ent, mask); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); if (ret == 0){ if (keys_ok) kadm5_store_principal_ent(sp, &ent); else kadm5_store_principal_ent_nokeys(sp, &ent); kadm5_free_principal_ent(kadm_handlep, &ent); } krb5_free_principal(contextp->context, princ); break; } case kadm_delete:{ op = "DELETE"; ret = krb5_ret_principal(sp, &princ); if(ret) goto fail; krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name)); krb5_warnx(contextp->context, "%s: %s %s", client, op, name); ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_DELETE, princ); if(ret){ krb5_free_principal(contextp->context, princ); goto fail; } ret = kadm5_delete_principal(kadm_handlep, princ); krb5_free_principal(contextp->context, princ); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); break; } case kadm_create:{ op = "CREATE"; ret = kadm5_ret_principal_ent(sp, &ent); if(ret) goto fail; ret = krb5_ret_int32(sp, &mask); if(ret){ kadm5_free_principal_ent(contextp->context, &ent); goto fail; } ret = krb5_ret_string(sp, &password); if(ret){ kadm5_free_principal_ent(contextp->context, &ent); goto fail; } krb5_unparse_name_fixed(contextp->context, ent.principal, name, sizeof(name)); krb5_warnx(contextp->context, "%s: %s %s", client, op, name); ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_ADD, ent.principal); if(ret){ kadm5_free_principal_ent(contextp->context, &ent); memset(password, 0, strlen(password)); free(password); goto fail; } ret = kadm5_create_principal(kadm_handlep, &ent, mask, password); kadm5_free_principal_ent(kadm_handlep, &ent); memset(password, 0, strlen(password)); free(password); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); break; } case kadm_modify:{ op = "MODIFY"; ret = kadm5_ret_principal_ent(sp, &ent); if(ret) goto fail; ret = krb5_ret_int32(sp, &mask); if(ret){ kadm5_free_principal_ent(contextp, &ent); goto fail; } krb5_unparse_name_fixed(contextp->context, ent.principal, name, sizeof(name)); krb5_warnx(contextp->context, "%s: %s %s", client, op, name); ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_MODIFY, ent.principal); if(ret){ kadm5_free_principal_ent(contextp, &ent); goto fail; } ret = kadm5_modify_principal(kadm_handlep, &ent, mask); kadm5_free_principal_ent(kadm_handlep, &ent); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); break; } case kadm_rename:{ op = "RENAME"; ret = krb5_ret_principal(sp, &princ); if(ret) goto fail; ret = krb5_ret_principal(sp, &princ2); if(ret){ krb5_free_principal(contextp->context, princ); goto fail; } krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name)); krb5_unparse_name_fixed(contextp->context, princ2, name2, sizeof(name2)); krb5_warnx(contextp->context, "%s: %s %s -> %s", client, op, name, name2); ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_ADD, princ2) || _kadm5_acl_check_permission(contextp, KADM5_PRIV_DELETE, princ); if(ret){ krb5_free_principal(contextp->context, princ); krb5_free_principal(contextp->context, princ2); goto fail; } ret = kadm5_rename_principal(kadm_handlep, princ, princ2); krb5_free_principal(contextp->context, princ); krb5_free_principal(contextp->context, princ2); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); break; } case kadm_chpass:{ op = "CHPASS"; ret = krb5_ret_principal(sp, &princ); if (ret) goto fail; ret = krb5_ret_string(sp, &password); if (ret) { krb5_free_principal(contextp->context, princ); goto fail; } ret = krb5_ret_int32(sp, &keepold); if (ret && ret != HEIM_ERR_EOF) { krb5_free_principal(contextp->context, princ); goto fail; } krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name)); krb5_warnx(contextp->context, "%s: %s %s", client, op, name); /* * The change is allowed if at least one of: * * a) allowed by sysadmin * b) it's for the principal him/herself and this was an * initial ticket, but then, check with the password quality * function. * c) the user is on the CPW ACL. */ if (krb5_config_get_bool_default(contextp->context, NULL, TRUE, "kadmin", "allow_self_change_password", NULL) && initial && krb5_principal_compare (contextp->context, contextp->caller, princ)) { krb5_data pwd_data; const char *pwd_reason; pwd_data.data = password; pwd_data.length = strlen(password); pwd_reason = kadm5_check_password_quality (contextp->context, princ, &pwd_data); if (pwd_reason != NULL) ret = KADM5_PASS_Q_DICT; else ret = 0; } else ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_CPW, princ); if(ret) { krb5_free_principal(contextp->context, princ); memset(password, 0, strlen(password)); free(password); goto fail; } ret = kadm5_chpass_principal_3(kadm_handlep, princ, keepold, 0, NULL, password); krb5_free_principal(contextp->context, princ); memset(password, 0, strlen(password)); free(password); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); break; } case kadm_chpass_with_key:{ int i; krb5_key_data *key_data; int n_key_data; op = "CHPASS_WITH_KEY"; ret = krb5_ret_principal(sp, &princ); if(ret) goto fail; ret = krb5_ret_int32(sp, &n_key_data); if (ret) { krb5_free_principal(contextp->context, princ); goto fail; } ret = krb5_ret_int32(sp, &keepold); if (ret && ret != HEIM_ERR_EOF) { krb5_free_principal(contextp->context, princ); goto fail; } /* n_key_data will be squeezed into an int16_t below. */ if (n_key_data < 0 || n_key_data >= 1 << 16 || (size_t)n_key_data > UINT_MAX/sizeof(*key_data)) { ret = ERANGE; krb5_free_principal(contextp->context, princ); goto fail; } key_data = malloc (n_key_data * sizeof(*key_data)); if (key_data == NULL && n_key_data != 0) { ret = ENOMEM; krb5_free_principal(contextp->context, princ); goto fail; } for (i = 0; i < n_key_data; ++i) { ret = kadm5_ret_key_data (sp, &key_data[i]); if (ret) { int16_t dummy = i; kadm5_free_key_data (contextp, &dummy, key_data); free (key_data); krb5_free_principal(contextp->context, princ); goto fail; } } krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name)); krb5_warnx(contextp->context, "%s: %s %s", client, op, name); /* * The change is only allowed if the user is on the CPW ACL, * this it to force password quality check on the user. */ ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_CPW, princ); if(ret) { int16_t dummy = n_key_data; kadm5_free_key_data (contextp, &dummy, key_data); free (key_data); krb5_free_principal(contextp->context, princ); goto fail; } ret = kadm5_chpass_principal_with_key_3(kadm_handlep, princ, keepold, n_key_data, key_data); { int16_t dummy = n_key_data; kadm5_free_key_data (contextp, &dummy, key_data); } free (key_data); krb5_free_principal(contextp->context, princ); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); break; } case kadm_randkey:{ op = "RANDKEY"; ret = krb5_ret_principal(sp, &princ); if(ret) goto fail; krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name)); krb5_warnx(contextp->context, "%s: %s %s", client, op, name); /* * The change is allowed if at least one of: * a) it's for the principal him/herself and this was an initial ticket * b) the user is on the CPW ACL. */ if (initial && krb5_principal_compare (contextp->context, contextp->caller, princ)) ret = 0; else ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_CPW, princ); if(ret) { krb5_free_principal(contextp->context, princ); goto fail; } /* * See comments in kadm5_c_randkey_principal() regarding the * protocol. */ ret = krb5_ret_int32(sp, &keepold); if (ret != 0 && ret != HEIM_ERR_EOF) { krb5_free_principal(contextp->context, princ); goto fail; } ret = krb5_ret_int32(sp, &n_ks_tuple); if (ret != 0 && ret != HEIM_ERR_EOF) { krb5_free_principal(contextp->context, princ); goto fail; } else if (ret == 0) { size_t i; if (n_ks_tuple < 0) { ret = EOVERFLOW; krb5_free_principal(contextp->context, princ); goto fail; } if ((ks_tuple = calloc(n_ks_tuple, sizeof (*ks_tuple))) == NULL) { ret = errno; krb5_free_principal(contextp->context, princ); goto fail; } for (i = 0; i < n_ks_tuple; i++) { ret = krb5_ret_int32(sp, &ks_tuple[i].ks_enctype); if (ret != 0) { krb5_free_principal(contextp->context, princ); goto fail; } ret = krb5_ret_int32(sp, &ks_tuple[i].ks_salttype); if (ret != 0) { krb5_free_principal(contextp->context, princ); goto fail; } } } ret = kadm5_randkey_principal_3(kadm_handlep, princ, keepold, n_ks_tuple, ks_tuple, &new_keys, &n_keys); krb5_free_principal(contextp->context, princ); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); if(ret == 0){ int i; krb5_store_int32(sp, n_keys); for(i = 0; i < n_keys; i++){ krb5_store_keyblock(sp, new_keys[i]); krb5_free_keyblock_contents(contextp->context, &new_keys[i]); } free(new_keys); } break; } case kadm_get_privs:{ uint32_t privs; ret = kadm5_get_privs(kadm_handlep, &privs); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); if(ret == 0) krb5_store_uint32(sp, privs); break; } case kadm_get_princs:{ op = "LIST"; ret = krb5_ret_int32(sp, &tmp); if(ret) goto fail; if(tmp){ ret = krb5_ret_string(sp, &expression); if(ret) goto fail; }else expression = NULL; krb5_warnx(contextp->context, "%s: %s %s", client, op, expression ? expression : "*"); ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_LIST, NULL); if(ret){ free(expression); goto fail; } ret = kadm5_get_principals(kadm_handlep, expression, &princs, &n_princs); free(expression); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, ret); if(ret == 0){ int i; krb5_store_int32(sp, n_princs); for(i = 0; i < n_princs; i++) krb5_store_string(sp, princs[i]); kadm5_free_name_list(kadm_handlep, princs, &n_princs); } break; } default: krb5_warnx(contextp->context, "%s: UNKNOWN OP %d", client, cmd); krb5_storage_free(sp); sp = krb5_storage_emem(); krb5_store_int32(sp, KADM5_FAILURE); break; } krb5_storage_to_data(sp, out); krb5_storage_free(sp); return 0; fail: krb5_warn(contextp->context, ret, "%s", op); krb5_storage_seek(sp, 0, SEEK_SET); krb5_store_int32(sp, ret); krb5_storage_to_data(sp, out); krb5_storage_free(sp); return 0; }
int del_enctype(void *opt, int argc, char **argv) { kadm5_principal_ent_rec princ; krb5_principal princ_ent = NULL; krb5_error_code ret; const char *princ_name; int i, j, k; krb5_key_data *new_key_data; int n_etypes; krb5_enctype *etypes; memset (&princ, 0, sizeof(princ)); princ_name = argv[0]; n_etypes = argc - 1; etypes = malloc (n_etypes * sizeof(*etypes)); if (etypes == NULL) { krb5_warnx (context, "out of memory"); return 0; } argv++; for (i = 0; i < n_etypes; ++i) { ret = krb5_string_to_enctype (context, argv[i], &etypes[i]); if (ret) { krb5_warnx (context, "bad enctype \"%s\"", argv[i]); goto out2; } } ret = krb5_parse_name(context, princ_name, &princ_ent); if (ret) { krb5_warn (context, ret, "krb5_parse_name %s", princ_name); goto out2; } ret = kadm5_get_principal(kadm_handle, princ_ent, &princ, KADM5_PRINCIPAL | KADM5_KEY_DATA); if (ret) { krb5_free_principal (context, princ_ent); krb5_warnx (context, "no such principal: %s", princ_name); goto out2; } new_key_data = malloc(princ.n_key_data * sizeof(*new_key_data)); if (new_key_data == NULL && princ.n_key_data != 0) { krb5_warnx (context, "out of memory"); goto out; } for (i = 0, j = 0; i < princ.n_key_data; ++i) { krb5_key_data *key = &princ.key_data[i]; int docopy = 1; for (k = 0; k < n_etypes; ++k) if (etypes[k] == key->key_data_type[0]) { docopy = 0; break; } if (docopy) { new_key_data[j++] = *key; } else { int16_t ignore = 1; kadm5_free_key_data (kadm_handle, &ignore, key); } } free (princ.key_data); princ.n_key_data = j; princ.key_data = new_key_data; ret = kadm5_modify_principal (kadm_handle, &princ, KADM5_KEY_DATA); if (ret) krb5_warn(context, ret, "kadm5_modify_principal"); out: krb5_free_principal (context, princ_ent); kadm5_free_principal_ent(kadm_handle, &princ); out2: free (etypes); return ret != 0; }