Exemple #1
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_get_validated_creds(krb5_context context,
			 krb5_creds *creds,
			 krb5_principal client,
			 krb5_ccache ccache,
			 char *service)
{
    krb5_verify_init_creds_opt vopt;
    krb5_principal server;
    krb5_error_code ret;

    if (krb5_principal_compare(context, creds->client, client) != TRUE) {
	krb5_set_error_message(context, KRB5_PRINC_NOMATCH,
			       N_("Validation credentials and client "
				  "doesn't match", ""));
	return KRB5_PRINC_NOMATCH;
    }

    ret = krb5_sname_to_principal (context, NULL, service, 
				   KRB5_NT_SRV_HST, &server);
    if(ret)
	return ret;

    krb5_verify_init_creds_opt_init(&vopt);

    ret = krb5_verify_init_creds(context, creds, server, NULL, NULL, &vopt);
    krb5_free_principal(context, server);

    return ret;
}
Exemple #2
0
static krb5_error_code
verify_common (krb5_context context,
	       krb5_principal principal,
	       krb5_ccache ccache,
	       krb5_keytab keytab,
	       krb5_boolean secure,
	       const char *service,
	       krb5_creds cred)
{
    krb5_error_code ret;
    krb5_principal server;
    krb5_verify_init_creds_opt vopt;
    krb5_ccache id;

    ret = krb5_sname_to_principal (context, NULL, service, KRB5_NT_SRV_HST,
				   &server);
    if(ret)
	return ret;

    krb5_verify_init_creds_opt_init(&vopt);
    krb5_verify_init_creds_opt_set_ap_req_nofail(&vopt, secure);

    ret = krb5_verify_init_creds(context,
				 &cred,
				 server,
				 keytab,
				 NULL,
				 &vopt);
    krb5_free_principal(context, server);
    if(ret)
	return ret;
    if(ccache == NULL)
	ret = krb5_cc_default (context, &id);
    else
	id = ccache;
    if(ret == 0){
	ret = krb5_cc_initialize(context, id, principal);
	if(ret == 0){
	    ret = krb5_cc_store_cred(context, id, &cred);
	}
	if(ccache == NULL)
	    krb5_cc_close(context, id);
    }
    krb5_free_cred_contents(context, &cred);
    return ret;
}
Exemple #3
0
krb5_error_code
func(krb5_context context,  krb5_creds *creds, krb5_principal server_principal)
{
    krb5_error_code ret = KRB5_OK;
    krb5_verify_init_creds_opt options;

    krb5_verify_init_creds_opt_init (&options);
    krb5_verify_init_creds_opt_set_ap_req_nofail (&options, 1);

    ret = krb5_verify_init_creds(context,
                                 creds,
                                 server_principal,
                                 NULL /* use default keytab */,
                                 NULL /* don't store creds in ccache */,
                                 &options);
    if (ret) {
        /* error while verifying credentials for server */
    }

    return ret;
}
static krb5_error_code
verify_common (krb5_context context,
	       krb5_principal principal,
	       krb5_principal server_principal,
	       krb5_ccache ccache,
	       krb5_keytab keytab,
	       krb5_boolean secure,
	       const char *service,
	       krb5_creds *cred)
{
    krb5_error_code ret;
    krb5_verify_init_creds_opt vopt;
    krb5_ccache id;

    krb5_verify_init_creds_opt_init(&vopt);
    krb5_verify_init_creds_opt_set_ap_req_nofail(&vopt, secure);
    krb5_verify_init_creds_opt_set_service(&vopt, service);

    ret = krb5_verify_init_creds(context,
				 cred,
				 server_principal,
				 keytab,
				 NULL,
				 &vopt);
    if(ret)
	return ret;
    if(ccache == NULL)
	ret = krb5_cc_default (context, &id);
    else
	id = ccache;
    if(ret == 0){
	ret = krb5_cc_initialize(context, id, principal);
	if(ret == 0){
	    ret = krb5_cc_store_cred(context, id, cred);
	}
	if(ccache == NULL)
	    krb5_cc_close(context, id);
    }
    return ret;
}
Exemple #5
0
int
main(int argc, const char **argv)
{
    krb5_context ctx;
    krb5_ccache ccache;
    krb5_creds mcreds, creds;
    krb5_keytab keytab;
    krb5_principal server;
    krb5_verify_init_creds_opt opts;
    int ret;

    ctx = NULL;
    ret = krb5_init_context(&ctx);
    if (ret != 0) {
        crit("error initializing Kerberos: %s", error_message(ret));
        return ret;
    }

    ccache = NULL;
    ret = krb5_cc_default(ctx, &ccache);
    if (ret != 0) {
        crit("error resolving ccache: %s", error_message(ret));
        return ret;
    }

    keytab = NULL;
    ret = krb5_kt_default(ctx, &keytab);
    if (ret != 0) {
        crit("error resolving keytab: %s", error_message(ret));
        return ret;
    }

    server = NULL;
    memset(&mcreds, 0, sizeof(mcreds));
    ret = krb5_cc_get_principal(ctx, ccache, &mcreds.client);
    if (ret != 0) {
        crit("error reading client name from ccache: %s",
             error_message(ret));
        return ret;
    }
    ret = krb5_build_principal_ext(ctx, &mcreds.server,
                                   v5_princ_realm_length(mcreds.client),
                                   v5_princ_realm_contents(mcreds.client),
                                   KRB5_TGS_NAME_SIZE,
                                   KRB5_TGS_NAME,
                                   v5_princ_realm_length(mcreds.client),
                                   v5_princ_realm_contents(mcreds.client),
                                   0);
    if (ret != 0) {
        crit("error building ticket granting server name: %s",
             error_message(ret));
        return ret;
    }

    ret = krb5_cc_retrieve_cred(ctx, ccache, 0, &mcreds, &creds);
    if (ret != 0) {
        crit("error reading ccache: %s", error_message(ret));
        return ret;
    }
    krb5_cc_close(ctx, ccache);

    krb5_verify_init_creds_opt_init(&opts);
    ret = krb5_verify_init_creds(ctx, &creds,
                                 server, keytab, NULL,
                                 &opts);
    if (ret != 0) {
        crit("error verifying creds: %s", error_message(ret));
    } else {
        printf("OK\n");
    }

    krb5_free_context(ctx);

    return ret;
}
Exemple #6
0
int
main(int argc, char **argv)
{
    krb5_context context;
    krb5_error_code ret;
    krb5_creds cred;
    krb5_preauthtype pre_auth_types[] = {KRB5_PADATA_ENC_TIMESTAMP};
    krb5_get_init_creds_opt *get_options;
    krb5_verify_init_creds_opt verify_options;
    krb5_principal principal = NULL;
    int optidx = 0;

    setprogname (argv[0]);

    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
	usage(1);

    if (help_flag)
	usage (0);

    if(version_flag) {
	print_version(NULL);
	exit(0);
    }

    argc -= optidx;
    argv += optidx;

    ret = krb5_init_context(&context);
    if (ret)
	errx (1, "krb5_init_context failed: %d", ret);

    ret = krb5_get_init_creds_opt_alloc (context, &get_options);
    if (ret)
	krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc");

    krb5_get_init_creds_opt_set_preauth_list (get_options,
					      pre_auth_types,
					      1);

    krb5_verify_init_creds_opt_init (&verify_options);

    if (argc) {
	ret = krb5_parse_name(context, argv[0], &principal);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_parse_name: %s", argv[0]);
    } else {
	ret = krb5_get_default_principal(context, &principal);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_get_default_principal");

    }

    ret = krb5_get_init_creds_password (context,
					&cred,
					principal,
					NULL,
					krb5_prompter_posix,
					NULL,
					0,
					NULL,
					get_options);
    if (ret)
	krb5_err(context, 1, ret,  "krb5_get_init_creds");

    ret = krb5_verify_init_creds (context,
				  &cred,
				  NULL,
				  NULL,
				  NULL,
				  &verify_options);
    if (ret)
	krb5_err(context, 1, ret, "krb5_verify_init_creds");
    krb5_free_cred_contents (context, &cred);
    krb5_free_context (context);
    return 0;
}
Exemple #7
0
static int
krb5_verify_password (POP *p)
{
    krb5_preauthtype pre_auth_types[] = {KRB5_PADATA_ENC_TIMESTAMP};
    krb5_get_init_creds_opt *get_options;
    krb5_verify_init_creds_opt verify_options;
    krb5_error_code ret;
    krb5_principal client, server;
    krb5_creds creds;
    const char *estr;

    ret = krb5_get_init_creds_opt_alloc (p->context, &get_options);
    if (ret) {
	estr = krb5_get_error_message(p->context, ret);
	pop_log(p, POP_PRIORITY, "krb5_get_init_creds_opt_alloc: %s", estr);
	krb5_free_error_message(p->context, estr);
	return 1;
    }

    krb5_get_init_creds_opt_set_preauth_list (get_options,
					      pre_auth_types,
					      1);

    krb5_verify_init_creds_opt_init (&verify_options);

    ret = krb5_parse_name (p->context, p->user, &client);
    if (ret) {
	krb5_get_init_creds_opt_free(p->context, get_options);
	estr = krb5_get_error_message(p->context, ret);
	pop_log(p, POP_PRIORITY, "krb5_parse_name: %s", estr);
	krb5_free_error_message(p->context, estr);
	return 1;
    }

    ret = krb5_get_init_creds_password (p->context,
					&creds,
					client,
					p->pop_parm[1],
					NULL,
					NULL,
					0,
					NULL,
					get_options);
    krb5_get_init_creds_opt_free(p->context, get_options);
    if (ret) {
	estr = krb5_get_error_message(p->context, ret);
	pop_log(p, POP_PRIORITY, "krb5_get_init_creds_password: %s", estr);
	krb5_free_error_message(p->context, estr);
	return 1;
    }

    ret = krb5_sname_to_principal (p->context,
				   p->myhost,
				   "pop",
				   KRB5_NT_SRV_HST,
				   &server);
    if (ret) {
	estr = krb5_get_error_message(p->context, ret);
	pop_log(p, POP_PRIORITY, "krb5_get_init_creds_password: %s", estr);
	krb5_free_error_message(p->context, estr);
	return 1;
    }

    ret = krb5_verify_init_creds (p->context,
				  &creds,
				  server,
				  NULL,
				  NULL,
				  &verify_options);
    krb5_free_principal (p->context, client);
    krb5_free_principal (p->context, server);
    krb5_free_cred_contents (p->context, &creds);
    return ret;
}
Exemple #8
0
    int
cosign_login_krb5( struct connlist *head, char *cosignname, char *id, 
	char *realm, char *passwd, char *ip_addr, char *cookie, 
	struct subparams *sp, char **msg )
{
    krb5_error_code             kerror = 0;
    krb5_context                kcontext;
    krb5_principal              kprinc;
    krb5_principal              sprinc;
    krb5_get_init_creds_opt     kopts;
    krb5_verify_init_creds_opt 	kvic_opts[ 1 ];
    krb5_creds                  kcreds;
    krb5_ccache                 kccache;
    krb5_keytab                 keytab = 0;
    char			*tmpl = ERROR_HTML; 
    char			*sprinc_name = NULL;
    char                        ktbuf[ MAX_KEYTAB_NAME_LEN + 1 ];
    char                        tmpkrb[ 16 ], krbpath [ MAXPATHLEN ];
    int				i;

    lcgi_configure();

    if (( kerror = krb5_init_context( &kcontext ))) {
	sl[ SL_ERROR ].sl_data = (char *)error_message( kerror );
	sl[ SL_TITLE ].sl_data = "Authentication Required ( kerberos error )";
	subfile( tmpl, sl, 0 );
	exit( 0 );
    }

    if (( kerror = krb5_parse_name( kcontext, id, &kprinc ))) {
	sl[ SL_ERROR ].sl_data = (char *)error_message( kerror );
	sl[ SL_TITLE ].sl_data = "Authentication Required ( kerberos error )";
	subfile( tmpl, sl, 0 );
	exit( 0 );
    }

    /* need to get realm out */
    if ( realm == NULL || *realm == '\0' ) {
	if (( kerror = krb5_get_default_realm( kcontext, &realm )) != 0 ) {
	    sl[ SL_ERROR ].sl_data = (char *)error_message( kerror );
 	    sl[ SL_TITLE ].sl_data = "Authentication Required "
		    "( krb realm error )";
	    subfile( tmpl, sl, 0 );
	    exit( 0 );
    	}
    }

    if ( store_tickets ) {
	if ( mkcookie( sizeof( tmpkrb ), tmpkrb ) != 0 ) {
	    sl[ SL_ERROR ].sl_data = "An unknown error occurred.";
	    sl[ SL_TITLE ].sl_data = "Authentication Required (kerberos error)";
	    subfile( tmpl, sl, 0 );
	    exit( 0 );
	}

	if ( snprintf( krbpath, sizeof( krbpath ), "%s/%s",
		ticket_path, tmpkrb ) >= sizeof( krbpath )) {
	    sl[ SL_ERROR ].sl_data = "An unknown error occurred.";
	    sl[ SL_TITLE ].sl_data = "Authentication Required (krbpath error)";
	    subfile( tmpl, sl, 0 );
	    exit( 0 );
	}

	if (( kerror = krb5_cc_resolve( kcontext, krbpath, &kccache )) != 0 ) {
	    sl[ SL_ERROR ].sl_data = (char *)error_message( kerror );
	    sl[ SL_TITLE ].sl_data = "Authentication Required (kerberos error)";
	    subfile( tmpl, sl, 0 );
	    exit( 0 );
	}
    }

    krb5_get_init_creds_opt_init( &kopts );
    krb5_get_init_creds_opt_set_tkt_life( &kopts, tkt_life );
    krb5_get_init_creds_opt_set_renew_life( &kopts, 0 );
    krb5_get_init_creds_opt_set_forwardable( &kopts, 1 );
    krb5_get_init_creds_opt_set_proxiable( &kopts, 0 );

    if (( kerror = krb5_get_init_creds_password( kcontext, &kcreds, 
	    kprinc, passwd, NULL, NULL, 0, NULL /*keytab */, &kopts ))) {

	if (( kerror == KRB5KRB_AP_ERR_BAD_INTEGRITY ) ||
		( kerror == KRB5KDC_ERR_PREAUTH_FAILED ) ||
		( kerror == KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN )) {
	    return( COSIGN_CGI_ERROR );	/* draw login or reauth page */
        } else if ( kerror == KRB5KDC_ERR_KEY_EXP ) {
	    *msg = (char *)error_message( kerror );
            return( COSIGN_CGI_PASSWORD_EXPIRED );
	} else {
	    sl[ SL_ERROR ].sl_data = (char *)error_message( kerror );
	    sl[ SL_TITLE ].sl_data = "Error";
	    subfile( tmpl, sl, 0 );
	    exit( 0 );
	}
    }

    /* verify no KDC spoofing */
    if ( *keytab_path != '\0' ) {
	if ( strlen( keytab_path ) > MAX_KEYTAB_NAME_LEN ) {
	    sl[ SL_ERROR ].sl_data = "server configuration error";
	    sl[ SL_TITLE ].sl_data = "Ticket Verification Error";
	    subfile( tmpl, sl, 0 );
	    exit( 0 );
	}
	strcpy( ktbuf, keytab_path );

	/* from mdw */
	krb5_verify_init_creds_opt_init( kvic_opts );
	krb5_verify_init_creds_opt_set_ap_req_nofail( kvic_opts, 1 );

	if (( kerror = krb5_kt_resolve( kcontext, ktbuf, &keytab )) != 0 ) {
	    sl[ SL_ERROR ].sl_data = (char *)error_message( kerror );
	    sl[ SL_TITLE ].sl_data = "KT Resolve Error";
	    subfile( tmpl, sl, 0 );
	    exit( 0 );
	}

	if ( cosign_princ ) {
	    kerror = krb5_parse_name( kcontext, cosign_princ, &sprinc );
	} else {
	    kerror = krb5_sname_to_principal( kcontext, NULL, "cosign",
			KRB5_NT_SRV_HST, &sprinc );
	}
	if ( kerror != 0 ) {
	    sl[ SL_ERROR ].sl_data = (char *)error_message( kerror );
	    sl[ SL_TITLE ].sl_data = "Server Principal Error";
	    subfile( tmpl, sl, 0 );
	    exit( 0 );
	}

	if (( kerror = krb5_verify_init_creds(
		kcontext, &kcreds, sprinc, keytab, NULL, kvic_opts )) != 0 ) {
	    if ( krb5_unparse_name( kcontext, sprinc, &sprinc_name ) == 0 ) {
		fprintf( stderr, "ticket verify error for "
			 "user %s, keytab principal %s", id, sprinc_name );
		free( sprinc_name );
	    } else {
		fprintf( stderr, "ticket verify error for user %s", id );
	    }
	    sl[ SL_ERROR ].sl_data = (char *)error_message( kerror );
	    sl[ SL_TITLE ].sl_data = "Ticket Verify Error";
	    subfile( tmpl, sl, 0 );
	    krb5_free_principal( kcontext, sprinc );
	    exit( 0 );
	}
	(void)krb5_kt_close( kcontext, keytab );
	krb5_free_principal( kcontext, sprinc );
    }

    for ( i = 0; i < COSIGN_MAXFACTORS - 1; i++ ) {
	if ( new_factors[ i ] == NULL ) {
	    new_factors[ i ] = strdup( realm );
	    new_factors[ i + 1 ] = NULL;
	    break;
	}
	if ( strcmp( new_factors[ i ], realm ) == 0 ) {
	    break;
	}
    }

    if ( sp->sp_reauth && sp->sp_ipchanged == 0 ) {
	return( COSIGN_CGI_OK );
    }

    if ( store_tickets ) {
	if (( kerror = krb5_cc_initialize( kcontext, kccache, kprinc )) != 0 ) {
	    sl[ SL_ERROR ].sl_data = (char *)error_message( kerror );
	    sl[ SL_TITLE ].sl_data = "CC Initialize Error";
	    subfile( tmpl, sl, 0 );
	    exit( 0 );
	}
	if (( kerror = krb5_cc_store_cred( kcontext, kccache, &kcreds ))
		!= 0 ) {
	    sl[ SL_ERROR ].sl_data = (char *)error_message( kerror );
	    sl[ SL_TITLE ].sl_data = "CC Storing Error";
	    subfile( tmpl, sl, 0 );
	    exit( 0 );
	}
	krb5_cc_close( kcontext, kccache );
    }

    krb5_free_cred_contents( kcontext, &kcreds );
    krb5_free_principal( kcontext, kprinc );
    krb5_free_context( kcontext );

    /* password has been accepted, tell cosignd */
    if ( cosign_login( head, cookie, ip_addr, cosignname, realm, 
	    ( store_tickets ? krbpath : NULL )) < 0 ) {
	fprintf( stderr, "cosign_login_krb5: login failed\n") ;
	sl[ SL_ERROR ].sl_data = "We were unable to contact the "
		"authentication server. Please try again later.";
	sl[ SL_TITLE ].sl_data = "Error: Please try later";
	subfile( tmpl, sl, 0 );
	exit( 0 );
    }

    return( COSIGN_CGI_OK );
}
Exemple #9
0
int
main(int argc, char **argv)
{
    krb5_context context;
    krb5_error_code ret;
    krb5_creds cred;
    krb5_preauthtype pre_auth_types[] = {KRB5_PADATA_ENC_TIMESTAMP};
    krb5_get_init_creds_opt *get_options;
    krb5_verify_init_creds_opt verify_options;
    int optind = 0;

    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
	usage(1);
    
    if (help_flag)
	usage (0);

    if(version_flag) {
	print_version(NULL);
	exit(0);
    }

    ret = krb5_init_context(&context);
    if (ret)
	errx (1, "krb5_init_context failed: %d", ret);

    ret = krb5_get_init_creds_opt_alloc (context, &get_options);
    if (ret)
	krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc");

    krb5_get_init_creds_opt_set_preauth_list (get_options,
					      pre_auth_types,
					      1);

    krb5_verify_init_creds_opt_init (&verify_options);
    
    ret = krb5_get_init_creds_password (context,
					&cred,
					NULL,
					NULL,
					krb5_prompter_posix,
					NULL,
					0,
					NULL,
					get_options);
    if (ret)
	errx (1, "krb5_get_init_creds: %s", krb5_get_err_text(context, ret));

    ret = krb5_verify_init_creds (context,
				  &cred,
				  NULL,
				  NULL,
				  NULL,
				  &verify_options);
    if (ret)
	errx (1, "krb5_verify_init_creds: %s",
	      krb5_get_err_text(context, ret));
    krb5_free_cred_contents (context, &cred);
    krb5_free_context (context);
    return 0;
}
Exemple #10
0
static int chk_kerberos(
	const struct berval *sc,
	const struct berval * passwd,
	const struct berval * cred,
	const char **text )
{
	unsigned int i;
	int rtn;

	for( i=0; i<cred->bv_len; i++) {
		if(cred->bv_val[i] == '\0') {
			return LUTIL_PASSWD_ERR;	/* NUL character in password */
		}
	}

	if( cred->bv_val[i] != '\0' ) {
		return LUTIL_PASSWD_ERR;	/* cred must behave like a string */
	}

	for( i=0; i<passwd->bv_len; i++) {
		if(passwd->bv_val[i] == '\0') {
			return LUTIL_PASSWD_ERR;	/* NUL character in password */
		}
	}

	if( passwd->bv_val[i] != '\0' ) {
		return LUTIL_PASSWD_ERR;	/* passwd must behave like a string */
	}

	rtn = LUTIL_PASSWD_ERR;

#ifdef HAVE_KRB5 /* HAVE_HEIMDAL_KRB5 */
	{
/* Portions:
 * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska H\xf6gskolan
 * (Royal Institute of Technology, Stockholm, Sweden).
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the Institute nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

		krb5_context context;
   		krb5_error_code ret;
   		krb5_creds creds;
   		krb5_get_init_creds_opt get_options;
   		krb5_verify_init_creds_opt verify_options;
		krb5_principal client, server;
#ifdef notdef
		krb5_preauthtype pre_auth_types[] = {KRB5_PADATA_ENC_TIMESTAMP};
#endif

		ret = krb5_init_context( &context );
		if (ret) {
			return LUTIL_PASSWD_ERR;
		}

#ifdef notdef
		krb5_get_init_creds_opt_set_preauth_list(&get_options,
			pre_auth_types, 1);
#endif

   		krb5_get_init_creds_opt_init( &get_options );

		krb5_verify_init_creds_opt_init( &verify_options );
	
		ret = krb5_parse_name( context, passwd->bv_val, &client );

		if (ret) {
			krb5_free_context( context );
			return LUTIL_PASSWD_ERR;
		}

		ret = krb5_get_init_creds_password( context,
			&creds, client, cred->bv_val, NULL,
			NULL, 0, NULL, &get_options );

		if (ret) {
			krb5_free_principal( context, client );
			krb5_free_context( context );
			return LUTIL_PASSWD_ERR;
		}

		{
			char *host = ldap_pvt_get_fqdn( NULL );

			if( host == NULL ) {
				krb5_free_principal( context, client );
				krb5_free_context( context );
				return LUTIL_PASSWD_ERR;
			}

			ret = krb5_sname_to_principal( context,
				host, "ldap", KRB5_NT_SRV_HST, &server );

			ber_memfree( host );
		}

		if (ret) {
			krb5_free_principal( context, client );
			krb5_free_context( context );
			return LUTIL_PASSWD_ERR;
		}

		ret = krb5_verify_init_creds( context,
			&creds, server, NULL, NULL, &verify_options );

		krb5_free_principal( context, client );
		krb5_free_principal( context, server );
		krb5_free_cred_contents( context, &creds );
		krb5_free_context( context );

		rtn = ret ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
	}
#elif	defined(HAVE_KRB4)
	{
		/* Borrowed from Heimdal kpopper */
/* Portions:
 * Copyright (c) 1989 Regents of the University of California.
 * All rights reserved.  The Berkeley software License Agreement
 * specifies the terms and conditions for redistribution.
 */

		int status;
		char lrealm[REALM_SZ];
		char tkt[MAXHOSTNAMELEN];

		status = krb_get_lrealm(lrealm,1);
		if (status == KFAILURE) {
			return LUTIL_PASSWD_ERR;
		}

		snprintf(tkt, sizeof(tkt), "%s_slapd.%u",
			TKT_ROOT, (unsigned)getpid());
		krb_set_tkt_string (tkt);

		status = krb_verify_user( passwd->bv_val, "", lrealm,
			cred->bv_val, 1, "ldap");

		dest_tkt(); /* no point in keeping the tickets */

		return status == KFAILURE ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
	}
#endif

	return rtn;
}
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;
}