static int krb5_instantiate(CONF_SECTION *conf, void *instance)
{
	rlm_krb5_t *inst = instance;
	krb5_error_code ret;
#ifndef HEIMDAL_KRB5
	krb5_keytab keytab;
	char keytab_name[200];
	char *princ_name;
#endif

#ifdef HEIMDAL_KRB5
	DEBUG("Using Heimdal Kerberos library");
#else
	DEBUG("Using MIT Kerberos library");
#endif

#ifndef KRB5_IS_THREAD_SAFE
	if (!krb5_is_thread_safe()) {
		WDEBUG("libkrb5 is not threadsafe, recompile it, and the server with thread support enabled");
		WDEBUG("rlm_krb5 will run in single threaded mode, performance may be degraded");
	} else {
		WDEBUG("Build time libkrb5 was not threadsafe, but run time library claims to be");
		WDEBUG("Reconfigure and recompile rlm_krb5 to enable thread support");
	}
#endif
	inst->xlat_name = cf_section_name2(conf);
	if (!inst->xlat_name) {
		inst->xlat_name = cf_section_name1(conf);
	}

	ret = krb5_init_context(&inst->context);
	if (ret) {
		ERROR("rlm_krb5 (%s): context initialisation failed: %s", inst->xlat_name,
		      rlm_krb5_error(NULL, ret));

		return -1;
	}

	/*
	 *	Split service principal into service and host components
	 *	they're needed to build the server principal in MIT,
	 *	and to set the validation service in Heimdal.
	 */
	if (inst->service_princ) {
		size_t len;
		/* Service principal appears to contain a host component */
		inst->hostname = strchr(inst->service_princ, '/');
		if (inst->hostname) {
			len = (inst->hostname - inst->service_princ);
			inst->hostname++;
		} else {
			len = strlen(inst->service_princ);
		}

		if (len) {
			inst->service = talloc_array(inst, char, (len + 1));
			strlcpy(inst->service, inst->service_princ, len + 1);
		}
	}
static int krb5_instantiate(CONF_SECTION *conf, void **instance)
{
	rlm_krb5_t *inst;
	krb5_error_code ret;
	
	krb5_context *context;
	char *princ_name;
	
#ifndef HEIMDAL_KRB5
	radlog(L_ERR, "rlm_krb5 (*): Using MIT Kerberos library");
#else
	radlog(L_ERR, "rlm_krb5 (*): Using Heimdal Kerberos library");
#endif
	/*
 	 *	@todo Update configure script to call krb5_is_thread_safe,
 	 *	this should really be a warning.
 	 */
	if (!krb5_is_thread_safe()) {
		radlog(L_ERR, "rlm_krb5 (*): krb5 library is not threadsafe, "
		       "please recompile it with thread support enabled");
		       
		return -1;
	}

	inst = rad_calloc(sizeof(*inst));
	if (cf_section_parse(conf, inst, module_config) < 0) {
		free(inst);
		return -1;
	}
	
	inst->xlat_name = cf_section_name2(conf);
	if (!inst->xlat_name) {
		inst->xlat_name = cf_section_name1(conf);
	}

	rad_assert(inst->xlat_name);
	
	context = inst->context = rad_calloc(sizeof(*context));
	ret = krb5_init_context(context);
	if (ret) {
		radlog(L_ERR, "rlm_krb5 (%s): Context initialisation "
		       "failed: %s", inst->xlat_name, error_message(ret));
  
		goto error;
	} else {
		radlog(L_DBG, "rlm_krb5 (%s): Context initialised "
		       "successfully", inst->xlat_name);
	}
	
	/*
	 *	Split service principal into service and host components
	 *	they're needed to build the server principal in MIT,
	 *	and to set the validation service in Heimdal.
	 */
	if (inst->service_princ) {
		size_t len;
		/* Service principal appears to contain a host component */
		inst->hostname = strchr(inst->service_princ, '/');
		if (inst->hostname) {	
			len = (inst->hostname - inst->service_princ);			
			inst->hostname++;
		} else {
			len = SERVICE_NAME_LEN;
		}
		
		if (len) {
			inst->service = rad_malloc(len + 1);
			strlcpy(inst->service, inst->service_princ, len);
		}
	}
	
#ifndef HEIMDAL_KRB5
	/*
	 *	Convert the service principal string to a krb5 principal.
	 */
	ret = krb5_sname_to_principal(*context, inst->hostname,
				      inst->service, KRB5_NT_SRV_HST,
				      &(inst->server));
	if (ret) {
		radlog(L_ERR, "rlm_krb5 (%s): Failed parsing service "
		       "principal: %s", inst->xlat_name, error_message(ret));

		goto error;
	}
	
	ret = krb5_unparse_name(*context, inst->server, &princ_name);
	if (ret) {
		/* Uh? */
		radlog(L_ERR, "rlm_krb5 (%s): Failed constructing service "
		       "principal string: %s", inst->xlat_name,
		       error_message(ret));

		goto error;
	}
	
	/*
	 *	Not necessarily the same as the config item
	 */
	radlog(L_DBG, "rlm_krb5 (%s): Using service principal \"%s\"",
	       inst->xlat_name, princ_name);
	       
	krb5_free_unparsed_name(*context, princ_name);
	
	/*
	 *	Setup options for getting credentials and verifying them
	 */
	 
	/* For some reason the 'init' version of this function is deprecated */
	ret = krb5_get_init_creds_opt_alloc(*context, &(inst->gic_options));
	if (ret) {
		radlog(L_ERR, "rlm_krb5 (%s): Couldn't allocated inital "
		       "credential options: %s", inst->xlat_name,
		       error_message(ret));
		
		goto error;
	}
	
	inst->vic_options = rad_calloc(sizeof(*(inst->vic_options)));
	if (!inst->vic_options) goto error;
	
	krb5_verify_init_creds_opt_init(inst->vic_options);
	krb5_verify_init_creds_opt_set_ap_req_nofail(inst->vic_options,
						     TRUE);
	
#else
	if (inst->hostname) {
		radlog(L_DBG, "rlm_krb5 (%s): Ignoring hostname component of "
		       "service principal \"%s\", not needed/supported by "
		       "Heimdal", inst->xlat_name, hostname);
	}
#endif
	 
	*instance = inst;
	return 0;
	
	error:
	krb5_detach(inst);
	return -1;
}