コード例 #1
0
static krb5_error_code
copy_creds_except(krb5_context context, krb5_ccache incc,
                  krb5_ccache outcc, krb5_principal princ)
{
    krb5_error_code ret, ret2;
    krb5_cc_cursor cur;
    krb5_creds creds;

    /* Turn off TC_OPENCLOSE on input ccache. */
    ret = krb5_cc_set_flags(context, incc, 0);
    if (ret)
        return ret;
    ret = krb5_cc_start_seq_get(context, incc, &cur);
    if (ret)
        goto cleanup;

    while (!(ret = krb5_cc_next_cred(context, incc, &cur, &creds))) {
        if (krb5_principal_compare(context, princ, creds.server))
            continue;

        ret = krb5_cc_store_cred(context, outcc, &creds);
        krb5_free_cred_contents(context, &creds);
        if (ret)
            goto cleanup;
    }

    if (ret != KRB5_CC_END)
        goto cleanup;
    ret = 0;

cleanup:
    ret2 = krb5_cc_set_flags(context, incc, KRB5_TC_OPENCLOSE);
    return (ret == 0) ? ret2 : ret;
}
コード例 #2
0
ファイル: krb5_util.c プロジェクト: Einheri/wl500g
static int
query_krb5_ccache(const char* cred_cache, char **ret_princname,
		  char **ret_realm)
{
	krb5_error_code ret;
	krb5_context context;
	krb5_ccache ccache;
	krb5_principal principal;
	int found = 0;
	char *str = NULL;
	char *princstring;

	ret = krb5_init_context(&context);
	if (ret) 
		return 0;

	if(!cred_cache || krb5_cc_resolve(context, cred_cache, &ccache))
		goto err_cache;

	if (krb5_cc_set_flags(context, ccache, 0))
		goto err_princ;

	ret = krb5_cc_get_principal(context, ccache, &principal);
	if (ret) 
		goto err_princ;

	found = check_for_tgt(context, ccache, principal);
	if (found) {
		ret = krb5_unparse_name(context, principal, &princstring);
		if (ret == 0) {
		    if ((str = strchr(princstring, '@')) != NULL) {
			    *str = '\0';
			    *ret_princname = strdup(princstring);
			    *ret_realm = strdup(str+1);
		    }
		    k5_free_unparsed_name(context, princstring);
		} else {
			found = 0;
		}
	}
	krb5_free_principal(context, principal);
err_princ:
	krb5_cc_set_flags(context, ccache,  KRB5_TC_OPENCLOSE);
	krb5_cc_close(context, ccache);
err_cache:
	krb5_free_context(context);
	return found;
}
コード例 #3
0
ファイル: ms2mit.c プロジェクト: irakhlin/krb5
/*
 * Check if a ccache has any tickets.
 */
static krb5_error_code
cc_has_tickets(krb5_context kcontext, krb5_ccache ccache, int *has_tickets)
{
    krb5_error_code code;
    krb5_cc_cursor cursor;
    krb5_creds creds;
    krb5_timestamp now = time(0);

    *has_tickets = 0;

    code = krb5_cc_set_flags(kcontext, ccache, KRB5_TC_NOTICKET);
    if (code)
        return code;

    code = krb5_cc_start_seq_get(kcontext, ccache, &cursor);
    if (code)
        return code;

    while (!*has_tickets) {
        code = krb5_cc_next_cred(kcontext, ccache, &cursor, &creds);
        if (code)
            break;

        if (!krb5_is_config_principal(kcontext, creds.server) &&
            creds.times.endtime > now)
            *has_tickets = 1;

        krb5_free_cred_contents(kcontext, &creds);
    }
    krb5_cc_end_seq_get(kcontext, ccache, &cursor);

    return 0;
}
コード例 #4
0
ファイル: vfy_increds.c プロジェクト: jmoldow/krb5
static krb5_error_code
copy_creds_except(krb5_context context, krb5_ccache incc,
                  krb5_ccache outcc, krb5_principal princ)
{
    krb5_error_code code;
    krb5_flags flags;
    krb5_cc_cursor cur;
    krb5_creds creds;

    flags = 0;                           /* turns off OPENCLOSE mode */
    if ((code = krb5_cc_set_flags(context, incc, flags)))
        return(code);

    if ((code = krb5_cc_start_seq_get(context, incc, &cur)))
        goto cleanup;

    while (!(code = krb5_cc_next_cred(context, incc, &cur, &creds))) {
        if (krb5_principal_compare(context, princ, creds.server))
            continue;

        code = krb5_cc_store_cred(context, outcc, &creds);
        krb5_free_cred_contents(context, &creds);
        if (code)
            goto cleanup;
    }

    if (code != KRB5_CC_END)
        goto cleanup;

    code = 0;

cleanup:
    flags = KRB5_TC_OPENCLOSE;

    if (code)
        krb5_cc_set_flags(context, incc, flags);
    else
        code = krb5_cc_set_flags(context, incc, flags);

    return(code);
}
コード例 #5
0
ファイル: cccopy.c プロジェクト: andreiw/polaris
krb5_error_code KRB5_CALLCONV
krb5_cc_copy_creds(krb5_context context, krb5_ccache incc, krb5_ccache outcc)
{
    krb5_error_code code;
    krb5_flags flags;
    krb5_cc_cursor cur = 0;
    krb5_creds creds;

    flags = 0;				/* turns off OPENCLOSE mode */
    if ((code = krb5_cc_set_flags(context, incc, flags)))
	return(code);
    /* the code for this will open the file for reading only, which
       is not what I had in mind.  So I won't turn off OPENCLOSE
       for the output ccache */
#if 0
    if ((code = krb5_cc_set_flags(context, outcc, flags)))
	return(code);
#endif

    if ((code = krb5_cc_start_seq_get(context, incc, &cur)))
	goto cleanup;

    while (!(code = krb5_cc_next_cred(context, incc, &cur, &creds))) {
	code = krb5_cc_store_cred(context, outcc, &creds);
	krb5_free_cred_contents(context, &creds);
	if (code)
	    goto cleanup;
    }

    if (code != KRB5_CC_END)
	goto cleanup;

    code = krb5_cc_end_seq_get(context, incc, &cur);
    cur = 0;
    if (code)
        goto cleanup;

    code = 0;

cleanup:
    flags = KRB5_TC_OPENCLOSE;

    /* If set then we are in an error pathway */
    if (cur) 
      krb5_cc_end_seq_get(context, incc, &cur);

    if (code)
	krb5_cc_set_flags(context, incc, flags);
    else
	code = krb5_cc_set_flags(context, incc, flags);

#if 0
    if (code)
	krb5_cc_set_flags(context, outcc, flags);
    else
	code = krb5_cc_set_flags(context, outcc, flags);
#endif

    return(code);
}
コード例 #6
0
ファイル: klist.c プロジェクト: crherar/Admin
static void
print_tickets (krb5_context context,
	       krb5_ccache ccache,
	       krb5_principal principal,
	       int do_verbose,
	       int do_flags,
	       int do_hidden)
{
    krb5_error_code ret;
    char *str, *name;
    krb5_cc_cursor cursor;
    krb5_creds creds;
    krb5_deltat sec;

    rtbl_t ct = NULL;

    ret = krb5_unparse_name (context, principal, &str);
    if (ret)
	krb5_err (context, 1, ret, "krb5_unparse_name");

    printf ("%17s: %s:%s\n",
	    N_("Credentials cache", ""),
	    krb5_cc_get_type(context, ccache),
	    krb5_cc_get_name(context, ccache));
    printf ("%17s: %s\n", N_("Principal", ""), str);

    ret = krb5_cc_get_friendly_name(context, ccache, &name);
    if (ret == 0) {
	if (strcmp(name, str) != 0)
	    printf ("%17s: %s\n", N_("Friendly name", ""), name);
	free(name);
    }
    free (str);

    if(do_verbose) {
	printf ("%17s: %d\n", N_("Cache version", ""),
		krb5_cc_get_version(context, ccache));
    } else {
        krb5_cc_set_flags(context, ccache, KRB5_TC_NOTICKET);
    }

    ret = krb5_cc_get_kdc_offset(context, ccache, &sec);

    if (ret == 0 && do_verbose && sec != 0) {
	char buf[BUFSIZ];
	int val;
	int sig;

	val = sec;
	sig = 1;
	if (val < 0) {
	    sig = -1;
	    val = -val;
	}
	
	unparse_time (val, buf, sizeof(buf));

	printf ("%17s: %s%s\n", N_("KDC time offset", ""),
		sig == -1 ? "-" : "", buf);
    }

    printf("\n");

    ret = krb5_cc_start_seq_get (context, ccache, &cursor);
    if (ret)
	krb5_err(context, 1, ret, "krb5_cc_start_seq_get");

    if(!do_verbose) {
	ct = rtbl_create();
	rtbl_add_column(ct, COL_ISSUED, 0);
	rtbl_add_column(ct, COL_EXPIRES, 0);
	if(do_flags)
	    rtbl_add_column(ct, COL_FLAGS, 0);
	rtbl_add_column(ct, COL_PRINCIPAL, 0);
	rtbl_set_separator(ct, "  ");
    }
    while ((ret = krb5_cc_next_cred (context,
				     ccache,
				     &cursor,
				     &creds)) == 0) {
	if (!do_hidden && krb5_is_config_principal(context, creds.server)) {
	    ;
	}else if(do_verbose){
	    print_cred_verbose(context, &creds);
	}else{
	    print_cred(context, &creds, ct, do_flags);
	}
	krb5_free_cred_contents (context, &creds);
    }
    if(ret != KRB5_CC_END)
	krb5_err(context, 1, ret, "krb5_cc_get_next");
    ret = krb5_cc_end_seq_get (context, ccache, &cursor);
    if (ret)
	krb5_err (context, 1, ret, "krb5_cc_end_seq_get");
    if(!do_verbose) {
	rtbl_format(ct, stdout);
	rtbl_destroy(ct);
    }
}
コード例 #7
0
ファイル: nativeccache.c プロジェクト: lmsf/jdk9-dev
/*
 * Class:     sun_security_krb5_Credentials
 * Method:    acquireDefaultNativeCreds
 * Signature: ([I])Lsun/security/krb5/Credentials;
 */
JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativeCreds
(JNIEnv *env, jclass krbcredsClass, jintArray jetypes)
{
    jobject krbCreds = NULL;
    krb5_error_code err = 0;
    krb5_ccache ccache = NULL;
    krb5_cc_cursor cursor = NULL;
    krb5_creds creds;
    krb5_flags flags = 0;
    krb5_context kcontext = NULL;

    int netypes;
    jint *etypes = NULL;

    /* Initialize the Kerberos 5 context */
    err = krb5_init_context (&kcontext);

    if (!err) {
        err = krb5_cc_default (kcontext, &ccache);
    }

    if (!err) {
        err = krb5_cc_set_flags (kcontext, ccache, flags); /* turn off OPENCLOSE */
    }

    if (!err) {
        err = krb5_cc_start_seq_get (kcontext, ccache, &cursor);
    }

    netypes = (*env)->GetArrayLength(env, jetypes);
    etypes = (jint *) (*env)->GetIntArrayElements(env, jetypes, NULL);

    if (etypes != NULL && !err) {
        while ((err = krb5_cc_next_cred (kcontext, ccache, &cursor, &creds)) == 0) {
            char *serverName = NULL;

            if (!err) {
                err = krb5_unparse_name (kcontext, creds.server, &serverName);
                printiferr (err, "while unparsing server name");
            }

            if (!err) {
                char* slash = strchr(serverName, '/');
                char* at = strchr(serverName, '@');
                // Make sure the server's name is krbtgt/REALM@REALM, the etype
                // is supported, and the ticket has not expired
                if (slash && at &&
                        strncmp (serverName, "krbtgt", slash-serverName) == 0 &&
                            // the ablove line shows at must be after slash
                        strncmp (slash+1, at+1, at-slash-1) == 0 &&
                        isIn (creds.keyblock.enctype, netypes, etypes) &&
                        creds.times.endtime > time(0)) {
                    jobject ticket, clientPrincipal, targetPrincipal, encryptionKey;
                    jobject ticketFlags, startTime, endTime;
                    jobject authTime, renewTillTime, hostAddresses;

                    ticket = clientPrincipal = targetPrincipal = encryptionKey = NULL;
                    ticketFlags = startTime = endTime = NULL;
                    authTime = renewTillTime = hostAddresses = NULL;

                    // For the default credentials we're only interested in the krbtgt server.
                    clientPrincipal = BuildClientPrincipal(env, kcontext, creds.client);
                    if (clientPrincipal == NULL) goto cleanup;

                    targetPrincipal = BuildClientPrincipal(env, kcontext, creds.server);
                    if (targetPrincipal == NULL) goto cleanup;

                    // Build a sun/security/krb5/internal/Ticket
                    ticket = BuildTicket(env, &creds.ticket);
                    if (ticket == NULL) goto cleanup;

                    // Get the encryption key
                    encryptionKey = BuildEncryptionKey(env, &creds.keyblock);
                    if (encryptionKey == NULL) goto cleanup;

                    // and the ticket flags
                    ticketFlags = BuildTicketFlags(env, creds.ticket_flags);
                    if (ticketFlags == NULL) goto cleanup;

                    // Get the timestamps out.
                    startTime = BuildKerberosTime(env, creds.times.starttime);
                    if (startTime == NULL) goto cleanup;

                    authTime = BuildKerberosTime(env, creds.times.authtime);
                    if (authTime == NULL) goto cleanup;

                    endTime = BuildKerberosTime(env, creds.times.endtime);
                    if (endTime == NULL) goto cleanup;

                    renewTillTime = BuildKerberosTime(env, creds.times.renew_till);
                    if (renewTillTime == NULL) goto cleanup;

                    // Create the addresses object.
                    hostAddresses = BuildAddressList(env, creds.addresses);

                    if (krbcredsConstructor == 0) {
                        krbcredsConstructor = (*env)->GetMethodID(env, krbcredsClass, "<init>",
                                                                  "(Lsun/security/krb5/internal/Ticket;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/EncryptionKey;Lsun/security/krb5/internal/TicketFlags;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/HostAddresses;)V");
                        if (krbcredsConstructor == 0) {
                            printf("Couldn't find sun.security.krb5.internal.Ticket constructor\n");
                            break;
                        }
                    }

                    // and now go build a KrbCreds object
                    krbCreds = (*env)->NewObject(
                                                 env,
                                                 krbcredsClass,
                                                 krbcredsConstructor,
                                                 ticket,
                                                 clientPrincipal,
                                                 targetPrincipal,
                                                 encryptionKey,
                                                 ticketFlags,
                                                 authTime,
                                                 startTime,
                                                 endTime,
                                                 renewTillTime,
                                                 hostAddresses);
cleanup:
                    if (ticket) (*env)->DeleteLocalRef(env, ticket);
                    if (clientPrincipal) (*env)->DeleteLocalRef(env, clientPrincipal);
                    if (targetPrincipal) (*env)->DeleteLocalRef(env, targetPrincipal);
                    if (encryptionKey) (*env)->DeleteLocalRef(env, encryptionKey);
                    if (ticketFlags) (*env)->DeleteLocalRef(env, ticketFlags);
                    if (authTime) (*env)->DeleteLocalRef(env, authTime);
                    if (startTime) (*env)->DeleteLocalRef(env, startTime);
                    if (endTime) (*env)->DeleteLocalRef(env, endTime);
                    if (renewTillTime) (*env)->DeleteLocalRef(env, renewTillTime);
                    if (hostAddresses) (*env)->DeleteLocalRef(env, hostAddresses);

                    // Stop if there is an exception or we already found the initial TGT
                    if ((*env)->ExceptionCheck(env) || krbCreds) {
                        break;
                    }
                }
            }

            if (serverName != NULL) { krb5_free_unparsed_name (kcontext, serverName); }

            krb5_free_cred_contents (kcontext, &creds);
        }

        if (err == KRB5_CC_END) { err = 0; }
        printiferr (err, "while retrieving a ticket");
    }

    if (!err) {
        err = krb5_cc_end_seq_get (kcontext, ccache, &cursor);
        printiferr (err, "while finishing ticket retrieval");
    }

    if (!err) {
        flags = KRB5_TC_OPENCLOSE; /* restore OPENCLOSE mode */
        err = krb5_cc_set_flags (kcontext, ccache, flags);
        printiferr (err, "while finishing ticket retrieval");
    }

    if (etypes != NULL) {
        (*env)->ReleaseIntArrayElements(env, jetypes, etypes, 0);
    }

    krb5_free_context (kcontext);
    return krbCreds;
}
コード例 #8
0
ファイル: t_cc.c プロジェクト: Baalmart/krb5
static void
cc_test(krb5_context context, const char *name, krb5_flags flags)
{
    krb5_ccache id, id2;
    krb5_creds creds;
    krb5_error_code kret;
    krb5_cc_cursor cursor;
    krb5_principal tmp;

    const char *c_name;
    char newcache[300];
    char *save_type;

    kret = init_test_cred(context);
    CHECK(kret, "init_creds");

    kret = krb5_cc_resolve(context, name, &id);
    CHECK(kret, "resolve");
    kret = krb5_cc_initialize(context, id, test_creds.client);
    CHECK(kret, "initialize");

    c_name = krb5_cc_get_name(context, id);
    CHECK_STR(c_name, "get_name");

    c_name = krb5_cc_get_type(context, id);
    CHECK_STR(c_name, "get_type");
    save_type=strdup(c_name);
    CHECK_STR(save_type, "copying type");

    kret = krb5_cc_store_cred(context, id, &test_creds);
    CHECK(kret, "store");

    kret = krb5_cc_get_principal(context, id, &tmp);
    CHECK(kret, "get_principal");

    CHECK_BOOL(krb5_realm_compare(context, tmp, test_creds.client) != TRUE,
               "realms do not match", "realm_compare");


    CHECK_BOOL(krb5_principal_compare(context, tmp, test_creds.client) != TRUE,
               "principals do not match", "principal_compare");

    krb5_free_principal(context, tmp);

    kret = krb5_cc_set_flags (context, id, flags);
    CHECK(kret, "set_flags");

    kret = krb5_cc_start_seq_get(context, id, &cursor);
    CHECK(kret, "start_seq_get");
    kret = 0;
    while (kret != KRB5_CC_END) {
        if(debug) printf("Calling next_cred\n");
        kret = krb5_cc_next_cred(context, id, &cursor, &creds);
        if(kret == KRB5_CC_END) {
            if(debug) printf("next_cred: ok at end\n");
        }
        else {
            CHECK(kret, "next_cred");
            krb5_free_cred_contents(context, &creds);
        }

    }
    kret = krb5_cc_end_seq_get(context, id, &cursor);
    CHECK(kret, "end_seq_get");

    kret = krb5_cc_close(context, id);
    CHECK(kret, "close");


    /* ------------------------------------------------- */
    kret = krb5_cc_resolve(context, name, &id);
    CHECK(kret, "resolve2");

    {
        /* Copy the cache test*/
        snprintf(newcache, sizeof(newcache), "%s.new", name);
        kret = krb5_cc_resolve(context, newcache, &id2);
        CHECK(kret, "resolve of new cache");

        /* This should fail as the new creds are not initialized */
        kret = krb5_cc_copy_creds(context, id, id2);
        CHECK_FAIL(KRB5_FCC_NOFILE, kret, "copy_creds");

        kret = krb5_cc_initialize(context, id2, test_creds.client);
        CHECK(kret, "initialize of id2");

        kret = krb5_cc_copy_creds(context, id, id2);
        CHECK(kret, "copy_creds");

        kret = krb5_cc_destroy(context, id2);
        CHECK(kret, "destroy new cache");
    }

    /* Destroy the first cache */
    kret = krb5_cc_destroy(context, id);
    CHECK(kret, "destroy");

    /* ----------------------------------------------------- */
    /* Tests the generate new code */
    kret = krb5_cc_new_unique(context, save_type,
                              NULL, &id2);
    CHECK(kret, "new_unique");

    kret = krb5_cc_initialize(context, id2, test_creds.client);
    CHECK(kret, "initialize");

    kret = krb5_cc_store_cred(context, id2, &test_creds);
    CHECK(kret, "store");

    kret = krb5_cc_destroy(context, id2);
    CHECK(kret, "destroy id2");

    free(save_type);
    free_test_cred(context);

}
コード例 #9
0
ファイル: ms2mit.c プロジェクト: FarazShaikh/LikewiseSMB2
void
main(
    int argc,
    char *argv[]
    )
{
    krb5_context kcontext;
    krb5_error_code code;
    krb5_ccache ccache=NULL;
    krb5_ccache mslsa_ccache=NULL;
    krb5_cc_cursor cursor;
    krb5_creds creds;
    krb5_principal princ;
    int initial_ticket = 0;
    int option;
    char * ccachestr = 0;

    prog = strrchr(argv[0], '/');
    prog = prog ? (prog + 1) : argv[0];

    while ((option = getopt(argc, argv, "c:h")) != -1) {
        switch (option) {
        case 'c':
            ccachestr = optarg;
            break;
        case 'h':
        default:
            xusage();
            break;
        }
    }
        
    if (code = krb5_init_context(&kcontext)) {
        com_err(argv[0], code, "while initializing kerberos library");
        exit(1);
    }
  
    if (code = krb5_cc_resolve(kcontext, "MSLSA:", &mslsa_ccache)) {
        com_err(argv[0], code, "while opening MS LSA ccache");
        krb5_free_context(kcontext);
        exit(1);
    }

    if (code = krb5_cc_set_flags(kcontext, mslsa_ccache, KRB5_TC_NOTICKET)) {
        com_err(argv[0], code, "while setting KRB5_TC_NOTICKET flag");
        krb5_cc_close(kcontext, mslsa_ccache);
        krb5_free_context(kcontext);
        exit(1);
    }

    /* Enumerate tickets from cache looking for an initial ticket */
    if ((code = krb5_cc_start_seq_get(kcontext, mslsa_ccache, &cursor))) {
        com_err(argv[0], code, "while initiating the cred sequence of MS LSA ccache");
        krb5_cc_close(kcontext, mslsa_ccache);
        krb5_free_context(kcontext);
        exit(1);
    }

    while (!(code = krb5_cc_next_cred(kcontext, mslsa_ccache, &cursor, &creds))) 
    {
        if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
            krb5_free_cred_contents(kcontext, &creds);
            initial_ticket = 1;
            break;
        }
        krb5_free_cred_contents(kcontext, &creds);
    }
    krb5_cc_end_seq_get(kcontext, mslsa_ccache, &cursor);

    if (code = krb5_cc_set_flags(kcontext, mslsa_ccache, 0)) {
        com_err(argv[0], code, "while clearing flags");
        krb5_cc_close(kcontext, mslsa_ccache);
        krb5_free_context(kcontext);
        exit(1);
    }

    if ( !initial_ticket ) {
        fprintf(stderr, "%s: Initial Ticket Getting Tickets are not available from the MS LSA\n",
                argv[0]);
        krb5_cc_close(kcontext, mslsa_ccache);
        krb5_free_context(kcontext);
        exit(1);
    }

    if (code = krb5_cc_get_principal(kcontext, mslsa_ccache, &princ)) {
        com_err(argv[0], code, "while obtaining MS LSA principal");
        krb5_cc_close(kcontext, mslsa_ccache);
        krb5_free_context(kcontext);
        exit(1);
    }

    if (ccachestr)
        code = krb5_cc_resolve(kcontext, ccachestr, &ccache);
    else
        code = krb5_cc_default(kcontext, &ccache);
    if (code) {
        com_err(argv[0], code, "while getting default ccache");
        krb5_free_principal(kcontext, princ);
        krb5_cc_close(kcontext, mslsa_ccache);
        krb5_free_context(kcontext);
        exit(1);
    }
    if (code = krb5_cc_initialize(kcontext, ccache, princ)) {
        com_err (argv[0], code, "when initializing ccache");
        krb5_free_principal(kcontext, princ);
        krb5_cc_close(kcontext, mslsa_ccache);
        krb5_cc_close(kcontext, ccache);
        krb5_free_context(kcontext);
        exit(1);
    }

    if (code = krb5_cc_copy_creds(kcontext, mslsa_ccache, ccache)) {
        com_err (argv[0], code, "while copying MS LSA ccache to default ccache");
        krb5_free_principal(kcontext, princ);
        krb5_cc_close(kcontext, ccache);
        krb5_cc_close(kcontext, mslsa_ccache);
        krb5_free_context(kcontext);
        exit(1);
    }

    krb5_free_principal(kcontext, princ);
    krb5_cc_close(kcontext, ccache);
    krb5_cc_close(kcontext, mslsa_ccache);
    krb5_free_context(kcontext);
    return(0);
}
コード例 #10
0
ファイル: nativeccache.c プロジェクト: mamingzhang/jdk7u-jdk
/*
 * Class:     sun_security_krb5_Credentials
 * Method:    acquireDefaultNativeCreds
 * Signature: ()Lsun/security/krb5/Credentials;
 */
JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativeCreds
(JNIEnv *env, jclass krbcredsClass)
{
    jobject krbCreds = NULL;
    krb5_error_code err = 0;
    krb5_ccache ccache = NULL;
    krb5_cc_cursor cursor = NULL;
    krb5_creds creds;
    krb5_flags flags = 0;
    krb5_context kcontext = NULL;

    /* Initialize the Kerberos 5 context */
    err = krb5_init_context (&kcontext);

    if (!err) {
        err = krb5_cc_default (kcontext, &ccache);
    }

    if (!err) {
        err = krb5_cc_set_flags (kcontext, ccache, flags); /* turn off OPENCLOSE */
    }

    if (!err) {
        err = krb5_cc_start_seq_get (kcontext, ccache, &cursor);
    }

    if (!err) {
        while ((err = krb5_cc_next_cred (kcontext, ccache, &cursor, &creds)) == 0) {
            char *serverName = NULL;

            if (!err) {
                err = krb5_unparse_name (kcontext, creds.server, &serverName);
                printiferr (err, "while unparsing server name");
            }

            if (!err) {
                if (strncmp (serverName, "krbtgt", strlen("krbtgt")) == 0) {
                    jobject ticket, clientPrincipal, targetPrincipal, encryptionKey;
                    jobject ticketFlags, startTime, endTime;
                    jobject authTime, renewTillTime, hostAddresses;

                    ticket = clientPrincipal = targetPrincipal = encryptionKey = NULL;
                    ticketFlags = startTime = endTime = NULL;
                    authTime = renewTillTime = hostAddresses = NULL;

                    // For the default credentials we're only interested in the krbtgt server.
                    clientPrincipal = BuildClientPrincipal(env, kcontext, creds.client);
                    if (clientPrincipal == NULL) goto cleanup;

                    targetPrincipal = BuildClientPrincipal(env, kcontext, creds.server);
                    if (targetPrincipal == NULL) goto cleanup;

                    // Build a com.ibm.security.krb5.Ticket
                    ticket = BuildTicket(env, &creds.ticket);
                    if (ticket == NULL) goto cleanup;

                    // Get the encryption key
                    encryptionKey = BuildEncryptionKey(env, &creds.keyblock);
                    if (encryptionKey == NULL) goto cleanup;

                    // and the ticket flags
                    ticketFlags = BuildTicketFlags(env, creds.ticket_flags);
                    if (ticketFlags == NULL) goto cleanup;

                    // Get the timestamps out.
                    startTime = BuildKerberosTime(env, creds.times.starttime);
                    if (startTime == NULL) goto cleanup;

                    authTime = BuildKerberosTime(env, creds.times.authtime);
                    if (authTime == NULL) goto cleanup;

                    endTime = BuildKerberosTime(env, creds.times.endtime);
                    if (endTime == NULL) goto cleanup;

                    renewTillTime = BuildKerberosTime(env, creds.times.renew_till);
                    if (renewTillTime == NULL) goto cleanup;

                    // Create the addresses object.
                    hostAddresses = BuildAddressList(env, creds.addresses);

                    if (krbcredsConstructor == 0) {
                        krbcredsConstructor = (*env)->GetMethodID(env, krbcredsClass, "<init>",
                                              "(Lsun/security/krb5/internal/Ticket;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/EncryptionKey;Lsun/security/krb5/internal/TicketFlags;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/HostAddresses;)V");
                        if (krbcredsConstructor == 0) {
                            printf("Couldn't find com.ibm.security.krb5.Credentials constructor\n");
                            break;
                        }
                    }

                    // and now go build a KrbCreds object
                    krbCreds = (*env)->NewObject(
                                   env,
                                   krbcredsClass,
                                   krbcredsConstructor,
                                   ticket,
                                   clientPrincipal,
                                   targetPrincipal,
                                   encryptionKey,
                                   ticketFlags,
                                   authTime,
                                   startTime,
                                   endTime,
                                   renewTillTime,
                                   hostAddresses);
cleanup:
                    if (ticket) (*env)->DeleteLocalRef(env, ticket);
                    if (clientPrincipal) (*env)->DeleteLocalRef(env, clientPrincipal);
                    if (targetPrincipal) (*env)->DeleteLocalRef(env, targetPrincipal);
                    if (encryptionKey) (*env)->DeleteLocalRef(env, encryptionKey);
                    if (ticketFlags) (*env)->DeleteLocalRef(env, ticketFlags);
                    if (authTime) (*env)->DeleteLocalRef(env, authTime);
                    if (startTime) (*env)->DeleteLocalRef(env, startTime);
                    if (endTime) (*env)->DeleteLocalRef(env, endTime);
                    if (renewTillTime) (*env)->DeleteLocalRef(env, renewTillTime);
                    if (hostAddresses) (*env)->DeleteLocalRef(env, hostAddresses);
                }

            }

            if (serverName != NULL) {
                krb5_free_unparsed_name (kcontext, serverName);
            }

            krb5_free_cred_contents (kcontext, &creds);
        }

        if (err == KRB5_CC_END) {
            err = 0;
        }
        printiferr (err, "while retrieving a ticket");

    }

    if (!err) {
        err = krb5_cc_end_seq_get (kcontext, ccache, &cursor);
        printiferr (err, "while finishing ticket retrieval");
    }

    if (!err) {
        flags = KRB5_TC_OPENCLOSE; /* restore OPENCLOSE mode */
        err = krb5_cc_set_flags (kcontext, ccache, flags);
        printiferr (err, "while finishing ticket retrieval");
    }

    krb5_free_context (kcontext);
    return krbCreds;
}
コード例 #11
0
ファイル: cc_retr.c プロジェクト: NanXiao/illumos-joyent
static krb5_error_code
krb5_cc_retrieve_cred_seq (krb5_context context, krb5_ccache id,
			   krb5_flags whichfields, krb5_creds *mcreds,
			   krb5_creds *creds, int nktypes, krb5_enctype *ktypes)
{
     /* This function could be considerably faster if it kept indexing */
     /* information.. sounds like a "next version" idea to me. :-) */

     krb5_cc_cursor cursor;
     krb5_error_code kret;
     krb5_error_code nomatch_err = KRB5_CC_NOTFOUND;
     struct {
       krb5_creds creds;
       int pref;
     } fetched, best;
     int have_creds = 0;
     krb5_flags oflags = 0;
#define fetchcreds (fetched.creds)

     /* Solaris Kerberos */
     memset(&best, 0, sizeof (best));
     memset(&fetched, 0, sizeof (fetched));

     kret = krb5_cc_get_flags(context, id, &oflags);
     if (kret != KRB5_OK)
	  return kret;
     if (oflags & KRB5_TC_OPENCLOSE)
	 (void) krb5_cc_set_flags(context, id, oflags & ~KRB5_TC_OPENCLOSE);
     kret = krb5_cc_start_seq_get(context, id, &cursor);
     if (kret != KRB5_OK) {
	  if (oflags & KRB5_TC_OPENCLOSE)
	       krb5_cc_set_flags(context, id, oflags);
	  return kret;
     }

     while ((kret = krb5_cc_next_cred(context, id, &cursor, &fetchcreds)) == KRB5_OK) {
      if (krb5int_cc_creds_match_request(context, whichfields, mcreds, &fetchcreds))
      {
	      if (ktypes) {
		  fetched.pref = pref (fetchcreds.keyblock.enctype,
				       nktypes, ktypes);
		  if (fetched.pref < 0)
		      nomatch_err = KRB5_CC_NOT_KTYPE;
		  else if (!have_creds || fetched.pref < best.pref) {
		      if (have_creds)
			  krb5_free_cred_contents (context, &best.creds);
		      else
			  have_creds = 1;
		      best = fetched;
		      continue;
		  }
	      } else {
		  krb5_cc_end_seq_get(context, id, &cursor);
		  *creds = fetchcreds;
		  /* Solaris Kerberos */
		  creds->keyblock.hKey = CK_INVALID_HANDLE;
		  if (oflags & KRB5_TC_OPENCLOSE)
		      krb5_cc_set_flags(context, id, oflags);
		  return KRB5_OK;
	      }
	  }

	  /* This one doesn't match */
	  krb5_free_cred_contents(context, &fetchcreds);
     }

     /* If we get here, a match wasn't found */
     krb5_cc_end_seq_get(context, id, &cursor);
     if (oflags & KRB5_TC_OPENCLOSE)
	 krb5_cc_set_flags(context, id, oflags);
     if (have_creds) {
	 *creds = best.creds;
	 /* Solaris Kerberos */
	 creds->keyblock.hKey = CK_INVALID_HANDLE;
	 return KRB5_OK;
     } else
	 return nomatch_err;
}
コード例 #12
0
ファイル: pklist.c プロジェクト: logavanc/code
/*
 * Output the ccache contents
 */
int do_ccache(krb5_ccache cache) {
	char		*ccname = NULL;
	krb5_creds	creds;
	krb5_cc_cursor	cursor;
	krb5_principal	princ = NULL;
	char		*princname = NULL;
	krb5_flags	flags = 0;
	krb5_error_code	retval;
	int		status = 1;

	asprintf(&ccname, "%s:%s",
		krb5_cc_get_type(ctx, cache),
		krb5_cc_get_name(ctx, cache));
	if (!ccname)
		goto cleanup;

	if (show_ccname_only && !show_collection) {
		// With just -N, always show the name...
		printf("%s\n", ccname);
		status = 0;
		goto cleanup;
	}

	retval = krb5_cc_set_flags(ctx, cache, flags);
	if (retval) {
		if (quiet_errors)
			;
		else if (retval == KRB5_FCC_NOFILE)
			com_err(progname, retval, "(ticket cache %s)", ccname);
		else
			com_err(progname, retval, "while setting cache flags (ticket cache %s)", ccname);
		goto cleanup;
	}

	retval = krb5_cc_get_principal(ctx, cache, &princ);
	if (retval) {
		if (quiet_errors)
			;
		else if (retval == KRB5_FCC_NOFILE)
			com_err(progname, retval, "(ticket cache %s)", ccname);
		else
			com_err(progname, retval, "while obtaining default principal (ticket cache %s)", ccname);
		goto cleanup;
	}

	if (show_nothing) {
		status = 0;
		goto cleanup;
	}

	retval = krb5_unparse_name(ctx, princ, &princname);
	if (retval)
		goto cleanup;

	if (show_ccname_only && show_collection) {
		// ...with -l -N, only show names pointing to valid ccaches.
		printf("%s\n", ccname);
		status = 0;
		goto cleanup;
	}

	if (show_defname_only) {
		printf("%s\n", princname);
		status = 0;
		goto cleanup;
	}

	if (!show_names_only) {
		if (show_collection == 1) {
			// only show the header
			printf("cache\t%s\t%s\n", ccname, princname);
			status = 0;
			goto cleanup;
		} else {
			// TODO: should the format be merged into the one above?
			// separate cache/principal kept for now, for compat reasons
			printf("cache\t%s\n", ccname);
			printf("principal\t%s\n", princname);
		}
		printf("CREDENTIALS\tclient_name\tserver_name\tstart_time\texpiry_time\trenew_time\tflags\tticket_data\n");
	}

	retval = krb5_cc_start_seq_get(ctx, cache, &cursor);
	if (retval) {
		com_err(progname, retval, "while starting to retrieve tickets");
		goto cleanup;
	}

	for (;;) {
		retval = krb5_cc_next_cred(ctx, cache, &cursor, &creds);
		if (retval)
			break;
		show_cred(&creds);
		krb5_free_cred_contents(ctx, &creds);
	}

	if (retval == KRB5_CC_END) {
		krb5_cc_end_seq_get(ctx, cache, &cursor);
		status = 0;
	} else {
		com_err(progname, retval, "while retrieving a ticket");
	}

cleanup:
	if (princ)
		krb5_free_principal(ctx, princ);
	if (princname)
		krb5_free_unparsed_name(ctx, princname);
	if (ccname)
		free(ccname);
	return status;
}
コード例 #13
0
ファイル: cifs.upcall.c プロジェクト: MageSlayer/cifs-utils
static int
cifs_krb5_get_req(const char *host, const char *ccname,
		  DATA_BLOB * mechtoken, DATA_BLOB * sess_key)
{
	krb5_error_code ret;
	krb5_keyblock *tokb;
	krb5_context context;
	krb5_ccache ccache;
	krb5_creds in_creds, *out_creds;
	krb5_data apreq_pkt, in_data;
	krb5_auth_context auth_context = NULL;
#if defined(HAVE_KRB5_AUTH_CON_SETADDRS) && defined(HAVE_KRB5_AUTH_CON_SET_REQ_CKSUMTYPE)
	static const uint8_t gss_cksum[24] = { 0x10, 0x00, /* ... */};
#endif

	ret = krb5_init_context(&context);
	if (ret) {
		syslog(LOG_DEBUG, "%s: unable to init krb5 context", __func__);
		return ret;
	}

	ret = krb5_cc_resolve(context, ccname, &ccache);
	if (ret) {
		syslog(LOG_DEBUG, "%s: unable to resolve %s to ccache\n",
		       __func__, ccname);
		goto out_free_context;
	}

	memset(&in_creds, 0, sizeof(in_creds));

	ret = krb5_cc_get_principal(context, ccache, &in_creds.client);
	if (ret) {
		syslog(LOG_DEBUG, "%s: unable to get client principal name",
		       __func__);
		goto out_free_ccache;
	}

	ret = krb5_sname_to_principal(context, host, "cifs", KRB5_NT_UNKNOWN,
					&in_creds.server);
	if (ret) {
		syslog(LOG_DEBUG, "%s: unable to convert sname to princ (%s).",
		       __func__, host);
		goto out_free_principal;
	}

	ret = krb5_get_credentials(context, 0, ccache, &in_creds, &out_creds);
	krb5_free_principal(context, in_creds.server);
	if (ret) {
		syslog(LOG_DEBUG, "%s: unable to get credentials for %s",
		       __func__, host);
		goto out_free_principal;
	}

	in_data.length = 0;
	in_data.data = NULL;

	ret = krb5_auth_con_init(context, &auth_context);
	if (ret) {
		syslog(LOG_DEBUG, "%s: unable to create auth_context: %d",
		       __func__, ret);
		goto out_free_creds;
	}

#if defined(HAVE_KRB5_AUTH_CON_SETADDRS) && defined(HAVE_KRB5_AUTH_CON_SET_REQ_CKSUMTYPE)
	/* Ensure we will get an addressless ticket. */
	ret = krb5_auth_con_setaddrs(context, auth_context, NULL, NULL);
	if (ret) {
		syslog(LOG_DEBUG, "%s: unable to set NULL addrs: %d",
		       __func__, ret);
		goto out_free_auth;
	}

	/*
	 * Create a GSSAPI checksum (0x8003), see RFC 4121.
	 *
	 * The current layout is
	 *
	 * 0x10, 0x00, 0x00, 0x00 - length = 16
	 * 0x00, 0x00, 0x00, 0x00 - channel binding info - 16 zero bytes
	 * 0x00, 0x00, 0x00, 0x00
	 * 0x00, 0x00, 0x00, 0x00
	 * 0x00, 0x00, 0x00, 0x00
	 * 0x00, 0x00, 0x00, 0x00 - flags
	 *
	 * GSS_C_NO_CHANNEL_BINDINGS means 16 zero bytes,
	 * this is needed to work against some closed source
	 * SMB servers.
	 *
	 * See https://bugzilla.samba.org/show_bug.cgi?id=7890
	 */
	in_data.data = discard_const_p(char, gss_cksum);
	in_data.length = 24;

	/* MIT krb5 < 1.7 is missing the prototype, but still has the symbol */
#if !HAVE_DECL_KRB5_AUTH_CON_SET_REQ_CKSUMTYPE
	krb5_error_code krb5_auth_con_set_req_cksumtype(
		krb5_context      context,
		krb5_auth_context auth_context,
		krb5_cksumtype    cksumtype);
#endif
	ret = krb5_auth_con_set_req_cksumtype(context, auth_context, 0x8003);
	if (ret) {
		syslog(LOG_DEBUG, "%s: unable to set 0x8003 checksum",
		       __func__);
		goto out_free_auth;
	}
#endif

	apreq_pkt.length = 0;
	apreq_pkt.data = NULL;
	ret = krb5_mk_req_extended(context, &auth_context, AP_OPTS_USE_SUBKEY,
				   &in_data, out_creds, &apreq_pkt);
	if (ret) {
		syslog(LOG_DEBUG, "%s: unable to make AP-REQ for %s",
		       __func__, host);
		goto out_free_auth;
	}

	ret = krb5_auth_con_getsendsubkey(context, auth_context, &tokb);
	if (ret) {
		syslog(LOG_DEBUG, "%s: unable to get session key for %s",
		       __func__, host);
		goto out_free_auth;
	}

	*mechtoken = data_blob(apreq_pkt.data, apreq_pkt.length);
	*sess_key = data_blob(KRB5_KEY_DATA(tokb), KRB5_KEY_LENGTH(tokb));

	krb5_free_keyblock(context, tokb);
out_free_auth:
	krb5_auth_con_free(context, auth_context);
out_free_creds:
	krb5_free_creds(context, out_creds);
out_free_principal:
	krb5_free_principal(context, in_creds.client);
out_free_ccache:
#if defined(KRB5_TC_OPENCLOSE)
	krb5_cc_set_flags(context, ccache, KRB5_TC_OPENCLOSE);
#endif
	krb5_cc_close(context, ccache);
out_free_context:
	krb5_free_context(context);
	return ret;
}
コード例 #14
0
ファイル: cifs.upcall.c プロジェクト: MageSlayer/cifs-utils
/* does the ccache have a valid TGT? */
static time_t get_tgt_time(const char *ccname)
{
	krb5_context context;
	krb5_ccache ccache;
	krb5_cc_cursor cur;
	krb5_creds creds;
	krb5_principal principal;
	time_t credtime = 0;
	char *realm = NULL;

	if (krb5_init_context(&context)) {
		syslog(LOG_DEBUG, "%s: unable to init krb5 context", __func__);
		return 0;
	}

	if (krb5_cc_resolve(context, ccname, &ccache)) {
		syslog(LOG_DEBUG, "%s: unable to resolve krb5 cache", __func__);
		goto err_cache;
	}

	if (krb5_cc_set_flags(context, ccache, 0)) {
		syslog(LOG_DEBUG, "%s: unable to set flags", __func__);
		goto err_cache;
	}

	if (krb5_cc_get_principal(context, ccache, &principal)) {
		syslog(LOG_DEBUG, "%s: unable to get principal", __func__);
		goto err_princ;
	}

	if (krb5_cc_start_seq_get(context, ccache, &cur)) {
		syslog(LOG_DEBUG, "%s: unable to seq start", __func__);
		goto err_ccstart;
	}

	if ((realm = cifs_krb5_principal_get_realm(context, principal)) == NULL) {
		syslog(LOG_DEBUG, "%s: unable to get realm", __func__);
		goto err_ccstart;
	}

	while (!credtime && !krb5_cc_next_cred(context, ccache, &cur, &creds)) {
		char *name;
		if (krb5_unparse_name(context, creds.server, &name)) {
			syslog(LOG_DEBUG, "%s: unable to unparse name",
			       __func__);
			goto err_endseq;
		}
		if (krb5_realm_compare(context, creds.server, principal) &&
		    !strncasecmp(name, KRB5_TGS_NAME, KRB5_TGS_NAME_SIZE) &&
		    !strncasecmp(name + KRB5_TGS_NAME_SIZE + 1, realm,
				 strlen(realm))
		    && creds.times.endtime > time(NULL))
			credtime = creds.times.endtime;
		krb5_free_cred_contents(context, &creds);
		krb5_free_unparsed_name(context, name);
	}
err_endseq:
	krb5_cc_end_seq_get(context, ccache, &cur);
err_ccstart:
	krb5_free_principal(context, principal);
err_princ:
#if defined(KRB5_TC_OPENCLOSE)
	krb5_cc_set_flags(context, ccache, KRB5_TC_OPENCLOSE);
#endif
	krb5_cc_close(context, ccache);
err_cache:
	krb5_free_context(context);
	return credtime;
}
コード例 #15
0
int
main(int argc, const char **argv)
{
    poptContext poptContext;
    int poptResult;
    uid_t uid;
    int kq;
    HANDLE lsaConnection = (HANDLE) NULL;
    PVOID pUserInfo = NULL;
    struct kevent event = { 0 };
    int numChanges = 1;
    krb5_context krb5Context = NULL;
    char krb5FileCachePath[PATH_MAX];
    krb5_ccache krb5FileCache = NULL;
    krb5_ccache krb5MemoryCache = NULL;
    krb5_cc_cursor krb5Cursor = NULL;
    krb5_creds krb5Credentials = { 0 };
    krb5_principal krb5Principal = NULL;
    krb5_error_code krb5Error;
    int exitStatus = 0;
    DWORD dwError = LW_ERROR_SUCCESS;

    poptContext = poptGetContext(NULL, argc, argv, Options, 0);
    while ((poptResult = poptGetNextOpt(poptContext)) >= 0)
    {
        /* All options are processed automatically. */
    }

    if (poptResult < -1)
    {
        fprintf(stderr, "%s: %s: %s\n", getprogname(),
                poptBadOption(poptContext, POPT_BADOPTION_NOALIAS),
                poptStrerror(poptResult));
        exitStatus = 1;
        goto error;
    }

    uid = getuid();

    /* Make sure we're running as an AD user. */
    dwError = LsaOpenServer(&lsaConnection);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LsaFindUserById(
                  lsaConnection,
                  uid,
                  0,
                  &pUserInfo);
    if (dwError == LW_ERROR_NO_SUCH_USER)
    {
        /*
         * Running as a non-AD user; exit 0 so launchd doesn't restart
         * the ticketcopy program (see com.beyondtrust.pbis.ticketcopy.plist).
         */
        LSA_LOG_DEBUG(
            "uid %lu is not an AD user; exiting",
            (unsigned long) uid);
        dwError = LW_ERROR_SUCCESS;
        goto cleanup;
    }
    BAIL_ON_LSA_ERROR(dwError);

    kq = kqueue();
    BAIL_ON_UNIX_ERROR(kq == -1);

    krb5Error = krb5_init_context(&krb5Context);
    BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError);

    krb5Error = krb5_cc_default(krb5Context, &krb5MemoryCache);
    BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError);

    snprintf(
        krb5FileCachePath,
        sizeof(krb5FileCachePath),
        "FILE:/tmp/krb5cc_%lu",
        (unsigned long) uid);

    while (1) /* Forever (or until an error occurs) */
    {
        while ((event.ident = open(krb5FileCachePath + 5, O_RDONLY)) == -1)
        {
            sleep(5);
        }

        event.filter = EVFILT_VNODE;
        event.flags = EV_ADD | EV_ENABLE | EV_CLEAR;
        event.fflags = NOTE_DELETE | NOTE_WRITE;
        numChanges = 1;

        krb5Error = krb5_cc_resolve(
                        krb5Context,
                        krb5FileCachePath,
                        &krb5FileCache);
        BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError);

        while (1) /* While the file continues to exist. */
        {
            /*
             * Turn off KRB5_TC_OPENCLOSE so the file will be opened once
             * and kept open.  This causes it to actually attempt to open
             * the file, so this is where we check for the file not
             * existing and retry after sleeping a bit.
             */
            krb5Error = krb5_cc_set_flags(krb5Context, krb5FileCache, 0);
            if (krb5Error == KRB5_FCC_NOFILE)
            {
                break;
            }
            BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError);

            /* Copy all credentials from the file to the memory cache. */
            krb5Error = krb5_cc_start_seq_get(
                            krb5Context,
                            krb5FileCache,
                            &krb5Cursor);
            BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError);

            while ((krb5Error = krb5_cc_next_cred(
                                    krb5Context,
                                    krb5FileCache,
                                    &krb5Cursor,
                                    &krb5Credentials)) == 0)
            {
                krb5Error = krb5_cc_store_cred(
                                krb5Context,
                                krb5MemoryCache,
                                &krb5Credentials);
                if (krb5Error == KRB5_FCC_NOFILE)
                {
                    krb5Error = krb5_cc_get_principal(
                                    krb5Context,
                                    krb5FileCache,
                                    &krb5Principal);
                    BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError);

                    /* The memory cache was destroyed; re-create it. */
                    krb5Error = krb5_cc_initialize(
                                    krb5Context,
                                    krb5MemoryCache,
                                    krb5Principal);
                    BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError);

                    krb5_free_principal(krb5Context, krb5Principal);
                    krb5Principal = NULL;

                    krb5Error = krb5_cc_store_cred(
                                    krb5Context,
                                    krb5MemoryCache,
                                    &krb5Credentials);
                }
                BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError);

                krb5_free_cred_contents(krb5Context, &krb5Credentials);
            }

            if (krb5Error != KRB5_CC_END)
            {
                BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError);
            }

            krb5Error = krb5_cc_end_seq_get(
                            krb5Context,
                            krb5FileCache,
                            &krb5Cursor);
            krb5Cursor = NULL;
            BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError);

            /*
             * Turn KRB5_TC_OPENCLOSE back on; this will cause
             * the file to be closed and any locks to be
             * released.
             */
            krb5Error = krb5_cc_set_flags(
                            krb5Context,
                            krb5FileCache,
                            KRB5_TC_OPENCLOSE);
            BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError);

            /*
             * Wait for the file to be modified or deleted.  The first
             * time this is called after the file is opened, numChanges
             * will be 1, which will install the fd into the event
             * list.  After that numChanges is changed to 0, so it will
             * just report events from the existing list.
             */
            if (kevent(kq, &event, numChanges, &event, 1, NULL) != 1)
            {
                fprintf(stderr, "kevent failed\n");
                exitStatus = 1;
                goto cleanup;
            }

            if (event.fflags & NOTE_DELETE)
            {
                break;
            }

            numChanges = 0;
        }

        krb5Error = krb5_cc_close(krb5Context, krb5FileCache);
        BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError);
        krb5FileCache = NULL;

        close(event.ident);
        event.ident = -1;

        /*
         * The cache file is usually removed as part of a
         * rename(2) system call, so only wait a short
         * time before the first attempt to re-open it.
         */
        usleep(100000);
    }

error:
cleanup:
    krb5_free_cred_contents(krb5Context, &krb5Credentials);

    if (krb5Cursor)
    {
        krb5_cc_end_seq_get(krb5Context, krb5FileCache, &krb5Cursor);
    }

    if (krb5FileCache)
    {
        krb5_cc_close(krb5Context, krb5FileCache);
    }

    if (krb5Principal)
    {
        krb5_free_principal(krb5Context, krb5Principal);
    }

    if (krb5Context)
    {
        krb5_free_context(krb5Context);
    }

    if (event.ident != -1)
    {
        close(event.ident);
    }

    if (pUserInfo)
    {
        LsaFreeUserInfo(0, pUserInfo);
    }

    if (lsaConnection != (HANDLE) NULL)
    {
        LsaCloseServer(lsaConnection);
    }

    if (dwError)
    {
        exitStatus = 1;
    }

    return exitStatus;
}