diff options
Diffstat (limited to 'crypto/heimdal/kadmin/server.c')
-rw-r--r-- | crypto/heimdal/kadmin/server.c | 193 |
1 files changed, 121 insertions, 72 deletions
diff --git a/crypto/heimdal/kadmin/server.c b/crypto/heimdal/kadmin/server.c index d491e46..add1dde 100644 --- a/crypto/heimdal/kadmin/server.c +++ b/crypto/heimdal/kadmin/server.c @@ -34,7 +34,7 @@ #include "kadmin_locl.h" #include <krb5-private.h> -RCSID("$Id: server.c,v 1.24 2000/01/02 03:58:45 assar Exp $"); +RCSID("$Id: server.c,v 1.32 2000/09/19 12:46:01 assar Exp $"); static kadm5_ret_t kadmind_dispatch(void *kadm_handle, krb5_boolean initial, @@ -73,7 +73,7 @@ kadmind_dispatch(void *kadm_handle, krb5_boolean initial, } 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); + ret = _kadm5_acl_check_permission(context, KADM5_PRIV_GET, princ); if(ret){ krb5_free_principal(context->context, princ); goto fail; @@ -96,7 +96,7 @@ kadmind_dispatch(void *kadm_handle, krb5_boolean initial, 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); + ret = _kadm5_acl_check_permission(context, KADM5_PRIV_DELETE, princ); if(ret){ krb5_free_principal(context->context, princ); goto fail; @@ -126,7 +126,8 @@ kadmind_dispatch(void *kadm_handle, krb5_boolean initial, 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); + 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)); @@ -156,7 +157,8 @@ kadmind_dispatch(void *kadm_handle, krb5_boolean initial, 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); + ret = _kadm5_acl_check_permission(context, KADM5_PRIV_MODIFY, + ent.principal); if(ret){ kadm5_free_principal_ent(context, &ent); goto fail; @@ -183,7 +185,11 @@ kadmind_dispatch(void *kadm_handle, krb5_boolean initial, krb5_warnx(context->context, "%s: %s %s -> %s", client, op, name, name2); ret = _kadm5_acl_check_permission(context, - KADM5_PRIV_ADD|KADM5_PRIV_DELETE); + KADM5_PRIV_ADD, + princ2) + || _kadm5_acl_check_permission(context, + KADM5_PRIV_DELETE, + princ); if(ret){ krb5_free_principal(context->context, princ); goto fail; @@ -220,7 +226,7 @@ kadmind_dispatch(void *kadm_handle, krb5_boolean initial, princ)) ret = 0; else - ret = _kadm5_acl_check_permission(context, KADM5_PRIV_CPW); + ret = _kadm5_acl_check_permission(context, KADM5_PRIV_CPW, princ); if(ret) { krb5_free_principal(context->context, princ); @@ -235,6 +241,77 @@ kadmind_dispatch(void *kadm_handle, krb5_boolean initial, 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; + } + + key_data = malloc (n_key_data * sizeof(*key_data)); + if (key_data == NULL) { + 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 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) { + 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); @@ -253,7 +330,7 @@ kadmind_dispatch(void *kadm_handle, krb5_boolean initial, princ)) ret = 0; else - ret = _kadm5_acl_check_permission(context, KADM5_PRIV_CPW); + ret = _kadm5_acl_check_permission(context, KADM5_PRIV_CPW, princ); if(ret) { krb5_free_principal(context->context, princ); @@ -296,7 +373,7 @@ kadmind_dispatch(void *kadm_handle, krb5_boolean initial, }else exp = NULL; krb5_warnx(context->context, "%s: %s %s", client, op, exp ? exp : "*"); - ret = _kadm5_acl_check_permission(context, KADM5_PRIV_LIST); + ret = _kadm5_acl_check_permission(context, KADM5_PRIV_LIST, NULL); if(ret){ free(exp); goto fail; @@ -342,52 +419,23 @@ v5_loop (krb5_context context, int fd) { krb5_error_code ret; - ssize_t n; - unsigned long len; - u_char tmp[4]; - struct iovec iov[2]; - krb5_data in, out, msg, reply; + krb5_data in, out; for (;;) { - n = krb5_net_read(context, &fd, tmp, 4); - if (n < 0) - krb5_err (context, 1, errno, "krb5_net_read"); - if (n == 0) - exit (0); - _krb5_get_int (tmp, &len, 4); - - ret = krb5_data_alloc(&in, len); - if (ret) - krb5_err (context, 1, ret, "krb5_data_alloc"); - - n = krb5_net_read(context, &fd, in.data, in.length); - if (n == 0) - exit (0); - if(n < 0) - krb5_errx(context, 1, "read error: %d", errno); - ret = krb5_rd_priv(context, ac, &in, &out, NULL); - if (ret) - krb5_err(context, 1, ret, "krb5_rd_priv"); + doing_useful_work = 0; + if(term_flag) + exit(0); + ret = krb5_read_priv_message(context, ac, &fd, &in); + if(ret == HEIM_ERR_EOF) + exit(0); + if(ret) + krb5_err(context, 1, ret, "krb5_read_priv_message"); + doing_useful_work = 1; + kadmind_dispatch(kadm_handle, initial, &in, &out); krb5_data_free(&in); - kadmind_dispatch(kadm_handle, initial, &out, &msg); - krb5_data_free(&out); - ret = krb5_mk_priv(context, ac, &msg, &reply, NULL); - krb5_data_free(&msg); - if(ret) - krb5_err(context, 1, ret, "krb5_mk_priv"); - - _krb5_put_int(tmp, reply.length, 4); - - iov[0].iov_base = tmp; - iov[0].iov_len = 4; - iov[1].iov_base = reply.data; - iov[1].iov_len = reply.length; - n = writev(fd, iov, 2); - krb5_data_free(&reply); - if(n < 0) - krb5_err(context, 1, errno, "writev"); - if(n < iov[0].iov_len + iov[1].iov_len) - krb5_errx(context, 1, "short write"); + ret = krb5_write_priv_message(context, ac, &fd, &out); + if(ret) + krb5_err(context, 1, ret, "krb5_write_priv_message"); } } @@ -411,7 +459,7 @@ handle_v5(krb5_context context, krb5_error_code ret; u_char version[sizeof(KRB5_SENDAUTH_VERSION)]; krb5_ticket *ticket; - krb5_principal server; + char *server_name; char *client; void *kadm_handle; ssize_t n; @@ -430,32 +478,33 @@ handle_v5(krb5_context context, if(memcmp(version, KRB5_SENDAUTH_VERSION, len) != 0) krb5_errx(context, 1, "bad sendauth version %.8s", version); - ret = krb5_parse_name(context, KADM5_ADMIN_SERVICE, &server); - if (ret) - krb5_err (context, 1, ret, "krb5_parse_name %s", KADM5_ADMIN_SERVICE); ret = krb5_recvauth_match_version(context, &ac, &fd, match_appl_version, &kadm_version, - server, KRB5_RECVAUTH_IGNORE_VERSION, + NULL, KRB5_RECVAUTH_IGNORE_VERSION, keytab, &ticket); - if(ret == KRB5_KT_NOTFOUND) { - char *name; - krb5_unparse_name(context, server, &name); - krb5_errx(context, 1, "krb5_recvauth: %s (%s)", - krb5_get_err_text(context, ret), - name); - } - krb5_free_principal(context, server); - + if(ret == KRB5_KT_NOTFOUND) + krb5_errx(context, 1, "krb5_recvauth: key no found"); if(ret) krb5_err(context, 1, ret, "krb5_recvauth"); + ret = krb5_unparse_name (context, ticket->server, &server_name); + if (ret) + krb5_err (context, 1, ret, "krb5_unparse_name"); + + if (strncmp (server_name, KADM5_ADMIN_SERVICE, + strlen(KADM5_ADMIN_SERVICE)) != 0) + krb5_errx (context, 1, "ticket for strange principal (%s)", + server_name); + + free (server_name); + memset(&realm_params, 0, sizeof(realm_params)); if(kadm_version == 1) { - krb5_data enc_data, params; - ret = krb5_read_message(context, &fd, &enc_data); - ret = krb5_rd_priv(context, ac, &enc_data, ¶ms, NULL); - krb5_data_free(&enc_data); + krb5_data params; + ret = krb5_read_priv_message(context, ac, &fd, ¶ms); + if(ret) + krb5_err(context, 1, ret, "krb5_read_priv_message"); _kadm5_unmarshal_params(context, ¶ms, &realm_params); } @@ -490,12 +539,12 @@ kadmind_loop(krb5_context context, if(n == 0) exit(0); if(n < 0) - krb5_errx(context, 1, "read error: %d", errno); + krb5_err(context, 1, errno, "read"); _krb5_get_int(tmp, &len, 4); if(len > 0xffff && (len & 0xffff) == ('K' << 8) + 'A') { len >>= 16; #ifdef KRB4 - handle_v4(context, len, fd); + handle_v4(context, keytab, len, fd); #else krb5_errx(context, 1, "packet appears to be version 4"); #endif |