init_c.c revision 120945
155682Smarkm/*
2120945Snectar * Copyright (c) 1997 - 2003 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
40120945SnectarRCSID("$Id: init_c.c,v 1.45 2003/04/01 15:06:41 lha Exp $");
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;
7555682Smarkm    if(params->mask & KADM5_CONFIG_REALM)
7655682Smarkm	(*ctx)->realm = strdup(params->realm);
7755682Smarkm    else
7855682Smarkm	krb5_get_default_realm((*ctx)->context, &(*ctx)->realm);
7955682Smarkm    if(params->mask & KADM5_CONFIG_ADMIN_SERVER)
8055682Smarkm	(*ctx)->admin_server = strdup(params->admin_server);
8155682Smarkm    else {
8255682Smarkm	char **hostlist;
8355682Smarkm
8455682Smarkm	ret = krb5_get_krb_admin_hst (context, &(*ctx)->realm, &hostlist);
8555682Smarkm	if (ret)
8655682Smarkm	    return ret;
8755682Smarkm	(*ctx)->admin_server = strdup(*hostlist);
8855682Smarkm	krb5_free_krbhst (context, hostlist);
8955682Smarkm    }
9055682Smarkm
9155682Smarkm    if ((*ctx)->admin_server == NULL)
9255682Smarkm	return ENOMEM;
9355682Smarkm    colon = strchr ((*ctx)->admin_server, ':');
9455682Smarkm    if (colon != NULL)
9555682Smarkm	*colon++ = '\0';
9655682Smarkm
9755682Smarkm    (*ctx)->kadmind_port = 0;
9855682Smarkm
9955682Smarkm    if(params->mask & KADM5_CONFIG_KADMIND_PORT)
10055682Smarkm	(*ctx)->kadmind_port = params->kadmind_port;
10155682Smarkm    else if (colon != NULL) {
10255682Smarkm	char *end;
10355682Smarkm
10455682Smarkm	(*ctx)->kadmind_port = htons(strtol (colon, &end, 0));
10555682Smarkm    }
10655682Smarkm    if ((*ctx)->kadmind_port == 0)
10755682Smarkm	(*ctx)->kadmind_port = krb5_getportbyname (context, "kerberos-adm",
10855682Smarkm						   "tcp", 749);
10955682Smarkm    return 0;
11055682Smarkm}
11155682Smarkm
11255682Smarkmstatic krb5_error_code
11355682Smarkmget_kadm_ticket(krb5_context context,
11455682Smarkm		krb5_ccache id,
11555682Smarkm		krb5_principal client,
11655682Smarkm		const char *server_name)
11755682Smarkm{
11855682Smarkm    krb5_error_code ret;
11955682Smarkm    krb5_creds in, *out;
12055682Smarkm
12155682Smarkm    memset(&in, 0, sizeof(in));
12255682Smarkm    in.client = client;
12355682Smarkm    ret = krb5_parse_name(context, server_name, &in.server);
12455682Smarkm    if(ret)
12555682Smarkm	return ret;
12655682Smarkm    ret = krb5_get_credentials(context, 0, id, &in, &out);
12755682Smarkm    if(ret == 0)
12855682Smarkm	krb5_free_creds(context, out);
12955682Smarkm    krb5_free_principal(context, in.server);
13055682Smarkm    return ret;
13155682Smarkm}
13255682Smarkm
13355682Smarkmstatic krb5_error_code
13455682Smarkmget_new_cache(krb5_context context,
13555682Smarkm	      krb5_principal client,
13655682Smarkm	      const char *password,
13755682Smarkm	      krb5_prompter_fct prompter,
13855682Smarkm	      const char *keytab,
13955682Smarkm	      const char *server_name,
14055682Smarkm	      krb5_ccache *ret_cache)
14155682Smarkm{
14255682Smarkm    krb5_error_code ret;
14355682Smarkm    krb5_creds cred;
14455682Smarkm    krb5_get_init_creds_opt opt;
14555682Smarkm    krb5_ccache id;
14655682Smarkm
14755682Smarkm    krb5_get_init_creds_opt_init (&opt);
14890926Snectar
14990926Snectar    krb5_get_init_creds_opt_set_default_flags(context, "kadmin",
15090926Snectar					      krb5_principal_get_realm(context,
15190926Snectar								       client),
15290926Snectar					      &opt);
15390926Snectar
15490926Snectar
15557416Smarkm    krb5_get_init_creds_opt_set_forwardable (&opt, FALSE);
15657416Smarkm    krb5_get_init_creds_opt_set_proxiable (&opt, FALSE);
15757416Smarkm
15855682Smarkm    if(password == NULL && prompter == NULL) {
15955682Smarkm	krb5_keytab kt;
16055682Smarkm	if(keytab == NULL)
16155682Smarkm	    ret = krb5_kt_default(context, &kt);
16255682Smarkm	else
16355682Smarkm	    ret = krb5_kt_resolve(context, keytab, &kt);
16455682Smarkm	if(ret)
16555682Smarkm	    return ret;
16655682Smarkm	ret = krb5_get_init_creds_keytab (context,
16755682Smarkm					  &cred,
16855682Smarkm					  client,
16955682Smarkm					  kt,
17055682Smarkm					  0,
17155682Smarkm					  server_name,
17255682Smarkm					  &opt);
17355682Smarkm	krb5_kt_close(context, kt);
17455682Smarkm    } else {
17555682Smarkm	ret = krb5_get_init_creds_password (context,
17655682Smarkm					    &cred,
17755682Smarkm					    client,
17855682Smarkm					    password,
17955682Smarkm					    prompter,
18055682Smarkm					    NULL,
18155682Smarkm					    0,
18255682Smarkm					    server_name,
18355682Smarkm					    &opt);
18455682Smarkm    }
18555682Smarkm    switch(ret){
18655682Smarkm    case 0:
18755682Smarkm	break;
18855682Smarkm    case KRB5_LIBOS_PWDINTR:	/* don't print anything if it was just C-c:ed */
18955682Smarkm    case KRB5KRB_AP_ERR_BAD_INTEGRITY:
19055682Smarkm    case KRB5KRB_AP_ERR_MODIFIED:
19155682Smarkm	return KADM5_BAD_PASSWORD;
19255682Smarkm    default:
19355682Smarkm	return ret;
19455682Smarkm    }
19555682Smarkm    ret = krb5_cc_gen_new(context, &krb5_mcc_ops, &id);
19655682Smarkm    if(ret)
19755682Smarkm	return ret;
19855682Smarkm    ret = krb5_cc_initialize (context, id, cred.client);
19955682Smarkm    if (ret)
20055682Smarkm	return ret;
20155682Smarkm    ret = krb5_cc_store_cred (context, id, &cred);
20255682Smarkm    if (ret)
20355682Smarkm	return ret;
20455682Smarkm    krb5_free_creds_contents (context, &cred);
20555682Smarkm    *ret_cache = id;
20655682Smarkm    return 0;
20755682Smarkm}
20855682Smarkm
20955682Smarkmstatic krb5_error_code
21055682Smarkmget_cred_cache(krb5_context context,
21155682Smarkm	       const char *client_name,
21255682Smarkm	       const char *server_name,
21355682Smarkm	       const char *password,
21455682Smarkm	       krb5_prompter_fct prompter,
21555682Smarkm	       const char *keytab,
21655682Smarkm	       krb5_ccache ccache,
21755682Smarkm	       krb5_ccache *ret_cache)
21855682Smarkm{
21955682Smarkm    krb5_error_code ret;
22055682Smarkm    krb5_ccache id = NULL;
22155682Smarkm    krb5_principal default_client = NULL, client = NULL;
22255682Smarkm
22355682Smarkm    /* treat empty password as NULL */
22455682Smarkm    if(password && *password == '\0')
22555682Smarkm	password = NULL;
22655682Smarkm    if(server_name == NULL)
22755682Smarkm	server_name = KADM5_ADMIN_SERVICE;
22855682Smarkm
22955682Smarkm    if(client_name != NULL) {
23055682Smarkm	ret = krb5_parse_name(context, client_name, &client);
23155682Smarkm	if(ret)
23255682Smarkm	    return ret;
23355682Smarkm    }
23455682Smarkm
23555682Smarkm    if(password != NULL || prompter != NULL) {
23655682Smarkm	/* get principal from default cache, ok if this doesn't work */
23755682Smarkm	ret = krb5_cc_default(context, &id);
23855682Smarkm	if(ret == 0) {
23955682Smarkm	    ret = krb5_cc_get_principal(context, id, &default_client);
24055682Smarkm	    if(ret) {
24155682Smarkm		krb5_cc_close(context, id);
24255682Smarkm		id = NULL;
243102644Snectar	    } else {
244102644Snectar		const char *name, *inst;
245102644Snectar		krb5_principal tmp;
246102644Snectar		name = krb5_principal_get_comp_string(context,
247102644Snectar						      default_client, 0);
248102644Snectar		inst = krb5_principal_get_comp_string(context,
249102644Snectar						      default_client, 1);
250102644Snectar		if(inst == NULL || strcmp(inst, "admin") != 0) {
251102644Snectar		    ret = krb5_make_principal(context, &tmp, NULL,
252102644Snectar					      name, "admin", NULL);
253102644Snectar		    if(ret != 0) {
254102644Snectar			krb5_free_principal(context, default_client);
255102644Snectar			krb5_cc_close(context, id);
256102644Snectar			return ret;
257102644Snectar		    }
258102644Snectar		    krb5_free_principal(context, default_client);
259102644Snectar		    default_client = tmp;
260102644Snectar		    krb5_cc_close(context, id);
261102644Snectar		    id = NULL;
262102644Snectar		}
26355682Smarkm	    }
26455682Smarkm	}
265102644Snectar
266102644Snectar	if (client != NULL) {
267102644Snectar	    /* A client was specified by the caller. */
268102644Snectar	    if (default_client != NULL) {
269102644Snectar		krb5_free_principal(context, default_client);
270102644Snectar		default_client = NULL;
271102644Snectar	    }
272102644Snectar	}
273102644Snectar	else if (default_client != NULL)
274102644Snectar	    /* No client was specified by the caller, but we have a
275102644Snectar	     * client from the default credentials cache.
276102644Snectar	     */
27755682Smarkm	    client = default_client;
278102644Snectar	else {
279102644Snectar	    /* No client was specified by the caller and we cannot determine
280102644Snectar	     * the client from a credentials cache.
281102644Snectar	     */
28255682Smarkm	    const char *user;
28355682Smarkm
28455682Smarkm	    user = get_default_username ();
28555682Smarkm
28655682Smarkm	    if(user == NULL)
28755682Smarkm		return KADM5_FAILURE;
28855682Smarkm	    ret = krb5_make_principal(context, &client,
28955682Smarkm				      NULL, user, "admin", NULL);
29055682Smarkm	    if(ret)
29155682Smarkm		return ret;
29255682Smarkm	    if (id != NULL) {
29355682Smarkm		krb5_cc_close(context, id);
29455682Smarkm		id = NULL;
29555682Smarkm	    }
29655682Smarkm	}
29755682Smarkm    } else if(ccache != NULL)
29855682Smarkm	id = ccache;
29955682Smarkm
30055682Smarkm    if(id && (default_client == NULL ||
30155682Smarkm	      krb5_principal_compare(context, client, default_client))) {
30255682Smarkm	ret = get_kadm_ticket(context, id, client, server_name);
30355682Smarkm	if(ret == 0) {
30455682Smarkm	    *ret_cache = id;
30555682Smarkm	    krb5_free_principal(context, default_client);
30655682Smarkm	    if (default_client != client)
30755682Smarkm		krb5_free_principal(context, client);
30855682Smarkm	    return 0;
30955682Smarkm	}
31055682Smarkm	if(ccache != NULL)
31155682Smarkm	    /* couldn't get ticket from cache */
31255682Smarkm	    return -1;
31355682Smarkm    }
31455682Smarkm    /* get creds via AS request */
31555682Smarkm    if(id)
31655682Smarkm	krb5_cc_close(context, id);
31755682Smarkm    if (client != default_client)
31855682Smarkm	krb5_free_principal(context, default_client);
31955682Smarkm
32055682Smarkm    ret = get_new_cache(context, client, password, prompter, keytab,
32155682Smarkm			server_name, ret_cache);
32255682Smarkm    krb5_free_principal(context, client);
32355682Smarkm    return ret;
32455682Smarkm}
32555682Smarkm
32672445Sassarstatic kadm5_ret_t
32772445Sassarkadm_connect(kadm5_client_context *ctx)
32855682Smarkm{
32955682Smarkm    kadm5_ret_t ret;
33055682Smarkm    krb5_principal server;
33155682Smarkm    krb5_ccache cc;
33255682Smarkm    int s;
33355682Smarkm    struct addrinfo *ai, *a;
33455682Smarkm    struct addrinfo hints;
33555682Smarkm    int error;
33655682Smarkm    char portstr[NI_MAXSERV];
33755682Smarkm    char *hostname, *slash;
338120945Snectar    char *service_name;
33972445Sassar    krb5_context context = ctx->context;
34055682Smarkm
34155682Smarkm    memset (&hints, 0, sizeof(hints));
34255682Smarkm    hints.ai_socktype = SOCK_STREAM;
34355682Smarkm    hints.ai_protocol = IPPROTO_TCP;
34472445Sassar
34555682Smarkm    snprintf (portstr, sizeof(portstr), "%u", ntohs(ctx->kadmind_port));
34655682Smarkm
34755682Smarkm    hostname = ctx->admin_server;
34855682Smarkm    slash = strchr (hostname, '/');
34955682Smarkm    if (slash != NULL)
35055682Smarkm	hostname = slash + 1;
35155682Smarkm
35255682Smarkm    error = getaddrinfo (hostname, portstr, &hints, &ai);
35355682Smarkm    if (error)
35455682Smarkm	return KADM5_BAD_SERVER_NAME;
35555682Smarkm
35655682Smarkm    for (a = ai; a != NULL; a = a->ai_next) {
35755682Smarkm	s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
35855682Smarkm	if (s < 0)
35955682Smarkm	    continue;
36055682Smarkm	if (connect (s, a->ai_addr, a->ai_addrlen) < 0) {
36155682Smarkm	    krb5_warn (context, errno, "connect(%s)", hostname);
36255682Smarkm	    close (s);
36355682Smarkm	    continue;
36455682Smarkm	}
36555682Smarkm	break;
36655682Smarkm    }
36755682Smarkm    if (a == NULL) {
36855682Smarkm	freeaddrinfo (ai);
36955682Smarkm	krb5_warnx (context, "failed to contact %s", hostname);
37055682Smarkm	return KADM5_FAILURE;
37155682Smarkm    }
37272445Sassar    ret = get_cred_cache(context, ctx->client_name, ctx->service_name,
37372445Sassar			 NULL, ctx->prompter, ctx->keytab,
37472445Sassar			 ctx->ccache, &cc);
37555682Smarkm
37655682Smarkm    if(ret) {
37755682Smarkm	freeaddrinfo (ai);
37855682Smarkm	close(s);
37955682Smarkm	return ret;
38055682Smarkm    }
381120945Snectar
382120945Snectar    if (ctx->realm)
383120945Snectar	asprintf(&service_name, "%s@%s", KADM5_ADMIN_SERVICE, ctx->realm);
384120945Snectar    else
385120945Snectar	asprintf(&service_name, "%s", KADM5_ADMIN_SERVICE);
386120945Snectar
387120945Snectar    if (service_name == NULL) {
388120945Snectar	freeaddrinfo (ai);
389120945Snectar	close(s);
390120945Snectar	return ENOMEM;
391120945Snectar    }
392120945Snectar
393120945Snectar    ret = krb5_parse_name(context, service_name, &server);
394120945Snectar    free(service_name);
39555682Smarkm    if(ret) {
39655682Smarkm	freeaddrinfo (ai);
39772445Sassar	if(ctx->ccache == NULL)
39855682Smarkm	    krb5_cc_close(context, cc);
39955682Smarkm	close(s);
40055682Smarkm	return ret;
40155682Smarkm    }
40255682Smarkm    ctx->ac = NULL;
40355682Smarkm
40455682Smarkm    ret = krb5_sendauth(context, &ctx->ac, &s,
40555682Smarkm			KADMIN_APPL_VERSION, NULL,
40655682Smarkm			server, AP_OPTS_MUTUAL_REQUIRED,
40755682Smarkm			NULL, NULL, cc, NULL, NULL, NULL);
40855682Smarkm    if(ret == 0) {
40972445Sassar	krb5_data params;
41090926Snectar	kadm5_config_params p;
41190926Snectar	memset(&p, 0, sizeof(p));
41290926Snectar	if(ctx->realm) {
41390926Snectar	    p.mask |= KADM5_CONFIG_REALM;
41490926Snectar	    p.realm = ctx->realm;
41590926Snectar	}
41690926Snectar	ret = _kadm5_marshal_params(context, &p, &params);
41755682Smarkm
41872445Sassar	ret = krb5_write_priv_message(context, ctx->ac, &s, &params);
41955682Smarkm	krb5_data_free(&params);
42072445Sassar	if(ret) {
42172445Sassar	    freeaddrinfo (ai);
42272445Sassar	    close(s);
42372445Sassar	    if(ctx->ccache == NULL)
42472445Sassar		krb5_cc_close(context, cc);
42572445Sassar	    return ret;
42672445Sassar	}
42755682Smarkm    } else if(ret == KRB5_SENDAUTH_BADAPPLVERS) {
42855682Smarkm	close(s);
42955682Smarkm
43055682Smarkm	s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
43155682Smarkm	if (s < 0) {
43255682Smarkm	    freeaddrinfo (ai);
43355682Smarkm	    return errno;
43455682Smarkm	}
43555682Smarkm	if (connect (s, a->ai_addr, a->ai_addrlen) < 0) {
43655682Smarkm	    close (s);
43755682Smarkm	    freeaddrinfo (ai);
43855682Smarkm	    return errno;
43955682Smarkm	}
44055682Smarkm	ret = krb5_sendauth(context, &ctx->ac, &s,
44155682Smarkm			    KADMIN_OLD_APPL_VERSION, NULL,
44255682Smarkm			    server, AP_OPTS_MUTUAL_REQUIRED,
44355682Smarkm			    NULL, NULL, cc, NULL, NULL, NULL);
44455682Smarkm    }
44555682Smarkm    freeaddrinfo (ai);
44655682Smarkm    if(ret) {
44755682Smarkm	close(s);
44855682Smarkm	return ret;
44955682Smarkm    }
45055682Smarkm
45155682Smarkm    krb5_free_principal(context, server);
45272445Sassar    if(ctx->ccache == NULL)
45355682Smarkm	krb5_cc_close(context, cc);
45455682Smarkm    if(ret) {
45555682Smarkm	close(s);
45655682Smarkm	return ret;
45755682Smarkm    }
45855682Smarkm    ctx->sock = s;
45972445Sassar
46072445Sassar    return 0;
46172445Sassar}
46272445Sassar
46372445Sassarkadm5_ret_t
46472445Sassar_kadm5_connect(void *handle)
46572445Sassar{
46672445Sassar    kadm5_client_context *ctx = handle;
46772445Sassar    if(ctx->sock == -1)
46872445Sassar	return kadm_connect(ctx);
46972445Sassar    return 0;
47072445Sassar}
47172445Sassar
47272445Sassarstatic kadm5_ret_t
47372445Sassarkadm5_c_init_with_context(krb5_context context,
47472445Sassar			  const char *client_name,
47572445Sassar			  const char *password,
47672445Sassar			  krb5_prompter_fct prompter,
47772445Sassar			  const char *keytab,
47872445Sassar			  krb5_ccache ccache,
47972445Sassar			  const char *service_name,
48072445Sassar			  kadm5_config_params *realm_params,
48172445Sassar			  unsigned long struct_version,
48272445Sassar			  unsigned long api_version,
48372445Sassar			  void **server_handle)
48472445Sassar{
48572445Sassar    kadm5_ret_t ret;
48672445Sassar    kadm5_client_context *ctx;
48772445Sassar    krb5_ccache cc;
48872445Sassar
48972445Sassar    ret = _kadm5_c_init_context(&ctx, realm_params, context);
49072445Sassar    if(ret)
49172445Sassar	return ret;
49272445Sassar
49372445Sassar    if(password != NULL && *password != '\0') {
49472445Sassar	ret = get_cred_cache(context, client_name, service_name,
49572445Sassar			     password, prompter, keytab, ccache, &cc);
49672445Sassar	if(ret)
49772445Sassar	    return ret; /* XXX */
49872445Sassar	ccache = cc;
49972445Sassar    }
50072445Sassar
50172445Sassar
50272445Sassar    if (client_name != NULL)
50372445Sassar	ctx->client_name = strdup(client_name);
50472445Sassar    else
50572445Sassar	ctx->client_name = NULL;
50672445Sassar    if (service_name != NULL)
50772445Sassar	ctx->service_name = strdup(service_name);
50872445Sassar    else
50972445Sassar	ctx->service_name = NULL;
51072445Sassar    ctx->prompter = prompter;
51172445Sassar    ctx->keytab = keytab;
51272445Sassar    ctx->ccache = ccache;
51390926Snectar    /* maybe we should copy the params here */
51472445Sassar    ctx->sock = -1;
51572445Sassar
51655682Smarkm    *server_handle = ctx;
51755682Smarkm    return 0;
51855682Smarkm}
51955682Smarkm
52055682Smarkmstatic kadm5_ret_t
52155682Smarkminit_context(const char *client_name,
52255682Smarkm	     const char *password,
52355682Smarkm	     krb5_prompter_fct prompter,
52455682Smarkm	     const char *keytab,
52555682Smarkm	     krb5_ccache ccache,
52655682Smarkm	     const char *service_name,
52755682Smarkm	     kadm5_config_params *realm_params,
52855682Smarkm	     unsigned long struct_version,
52955682Smarkm	     unsigned long api_version,
53055682Smarkm	     void **server_handle)
53155682Smarkm{
53255682Smarkm    krb5_context context;
53355682Smarkm    kadm5_ret_t ret;
53455682Smarkm    kadm5_server_context *ctx;
53555682Smarkm
53672445Sassar    ret = krb5_init_context(&context);
53772445Sassar    if (ret)
53872445Sassar	return ret;
53955682Smarkm    ret = kadm5_c_init_with_context(context,
54055682Smarkm				    client_name,
54155682Smarkm				    password,
54255682Smarkm				    prompter,
54355682Smarkm				    keytab,
54455682Smarkm				    ccache,
54555682Smarkm				    service_name,
54655682Smarkm				    realm_params,
54755682Smarkm				    struct_version,
54855682Smarkm				    api_version,
54955682Smarkm				    server_handle);
55055682Smarkm    if(ret){
55155682Smarkm	krb5_free_context(context);
55255682Smarkm	return ret;
55355682Smarkm    }
55455682Smarkm    ctx = *server_handle;
55555682Smarkm    ctx->my_context = 1;
55655682Smarkm    return 0;
55755682Smarkm}
55855682Smarkm
55955682Smarkmkadm5_ret_t
56055682Smarkmkadm5_c_init_with_password_ctx(krb5_context context,
56155682Smarkm			       const char *client_name,
56255682Smarkm			       const char *password,
56355682Smarkm			       const char *service_name,
56455682Smarkm			       kadm5_config_params *realm_params,
56555682Smarkm			       unsigned long struct_version,
56655682Smarkm			       unsigned long api_version,
56755682Smarkm			       void **server_handle)
56855682Smarkm{
56955682Smarkm    return kadm5_c_init_with_context(context,
57055682Smarkm				     client_name,
57155682Smarkm				     password,
57255682Smarkm				     krb5_prompter_posix,
57355682Smarkm				     NULL,
57455682Smarkm				     NULL,
57555682Smarkm				     service_name,
57655682Smarkm				     realm_params,
57755682Smarkm				     struct_version,
57855682Smarkm				     api_version,
57955682Smarkm				     server_handle);
58055682Smarkm}
58155682Smarkm
58255682Smarkmkadm5_ret_t
58355682Smarkmkadm5_c_init_with_password(const char *client_name,
58455682Smarkm			   const char *password,
58555682Smarkm			   const char *service_name,
58655682Smarkm			   kadm5_config_params *realm_params,
58755682Smarkm			   unsigned long struct_version,
58855682Smarkm			   unsigned long api_version,
58955682Smarkm			   void **server_handle)
59055682Smarkm{
59155682Smarkm    return init_context(client_name,
59255682Smarkm			password,
59355682Smarkm			krb5_prompter_posix,
59455682Smarkm			NULL,
59555682Smarkm			NULL,
59655682Smarkm			service_name,
59755682Smarkm			realm_params,
59855682Smarkm			struct_version,
59955682Smarkm			api_version,
60055682Smarkm			server_handle);
60155682Smarkm}
60255682Smarkm
60355682Smarkmkadm5_ret_t
60455682Smarkmkadm5_c_init_with_skey_ctx(krb5_context context,
60555682Smarkm			   const char *client_name,
60655682Smarkm			   const char *keytab,
60755682Smarkm			   const char *service_name,
60855682Smarkm			   kadm5_config_params *realm_params,
60955682Smarkm			   unsigned long struct_version,
61055682Smarkm			   unsigned long api_version,
61155682Smarkm			   void **server_handle)
61255682Smarkm{
61355682Smarkm    return kadm5_c_init_with_context(context,
61455682Smarkm				     client_name,
61555682Smarkm				     NULL,
61655682Smarkm				     NULL,
61755682Smarkm				     keytab,
61855682Smarkm				     NULL,
61955682Smarkm				     service_name,
62055682Smarkm				     realm_params,
62155682Smarkm				     struct_version,
62255682Smarkm				     api_version,
62355682Smarkm				     server_handle);
62455682Smarkm}
62555682Smarkm
62655682Smarkm
62755682Smarkmkadm5_ret_t
62855682Smarkmkadm5_c_init_with_skey(const char *client_name,
62955682Smarkm		     const char *keytab,
63055682Smarkm		     const char *service_name,
63155682Smarkm		     kadm5_config_params *realm_params,
63255682Smarkm		     unsigned long struct_version,
63355682Smarkm		     unsigned long api_version,
63455682Smarkm		     void **server_handle)
63555682Smarkm{
63655682Smarkm    return init_context(client_name,
63755682Smarkm			NULL,
63855682Smarkm			NULL,
63955682Smarkm			keytab,
64055682Smarkm			NULL,
64155682Smarkm			service_name,
64255682Smarkm			realm_params,
64355682Smarkm			struct_version,
64455682Smarkm			api_version,
64555682Smarkm			server_handle);
64655682Smarkm}
64755682Smarkm
64855682Smarkmkadm5_ret_t
64955682Smarkmkadm5_c_init_with_creds_ctx(krb5_context context,
65055682Smarkm			    const char *client_name,
65155682Smarkm			    krb5_ccache ccache,
65255682Smarkm			    const char *service_name,
65355682Smarkm			    kadm5_config_params *realm_params,
65455682Smarkm			    unsigned long struct_version,
65555682Smarkm			    unsigned long api_version,
65655682Smarkm			    void **server_handle)
65755682Smarkm{
65855682Smarkm    return kadm5_c_init_with_context(context,
65955682Smarkm				     client_name,
66055682Smarkm				     NULL,
66155682Smarkm				     NULL,
66255682Smarkm				     NULL,
66355682Smarkm				     ccache,
66455682Smarkm				     service_name,
66555682Smarkm				     realm_params,
66655682Smarkm				     struct_version,
66755682Smarkm				     api_version,
66855682Smarkm				     server_handle);
66955682Smarkm}
67055682Smarkm
67155682Smarkmkadm5_ret_t
67255682Smarkmkadm5_c_init_with_creds(const char *client_name,
67355682Smarkm			krb5_ccache ccache,
67455682Smarkm			const char *service_name,
67555682Smarkm			kadm5_config_params *realm_params,
67655682Smarkm			unsigned long struct_version,
67755682Smarkm			unsigned long api_version,
67855682Smarkm			void **server_handle)
67955682Smarkm{
68055682Smarkm    return init_context(client_name,
68155682Smarkm			NULL,
68255682Smarkm			NULL,
68355682Smarkm			NULL,
68455682Smarkm			ccache,
68555682Smarkm			service_name,
68655682Smarkm			realm_params,
68755682Smarkm			struct_version,
68855682Smarkm			api_version,
68955682Smarkm			server_handle);
69055682Smarkm}
69155682Smarkm
69255682Smarkm#if 0
69355682Smarkmkadm5_ret_t
69455682Smarkmkadm5_init(char *client_name, char *pass,
69555682Smarkm	   char *service_name,
69655682Smarkm	   kadm5_config_params *realm_params,
69755682Smarkm	   unsigned long struct_version,
69855682Smarkm	   unsigned long api_version,
69955682Smarkm	   void **server_handle)
70055682Smarkm{
70155682Smarkm}
70255682Smarkm#endif
70355682Smarkm
704