155682Smarkm/* 2233294Sstas * Copyright (c) 1997 - 2005 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 555682Smarkm * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 955682Smarkm * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 1655682Smarkm * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 2055682Smarkm * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "kadmin_locl.h" 3555682Smarkm#include <krb5-private.h> 3655682Smarkm 3755682Smarkmstatic kadm5_ret_t 38233294Sstaskadmind_dispatch(void *kadm_handlep, krb5_boolean initial, 3955682Smarkm krb5_data *in, krb5_data *out) 4055682Smarkm{ 4155682Smarkm kadm5_ret_t ret; 4255682Smarkm int32_t cmd, mask, tmp; 43233294Sstas kadm5_server_context *contextp = kadm_handlep; 4455682Smarkm char client[128], name[128], name2[128]; 45233294Sstas const char *op = ""; 4655682Smarkm krb5_principal princ, princ2; 4755682Smarkm kadm5_principal_ent_rec ent; 48178825Sdfr char *password, *expression; 4955682Smarkm krb5_keyblock *new_keys; 5055682Smarkm int n_keys; 5155682Smarkm char **princs; 5255682Smarkm int n_princs; 5355682Smarkm krb5_storage *sp; 54233294Sstas 55233294Sstas krb5_unparse_name_fixed(contextp->context, contextp->caller, 5655682Smarkm client, sizeof(client)); 57233294Sstas 5855682Smarkm sp = krb5_storage_from_data(in); 59233294Sstas if (sp == NULL) 60233294Sstas krb5_errx(contextp->context, 1, "out of memory"); 6155682Smarkm 6255682Smarkm krb5_ret_int32(sp, &cmd); 6355682Smarkm switch(cmd){ 6455682Smarkm case kadm_get:{ 6555682Smarkm op = "GET"; 6655682Smarkm ret = krb5_ret_principal(sp, &princ); 6755682Smarkm if(ret) 6855682Smarkm goto fail; 6955682Smarkm ret = krb5_ret_int32(sp, &mask); 7055682Smarkm if(ret){ 71233294Sstas krb5_free_principal(contextp->context, princ); 7255682Smarkm goto fail; 7355682Smarkm } 74233294Sstas mask |= KADM5_PRINCIPAL; 75233294Sstas krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name)); 76233294Sstas krb5_warnx(contextp->context, "%s: %s %s", client, op, name); 77233294Sstas ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_GET, princ); 7855682Smarkm if(ret){ 79233294Sstas krb5_free_principal(contextp->context, princ); 8055682Smarkm goto fail; 8155682Smarkm } 82233294Sstas ret = kadm5_get_principal(kadm_handlep, princ, &ent, mask); 8355682Smarkm krb5_storage_free(sp); 8455682Smarkm sp = krb5_storage_emem(); 8555682Smarkm krb5_store_int32(sp, ret); 8655682Smarkm if(ret == 0){ 8755682Smarkm kadm5_store_principal_ent(sp, &ent); 88233294Sstas kadm5_free_principal_ent(kadm_handlep, &ent); 8955682Smarkm } 90233294Sstas krb5_free_principal(contextp->context, princ); 9155682Smarkm break; 9255682Smarkm } 9355682Smarkm case kadm_delete:{ 9455682Smarkm op = "DELETE"; 9555682Smarkm ret = krb5_ret_principal(sp, &princ); 9655682Smarkm if(ret) 9755682Smarkm goto fail; 98233294Sstas krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name)); 99233294Sstas krb5_warnx(contextp->context, "%s: %s %s", client, op, name); 100233294Sstas ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_DELETE, princ); 10155682Smarkm if(ret){ 102233294Sstas krb5_free_principal(contextp->context, princ); 10355682Smarkm goto fail; 10455682Smarkm } 105233294Sstas ret = kadm5_delete_principal(kadm_handlep, princ); 106233294Sstas krb5_free_principal(contextp->context, princ); 10755682Smarkm krb5_storage_free(sp); 10855682Smarkm sp = krb5_storage_emem(); 10955682Smarkm krb5_store_int32(sp, ret); 11055682Smarkm break; 11155682Smarkm } 11255682Smarkm case kadm_create:{ 11355682Smarkm op = "CREATE"; 11455682Smarkm ret = kadm5_ret_principal_ent(sp, &ent); 11555682Smarkm if(ret) 11655682Smarkm goto fail; 11755682Smarkm ret = krb5_ret_int32(sp, &mask); 11855682Smarkm if(ret){ 119233294Sstas kadm5_free_principal_ent(contextp->context, &ent); 12055682Smarkm goto fail; 12155682Smarkm } 12255682Smarkm ret = krb5_ret_string(sp, &password); 12355682Smarkm if(ret){ 124233294Sstas kadm5_free_principal_ent(contextp->context, &ent); 12555682Smarkm goto fail; 12655682Smarkm } 127233294Sstas krb5_unparse_name_fixed(contextp->context, ent.principal, 12855682Smarkm name, sizeof(name)); 129233294Sstas krb5_warnx(contextp->context, "%s: %s %s", client, op, name); 130233294Sstas ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_ADD, 13172445Sassar ent.principal); 13255682Smarkm if(ret){ 133233294Sstas kadm5_free_principal_ent(contextp->context, &ent); 13455682Smarkm memset(password, 0, strlen(password)); 13555682Smarkm free(password); 13655682Smarkm goto fail; 13755682Smarkm } 138233294Sstas ret = kadm5_create_principal(kadm_handlep, &ent, 13955682Smarkm mask, password); 140233294Sstas kadm5_free_principal_ent(kadm_handlep, &ent); 14155682Smarkm memset(password, 0, strlen(password)); 14255682Smarkm free(password); 14355682Smarkm krb5_storage_free(sp); 14455682Smarkm sp = krb5_storage_emem(); 14555682Smarkm krb5_store_int32(sp, ret); 14655682Smarkm break; 14755682Smarkm } 14855682Smarkm case kadm_modify:{ 14955682Smarkm op = "MODIFY"; 15055682Smarkm ret = kadm5_ret_principal_ent(sp, &ent); 15155682Smarkm if(ret) 15255682Smarkm goto fail; 15355682Smarkm ret = krb5_ret_int32(sp, &mask); 15455682Smarkm if(ret){ 155233294Sstas kadm5_free_principal_ent(contextp, &ent); 15655682Smarkm goto fail; 15755682Smarkm } 158233294Sstas krb5_unparse_name_fixed(contextp->context, ent.principal, 15955682Smarkm name, sizeof(name)); 160233294Sstas krb5_warnx(contextp->context, "%s: %s %s", client, op, name); 161233294Sstas ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_MODIFY, 16272445Sassar ent.principal); 16355682Smarkm if(ret){ 164233294Sstas kadm5_free_principal_ent(contextp, &ent); 16555682Smarkm goto fail; 16655682Smarkm } 167233294Sstas ret = kadm5_modify_principal(kadm_handlep, &ent, mask); 168233294Sstas kadm5_free_principal_ent(kadm_handlep, &ent); 16955682Smarkm krb5_storage_free(sp); 17055682Smarkm sp = krb5_storage_emem(); 17155682Smarkm krb5_store_int32(sp, ret); 17255682Smarkm break; 17355682Smarkm } 17455682Smarkm case kadm_rename:{ 17555682Smarkm op = "RENAME"; 17655682Smarkm ret = krb5_ret_principal(sp, &princ); 17755682Smarkm if(ret) 17855682Smarkm goto fail; 17955682Smarkm ret = krb5_ret_principal(sp, &princ2); 18055682Smarkm if(ret){ 181233294Sstas krb5_free_principal(contextp->context, princ); 18255682Smarkm goto fail; 18355682Smarkm } 184233294Sstas krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name)); 185233294Sstas krb5_unparse_name_fixed(contextp->context, princ2, name2, sizeof(name2)); 186233294Sstas krb5_warnx(contextp->context, "%s: %s %s -> %s", 18755682Smarkm client, op, name, name2); 188233294Sstas ret = _kadm5_acl_check_permission(contextp, 18972445Sassar KADM5_PRIV_ADD, 19072445Sassar princ2) 191233294Sstas || _kadm5_acl_check_permission(contextp, 19272445Sassar KADM5_PRIV_DELETE, 19372445Sassar princ); 19455682Smarkm if(ret){ 195233294Sstas krb5_free_principal(contextp->context, princ); 196233294Sstas krb5_free_principal(contextp->context, princ2); 19755682Smarkm goto fail; 19855682Smarkm } 199233294Sstas ret = kadm5_rename_principal(kadm_handlep, princ, princ2); 200233294Sstas krb5_free_principal(contextp->context, princ); 201233294Sstas krb5_free_principal(contextp->context, princ2); 20255682Smarkm krb5_storage_free(sp); 20355682Smarkm sp = krb5_storage_emem(); 20455682Smarkm krb5_store_int32(sp, ret); 20555682Smarkm break; 20655682Smarkm } 20755682Smarkm case kadm_chpass:{ 20855682Smarkm op = "CHPASS"; 20955682Smarkm ret = krb5_ret_principal(sp, &princ); 21055682Smarkm if(ret) 21155682Smarkm goto fail; 21255682Smarkm ret = krb5_ret_string(sp, &password); 21355682Smarkm if(ret){ 214233294Sstas krb5_free_principal(contextp->context, princ); 21555682Smarkm goto fail; 21655682Smarkm } 217233294Sstas krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name)); 218233294Sstas krb5_warnx(contextp->context, "%s: %s %s", client, op, name); 21955682Smarkm 22055682Smarkm /* 22155682Smarkm * The change is allowed if at least one of: 222233294Sstas * 223233294Sstas * a) allowed by sysadmin 224233294Sstas * b) it's for the principal him/herself and this was an 225120945Snectar * initial ticket, but then, check with the password quality 226120945Snectar * function. 227233294Sstas * c) the user is on the CPW ACL. 22855682Smarkm */ 22955682Smarkm 230233294Sstas if (krb5_config_get_bool_default(contextp->context, NULL, TRUE, 231233294Sstas "kadmin", "allow_self_change_password", NULL) 232233294Sstas && initial 233233294Sstas && krb5_principal_compare (contextp->context, contextp->caller, 23455682Smarkm princ)) 235120945Snectar { 236120945Snectar krb5_data pwd_data; 237120945Snectar const char *pwd_reason; 238120945Snectar 239120945Snectar pwd_data.data = password; 240120945Snectar pwd_data.length = strlen(password); 241120945Snectar 242233294Sstas pwd_reason = kadm5_check_password_quality (contextp->context, 243120945Snectar princ, &pwd_data); 244120945Snectar if (pwd_reason != NULL) 245120945Snectar ret = KADM5_PASS_Q_DICT; 246120945Snectar else 247120945Snectar ret = 0; 248120945Snectar } else 249233294Sstas ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_CPW, princ); 25055682Smarkm 25155682Smarkm if(ret) { 252233294Sstas krb5_free_principal(contextp->context, princ); 253120945Snectar memset(password, 0, strlen(password)); 254120945Snectar free(password); 25555682Smarkm goto fail; 25655682Smarkm } 257233294Sstas ret = kadm5_chpass_principal(kadm_handlep, princ, password); 258233294Sstas krb5_free_principal(contextp->context, princ); 25955682Smarkm memset(password, 0, strlen(password)); 26055682Smarkm free(password); 26155682Smarkm krb5_storage_free(sp); 26255682Smarkm sp = krb5_storage_emem(); 26355682Smarkm krb5_store_int32(sp, ret); 26455682Smarkm break; 26555682Smarkm } 26672445Sassar case kadm_chpass_with_key:{ 26772445Sassar int i; 26872445Sassar krb5_key_data *key_data; 26972445Sassar int n_key_data; 27072445Sassar 27172445Sassar op = "CHPASS_WITH_KEY"; 27272445Sassar ret = krb5_ret_principal(sp, &princ); 27372445Sassar if(ret) 27472445Sassar goto fail; 27572445Sassar ret = krb5_ret_int32(sp, &n_key_data); 27672445Sassar if (ret) { 277233294Sstas krb5_free_principal(contextp->context, princ); 27872445Sassar goto fail; 27972445Sassar } 280103423Snectar /* n_key_data will be squeezed into an int16_t below. */ 281103423Snectar if (n_key_data < 0 || n_key_data >= 1 << 16 || 282233294Sstas (size_t)n_key_data > UINT_MAX/sizeof(*key_data)) { 283103423Snectar ret = ERANGE; 284233294Sstas krb5_free_principal(contextp->context, princ); 285103423Snectar goto fail; 286103423Snectar } 28772445Sassar 28872445Sassar key_data = malloc (n_key_data * sizeof(*key_data)); 289233294Sstas if (key_data == NULL && n_key_data != 0) { 29072445Sassar ret = ENOMEM; 291233294Sstas krb5_free_principal(contextp->context, princ); 29272445Sassar goto fail; 29372445Sassar } 29472445Sassar 29572445Sassar for (i = 0; i < n_key_data; ++i) { 29672445Sassar ret = kadm5_ret_key_data (sp, &key_data[i]); 29772445Sassar if (ret) { 29872445Sassar int16_t dummy = i; 29972445Sassar 300233294Sstas kadm5_free_key_data (contextp, &dummy, key_data); 30172445Sassar free (key_data); 302233294Sstas krb5_free_principal(contextp->context, princ); 30372445Sassar goto fail; 30472445Sassar } 30572445Sassar } 30672445Sassar 307233294Sstas krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name)); 308233294Sstas krb5_warnx(contextp->context, "%s: %s %s", client, op, name); 30972445Sassar 31072445Sassar /* 311120945Snectar * The change is only allowed if the user is on the CPW ACL, 312120945Snectar * this it to force password quality check on the user. 31372445Sassar */ 31472445Sassar 315233294Sstas ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_CPW, princ); 31672445Sassar if(ret) { 31772445Sassar int16_t dummy = n_key_data; 31872445Sassar 319233294Sstas kadm5_free_key_data (contextp, &dummy, key_data); 32072445Sassar free (key_data); 321233294Sstas krb5_free_principal(contextp->context, princ); 32272445Sassar goto fail; 32372445Sassar } 324233294Sstas ret = kadm5_chpass_principal_with_key(kadm_handlep, princ, 32572445Sassar n_key_data, key_data); 32672445Sassar { 32772445Sassar int16_t dummy = n_key_data; 328233294Sstas kadm5_free_key_data (contextp, &dummy, key_data); 32972445Sassar } 33072445Sassar free (key_data); 331233294Sstas krb5_free_principal(contextp->context, princ); 33272445Sassar krb5_storage_free(sp); 33372445Sassar sp = krb5_storage_emem(); 33472445Sassar krb5_store_int32(sp, ret); 33572445Sassar break; 33672445Sassar } 33755682Smarkm case kadm_randkey:{ 33855682Smarkm op = "RANDKEY"; 33955682Smarkm ret = krb5_ret_principal(sp, &princ); 34055682Smarkm if(ret) 34155682Smarkm goto fail; 342233294Sstas krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name)); 343233294Sstas krb5_warnx(contextp->context, "%s: %s %s", client, op, name); 34455682Smarkm /* 34555682Smarkm * The change is allowed if at least one of: 34655682Smarkm * a) it's for the principal him/herself and this was an initial ticket 34755682Smarkm * b) the user is on the CPW ACL. 34855682Smarkm */ 34955682Smarkm 35055682Smarkm if (initial 351233294Sstas && krb5_principal_compare (contextp->context, contextp->caller, 35255682Smarkm princ)) 35355682Smarkm ret = 0; 35455682Smarkm else 355233294Sstas ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_CPW, princ); 35655682Smarkm 35755682Smarkm if(ret) { 358233294Sstas krb5_free_principal(contextp->context, princ); 35955682Smarkm goto fail; 36055682Smarkm } 361233294Sstas ret = kadm5_randkey_principal(kadm_handlep, princ, 36255682Smarkm &new_keys, &n_keys); 363233294Sstas krb5_free_principal(contextp->context, princ); 36455682Smarkm krb5_storage_free(sp); 36555682Smarkm sp = krb5_storage_emem(); 36655682Smarkm krb5_store_int32(sp, ret); 36755682Smarkm if(ret == 0){ 36855682Smarkm int i; 36955682Smarkm krb5_store_int32(sp, n_keys); 37055682Smarkm for(i = 0; i < n_keys; i++){ 37155682Smarkm krb5_store_keyblock(sp, new_keys[i]); 372233294Sstas krb5_free_keyblock_contents(contextp->context, &new_keys[i]); 37355682Smarkm } 374233294Sstas free(new_keys); 37555682Smarkm } 37655682Smarkm break; 37755682Smarkm } 37855682Smarkm case kadm_get_privs:{ 379178825Sdfr uint32_t privs; 380233294Sstas ret = kadm5_get_privs(kadm_handlep, &privs); 38155682Smarkm krb5_storage_free(sp); 38255682Smarkm sp = krb5_storage_emem(); 38355682Smarkm krb5_store_int32(sp, ret); 38455682Smarkm if(ret == 0) 385178825Sdfr krb5_store_uint32(sp, privs); 38655682Smarkm break; 38755682Smarkm } 38855682Smarkm case kadm_get_princs:{ 38955682Smarkm op = "LIST"; 39055682Smarkm ret = krb5_ret_int32(sp, &tmp); 39155682Smarkm if(ret) 39255682Smarkm goto fail; 39355682Smarkm if(tmp){ 394178825Sdfr ret = krb5_ret_string(sp, &expression); 39555682Smarkm if(ret) 39655682Smarkm goto fail; 39755682Smarkm }else 398178825Sdfr expression = NULL; 399233294Sstas krb5_warnx(contextp->context, "%s: %s %s", client, op, 400178825Sdfr expression ? expression : "*"); 401233294Sstas ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_LIST, NULL); 40255682Smarkm if(ret){ 403178825Sdfr free(expression); 40455682Smarkm goto fail; 40555682Smarkm } 406233294Sstas ret = kadm5_get_principals(kadm_handlep, expression, &princs, &n_princs); 407178825Sdfr free(expression); 40855682Smarkm krb5_storage_free(sp); 40955682Smarkm sp = krb5_storage_emem(); 41055682Smarkm krb5_store_int32(sp, ret); 41155682Smarkm if(ret == 0){ 41255682Smarkm int i; 41355682Smarkm krb5_store_int32(sp, n_princs); 41455682Smarkm for(i = 0; i < n_princs; i++) 41555682Smarkm krb5_store_string(sp, princs[i]); 416233294Sstas kadm5_free_name_list(kadm_handlep, princs, &n_princs); 41755682Smarkm } 41855682Smarkm break; 41955682Smarkm } 42055682Smarkm default: 421233294Sstas krb5_warnx(contextp->context, "%s: UNKNOWN OP %d", client, cmd); 42255682Smarkm krb5_storage_free(sp); 42355682Smarkm sp = krb5_storage_emem(); 42455682Smarkm krb5_store_int32(sp, KADM5_FAILURE); 42555682Smarkm break; 42655682Smarkm } 42755682Smarkm krb5_storage_to_data(sp, out); 42855682Smarkm krb5_storage_free(sp); 42955682Smarkm return 0; 43055682Smarkmfail: 431233294Sstas krb5_warn(contextp->context, ret, "%s", op); 432102644Snectar krb5_storage_seek(sp, 0, SEEK_SET); 43355682Smarkm krb5_store_int32(sp, ret); 43455682Smarkm krb5_storage_to_data(sp, out); 43555682Smarkm krb5_storage_free(sp); 43655682Smarkm return 0; 43755682Smarkm} 43855682Smarkm 43955682Smarkmstatic void 440233294Sstasv5_loop (krb5_context contextp, 44155682Smarkm krb5_auth_context ac, 44255682Smarkm krb5_boolean initial, 443233294Sstas void *kadm_handlep, 444233294Sstas krb5_socket_t fd) 44555682Smarkm{ 44655682Smarkm krb5_error_code ret; 44772445Sassar krb5_data in, out; 44855682Smarkm 44955682Smarkm for (;;) { 45072445Sassar doing_useful_work = 0; 45172445Sassar if(term_flag) 45272445Sassar exit(0); 453233294Sstas ret = krb5_read_priv_message(contextp, ac, &fd, &in); 45472445Sassar if(ret == HEIM_ERR_EOF) 45572445Sassar exit(0); 45672445Sassar if(ret) 457233294Sstas krb5_err(contextp, 1, ret, "krb5_read_priv_message"); 45872445Sassar doing_useful_work = 1; 459233294Sstas kadmind_dispatch(kadm_handlep, initial, &in, &out); 46055682Smarkm krb5_data_free(&in); 461233294Sstas ret = krb5_write_priv_message(contextp, ac, &fd, &out); 46272445Sassar if(ret) 463233294Sstas krb5_err(contextp, 1, ret, "krb5_write_priv_message"); 46455682Smarkm } 46555682Smarkm} 46655682Smarkm 46755682Smarkmstatic krb5_boolean 468103423Snectarmatch_appl_version(const void *data, const char *appl_version) 46955682Smarkm{ 47055682Smarkm unsigned minor; 47155682Smarkm if(sscanf(appl_version, "KADM0.%u", &minor) != 1) 47255682Smarkm return 0; 473233294Sstas /*XXX*/ 474233294Sstas *(unsigned*)(intptr_t)data = minor; 47555682Smarkm return 1; 47655682Smarkm} 47755682Smarkm 47855682Smarkmstatic void 479233294Sstashandle_v5(krb5_context contextp, 48055682Smarkm krb5_keytab keytab, 481233294Sstas krb5_socket_t fd) 48255682Smarkm{ 48355682Smarkm krb5_error_code ret; 48455682Smarkm krb5_ticket *ticket; 48572445Sassar char *server_name; 48655682Smarkm char *client; 487233294Sstas void *kadm_handlep; 48855682Smarkm krb5_boolean initial; 489233294Sstas krb5_auth_context ac = NULL; 49055682Smarkm 49155682Smarkm unsigned kadm_version; 49255682Smarkm kadm5_config_params realm_params; 49355682Smarkm 494233294Sstas ret = krb5_recvauth_match_version(contextp, &ac, &fd, 49555682Smarkm match_appl_version, &kadm_version, 496233294Sstas NULL, KRB5_RECVAUTH_IGNORE_VERSION, 49755682Smarkm keytab, &ticket); 498233294Sstas if (ret) 499233294Sstas krb5_err(contextp, 1, ret, "krb5_recvauth"); 50055682Smarkm 501233294Sstas ret = krb5_unparse_name (contextp, ticket->server, &server_name); 50272445Sassar if (ret) 503233294Sstas krb5_err (contextp, 1, ret, "krb5_unparse_name"); 50472445Sassar 50572445Sassar if (strncmp (server_name, KADM5_ADMIN_SERVICE, 50672445Sassar strlen(KADM5_ADMIN_SERVICE)) != 0) 507233294Sstas krb5_errx (contextp, 1, "ticket for strange principal (%s)", 50872445Sassar server_name); 50972445Sassar 51072445Sassar free (server_name); 51172445Sassar 51255682Smarkm memset(&realm_params, 0, sizeof(realm_params)); 51355682Smarkm 51455682Smarkm if(kadm_version == 1) { 51572445Sassar krb5_data params; 516233294Sstas ret = krb5_read_priv_message(contextp, ac, &fd, ¶ms); 51772445Sassar if(ret) 518233294Sstas krb5_err(contextp, 1, ret, "krb5_read_priv_message"); 519233294Sstas _kadm5_unmarshal_params(contextp, ¶ms, &realm_params); 52055682Smarkm } 52155682Smarkm 52255682Smarkm initial = ticket->ticket.flags.initial; 523233294Sstas ret = krb5_unparse_name(contextp, ticket->client, &client); 52455682Smarkm if (ret) 525233294Sstas krb5_err (contextp, 1, ret, "krb5_unparse_name"); 526233294Sstas krb5_free_ticket (contextp, ticket); 527233294Sstas ret = kadm5_s_init_with_password_ctx(contextp, 528233294Sstas client, 529233294Sstas NULL, 530233294Sstas KADM5_ADMIN_SERVICE, 531233294Sstas &realm_params, 532233294Sstas 0, 0, 533233294Sstas &kadm_handlep); 53455682Smarkm if(ret) 535233294Sstas krb5_err (contextp, 1, ret, "kadm5_init_with_password_ctx"); 536233294Sstas v5_loop (contextp, ac, initial, kadm_handlep, fd); 53755682Smarkm} 53855682Smarkm 53955682Smarkmkrb5_error_code 540233294Sstaskadmind_loop(krb5_context contextp, 541233294Sstas krb5_keytab keytab, 542233294Sstas krb5_socket_t sock) 54355682Smarkm{ 544233294Sstas u_char buf[sizeof(KRB5_SENDAUTH_VERSION) + 4]; 54555682Smarkm ssize_t n; 54655682Smarkm unsigned long len; 54755682Smarkm 548233294Sstas n = krb5_net_read(contextp, &sock, buf, 4); 54955682Smarkm if(n == 0) 55055682Smarkm exit(0); 55155682Smarkm if(n < 0) 552233294Sstas krb5_err(contextp, 1, errno, "read"); 553233294Sstas _krb5_get_int(buf, &len, 4); 554233294Sstas 555233294Sstas if (len == sizeof(KRB5_SENDAUTH_VERSION)) { 556233294Sstas 557233294Sstas n = krb5_net_read(contextp, &sock, buf + 4, len); 558233294Sstas if (n < 0) 559233294Sstas krb5_err (contextp, 1, errno, "reading sendauth version"); 560233294Sstas if (n == 0) 561233294Sstas krb5_errx (contextp, 1, "EOF reading sendauth version"); 562233294Sstas 563233294Sstas if(memcmp(buf + 4, KRB5_SENDAUTH_VERSION, len) == 0) { 564233294Sstas handle_v5(contextp, keytab, sock); 565233294Sstas return 0; 566233294Sstas } 567233294Sstas len += 4; 568233294Sstas } else 569233294Sstas len = 4; 570233294Sstas 571233294Sstas handle_mit(contextp, buf, len, sock); 572233294Sstas 57355682Smarkm return 0; 57455682Smarkm} 575