Ejemplo n.º 1
0
static void
krb5_start_session (void)
{
    krb5_error_code ret;
    char *estr;

    ret = krb5_cc_resolve (context, tkfile, &ccache2);
    if (ret) {
	estr = krb5_get_error_string(context);
	syslog(LOG_WARNING, "resolve cred cache %s: %s",
	       tkfile,
	       estr ? estr : krb5_get_err_text(context, ret));
	free(estr);
	krb5_cc_destroy(context, ccache);
	return;
    }

    ret = krb5_cc_copy_cache (context, ccache, ccache2);
    if (ret) {
	estr = krb5_get_error_string(context);
	syslog(LOG_WARNING, "storing credentials: %s",
	       estr ? estr : krb5_get_err_text(context, ret));
	free(estr);
	krb5_cc_destroy(context, ccache);
	return ;
    }

    krb5_cc_close(context, ccache2);
    krb5_cc_destroy(context, ccache);
    return;
}
Ejemplo n.º 2
0
OM_uint32
gss_krb5_copy_ccache(OM_uint32 *minor_status,
		     krb5_context context,
		     gss_cred_id_t cred,
		     krb5_ccache out)
{
    krb5_error_code kret;

    HEIMDAL_MUTEX_lock(&cred->cred_id_mutex);

    if (cred->ccache == NULL) {
	HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
	*minor_status = EINVAL;
	return GSS_S_FAILURE;
    }

    kret = krb5_cc_copy_cache(context, cred->ccache, out);
    HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
    if (kret) {
	*minor_status = kret;
	return GSS_S_FAILURE;
    }
    *minor_status = 0;
    return GSS_S_COMPLETE;
}
Ejemplo n.º 3
0
OM_uint32
gss_krb5_copy_ccache(OM_uint32 *minor_status,
		     gss_cred_id_t cred,
		     krb5_ccache out)
{
    gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
    krb5_context context;
    krb5_error_code kret;
    krb5_ccache id;
    OM_uint32 ret;
    char *str;

    ret = gss_inquire_cred_by_oid(minor_status,
				  cred,
				  GSS_KRB5_COPY_CCACHE_X,
				  &data_set);
    if (ret)
	return ret;

    if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) {
	gss_release_buffer_set(minor_status, &data_set);
	*minor_status = EINVAL;
	return GSS_S_FAILURE;
    }

    kret = krb5_init_context(&context);
    if (kret) {
	*minor_status = kret;
	gss_release_buffer_set(minor_status, &data_set);
	return GSS_S_FAILURE;
    }

    kret = asprintf(&str, "%.*s", (int)data_set->elements[0].length,
		    (char *)data_set->elements[0].value);
    gss_release_buffer_set(minor_status, &data_set);
    if (kret == -1) {
	*minor_status = ENOMEM;
	return GSS_S_FAILURE;
    }

    kret = krb5_cc_resolve(context, str, &id);
    free(str);
    if (kret) {
	*minor_status = kret;
	return GSS_S_FAILURE;
    }

    kret = krb5_cc_copy_cache(context, id, out);
    krb5_cc_close(context, id);
    krb5_free_context(context);
    if (kret) {
	*minor_status = kret;
	return GSS_S_FAILURE;
    }

    return ret;
}
Ejemplo n.º 4
0
static int
krb5_start_session (const struct passwd *pwd)
{
    krb5_error_code ret;
    char residual[64];

    /* copy credentials to file cache */
    snprintf(residual, sizeof(residual), "FILE:/tmp/krb5cc_%u",
	     (unsigned)pwd->pw_uid);
    krb5_cc_resolve(context, residual, &id2);
    ret = krb5_cc_copy_cache(context, id, id2);
    if (ret == 0)
	add_env("KRB5CCNAME", residual);
    else {
	krb5_cc_destroy (context, id2);
	return ret;
    }
    krb5_cc_close(context, id2);
    krb5_cc_destroy(context, id);
    return 0;
}
Ejemplo n.º 5
0
static void
test_copy(krb5_context context, const char *from, const char *to)
{
    krb5_ccache fromid, toid;
    krb5_error_code ret;
    krb5_principal p, p2;

    ret = krb5_parse_name(context, "*****@*****.**", &p);
    if (ret)
	krb5_err(context, 1, ret, "krb5_parse_name");

    ret = krb5_cc_new_unique(context, from, NULL, &fromid);
    if (ret)
	krb5_err(context, 1, ret, "krb5_cc_new_unique");

    ret = krb5_cc_initialize(context, fromid, p);
    if (ret)
	krb5_err(context, 1, ret, "krb5_cc_initialize");

    ret = krb5_cc_new_unique(context, to, NULL, &toid);
    if (ret)
	krb5_err(context, 1, ret, "krb5_cc_gen_new");

    ret = krb5_cc_copy_cache(context, fromid, toid);
    if (ret)
	krb5_err(context, 1, ret, "krb5_cc_copy_cache");

    ret = krb5_cc_get_principal(context, toid, &p2);
    if (ret)
	krb5_err(context, 1, ret, "krb5_cc_get_principal");

    if (krb5_principal_compare(context, p, p2) == FALSE)
	krb5_errx(context, 1, "p != p2");

    krb5_free_principal(context, p);
    krb5_free_principal(context, p2);

    krb5_cc_destroy(context, fromid);
    krb5_cc_destroy(context, toid);
}
Ejemplo n.º 6
0
Archivo: su.c Proyecto: Sp1l/heimdal
static int
krb5_start_session(void)
{
    krb5_ccache ccache2;
    char *cc_name;
    int ret;

    ret = krb5_cc_new_unique(context, krb5_cc_type_file, NULL, &ccache2);
    if (ret) {
	krb5_cc_destroy(context, ccache);
	return 1;
    }

    ret = krb5_cc_copy_cache(context, ccache, ccache2);
    if (ret) {
	krb5_cc_destroy(context, ccache);
	krb5_cc_destroy(context, ccache2);
	return 1;
    }

    ret = asprintf(&cc_name, "%s:%s", krb5_cc_get_type(context, ccache2),
		   krb5_cc_get_name(context, ccache2));
    if (ret == -1) {
	krb5_cc_destroy(context, ccache);
	krb5_cc_destroy(context, ccache2);
	errx(1, "malloc - out of memory");
    }
    esetenv("KRB5CCNAME", cc_name, 1);

    /* convert creds? */
    if(k_hasafs()) {
	if (k_setpag() == 0)
	    krb5_afslog(context, ccache2, NULL, NULL);
    }

    krb5_cc_close(context, ccache2);
    krb5_cc_destroy(context, ccache);
    return 0;
}
Ejemplo n.º 7
0
static krb5_error_code
fcc_remove_cred(krb5_context context,
		 krb5_ccache id,
		 krb5_flags which,
		 krb5_creds *cred)
{
    krb5_error_code ret;
    krb5_ccache copy, newfile;
    char *newname;
    int fd;

    ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &copy);
    if (ret)
	return ret;

    ret = krb5_cc_copy_cache(context, id, copy);
    if (ret) {
	krb5_cc_destroy(context, copy);
	return ret;
    }

    ret = krb5_cc_remove_cred(context, copy, which, cred);
    if (ret) {
	krb5_cc_destroy(context, copy);
	return ret;
    }

    asprintf(&newname, "FILE:%s.XXXXXX", FILENAME(id));
    if (newname == NULL) {
	krb5_cc_destroy(context, copy);
	return ret;
    }

    fd = mkstemp(&newname[5]);
    if (fd < 0) {
	ret = errno;
	krb5_cc_destroy(context, copy);
	return ret;
    }
    close(fd);

    ret = krb5_cc_resolve(context, newname, &newfile);
    if (ret) {
	unlink(&newname[5]);
	free(newname);
	krb5_cc_destroy(context, copy);
	return ret;
    }

    ret = krb5_cc_copy_cache(context, copy, newfile);
    krb5_cc_destroy(context, copy);
    if (ret) {
	free(newname);
	krb5_cc_destroy(context, newfile);
	return ret;
    }

    ret = rename(&newname[5], FILENAME(id));
    if (ret)
	ret = errno;
    free(newname);
    krb5_cc_close(context, newfile);

    return ret;
}
Ejemplo n.º 8
0
static void
store_tickets(struct passwd *pwd, int ticket_newfiles, int ticket_store,
    int token_install)
{
	char cc_file[MAXPATHLEN];
	krb5_ccache ccache_store;
#ifdef KRB524
	int get_krb4_ticket = 0;
	char krb4_ticket_file[MAXPATHLEN];
#endif

	if (ticket_newfiles)
		snprintf(cc_file, sizeof(cc_file), "FILE:/tmp/krb5cc_%d",
		    pwd->pw_uid);
	else
		snprintf(cc_file, sizeof(cc_file), "%s",
		    krb5_cc_default_name(context));

	if (ticket_store) {
		ret = krb5_cc_resolve(context, cc_file, &ccache_store);
		if (ret != 0) {
			krb5_syslog(context, LOG_ERR, ret,
			    "krb5_cc_gen_new");
			exit(1);
		}

		ret = krb5_cc_copy_cache(context, ccache, ccache_store);
		if (ret != 0)
			krb5_syslog(context, LOG_ERR, ret,
			    "krb5_cc_copy_cache");

		chown(krb5_cc_get_name(context, ccache_store),
		    pwd->pw_uid, pwd->pw_gid);

		fprintf(back, BI_SETENV " KRB5CCNAME %s:%s\n",
		    krb5_cc_get_type(context, ccache_store),
		    krb5_cc_get_name(context, ccache_store));

#ifdef KRB524
		get_krb4_ticket = krb5_config_get_bool_default (context,
		    NULL, get_krb4_ticket, "libdefaults",
		    "krb4_get_tickets", NULL);
		if (get_krb4_ticket) {
			CREDENTIALS c;
			krb5_creds cred;
			krb5_cc_cursor cursor;

			ret = krb5_cc_start_seq_get(context, ccache, &cursor);
			if (ret != 0) {
				krb5_syslog(context, LOG_ERR, ret,
				    "start seq");
				exit(1);
			}

			ret = krb5_cc_next_cred(context, ccache,
			    &cursor, &cred);
			if (ret != 0) {
				krb5_syslog(context, LOG_ERR, ret,
				    "next cred");
				exit(1);
			}

			ret = krb5_cc_end_seq_get(context, ccache,
			    &cursor);
			if (ret != 0) {
				krb5_syslog(context, LOG_ERR, ret,
				    "end seq");
				exit(1);
			}

			ret = krb524_convert_creds_kdc_ccache(context, ccache,
			    &cred, &c);
			if (ret != 0) {
				krb5_syslog(context, LOG_ERR, ret,
				    "convert");
			} else {
				snprintf(krb4_ticket_file,
				    sizeof(krb4_ticket_file),
				    "%s%d", TKT_ROOT, pwd->pw_uid);
				krb_set_tkt_string(krb4_ticket_file);
				tf_setup(&c, c.pname, c.pinst);
				chown(krb4_ticket_file,
				    pwd->pw_uid, pwd->pw_gid);
			}
		}
#endif
	}

	/* Need to chown the ticket file */
#ifdef KRB524
	if (get_krb4_ticket)
		fprintf(back, BI_SETENV " KRBTKFILE %s\n",
		    krb4_ticket_file);
#endif
}
Ejemplo n.º 9
0
int
auth_krb5_password(Authctxt *authctxt, const char *password)
{
#ifndef HEIMDAL
	krb5_creds creds;
	krb5_principal server;
#endif
	krb5_error_code problem;
	krb5_ccache ccache = NULL;
	int len;
	char *client, *platform_client;

	/* get platform-specific kerberos client principal name (if it exists) */
	platform_client = platform_krb5_get_principal_name(authctxt->pw->pw_name);
	client = platform_client ? platform_client : authctxt->pw->pw_name;

	temporarily_use_uid(authctxt->pw);

	problem = krb5_init(authctxt);
	if (problem)
		goto out;

	problem = krb5_parse_name(authctxt->krb5_ctx, client,
		    &authctxt->krb5_user);
	if (problem)
		goto out;

#ifdef HEIMDAL
	problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops, &ccache);
	if (problem)
		goto out;

	problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache,
		authctxt->krb5_user);
	if (problem)
		goto out;

	restore_uid();

	problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user,
	    ccache, password, 1, NULL);

	temporarily_use_uid(authctxt->pw);

	if (problem)
		goto out;

	problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops,
	    &authctxt->krb5_fwd_ccache);
	if (problem)
		goto out;

	problem = krb5_cc_copy_cache(authctxt->krb5_ctx, ccache,
	    authctxt->krb5_fwd_ccache);
	krb5_cc_destroy(authctxt->krb5_ctx, ccache);
	ccache = NULL;
	if (problem)
		goto out;

#else
	problem = krb5_get_init_creds_password(authctxt->krb5_ctx, &creds,
	    authctxt->krb5_user, (char *)password, NULL, NULL, 0, NULL, NULL);
	if (problem)
		goto out;

	problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL,
	    KRB5_NT_SRV_HST, &server);
	if (problem)
		goto out;

	restore_uid();
	problem = krb5_verify_init_creds(authctxt->krb5_ctx, &creds, server,
	    NULL, NULL, NULL);
	krb5_free_principal(authctxt->krb5_ctx, server);
	temporarily_use_uid(authctxt->pw);
	if (problem)
		goto out;

	if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, client)) {
		problem = -1;
		goto out;
	}

	problem = ssh_krb5_cc_gen(authctxt->krb5_ctx, &authctxt->krb5_fwd_ccache);
	if (problem)
		goto out;

	problem = krb5_cc_initialize(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
				     authctxt->krb5_user);
	if (problem)
		goto out;

	problem= krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
				 &creds);
	if (problem)
		goto out;
#endif

	authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);

	len = strlen(authctxt->krb5_ticket_file) + 6;
	authctxt->krb5_ccname = xmalloc(len);
	snprintf(authctxt->krb5_ccname, len, "FILE:%s",
	    authctxt->krb5_ticket_file);

#ifdef USE_PAM
	if (options.use_pam)
		do_pam_putenv("KRB5CCNAME", authctxt->krb5_ccname);
#endif

 out:
	restore_uid();
	
	if (platform_client != NULL)
		xfree(platform_client);

	if (problem) {
		if (ccache)
			krb5_cc_destroy(authctxt->krb5_ctx, ccache);

		if (authctxt->krb5_ctx != NULL && problem!=-1)
			debug("Kerberos password authentication failed: %s",
			    krb5_get_err_text(authctxt->krb5_ctx, problem));
		else
			debug("Kerberos password authentication failed: %d",
			    problem);

		krb5_cleanup_proc(authctxt);

		if (options.kerberos_or_local_passwd)
			return (-1);
		else
			return (0);
	}
	return (authctxt->valid ? 1 : 0);
}
Ejemplo n.º 10
0
OM_uint32 GSSAPI_CALLCONV _gsskrb5_add_cred (
     OM_uint32           *minor_status,
     const gss_cred_id_t input_cred_handle,
     const gss_name_t    desired_name,
     const gss_OID       desired_mech,
     gss_cred_usage_t    cred_usage,
     OM_uint32           initiator_time_req,
     OM_uint32           acceptor_time_req,
     gss_cred_id_t       *output_cred_handle,
     gss_OID_set         *actual_mechs,
     OM_uint32           *initiator_time_rec,
     OM_uint32           *acceptor_time_rec)
{
    krb5_context context;
    OM_uint32 ret, lifetime;
    gsskrb5_cred cred, handle;
    krb5_const_principal dname;

    handle = NULL;
    cred = (gsskrb5_cred)input_cred_handle;
    dname = (krb5_const_principal)desired_name;

    GSSAPI_KRB5_INIT (&context);

    if (gss_oid_equal(desired_mech, GSS_KRB5_MECHANISM) == 0) {
	*minor_status = 0;
	return GSS_S_BAD_MECH;
    }

    if (cred == NULL && output_cred_handle == NULL) {
	*minor_status = 0;
	return GSS_S_NO_CRED;
    }

    if (cred == NULL) { /* XXX standard conformance failure */
	*minor_status = 0;
	return GSS_S_NO_CRED;
    }

    /* check if requested output usage is compatible with output usage */
    if (output_cred_handle != NULL) {
	HEIMDAL_MUTEX_lock(&cred->cred_id_mutex);
	if (cred->usage != cred_usage && cred->usage != GSS_C_BOTH) {
	    HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
	    *minor_status = GSS_KRB5_S_G_BAD_USAGE;
	    return(GSS_S_FAILURE);
	}
    }

    /* check that we have the same name */
    if (dname != NULL &&
	krb5_principal_compare(context, dname,
			       cred->principal) != FALSE) {
	if (output_cred_handle)
	    HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
	*minor_status = 0;
	return GSS_S_BAD_NAME;
    }

    /* make a copy */
    if (output_cred_handle) {
	krb5_error_code kret;

	handle = calloc(1, sizeof(*handle));
	if (handle == NULL) {
	    HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
	    *minor_status = ENOMEM;
	    return (GSS_S_FAILURE);
	}

	handle->usage = cred_usage;
	handle->endtime = cred->endtime;
	handle->principal = NULL;
	handle->keytab = NULL;
	handle->ccache = NULL;
	HEIMDAL_MUTEX_init(&handle->cred_id_mutex);

	kret = krb5_copy_principal(context, cred->principal,
				  &handle->principal);
	if (kret) {
	    HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
	    free(handle);
	    *minor_status = kret;
	    return GSS_S_FAILURE;
	}

	if (cred->keytab) {
	    char *name = NULL;

	    ret = GSS_S_FAILURE;

	    kret = krb5_kt_get_full_name(context, cred->keytab, &name);
	    if (kret) {
		*minor_status = kret;
		goto failure;
	    }

	    kret = krb5_kt_resolve(context, name,
				   &handle->keytab);
	    krb5_xfree(name);
	    if (kret){
		*minor_status = kret;
		goto failure;
	    }
	}

	if (cred->ccache) {
	    const char *type, *name;
	    char *type_name = NULL;

	    ret = GSS_S_FAILURE;

	    type = krb5_cc_get_type(context, cred->ccache);
	    if (type == NULL){
		*minor_status = ENOMEM;
		goto failure;
	    }

	    if (strcmp(type, "MEMORY") == 0) {
		ret = krb5_cc_new_unique(context, type,
					 NULL, &handle->ccache);
		if (ret) {
		    *minor_status = ret;
		    goto failure;
		}

		ret = krb5_cc_copy_cache(context, cred->ccache,
					 handle->ccache);
		if (ret) {
		    *minor_status = ret;
		    goto failure;
		}

	    } else {
		name = krb5_cc_get_name(context, cred->ccache);
		if (name == NULL) {
		    *minor_status = ENOMEM;
		    goto failure;
		}

		kret = asprintf(&type_name, "%s:%s", type, name);
		if (kret < 0 || type_name == NULL) {
		    *minor_status = ENOMEM;
		    goto failure;
		}

		kret = krb5_cc_resolve(context, type_name,
				       &handle->ccache);
		free(type_name);
		if (kret) {
		    *minor_status = kret;
		    goto failure;
		}
	    }
	}
    }

    HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);

    ret = _gsskrb5_inquire_cred(minor_status, (gss_cred_id_t)cred,
				NULL, &lifetime, NULL, actual_mechs);
    if (ret)
	goto failure;

    if (initiator_time_rec)
	*initiator_time_rec = lifetime;
    if (acceptor_time_rec)
	*acceptor_time_rec = lifetime;

    if (output_cred_handle) {
	*output_cred_handle = (gss_cred_id_t)handle;
    }

    *minor_status = 0;
    return ret;

 failure:

    if (handle) {
	if (handle->principal)
	    krb5_free_principal(context, handle->principal);
	if (handle->keytab)
	    krb5_kt_close(context, handle->keytab);
	if (handle->ccache)
	    krb5_cc_destroy(context, handle->ccache);
	free(handle);
    }
    if (output_cred_handle)
	HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
    return ret;
}
Ejemplo n.º 11
0
int
auth_krb5_password(struct authctxt *authctxt, const char *password)
{
	krb5_error_code problem;
	krb5_ccache ccache = NULL;
	const char *errmsg;

	temporarily_use_uid(authctxt->pw);

	problem = krb5_init(authctxt);
	if (problem)
		goto out;

	problem = krb5_parse_name(authctxt->krb5_ctx, authctxt->pw->pw_name,
		    &authctxt->krb5_user);
	if (problem)
		goto out;

	problem = krb5_cc_new_unique(authctxt->krb5_ctx,
	     krb5_mcc_ops.prefix, NULL, &ccache);
	if (problem)
		goto out;

	problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache,
		authctxt->krb5_user);
	if (problem)
		goto out;

	restore_uid();

	problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user,
	    ccache, password, 1, NULL);

	temporarily_use_uid(authctxt->pw);

	if (problem)
		goto out;

	problem = krb5_cc_new_unique(authctxt->krb5_ctx,
	     krb5_fcc_ops.prefix, NULL, &authctxt->krb5_fwd_ccache);
	if (problem)
		goto out;

	problem = krb5_cc_copy_cache(authctxt->krb5_ctx, ccache,
	    authctxt->krb5_fwd_ccache);
	krb5_cc_destroy(authctxt->krb5_ctx, ccache);
	ccache = NULL;
	if (problem)
		goto out;

	authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx,
	    authctxt->krb5_fwd_ccache);

 out:
	restore_uid();

	if (problem) {
		if (ccache)
			krb5_cc_destroy(authctxt->krb5_ctx, ccache);

		if (authctxt->krb5_ctx != NULL) {
			errmsg = krb5_get_error_message(authctxt->krb5_ctx,
			    problem);
			debug("Kerberos password authentication failed: %s",
			    errmsg);
			krb5_free_error_message(authctxt->krb5_ctx, errmsg);
		} else
			debug("Kerberos password authentication failed: %d",
			    problem);

		krb5_cleanup_proc(authctxt);

		if (options.kerberos_or_local_passwd)
			return (-1);
		else
			return (0);
	}
	return (authctxt->valid ? 1 : 0);
}
Ejemplo n.º 12
0
int
auth_krb5_password(Authctxt *authctxt, const char *password)
{
#ifndef HEIMDAL
	krb5_creds creds;
	krb5_principal server;
	char ccname[40];
	int tmpfd;
	mode_t old_umask;
#endif
	krb5_error_code problem;
	krb5_ccache ccache = NULL;
	int len;

	if (!authctxt->valid)
		return (0);

	temporarily_use_uid(authctxt->pw);

	problem = krb5_init(authctxt);
	if (problem)
		goto out;

	problem = krb5_parse_name(authctxt->krb5_ctx, authctxt->pw->pw_name,
		    &authctxt->krb5_user);
	if (problem)
		goto out;

#ifdef HEIMDAL
	problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops, &ccache);
	if (problem)
		goto out;

	problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache,
		authctxt->krb5_user);
	if (problem)
		goto out;

	restore_uid();

	problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user,
	    ccache, password, 1, NULL);

	temporarily_use_uid(authctxt->pw);

	if (problem)
		goto out;

	problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops,
	    &authctxt->krb5_fwd_ccache);
	if (problem)
		goto out;

	problem = krb5_cc_copy_cache(authctxt->krb5_ctx, ccache,
	    authctxt->krb5_fwd_ccache);
	krb5_cc_destroy(authctxt->krb5_ctx, ccache);
	ccache = NULL;
	if (problem)
		goto out;

#else
	problem = krb5_get_init_creds_password(authctxt->krb5_ctx, &creds,
	    authctxt->krb5_user, (char *)password, NULL, NULL, 0, NULL, NULL);
	if (problem)
		goto out;

	problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL,
	    KRB5_NT_SRV_HST, &server);
	if (problem)
		goto out;

	restore_uid();
	problem = krb5_verify_init_creds(authctxt->krb5_ctx, &creds, server,
	    NULL, NULL, NULL);
	krb5_free_principal(authctxt->krb5_ctx, server);
	temporarily_use_uid(authctxt->pw);
	if (problem)
		goto out;

	if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user,
			  authctxt->pw->pw_name)) {
		problem = -1;
		goto out;
	}

	snprintf(ccname,sizeof(ccname),"FILE:/tmp/krb5cc_%d_XXXXXX",geteuid());

	old_umask = umask(0177);
	tmpfd = mkstemp(ccname + strlen("FILE:"));
	umask(old_umask);
	if (tmpfd == -1) {
		logit("mkstemp(): %.100s", strerror(errno));
		problem = errno;
		goto out;
	}

	if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
		logit("fchmod(): %.100s", strerror(errno));
		close(tmpfd);
		problem = errno;
		goto out;
	}
	close(tmpfd);

	problem = krb5_cc_resolve(authctxt->krb5_ctx, ccname, &authctxt->krb5_fwd_ccache);
	if (problem)
		goto out;

	problem = krb5_cc_initialize(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
				     authctxt->krb5_user);
	if (problem)
		goto out;

	problem= krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
				 &creds);
	if (problem)
		goto out;
#endif

	authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);

	len = strlen(authctxt->krb5_ticket_file) + 6;
	authctxt->krb5_ccname = xmalloc(len);
	snprintf(authctxt->krb5_ccname, len, "FILE:%s",
	    authctxt->krb5_ticket_file);

 out:
	restore_uid();

	if (problem) {
		if (ccache)
			krb5_cc_destroy(authctxt->krb5_ctx, ccache);

		if (authctxt->krb5_ctx != NULL && problem!=-1)
			debug("Kerberos password authentication failed: %s",
			    krb5_get_err_text(authctxt->krb5_ctx, problem));
		else
			debug("Kerberos password authentication failed: %d",
			    problem);

		krb5_cleanup_proc(authctxt);

		if (options.kerberos_or_local_passwd)
			return (-1);
		else
			return (0);
	}
	return (1);
}