diff --git a/kadmin/server.c b/kadmin/server.c new file mode 100644 index 000000000..cbb6f80ad --- /dev/null +++ b/kadmin/server.c @@ -0,0 +1,255 @@ +/* + * Copyright (c) 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "kadm5_locl.h" + +RCSID("$Id$"); + +kadm5_ret_t +kadmind_dispatch(void *kadm_handle, krb5_storage *sp) +{ + int32_t cmd; + kadm5_ret_t ret; + kadm5_server_context *context = kadm_handle; + char client[128], name[128], name2[128]; + char *op = ""; + krb5_principal princ, princ2; + kadm5_principal_ent_rec ent; + int32_t mask; + char *password; + krb5_keyblock *new_keys; + int n_keys; + + krb5_unparse_name_fixed(context->context, context->caller, + client, sizeof(client)); + + 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; + } + 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_ACL_GET); + if(ret){ + krb5_free_principal(context->context, princ); + goto fail; + } + ret = kadm5_get_principal(kadm_handle, princ, &ent, mask); + sp->seek(sp, 0, SEEK_SET); + krb5_store_int32(sp, ret); + if(ret == 0) + kadm5_store_principal_ent(sp, &ent); + kadm5_free_principal_ent(kadm_handle, &ent); + 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_ACL_DELETE); + if(ret){ + krb5_free_principal(context->context, princ); + goto fail; + } + ret = kadm5_delete_principal(kadm_handle, princ); + krb5_free_principal(context->context, princ); + sp->seek(sp, 0, SEEK_SET); + 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_ACL_CREATE); + 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); + sp->seek(sp, 0, SEEK_SET); + 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_ACL_MODIFY); + 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); + sp->seek(sp, 0, SEEK_SET); + 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_ACL_CREATE|KADM5_ACL_DELETE); + if(ret){ + krb5_free_principal(context->context, princ); + goto fail; + } + ret = kadm5_rename_principal(kadm_handle, princ, princ2); + krb5_free_principal(context->context, princ); + krb5_free_principal(context->context, princ2); + sp->seek(sp, 0, SEEK_SET); + 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); + ret = _kadm5_acl_check_permission(context, KADM5_ACL_CHPASS); + if(ret){ + krb5_free_principal(context->context, princ); + goto fail; + } + ret = kadm5_chpass_principal(kadm_handle, princ, password); + krb5_free_principal(context->context, princ); + memset(password, 0, strlen(password)); + free(password); + sp->seek(sp, 0, SEEK_SET); + 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); + ret = _kadm5_acl_check_permission(context, KADM5_ACL_CHPASS); + 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); + sp->seek(sp, 0, SEEK_SET); + 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(context->context, &new_keys[i]); + } + } + break; + } + default: + krb5_warnx(context->context, "%s: UNKNOWN OP %d", client, cmd); + sp->seek(sp, 0, SEEK_SET); + krb5_store_int32(sp, KADM5_FAILURE); + break; + } + return 0; +fail: + krb5_warnx(context->context, "%s", op); + sp->seek(sp, 0, SEEK_SET); + krb5_store_int32(sp, ret); + return 0; +} diff --git a/lib/kadm5/server.c b/lib/kadm5/server.c new file mode 100644 index 000000000..cbb6f80ad --- /dev/null +++ b/lib/kadm5/server.c @@ -0,0 +1,255 @@ +/* + * Copyright (c) 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "kadm5_locl.h" + +RCSID("$Id$"); + +kadm5_ret_t +kadmind_dispatch(void *kadm_handle, krb5_storage *sp) +{ + int32_t cmd; + kadm5_ret_t ret; + kadm5_server_context *context = kadm_handle; + char client[128], name[128], name2[128]; + char *op = ""; + krb5_principal princ, princ2; + kadm5_principal_ent_rec ent; + int32_t mask; + char *password; + krb5_keyblock *new_keys; + int n_keys; + + krb5_unparse_name_fixed(context->context, context->caller, + client, sizeof(client)); + + 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; + } + 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_ACL_GET); + if(ret){ + krb5_free_principal(context->context, princ); + goto fail; + } + ret = kadm5_get_principal(kadm_handle, princ, &ent, mask); + sp->seek(sp, 0, SEEK_SET); + krb5_store_int32(sp, ret); + if(ret == 0) + kadm5_store_principal_ent(sp, &ent); + kadm5_free_principal_ent(kadm_handle, &ent); + 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_ACL_DELETE); + if(ret){ + krb5_free_principal(context->context, princ); + goto fail; + } + ret = kadm5_delete_principal(kadm_handle, princ); + krb5_free_principal(context->context, princ); + sp->seek(sp, 0, SEEK_SET); + 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_ACL_CREATE); + 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); + sp->seek(sp, 0, SEEK_SET); + 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_ACL_MODIFY); + 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); + sp->seek(sp, 0, SEEK_SET); + 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_ACL_CREATE|KADM5_ACL_DELETE); + if(ret){ + krb5_free_principal(context->context, princ); + goto fail; + } + ret = kadm5_rename_principal(kadm_handle, princ, princ2); + krb5_free_principal(context->context, princ); + krb5_free_principal(context->context, princ2); + sp->seek(sp, 0, SEEK_SET); + 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); + ret = _kadm5_acl_check_permission(context, KADM5_ACL_CHPASS); + if(ret){ + krb5_free_principal(context->context, princ); + goto fail; + } + ret = kadm5_chpass_principal(kadm_handle, princ, password); + krb5_free_principal(context->context, princ); + memset(password, 0, strlen(password)); + free(password); + sp->seek(sp, 0, SEEK_SET); + 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); + ret = _kadm5_acl_check_permission(context, KADM5_ACL_CHPASS); + 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); + sp->seek(sp, 0, SEEK_SET); + 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(context->context, &new_keys[i]); + } + } + break; + } + default: + krb5_warnx(context->context, "%s: UNKNOWN OP %d", client, cmd); + sp->seek(sp, 0, SEEK_SET); + krb5_store_int32(sp, KADM5_FAILURE); + break; + } + return 0; +fail: + krb5_warnx(context->context, "%s", op); + sp->seek(sp, 0, SEEK_SET); + krb5_store_int32(sp, ret); + return 0; +}