init_c.c revision 127808
1145519Sdarrenr/*
2145510Sdarrenr * Copyright (c) 1997 - 2003 Kungliga Tekniska H�gskolan
322514Sdarrenr * (Royal Institute of Technology, Stockholm, Sweden).
453024Sguido * All rights reserved.
522514Sdarrenr *
680486Sdarrenr * Redistribution and use in source and binary forms, with or without
722514Sdarrenr * modification, are permitted provided that the following conditions
822514Sdarrenr * are met:
922514Sdarrenr *
1022514Sdarrenr * 1. Redistributions of source code must retain the above copyright
1122514Sdarrenr *    notice, this list of conditions and the following disclaimer.
1222514Sdarrenr *
1322514Sdarrenr * 2. Redistributions in binary form must reproduce the above copyright
1422514Sdarrenr *    notice, this list of conditions and the following disclaimer in the
1522514Sdarrenr *    documentation and/or other materials provided with the distribution.
1622514Sdarrenr *
1722514Sdarrenr * 3. Neither the name of the Institute nor the names of its contributors
1822514Sdarrenr *    may be used to endorse or promote products derived from this software
1922514Sdarrenr *    without specific prior written permission.
2022514Sdarrenr *
2122514Sdarrenr * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
2222514Sdarrenr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2322514Sdarrenr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2422514Sdarrenr * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
2522514Sdarrenr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2622514Sdarrenr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2722514Sdarrenr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2822514Sdarrenr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2922514Sdarrenr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3022514Sdarrenr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3122514Sdarrenr * SUCH DAMAGE.
3222514Sdarrenr */
3322514Sdarrenr
3422514Sdarrenr#include "kadm5_locl.h"
3522514Sdarrenr#include <sys/types.h>
3622514Sdarrenr#include <sys/socket.h>
3731183Speter#include <netinet/in.h>
38255332Scy#include <netdb.h>
3922514Sdarrenr
4022514SdarrenrRCSID("$Id: init_c.c,v 1.45.2.1 2003/12/21 22:48:13 lha Exp $");
4122514Sdarrenr
4222514Sdarrenrstatic void
4322514Sdarrenrset_funcs(kadm5_client_context *c)
4422514Sdarrenr{
4522514Sdarrenr#define SET(C, F) (C)->funcs.F = kadm5 ## _c_ ## F
4622514Sdarrenr    SET(c, chpass_principal);
4722514Sdarrenr    SET(c, chpass_principal_with_key);
4822514Sdarrenr    SET(c, create_principal);
4922514Sdarrenr    SET(c, delete_principal);
5022514Sdarrenr    SET(c, destroy);
5122514Sdarrenr    SET(c, flush);
5222514Sdarrenr    SET(c, get_principal);
5322514Sdarrenr    SET(c, get_principals);
5422514Sdarrenr    SET(c, get_privs);
5522514Sdarrenr    SET(c, modify_principal);
5622514Sdarrenr    SET(c, randkey_principal);
5722514Sdarrenr    SET(c, rename_principal);
5822514Sdarrenr}
5922514Sdarrenr
60255332Scykadm5_ret_t
6122514Sdarrenr_kadm5_c_init_context(kadm5_client_context **ctx,
6222514Sdarrenr		      kadm5_config_params *params,
6322514Sdarrenr		      krb5_context context)
6422514Sdarrenr{
6522514Sdarrenr    krb5_error_code ret;
6622514Sdarrenr    char *colon;
67255332Scy
6822514Sdarrenr    *ctx = malloc(sizeof(**ctx));
6922514Sdarrenr    if(*ctx == NULL)
7022514Sdarrenr	return ENOMEM;
7122514Sdarrenr    memset(*ctx, 0, sizeof(**ctx));
7222514Sdarrenr    krb5_add_et_list (context, initialize_kadm5_error_table_r);
7322514Sdarrenr    set_funcs(*ctx);
74255332Scy    (*ctx)->context = context;
7522514Sdarrenr    if(params->mask & KADM5_CONFIG_REALM) {
7622514Sdarrenr	ret = 0;
7722514Sdarrenr	(*ctx)->realm = strdup(params->realm);
7822514Sdarrenr	if ((*ctx)->realm == NULL)
7922514Sdarrenr	    ret = ENOMEM;
8022514Sdarrenr    } else
8122514Sdarrenr	ret = krb5_get_default_realm((*ctx)->context, &(*ctx)->realm);
8222514Sdarrenr    if (ret) {
8322514Sdarrenr	free(*ctx);
8422514Sdarrenr	return ret;
8522514Sdarrenr    }
8622514Sdarrenr    if(params->mask & KADM5_CONFIG_ADMIN_SERVER)
8722514Sdarrenr	(*ctx)->admin_server = strdup(params->admin_server);
8822514Sdarrenr    else {
8922514Sdarrenr	char **hostlist;
90255332Scy
91255332Scy	ret = krb5_get_krb_admin_hst (context, &(*ctx)->realm, &hostlist);
92255332Scy	if (ret) {
9322514Sdarrenr	    free((*ctx)->realm);
9422514Sdarrenr	    free(*ctx);
9522514Sdarrenr	    return ret;
9622514Sdarrenr	}
9722514Sdarrenr	(*ctx)->admin_server = strdup(*hostlist);
9822514Sdarrenr	krb5_free_krbhst (context, hostlist);
9922514Sdarrenr    }
10022514Sdarrenr
10122514Sdarrenr    if ((*ctx)->admin_server == NULL) {
10222514Sdarrenr	return ENOMEM;
10322514Sdarrenr	free((*ctx)->realm);
10422514Sdarrenr	free(*ctx);
10522514Sdarrenr    }
10622514Sdarrenr    colon = strchr ((*ctx)->admin_server, ':');
10722514Sdarrenr    if (colon != NULL)
10822514Sdarrenr	*colon++ = '\0';
10922514Sdarrenr
11022514Sdarrenr    (*ctx)->kadmind_port = 0;
11122514Sdarrenr
11222514Sdarrenr    if(params->mask & KADM5_CONFIG_KADMIND_PORT)
11322514Sdarrenr	(*ctx)->kadmind_port = params->kadmind_port;
11422514Sdarrenr    else if (colon != NULL) {
11522514Sdarrenr	char *end;
11622514Sdarrenr
11722514Sdarrenr	(*ctx)->kadmind_port = htons(strtol (colon, &end, 0));
11822514Sdarrenr    }
11922514Sdarrenr    if ((*ctx)->kadmind_port == 0)
12022514Sdarrenr	(*ctx)->kadmind_port = krb5_getportbyname (context, "kerberos-adm",
12122514Sdarrenr						   "tcp", 749);
12222514Sdarrenr    return 0;
123255332Scy}
124255332Scy
125255332Scystatic krb5_error_code
12622514Sdarrenrget_kadm_ticket(krb5_context context,
12722514Sdarrenr		krb5_ccache id,
12822514Sdarrenr		krb5_principal client,
12922514Sdarrenr		const char *server_name)
13022514Sdarrenr{
13122514Sdarrenr    krb5_error_code ret;
13222514Sdarrenr    krb5_creds in, *out;
13322514Sdarrenr
13422514Sdarrenr    memset(&in, 0, sizeof(in));
13522514Sdarrenr    in.client = client;
13622514Sdarrenr    ret = krb5_parse_name(context, server_name, &in.server);
13722514Sdarrenr    if(ret)
13822514Sdarrenr	return ret;
13922514Sdarrenr    ret = krb5_get_credentials(context, 0, id, &in, &out);
14022514Sdarrenr    if(ret == 0)
14122514Sdarrenr	krb5_free_creds(context, out);
14222514Sdarrenr    krb5_free_principal(context, in.server);
14322514Sdarrenr    return ret;
14422514Sdarrenr}
14522514Sdarrenr
14622514Sdarrenrstatic krb5_error_code
14722514Sdarrenrget_new_cache(krb5_context context,
14822514Sdarrenr	      krb5_principal client,
14922514Sdarrenr	      const char *password,
15022514Sdarrenr	      krb5_prompter_fct prompter,
15122514Sdarrenr	      const char *keytab,
15222514Sdarrenr	      const char *server_name,
15322514Sdarrenr	      krb5_ccache *ret_cache)
15422514Sdarrenr{
15522514Sdarrenr    krb5_error_code ret;
15622514Sdarrenr    krb5_creds cred;
15722514Sdarrenr    krb5_get_init_creds_opt opt;
15822514Sdarrenr    krb5_ccache id;
15922514Sdarrenr
16022514Sdarrenr    krb5_get_init_creds_opt_init (&opt);
16122514Sdarrenr
16222514Sdarrenr    krb5_get_init_creds_opt_set_default_flags(context, "kadmin",
16322514Sdarrenr					      krb5_principal_get_realm(context,
16422514Sdarrenr								       client),
16522514Sdarrenr					      &opt);
16622514Sdarrenr
16722514Sdarrenr
16822514Sdarrenr    krb5_get_init_creds_opt_set_forwardable (&opt, FALSE);
16922514Sdarrenr    krb5_get_init_creds_opt_set_proxiable (&opt, FALSE);
17022514Sdarrenr
17122514Sdarrenr    if(password == NULL && prompter == NULL) {
17222514Sdarrenr	krb5_keytab kt;
17322514Sdarrenr	if(keytab == NULL)
17422514Sdarrenr	    ret = krb5_kt_default(context, &kt);
17522514Sdarrenr	else
17622514Sdarrenr	    ret = krb5_kt_resolve(context, keytab, &kt);
17722514Sdarrenr	if(ret)
17822514Sdarrenr	    return ret;
17922514Sdarrenr	ret = krb5_get_init_creds_keytab (context,
18022514Sdarrenr					  &cred,
18122514Sdarrenr					  client,
18222514Sdarrenr					  kt,
18322514Sdarrenr					  0,
184255332Scy					  server_name,
18522514Sdarrenr					  &opt);
18622514Sdarrenr	krb5_kt_close(context, kt);
18722514Sdarrenr    } else {
18822514Sdarrenr	ret = krb5_get_init_creds_password (context,
18922514Sdarrenr					    &cred,
19022514Sdarrenr					    client,
19122514Sdarrenr					    password,
19222514Sdarrenr					    prompter,
19322514Sdarrenr					    NULL,
19422514Sdarrenr					    0,
19522514Sdarrenr					    server_name,
19622514Sdarrenr					    &opt);
19722514Sdarrenr    }
19822514Sdarrenr    switch(ret){
19922514Sdarrenr    case 0:
20022514Sdarrenr	break;
20122514Sdarrenr    case KRB5_LIBOS_PWDINTR:	/* don't print anything if it was just C-c:ed */
20222514Sdarrenr    case KRB5KRB_AP_ERR_BAD_INTEGRITY:
20322514Sdarrenr    case KRB5KRB_AP_ERR_MODIFIED:
20422514Sdarrenr	return KADM5_BAD_PASSWORD;
20522514Sdarrenr    default:
20622514Sdarrenr	return ret;
20722514Sdarrenr    }
20822514Sdarrenr    ret = krb5_cc_gen_new(context, &krb5_mcc_ops, &id);
20922514Sdarrenr    if(ret)
21022514Sdarrenr	return ret;
21122514Sdarrenr    ret = krb5_cc_initialize (context, id, cred.client);
212255332Scy    if (ret)
21322514Sdarrenr	return ret;
21422514Sdarrenr    ret = krb5_cc_store_cred (context, id, &cred);
21522514Sdarrenr    if (ret)
21622514Sdarrenr	return ret;
21722514Sdarrenr    krb5_free_creds_contents (context, &cred);
21822514Sdarrenr    *ret_cache = id;
21922514Sdarrenr    return 0;
22022514Sdarrenr}
22122514Sdarrenr
22222514Sdarrenrstatic krb5_error_code
22322514Sdarrenrget_cred_cache(krb5_context context,
22422514Sdarrenr	       const char *client_name,
22522514Sdarrenr	       const char *server_name,
22622514Sdarrenr	       const char *password,
22722514Sdarrenr	       krb5_prompter_fct prompter,
22822514Sdarrenr	       const char *keytab,
229255332Scy	       krb5_ccache ccache,
230255332Scy	       krb5_ccache *ret_cache)
23122514Sdarrenr{
23222514Sdarrenr    krb5_error_code ret;
23322514Sdarrenr    krb5_ccache id = NULL;
23422514Sdarrenr    krb5_principal default_client = NULL, client = NULL;
23522514Sdarrenr
23622514Sdarrenr    /* treat empty password as NULL */
23722514Sdarrenr    if(password && *password == '\0')
23822514Sdarrenr	password = NULL;
23922514Sdarrenr    if(server_name == NULL)
24022514Sdarrenr	server_name = KADM5_ADMIN_SERVICE;
24122514Sdarrenr
24222514Sdarrenr    if(client_name != NULL) {
24322514Sdarrenr	ret = krb5_parse_name(context, client_name, &client);
24422514Sdarrenr	if(ret)
24522514Sdarrenr	    return ret;
24622514Sdarrenr    }
24722514Sdarrenr
24822514Sdarrenr    if(password != NULL || prompter != NULL) {
24922514Sdarrenr	/* get principal from default cache, ok if this doesn't work */
25022514Sdarrenr	ret = krb5_cc_default(context, &id);
25122514Sdarrenr	if(ret == 0) {
25222514Sdarrenr	    ret = krb5_cc_get_principal(context, id, &default_client);
25322514Sdarrenr	    if(ret) {
25422514Sdarrenr		krb5_cc_close(context, id);
25522514Sdarrenr		id = NULL;
25622514Sdarrenr	    } else {
25722514Sdarrenr		const char *name, *inst;
25822514Sdarrenr		krb5_principal tmp;
25922514Sdarrenr		name = krb5_principal_get_comp_string(context,
26022514Sdarrenr						      default_client, 0);
26122514Sdarrenr		inst = krb5_principal_get_comp_string(context,
26222514Sdarrenr						      default_client, 1);
26322514Sdarrenr		if(inst == NULL || strcmp(inst, "admin") != 0) {
26422514Sdarrenr		    ret = krb5_make_principal(context, &tmp, NULL,
26522514Sdarrenr					      name, "admin", NULL);
26622514Sdarrenr		    if(ret != 0) {
26722514Sdarrenr			krb5_free_principal(context, default_client);
26822514Sdarrenr			krb5_cc_close(context, id);
26922514Sdarrenr			return ret;
27022514Sdarrenr		    }
27122514Sdarrenr		    krb5_free_principal(context, default_client);
27222514Sdarrenr		    default_client = tmp;
27322514Sdarrenr		    krb5_cc_close(context, id);
27422514Sdarrenr		    id = NULL;
27522514Sdarrenr		}
27622514Sdarrenr	    }
27722514Sdarrenr	}
27822514Sdarrenr
27922514Sdarrenr	if (client != NULL) {
28022514Sdarrenr	    /* A client was specified by the caller. */
28122514Sdarrenr	    if (default_client != NULL) {
28222514Sdarrenr		krb5_free_principal(context, default_client);
28322514Sdarrenr		default_client = NULL;
28422514Sdarrenr	    }
28522514Sdarrenr	}
28622514Sdarrenr	else if (default_client != NULL)
28722514Sdarrenr	    /* No client was specified by the caller, but we have a
28822514Sdarrenr	     * client from the default credentials cache.
28922514Sdarrenr	     */
29022514Sdarrenr	    client = default_client;
29122514Sdarrenr	else {
29222514Sdarrenr	    /* No client was specified by the caller and we cannot determine
29322514Sdarrenr	     * the client from a credentials cache.
29422514Sdarrenr	     */
29522514Sdarrenr	    const char *user;
29622514Sdarrenr
29722514Sdarrenr	    user = get_default_username ();
29822514Sdarrenr
29922514Sdarrenr	    if(user == NULL)
30022514Sdarrenr		return KADM5_FAILURE;
30122514Sdarrenr	    ret = krb5_make_principal(context, &client,
30222514Sdarrenr				      NULL, user, "admin", NULL);
30322514Sdarrenr	    if(ret)
304255332Scy		return ret;
305255332Scy	    if (id != NULL) {
30622514Sdarrenr		krb5_cc_close(context, id);
30722514Sdarrenr		id = NULL;
30822514Sdarrenr	    }
30922514Sdarrenr	}
31022514Sdarrenr    } else if(ccache != NULL)
31122514Sdarrenr	id = ccache;
31222514Sdarrenr
31322514Sdarrenr    if(id && (default_client == NULL ||
31422514Sdarrenr	      krb5_principal_compare(context, client, default_client))) {
315	ret = get_kadm_ticket(context, id, client, server_name);
316	if(ret == 0) {
317	    *ret_cache = id;
318	    krb5_free_principal(context, default_client);
319	    if (default_client != client)
320		krb5_free_principal(context, client);
321	    return 0;
322	}
323	if(ccache != NULL)
324	    /* couldn't get ticket from cache */
325	    return -1;
326    }
327    /* get creds via AS request */
328    if(id)
329	krb5_cc_close(context, id);
330    if (client != default_client)
331	krb5_free_principal(context, default_client);
332
333    ret = get_new_cache(context, client, password, prompter, keytab,
334			server_name, ret_cache);
335    krb5_free_principal(context, client);
336    return ret;
337}
338
339static kadm5_ret_t
340kadm_connect(kadm5_client_context *ctx)
341{
342    kadm5_ret_t ret;
343    krb5_principal server;
344    krb5_ccache cc;
345    int s;
346    struct addrinfo *ai, *a;
347    struct addrinfo hints;
348    int error;
349    char portstr[NI_MAXSERV];
350    char *hostname, *slash;
351    char *service_name;
352    krb5_context context = ctx->context;
353
354    memset (&hints, 0, sizeof(hints));
355    hints.ai_socktype = SOCK_STREAM;
356    hints.ai_protocol = IPPROTO_TCP;
357
358    snprintf (portstr, sizeof(portstr), "%u", ntohs(ctx->kadmind_port));
359
360    hostname = ctx->admin_server;
361    slash = strchr (hostname, '/');
362    if (slash != NULL)
363	hostname = slash + 1;
364
365    error = getaddrinfo (hostname, portstr, &hints, &ai);
366    if (error)
367	return KADM5_BAD_SERVER_NAME;
368
369    for (a = ai; a != NULL; a = a->ai_next) {
370	s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
371	if (s < 0)
372	    continue;
373	if (connect (s, a->ai_addr, a->ai_addrlen) < 0) {
374	    krb5_warn (context, errno, "connect(%s)", hostname);
375	    close (s);
376	    continue;
377	}
378	break;
379    }
380    if (a == NULL) {
381	freeaddrinfo (ai);
382	krb5_warnx (context, "failed to contact %s", hostname);
383	return KADM5_FAILURE;
384    }
385    ret = get_cred_cache(context, ctx->client_name, ctx->service_name,
386			 NULL, ctx->prompter, ctx->keytab,
387			 ctx->ccache, &cc);
388
389    if(ret) {
390	freeaddrinfo (ai);
391	close(s);
392	return ret;
393    }
394
395    if (ctx->realm)
396	asprintf(&service_name, "%s@%s", KADM5_ADMIN_SERVICE, ctx->realm);
397    else
398	asprintf(&service_name, "%s", KADM5_ADMIN_SERVICE);
399
400    if (service_name == NULL) {
401	freeaddrinfo (ai);
402	close(s);
403	return ENOMEM;
404    }
405
406    ret = krb5_parse_name(context, service_name, &server);
407    free(service_name);
408    if(ret) {
409	freeaddrinfo (ai);
410	if(ctx->ccache == NULL)
411	    krb5_cc_close(context, cc);
412	close(s);
413	return ret;
414    }
415    ctx->ac = NULL;
416
417    ret = krb5_sendauth(context, &ctx->ac, &s,
418			KADMIN_APPL_VERSION, NULL,
419			server, AP_OPTS_MUTUAL_REQUIRED,
420			NULL, NULL, cc, NULL, NULL, NULL);
421    if(ret == 0) {
422	krb5_data params;
423	kadm5_config_params p;
424	memset(&p, 0, sizeof(p));
425	if(ctx->realm) {
426	    p.mask |= KADM5_CONFIG_REALM;
427	    p.realm = ctx->realm;
428	}
429	ret = _kadm5_marshal_params(context, &p, &params);
430
431	ret = krb5_write_priv_message(context, ctx->ac, &s, &params);
432	krb5_data_free(&params);
433	if(ret) {
434	    freeaddrinfo (ai);
435	    close(s);
436	    if(ctx->ccache == NULL)
437		krb5_cc_close(context, cc);
438	    return ret;
439	}
440    } else if(ret == KRB5_SENDAUTH_BADAPPLVERS) {
441	close(s);
442
443	s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
444	if (s < 0) {
445	    freeaddrinfo (ai);
446	    return errno;
447	}
448	if (connect (s, a->ai_addr, a->ai_addrlen) < 0) {
449	    close (s);
450	    freeaddrinfo (ai);
451	    return errno;
452	}
453	ret = krb5_sendauth(context, &ctx->ac, &s,
454			    KADMIN_OLD_APPL_VERSION, NULL,
455			    server, AP_OPTS_MUTUAL_REQUIRED,
456			    NULL, NULL, cc, NULL, NULL, NULL);
457    }
458    freeaddrinfo (ai);
459    if(ret) {
460	close(s);
461	return ret;
462    }
463
464    krb5_free_principal(context, server);
465    if(ctx->ccache == NULL)
466	krb5_cc_close(context, cc);
467    if(ret) {
468	close(s);
469	return ret;
470    }
471    ctx->sock = s;
472
473    return 0;
474}
475
476kadm5_ret_t
477_kadm5_connect(void *handle)
478{
479    kadm5_client_context *ctx = handle;
480    if(ctx->sock == -1)
481	return kadm_connect(ctx);
482    return 0;
483}
484
485static kadm5_ret_t
486kadm5_c_init_with_context(krb5_context context,
487			  const char *client_name,
488			  const char *password,
489			  krb5_prompter_fct prompter,
490			  const char *keytab,
491			  krb5_ccache ccache,
492			  const char *service_name,
493			  kadm5_config_params *realm_params,
494			  unsigned long struct_version,
495			  unsigned long api_version,
496			  void **server_handle)
497{
498    kadm5_ret_t ret;
499    kadm5_client_context *ctx;
500    krb5_ccache cc;
501
502    ret = _kadm5_c_init_context(&ctx, realm_params, context);
503    if(ret)
504	return ret;
505
506    if(password != NULL && *password != '\0') {
507	ret = get_cred_cache(context, client_name, service_name,
508			     password, prompter, keytab, ccache, &cc);
509	if(ret)
510	    return ret; /* XXX */
511	ccache = cc;
512    }
513
514
515    if (client_name != NULL)
516	ctx->client_name = strdup(client_name);
517    else
518	ctx->client_name = NULL;
519    if (service_name != NULL)
520	ctx->service_name = strdup(service_name);
521    else
522	ctx->service_name = NULL;
523    ctx->prompter = prompter;
524    ctx->keytab = keytab;
525    ctx->ccache = ccache;
526    /* maybe we should copy the params here */
527    ctx->sock = -1;
528
529    *server_handle = ctx;
530    return 0;
531}
532
533static kadm5_ret_t
534init_context(const char *client_name,
535	     const char *password,
536	     krb5_prompter_fct prompter,
537	     const char *keytab,
538	     krb5_ccache ccache,
539	     const char *service_name,
540	     kadm5_config_params *realm_params,
541	     unsigned long struct_version,
542	     unsigned long api_version,
543	     void **server_handle)
544{
545    krb5_context context;
546    kadm5_ret_t ret;
547    kadm5_server_context *ctx;
548
549    ret = krb5_init_context(&context);
550    if (ret)
551	return ret;
552    ret = kadm5_c_init_with_context(context,
553				    client_name,
554				    password,
555				    prompter,
556				    keytab,
557				    ccache,
558				    service_name,
559				    realm_params,
560				    struct_version,
561				    api_version,
562				    server_handle);
563    if(ret){
564	krb5_free_context(context);
565	return ret;
566    }
567    ctx = *server_handle;
568    ctx->my_context = 1;
569    return 0;
570}
571
572kadm5_ret_t
573kadm5_c_init_with_password_ctx(krb5_context context,
574			       const char *client_name,
575			       const char *password,
576			       const char *service_name,
577			       kadm5_config_params *realm_params,
578			       unsigned long struct_version,
579			       unsigned long api_version,
580			       void **server_handle)
581{
582    return kadm5_c_init_with_context(context,
583				     client_name,
584				     password,
585				     krb5_prompter_posix,
586				     NULL,
587				     NULL,
588				     service_name,
589				     realm_params,
590				     struct_version,
591				     api_version,
592				     server_handle);
593}
594
595kadm5_ret_t
596kadm5_c_init_with_password(const char *client_name,
597			   const char *password,
598			   const char *service_name,
599			   kadm5_config_params *realm_params,
600			   unsigned long struct_version,
601			   unsigned long api_version,
602			   void **server_handle)
603{
604    return init_context(client_name,
605			password,
606			krb5_prompter_posix,
607			NULL,
608			NULL,
609			service_name,
610			realm_params,
611			struct_version,
612			api_version,
613			server_handle);
614}
615
616kadm5_ret_t
617kadm5_c_init_with_skey_ctx(krb5_context context,
618			   const char *client_name,
619			   const char *keytab,
620			   const char *service_name,
621			   kadm5_config_params *realm_params,
622			   unsigned long struct_version,
623			   unsigned long api_version,
624			   void **server_handle)
625{
626    return kadm5_c_init_with_context(context,
627				     client_name,
628				     NULL,
629				     NULL,
630				     keytab,
631				     NULL,
632				     service_name,
633				     realm_params,
634				     struct_version,
635				     api_version,
636				     server_handle);
637}
638
639
640kadm5_ret_t
641kadm5_c_init_with_skey(const char *client_name,
642		     const char *keytab,
643		     const char *service_name,
644		     kadm5_config_params *realm_params,
645		     unsigned long struct_version,
646		     unsigned long api_version,
647		     void **server_handle)
648{
649    return init_context(client_name,
650			NULL,
651			NULL,
652			keytab,
653			NULL,
654			service_name,
655			realm_params,
656			struct_version,
657			api_version,
658			server_handle);
659}
660
661kadm5_ret_t
662kadm5_c_init_with_creds_ctx(krb5_context context,
663			    const char *client_name,
664			    krb5_ccache ccache,
665			    const char *service_name,
666			    kadm5_config_params *realm_params,
667			    unsigned long struct_version,
668			    unsigned long api_version,
669			    void **server_handle)
670{
671    return kadm5_c_init_with_context(context,
672				     client_name,
673				     NULL,
674				     NULL,
675				     NULL,
676				     ccache,
677				     service_name,
678				     realm_params,
679				     struct_version,
680				     api_version,
681				     server_handle);
682}
683
684kadm5_ret_t
685kadm5_c_init_with_creds(const char *client_name,
686			krb5_ccache ccache,
687			const char *service_name,
688			kadm5_config_params *realm_params,
689			unsigned long struct_version,
690			unsigned long api_version,
691			void **server_handle)
692{
693    return init_context(client_name,
694			NULL,
695			NULL,
696			NULL,
697			ccache,
698			service_name,
699			realm_params,
700			struct_version,
701			api_version,
702			server_handle);
703}
704
705#if 0
706kadm5_ret_t
707kadm5_init(char *client_name, char *pass,
708	   char *service_name,
709	   kadm5_config_params *realm_params,
710	   unsigned long struct_version,
711	   unsigned long api_version,
712	   void **server_handle)
713{
714}
715#endif
716
717