155682Smarkm/* 2178825Sdfr * Copyright (c) 1997 - 2006 Kungliga Tekniska H�gskolan 355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden). 455682Smarkm * All rights reserved. 555682Smarkm * 655682Smarkm * Redistribution and use in source and binary forms, with or without 755682Smarkm * modification, are permitted provided that the following conditions 855682Smarkm * are met: 955682Smarkm * 1055682Smarkm * 1. Redistributions of source code must retain the above copyright 1155682Smarkm * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1455682Smarkm * notice, this list of conditions and the following disclaimer in the 1555682Smarkm * documentation and/or other materials provided with the distribution. 1655682Smarkm * 1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors 1855682Smarkm * may be used to endorse or promote products derived from this software 1955682Smarkm * without specific prior written permission. 2055682Smarkm * 2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2455682Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3155682Smarkm * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "kadm5_locl.h" 3555682Smarkm#include <sys/types.h> 3655682Smarkm#include <sys/socket.h> 3755682Smarkm#include <netinet/in.h> 3855682Smarkm#include <netdb.h> 3955682Smarkm 40178825SdfrRCSID("$Id: init_c.c 21972 2007-10-18 19:11:15Z lha $"); 4155682Smarkm 4255682Smarkmstatic void 4355682Smarkmset_funcs(kadm5_client_context *c) 4455682Smarkm{ 4555682Smarkm#define SET(C, F) (C)->funcs.F = kadm5 ## _c_ ## F 4655682Smarkm SET(c, chpass_principal); 4772445Sassar SET(c, chpass_principal_with_key); 4855682Smarkm SET(c, create_principal); 4955682Smarkm SET(c, delete_principal); 5055682Smarkm SET(c, destroy); 5155682Smarkm SET(c, flush); 5255682Smarkm SET(c, get_principal); 5355682Smarkm SET(c, get_principals); 5455682Smarkm SET(c, get_privs); 5555682Smarkm SET(c, modify_principal); 5655682Smarkm SET(c, randkey_principal); 5755682Smarkm SET(c, rename_principal); 5855682Smarkm} 5955682Smarkm 6055682Smarkmkadm5_ret_t 6155682Smarkm_kadm5_c_init_context(kadm5_client_context **ctx, 6255682Smarkm kadm5_config_params *params, 6355682Smarkm krb5_context context) 6455682Smarkm{ 6555682Smarkm krb5_error_code ret; 6655682Smarkm char *colon; 6755682Smarkm 6855682Smarkm *ctx = malloc(sizeof(**ctx)); 6955682Smarkm if(*ctx == NULL) 7055682Smarkm return ENOMEM; 7155682Smarkm memset(*ctx, 0, sizeof(**ctx)); 7255682Smarkm krb5_add_et_list (context, initialize_kadm5_error_table_r); 7355682Smarkm set_funcs(*ctx); 7455682Smarkm (*ctx)->context = context; 75127808Snectar if(params->mask & KADM5_CONFIG_REALM) { 76127808Snectar ret = 0; 7755682Smarkm (*ctx)->realm = strdup(params->realm); 78127808Snectar if ((*ctx)->realm == NULL) 79127808Snectar ret = ENOMEM; 80127808Snectar } else 81127808Snectar ret = krb5_get_default_realm((*ctx)->context, &(*ctx)->realm); 82127808Snectar if (ret) { 83127808Snectar free(*ctx); 84127808Snectar return ret; 85127808Snectar } 8655682Smarkm if(params->mask & KADM5_CONFIG_ADMIN_SERVER) 8755682Smarkm (*ctx)->admin_server = strdup(params->admin_server); 8855682Smarkm else { 8955682Smarkm char **hostlist; 9055682Smarkm 9155682Smarkm ret = krb5_get_krb_admin_hst (context, &(*ctx)->realm, &hostlist); 92127808Snectar if (ret) { 93127808Snectar free((*ctx)->realm); 94127808Snectar free(*ctx); 9555682Smarkm return ret; 96127808Snectar } 9755682Smarkm (*ctx)->admin_server = strdup(*hostlist); 9855682Smarkm krb5_free_krbhst (context, hostlist); 9955682Smarkm } 10055682Smarkm 101127808Snectar if ((*ctx)->admin_server == NULL) { 102127808Snectar free((*ctx)->realm); 103127808Snectar free(*ctx); 104178825Sdfr return ENOMEM; 105127808Snectar } 10655682Smarkm colon = strchr ((*ctx)->admin_server, ':'); 10755682Smarkm if (colon != NULL) 10855682Smarkm *colon++ = '\0'; 10955682Smarkm 11055682Smarkm (*ctx)->kadmind_port = 0; 11155682Smarkm 11255682Smarkm if(params->mask & KADM5_CONFIG_KADMIND_PORT) 11355682Smarkm (*ctx)->kadmind_port = params->kadmind_port; 11455682Smarkm else if (colon != NULL) { 11555682Smarkm char *end; 11655682Smarkm 11755682Smarkm (*ctx)->kadmind_port = htons(strtol (colon, &end, 0)); 11855682Smarkm } 11955682Smarkm if ((*ctx)->kadmind_port == 0) 12055682Smarkm (*ctx)->kadmind_port = krb5_getportbyname (context, "kerberos-adm", 12155682Smarkm "tcp", 749); 12255682Smarkm return 0; 12355682Smarkm} 12455682Smarkm 12555682Smarkmstatic krb5_error_code 12655682Smarkmget_kadm_ticket(krb5_context context, 12755682Smarkm krb5_ccache id, 12855682Smarkm krb5_principal client, 12955682Smarkm const char *server_name) 13055682Smarkm{ 13155682Smarkm krb5_error_code ret; 13255682Smarkm krb5_creds in, *out; 13355682Smarkm 13455682Smarkm memset(&in, 0, sizeof(in)); 13555682Smarkm in.client = client; 13655682Smarkm ret = krb5_parse_name(context, server_name, &in.server); 13755682Smarkm if(ret) 13855682Smarkm return ret; 13955682Smarkm ret = krb5_get_credentials(context, 0, id, &in, &out); 14055682Smarkm if(ret == 0) 14155682Smarkm krb5_free_creds(context, out); 14255682Smarkm krb5_free_principal(context, in.server); 14355682Smarkm return ret; 14455682Smarkm} 14555682Smarkm 14655682Smarkmstatic krb5_error_code 14755682Smarkmget_new_cache(krb5_context context, 14855682Smarkm krb5_principal client, 14955682Smarkm const char *password, 15055682Smarkm krb5_prompter_fct prompter, 15155682Smarkm const char *keytab, 15255682Smarkm const char *server_name, 15355682Smarkm krb5_ccache *ret_cache) 15455682Smarkm{ 15555682Smarkm krb5_error_code ret; 15655682Smarkm krb5_creds cred; 157178825Sdfr krb5_get_init_creds_opt *opt; 15855682Smarkm krb5_ccache id; 15955682Smarkm 160178825Sdfr ret = krb5_get_init_creds_opt_alloc (context, &opt); 161178825Sdfr if (ret) 162178825Sdfr return ret; 16390926Snectar 16490926Snectar krb5_get_init_creds_opt_set_default_flags(context, "kadmin", 16590926Snectar krb5_principal_get_realm(context, 16690926Snectar client), 167178825Sdfr opt); 16890926Snectar 16990926Snectar 170178825Sdfr krb5_get_init_creds_opt_set_forwardable (opt, FALSE); 171178825Sdfr krb5_get_init_creds_opt_set_proxiable (opt, FALSE); 17257416Smarkm 17355682Smarkm if(password == NULL && prompter == NULL) { 17455682Smarkm krb5_keytab kt; 17555682Smarkm if(keytab == NULL) 17655682Smarkm ret = krb5_kt_default(context, &kt); 17755682Smarkm else 17855682Smarkm ret = krb5_kt_resolve(context, keytab, &kt); 179178825Sdfr if(ret) { 180178825Sdfr krb5_get_init_creds_opt_free(context, opt); 18155682Smarkm return ret; 182178825Sdfr } 18355682Smarkm ret = krb5_get_init_creds_keytab (context, 18455682Smarkm &cred, 18555682Smarkm client, 18655682Smarkm kt, 18755682Smarkm 0, 18855682Smarkm server_name, 189178825Sdfr opt); 19055682Smarkm krb5_kt_close(context, kt); 19155682Smarkm } else { 19255682Smarkm ret = krb5_get_init_creds_password (context, 19355682Smarkm &cred, 19455682Smarkm client, 19555682Smarkm password, 19655682Smarkm prompter, 19755682Smarkm NULL, 19855682Smarkm 0, 19955682Smarkm server_name, 200178825Sdfr opt); 20155682Smarkm } 202178825Sdfr krb5_get_init_creds_opt_free(context, opt); 20355682Smarkm switch(ret){ 20455682Smarkm case 0: 20555682Smarkm break; 20655682Smarkm case KRB5_LIBOS_PWDINTR: /* don't print anything if it was just C-c:ed */ 20755682Smarkm case KRB5KRB_AP_ERR_BAD_INTEGRITY: 20855682Smarkm case KRB5KRB_AP_ERR_MODIFIED: 20955682Smarkm return KADM5_BAD_PASSWORD; 21055682Smarkm default: 21155682Smarkm return ret; 21255682Smarkm } 21355682Smarkm ret = krb5_cc_gen_new(context, &krb5_mcc_ops, &id); 21455682Smarkm if(ret) 21555682Smarkm return ret; 21655682Smarkm ret = krb5_cc_initialize (context, id, cred.client); 21755682Smarkm if (ret) 21855682Smarkm return ret; 21955682Smarkm ret = krb5_cc_store_cred (context, id, &cred); 22055682Smarkm if (ret) 22155682Smarkm return ret; 222178825Sdfr krb5_free_cred_contents (context, &cred); 22355682Smarkm *ret_cache = id; 22455682Smarkm return 0; 22555682Smarkm} 22655682Smarkm 227178825Sdfr/* 228178825Sdfr * Check the credential cache `id� to figure out what principal to use 229178825Sdfr * when talking to the kadmind. If there is a initial kadmin/admin@ 230178825Sdfr * credential in the cache, use that client principal. Otherwise, use 231178825Sdfr * the client principals first component and add /admin to the 232178825Sdfr * principal. 233178825Sdfr */ 234178825Sdfr 23555682Smarkmstatic krb5_error_code 236178825Sdfrget_cache_principal(krb5_context context, 237178825Sdfr krb5_ccache *id, 238178825Sdfr krb5_principal *client) 23955682Smarkm{ 24055682Smarkm krb5_error_code ret; 241178825Sdfr const char *name, *inst; 242178825Sdfr krb5_principal p1, p2; 243178825Sdfr 244178825Sdfr ret = krb5_cc_default(context, id); 245178825Sdfr if(ret) { 246178825Sdfr *id = NULL; 247178825Sdfr return ret; 248178825Sdfr } 249178825Sdfr 250178825Sdfr ret = krb5_cc_get_principal(context, *id, &p1); 251178825Sdfr if(ret) { 252178825Sdfr krb5_cc_close(context, *id); 253178825Sdfr *id = NULL; 254178825Sdfr return ret; 255178825Sdfr } 256178825Sdfr 257178825Sdfr ret = krb5_make_principal(context, &p2, NULL, 258178825Sdfr "kadmin", "admin", NULL); 259178825Sdfr if (ret) { 260178825Sdfr krb5_cc_close(context, *id); 261178825Sdfr *id = NULL; 262178825Sdfr krb5_free_principal(context, p1); 263178825Sdfr return ret; 264178825Sdfr } 265178825Sdfr 266178825Sdfr { 267178825Sdfr krb5_creds in, *out; 268178825Sdfr krb5_kdc_flags flags; 269178825Sdfr 270178825Sdfr flags.i = 0; 271178825Sdfr memset(&in, 0, sizeof(in)); 272178825Sdfr 273178825Sdfr in.client = p1; 274178825Sdfr in.server = p2; 275178825Sdfr 276178825Sdfr /* check for initial ticket kadmin/admin */ 277178825Sdfr ret = krb5_get_credentials_with_flags(context, KRB5_GC_CACHED, flags, 278178825Sdfr *id, &in, &out); 279178825Sdfr krb5_free_principal(context, p2); 280178825Sdfr if (ret == 0) { 281178825Sdfr if (out->flags.b.initial) { 282178825Sdfr *client = p1; 283178825Sdfr krb5_free_creds(context, out); 284178825Sdfr return 0; 285178825Sdfr } 286178825Sdfr krb5_free_creds(context, out); 287178825Sdfr } 288178825Sdfr } 289178825Sdfr krb5_cc_close(context, *id); 290178825Sdfr *id = NULL; 291178825Sdfr 292178825Sdfr name = krb5_principal_get_comp_string(context, p1, 0); 293178825Sdfr inst = krb5_principal_get_comp_string(context, p1, 1); 294178825Sdfr if(inst == NULL || strcmp(inst, "admin") != 0) { 295178825Sdfr ret = krb5_make_principal(context, &p2, NULL, name, "admin", NULL); 296178825Sdfr krb5_free_principal(context, p1); 297178825Sdfr if(ret != 0) 298178825Sdfr return ret; 299178825Sdfr 300178825Sdfr *client = p2; 301178825Sdfr return 0; 302178825Sdfr } 303178825Sdfr 304178825Sdfr *client = p1; 305178825Sdfr 306178825Sdfr return 0; 307178825Sdfr} 308178825Sdfr 309178825Sdfrkrb5_error_code 310178825Sdfr_kadm5_c_get_cred_cache(krb5_context context, 311178825Sdfr const char *client_name, 312178825Sdfr const char *server_name, 313178825Sdfr const char *password, 314178825Sdfr krb5_prompter_fct prompter, 315178825Sdfr const char *keytab, 316178825Sdfr krb5_ccache ccache, 317178825Sdfr krb5_ccache *ret_cache) 318178825Sdfr{ 319178825Sdfr krb5_error_code ret; 32055682Smarkm krb5_ccache id = NULL; 32155682Smarkm krb5_principal default_client = NULL, client = NULL; 32255682Smarkm 32355682Smarkm /* treat empty password as NULL */ 32455682Smarkm if(password && *password == '\0') 32555682Smarkm password = NULL; 32655682Smarkm if(server_name == NULL) 32755682Smarkm server_name = KADM5_ADMIN_SERVICE; 32855682Smarkm 32955682Smarkm if(client_name != NULL) { 33055682Smarkm ret = krb5_parse_name(context, client_name, &client); 33155682Smarkm if(ret) 33255682Smarkm return ret; 33355682Smarkm } 33455682Smarkm 335178825Sdfr if(ccache != NULL) { 336178825Sdfr id = ccache; 337178825Sdfr ret = krb5_cc_get_principal(context, id, &client); 338178825Sdfr if(ret) 339178825Sdfr return ret; 340178825Sdfr } else { 34155682Smarkm /* get principal from default cache, ok if this doesn't work */ 342102644Snectar 343178825Sdfr ret = get_cache_principal(context, &id, &default_client); 344178825Sdfr if (ret) { 345178825Sdfr /* 346178825Sdfr * No client was specified by the caller and we cannot 347178825Sdfr * determine the client from a credentials cache. 348102644Snectar */ 34955682Smarkm const char *user; 35055682Smarkm 35155682Smarkm user = get_default_username (); 35255682Smarkm 353178825Sdfr if(user == NULL) { 354178825Sdfr krb5_set_error_string(context, "Unable to find local user name"); 35555682Smarkm return KADM5_FAILURE; 356178825Sdfr } 357178825Sdfr ret = krb5_make_principal(context, &default_client, 35855682Smarkm NULL, user, "admin", NULL); 35955682Smarkm if(ret) 36055682Smarkm return ret; 36155682Smarkm } 362178825Sdfr } 363178825Sdfr 364178825Sdfr 365178825Sdfr /* 366178825Sdfr * No client was specified by the caller, but we have a client 367178825Sdfr * from the default credentials cache. 368178825Sdfr */ 369178825Sdfr if (client == NULL && default_client != NULL) 370178825Sdfr client = default_client; 371178825Sdfr 37255682Smarkm 37355682Smarkm if(id && (default_client == NULL || 37455682Smarkm krb5_principal_compare(context, client, default_client))) { 37555682Smarkm ret = get_kadm_ticket(context, id, client, server_name); 37655682Smarkm if(ret == 0) { 37755682Smarkm *ret_cache = id; 37855682Smarkm krb5_free_principal(context, default_client); 37955682Smarkm if (default_client != client) 38055682Smarkm krb5_free_principal(context, client); 38155682Smarkm return 0; 38255682Smarkm } 38355682Smarkm if(ccache != NULL) 38455682Smarkm /* couldn't get ticket from cache */ 38555682Smarkm return -1; 38655682Smarkm } 38755682Smarkm /* get creds via AS request */ 388178825Sdfr if(id && (id != ccache)) 38955682Smarkm krb5_cc_close(context, id); 39055682Smarkm if (client != default_client) 39155682Smarkm krb5_free_principal(context, default_client); 39255682Smarkm 39355682Smarkm ret = get_new_cache(context, client, password, prompter, keytab, 39455682Smarkm server_name, ret_cache); 39555682Smarkm krb5_free_principal(context, client); 39655682Smarkm return ret; 39755682Smarkm} 39855682Smarkm 39972445Sassarstatic kadm5_ret_t 40072445Sassarkadm_connect(kadm5_client_context *ctx) 40155682Smarkm{ 40255682Smarkm kadm5_ret_t ret; 40355682Smarkm krb5_principal server; 40455682Smarkm krb5_ccache cc; 40555682Smarkm int s; 40655682Smarkm struct addrinfo *ai, *a; 40755682Smarkm struct addrinfo hints; 40855682Smarkm int error; 40955682Smarkm char portstr[NI_MAXSERV]; 41055682Smarkm char *hostname, *slash; 411120945Snectar char *service_name; 41272445Sassar krb5_context context = ctx->context; 41355682Smarkm 41455682Smarkm memset (&hints, 0, sizeof(hints)); 41555682Smarkm hints.ai_socktype = SOCK_STREAM; 41655682Smarkm hints.ai_protocol = IPPROTO_TCP; 41772445Sassar 41855682Smarkm snprintf (portstr, sizeof(portstr), "%u", ntohs(ctx->kadmind_port)); 41955682Smarkm 42055682Smarkm hostname = ctx->admin_server; 42155682Smarkm slash = strchr (hostname, '/'); 42255682Smarkm if (slash != NULL) 42355682Smarkm hostname = slash + 1; 42455682Smarkm 42555682Smarkm error = getaddrinfo (hostname, portstr, &hints, &ai); 426178825Sdfr if (error) { 427178825Sdfr krb5_clear_error_string(context); 42855682Smarkm return KADM5_BAD_SERVER_NAME; 429178825Sdfr } 43055682Smarkm 43155682Smarkm for (a = ai; a != NULL; a = a->ai_next) { 43255682Smarkm s = socket (a->ai_family, a->ai_socktype, a->ai_protocol); 43355682Smarkm if (s < 0) 43455682Smarkm continue; 43555682Smarkm if (connect (s, a->ai_addr, a->ai_addrlen) < 0) { 436178825Sdfr krb5_clear_error_string(context); 43755682Smarkm krb5_warn (context, errno, "connect(%s)", hostname); 43855682Smarkm close (s); 43955682Smarkm continue; 44055682Smarkm } 44155682Smarkm break; 44255682Smarkm } 44355682Smarkm if (a == NULL) { 44455682Smarkm freeaddrinfo (ai); 445178825Sdfr krb5_clear_error_string(context); 44655682Smarkm krb5_warnx (context, "failed to contact %s", hostname); 44755682Smarkm return KADM5_FAILURE; 44855682Smarkm } 449178825Sdfr ret = _kadm5_c_get_cred_cache(context, 450178825Sdfr ctx->client_name, 451178825Sdfr ctx->service_name, 452178825Sdfr NULL, ctx->prompter, ctx->keytab, 453178825Sdfr ctx->ccache, &cc); 45455682Smarkm 45555682Smarkm if(ret) { 45655682Smarkm freeaddrinfo (ai); 45755682Smarkm close(s); 45855682Smarkm return ret; 45955682Smarkm } 460120945Snectar 461120945Snectar if (ctx->realm) 462120945Snectar asprintf(&service_name, "%s@%s", KADM5_ADMIN_SERVICE, ctx->realm); 463120945Snectar else 464120945Snectar asprintf(&service_name, "%s", KADM5_ADMIN_SERVICE); 465120945Snectar 466120945Snectar if (service_name == NULL) { 467120945Snectar freeaddrinfo (ai); 468120945Snectar close(s); 469178825Sdfr krb5_clear_error_string(context); 470120945Snectar return ENOMEM; 471120945Snectar } 472120945Snectar 473120945Snectar ret = krb5_parse_name(context, service_name, &server); 474120945Snectar free(service_name); 47555682Smarkm if(ret) { 47655682Smarkm freeaddrinfo (ai); 47772445Sassar if(ctx->ccache == NULL) 47855682Smarkm krb5_cc_close(context, cc); 47955682Smarkm close(s); 48055682Smarkm return ret; 48155682Smarkm } 48255682Smarkm ctx->ac = NULL; 48355682Smarkm 48455682Smarkm ret = krb5_sendauth(context, &ctx->ac, &s, 48555682Smarkm KADMIN_APPL_VERSION, NULL, 48655682Smarkm server, AP_OPTS_MUTUAL_REQUIRED, 48755682Smarkm NULL, NULL, cc, NULL, NULL, NULL); 48855682Smarkm if(ret == 0) { 48972445Sassar krb5_data params; 49090926Snectar kadm5_config_params p; 49190926Snectar memset(&p, 0, sizeof(p)); 49290926Snectar if(ctx->realm) { 49390926Snectar p.mask |= KADM5_CONFIG_REALM; 49490926Snectar p.realm = ctx->realm; 49590926Snectar } 49690926Snectar ret = _kadm5_marshal_params(context, &p, ¶ms); 49755682Smarkm 49872445Sassar ret = krb5_write_priv_message(context, ctx->ac, &s, ¶ms); 49955682Smarkm krb5_data_free(¶ms); 50072445Sassar if(ret) { 50172445Sassar freeaddrinfo (ai); 50272445Sassar close(s); 50372445Sassar if(ctx->ccache == NULL) 50472445Sassar krb5_cc_close(context, cc); 50572445Sassar return ret; 50672445Sassar } 50755682Smarkm } else if(ret == KRB5_SENDAUTH_BADAPPLVERS) { 50855682Smarkm close(s); 50955682Smarkm 51055682Smarkm s = socket (a->ai_family, a->ai_socktype, a->ai_protocol); 51155682Smarkm if (s < 0) { 51255682Smarkm freeaddrinfo (ai); 513178825Sdfr krb5_clear_error_string(context); 51455682Smarkm return errno; 51555682Smarkm } 51655682Smarkm if (connect (s, a->ai_addr, a->ai_addrlen) < 0) { 51755682Smarkm close (s); 51855682Smarkm freeaddrinfo (ai); 519178825Sdfr krb5_clear_error_string(context); 52055682Smarkm return errno; 52155682Smarkm } 52255682Smarkm ret = krb5_sendauth(context, &ctx->ac, &s, 52355682Smarkm KADMIN_OLD_APPL_VERSION, NULL, 52455682Smarkm server, AP_OPTS_MUTUAL_REQUIRED, 52555682Smarkm NULL, NULL, cc, NULL, NULL, NULL); 52655682Smarkm } 52755682Smarkm freeaddrinfo (ai); 52855682Smarkm if(ret) { 52955682Smarkm close(s); 53055682Smarkm return ret; 53155682Smarkm } 53255682Smarkm 53355682Smarkm krb5_free_principal(context, server); 53472445Sassar if(ctx->ccache == NULL) 53555682Smarkm krb5_cc_close(context, cc); 53655682Smarkm ctx->sock = s; 53772445Sassar 53872445Sassar return 0; 53972445Sassar} 54072445Sassar 54172445Sassarkadm5_ret_t 54272445Sassar_kadm5_connect(void *handle) 54372445Sassar{ 54472445Sassar kadm5_client_context *ctx = handle; 54572445Sassar if(ctx->sock == -1) 54672445Sassar return kadm_connect(ctx); 54772445Sassar return 0; 54872445Sassar} 54972445Sassar 55072445Sassarstatic kadm5_ret_t 55172445Sassarkadm5_c_init_with_context(krb5_context context, 55272445Sassar const char *client_name, 55372445Sassar const char *password, 55472445Sassar krb5_prompter_fct prompter, 55572445Sassar const char *keytab, 55672445Sassar krb5_ccache ccache, 55772445Sassar const char *service_name, 55872445Sassar kadm5_config_params *realm_params, 55972445Sassar unsigned long struct_version, 56072445Sassar unsigned long api_version, 56172445Sassar void **server_handle) 56272445Sassar{ 56372445Sassar kadm5_ret_t ret; 56472445Sassar kadm5_client_context *ctx; 56572445Sassar krb5_ccache cc; 56672445Sassar 56772445Sassar ret = _kadm5_c_init_context(&ctx, realm_params, context); 56872445Sassar if(ret) 56972445Sassar return ret; 57072445Sassar 57172445Sassar if(password != NULL && *password != '\0') { 572178825Sdfr ret = _kadm5_c_get_cred_cache(context, 573178825Sdfr client_name, 574178825Sdfr service_name, 575178825Sdfr password, prompter, keytab, ccache, &cc); 57672445Sassar if(ret) 57772445Sassar return ret; /* XXX */ 57872445Sassar ccache = cc; 57972445Sassar } 58072445Sassar 58172445Sassar 58272445Sassar if (client_name != NULL) 58372445Sassar ctx->client_name = strdup(client_name); 58472445Sassar else 58572445Sassar ctx->client_name = NULL; 58672445Sassar if (service_name != NULL) 58772445Sassar ctx->service_name = strdup(service_name); 58872445Sassar else 58972445Sassar ctx->service_name = NULL; 59072445Sassar ctx->prompter = prompter; 59172445Sassar ctx->keytab = keytab; 59272445Sassar ctx->ccache = ccache; 59390926Snectar /* maybe we should copy the params here */ 59472445Sassar ctx->sock = -1; 59572445Sassar 59655682Smarkm *server_handle = ctx; 59755682Smarkm return 0; 59855682Smarkm} 59955682Smarkm 60055682Smarkmstatic kadm5_ret_t 60155682Smarkminit_context(const char *client_name, 60255682Smarkm const char *password, 60355682Smarkm krb5_prompter_fct prompter, 60455682Smarkm const char *keytab, 60555682Smarkm krb5_ccache ccache, 60655682Smarkm const char *service_name, 60755682Smarkm kadm5_config_params *realm_params, 60855682Smarkm unsigned long struct_version, 60955682Smarkm unsigned long api_version, 61055682Smarkm void **server_handle) 61155682Smarkm{ 61255682Smarkm krb5_context context; 61355682Smarkm kadm5_ret_t ret; 61455682Smarkm kadm5_server_context *ctx; 61555682Smarkm 61672445Sassar ret = krb5_init_context(&context); 61772445Sassar if (ret) 61872445Sassar return ret; 61955682Smarkm ret = kadm5_c_init_with_context(context, 62055682Smarkm client_name, 62155682Smarkm password, 62255682Smarkm prompter, 62355682Smarkm keytab, 62455682Smarkm ccache, 62555682Smarkm service_name, 62655682Smarkm realm_params, 62755682Smarkm struct_version, 62855682Smarkm api_version, 62955682Smarkm server_handle); 63055682Smarkm if(ret){ 63155682Smarkm krb5_free_context(context); 63255682Smarkm return ret; 63355682Smarkm } 63455682Smarkm ctx = *server_handle; 63555682Smarkm ctx->my_context = 1; 63655682Smarkm return 0; 63755682Smarkm} 63855682Smarkm 63955682Smarkmkadm5_ret_t 64055682Smarkmkadm5_c_init_with_password_ctx(krb5_context context, 64155682Smarkm const char *client_name, 64255682Smarkm const char *password, 64355682Smarkm const char *service_name, 64455682Smarkm kadm5_config_params *realm_params, 64555682Smarkm unsigned long struct_version, 64655682Smarkm unsigned long api_version, 64755682Smarkm void **server_handle) 64855682Smarkm{ 64955682Smarkm return kadm5_c_init_with_context(context, 65055682Smarkm client_name, 65155682Smarkm password, 65255682Smarkm krb5_prompter_posix, 65355682Smarkm NULL, 65455682Smarkm NULL, 65555682Smarkm service_name, 65655682Smarkm realm_params, 65755682Smarkm struct_version, 65855682Smarkm api_version, 65955682Smarkm server_handle); 66055682Smarkm} 66155682Smarkm 66255682Smarkmkadm5_ret_t 66355682Smarkmkadm5_c_init_with_password(const char *client_name, 66455682Smarkm const char *password, 66555682Smarkm const char *service_name, 66655682Smarkm kadm5_config_params *realm_params, 66755682Smarkm unsigned long struct_version, 66855682Smarkm unsigned long api_version, 66955682Smarkm void **server_handle) 67055682Smarkm{ 67155682Smarkm return init_context(client_name, 67255682Smarkm password, 67355682Smarkm krb5_prompter_posix, 67455682Smarkm NULL, 67555682Smarkm NULL, 67655682Smarkm service_name, 67755682Smarkm realm_params, 67855682Smarkm struct_version, 67955682Smarkm api_version, 68055682Smarkm server_handle); 68155682Smarkm} 68255682Smarkm 68355682Smarkmkadm5_ret_t 68455682Smarkmkadm5_c_init_with_skey_ctx(krb5_context context, 68555682Smarkm const char *client_name, 68655682Smarkm const char *keytab, 68755682Smarkm const char *service_name, 68855682Smarkm kadm5_config_params *realm_params, 68955682Smarkm unsigned long struct_version, 69055682Smarkm unsigned long api_version, 69155682Smarkm void **server_handle) 69255682Smarkm{ 69355682Smarkm return kadm5_c_init_with_context(context, 69455682Smarkm client_name, 69555682Smarkm NULL, 69655682Smarkm NULL, 69755682Smarkm keytab, 69855682Smarkm NULL, 69955682Smarkm service_name, 70055682Smarkm realm_params, 70155682Smarkm struct_version, 70255682Smarkm api_version, 70355682Smarkm server_handle); 70455682Smarkm} 70555682Smarkm 70655682Smarkm 70755682Smarkmkadm5_ret_t 70855682Smarkmkadm5_c_init_with_skey(const char *client_name, 70955682Smarkm const char *keytab, 71055682Smarkm const char *service_name, 71155682Smarkm kadm5_config_params *realm_params, 71255682Smarkm unsigned long struct_version, 71355682Smarkm unsigned long api_version, 71455682Smarkm void **server_handle) 71555682Smarkm{ 71655682Smarkm return init_context(client_name, 71755682Smarkm NULL, 71855682Smarkm NULL, 71955682Smarkm keytab, 72055682Smarkm NULL, 72155682Smarkm service_name, 72255682Smarkm realm_params, 72355682Smarkm struct_version, 72455682Smarkm api_version, 72555682Smarkm server_handle); 72655682Smarkm} 72755682Smarkm 72855682Smarkmkadm5_ret_t 72955682Smarkmkadm5_c_init_with_creds_ctx(krb5_context context, 73055682Smarkm const char *client_name, 73155682Smarkm krb5_ccache ccache, 73255682Smarkm const char *service_name, 73355682Smarkm kadm5_config_params *realm_params, 73455682Smarkm unsigned long struct_version, 73555682Smarkm unsigned long api_version, 73655682Smarkm void **server_handle) 73755682Smarkm{ 73855682Smarkm return kadm5_c_init_with_context(context, 73955682Smarkm client_name, 74055682Smarkm NULL, 74155682Smarkm NULL, 74255682Smarkm NULL, 74355682Smarkm ccache, 74455682Smarkm service_name, 74555682Smarkm realm_params, 74655682Smarkm struct_version, 74755682Smarkm api_version, 74855682Smarkm server_handle); 74955682Smarkm} 75055682Smarkm 75155682Smarkmkadm5_ret_t 75255682Smarkmkadm5_c_init_with_creds(const char *client_name, 75355682Smarkm krb5_ccache ccache, 75455682Smarkm const char *service_name, 75555682Smarkm kadm5_config_params *realm_params, 75655682Smarkm unsigned long struct_version, 75755682Smarkm unsigned long api_version, 75855682Smarkm void **server_handle) 75955682Smarkm{ 76055682Smarkm return init_context(client_name, 76155682Smarkm NULL, 76255682Smarkm NULL, 76355682Smarkm NULL, 76455682Smarkm ccache, 76555682Smarkm service_name, 76655682Smarkm realm_params, 76755682Smarkm struct_version, 76855682Smarkm api_version, 76955682Smarkm server_handle); 77055682Smarkm} 77155682Smarkm 77255682Smarkm#if 0 77355682Smarkmkadm5_ret_t 77455682Smarkmkadm5_init(char *client_name, char *pass, 77555682Smarkm char *service_name, 77655682Smarkm kadm5_config_params *realm_params, 77755682Smarkm unsigned long struct_version, 77855682Smarkm unsigned long api_version, 77955682Smarkm void **server_handle) 78055682Smarkm{ 78155682Smarkm} 78255682Smarkm#endif 78355682Smarkm 784