Esempio n. 1
0
int print_ccaches (const char *in_name)
{
    kim_error err = 0;
    kim_ccache primary_cache = NULL;
    int found_tgt = 0;
    
    /* Start by printing out the main ccache... either the default or inName */
    if (!err) {
        if (in_name) {
            err = kim_ccache_create_from_display_name (&primary_cache, in_name);
            printiferr (err, "while locating credentials cache '%s'", in_name);
        } else {
            err = kim_ccache_create_from_default (&primary_cache);
            printiferr (err, "while locating the default credentials cache");
        }
    }
    
    /* print the v5 tickets in mainCCache */
    if (!err) {
        int found = 0;
        err = print_ccache (primary_cache, &found);
        if (!err) { found_tgt += found; }
    }
        
    if (show_all) {
        kim_ccache_iterator iterator = NULL;

        if (!err) {
            err = kim_ccache_iterator_create (&iterator);
        }
        
        while (!err) {
            kim_ccache ccache = NULL;
            kim_comparison comparison;
            
            err = kim_ccache_iterator_next (iterator, &ccache);
            if (!err && !ccache) { break; }
            
            if (!err) {
                err = kim_ccache_compare (ccache, primary_cache, &comparison);
            }
                        
            /* if we haven't printed this ccache already, print it */
            if (!err && !kim_comparison_is_equal_to (comparison)) {
                int found;
                
                /* Print spacing between caches in the list */
                printfiller ('-', 79);
                printmsg ("\n");

                err = print_ccache (ccache, &found);
                if (!err) { found_tgt += found; }
            }

            kim_ccache_free (&ccache);
        }
        
        kim_ccache_iterator_free (&iterator);
    }

    kim_ccache_free (&primary_cache);
    
    return (err || !found_tgt) ? 1 : 0;
}
Esempio n. 2
0
int print_ccache (kim_ccache in_ccache, int *out_found_valid_tgt)
{
    kim_error err = 0;
    kim_credential_iterator iterator = NULL;
    kim_identity ccache_identity = NULL;
    kim_string type = NULL;
    kim_string name = NULL;
    kim_string ccache_identity_string = NULL;
    int found_tickets = 0;

    *out_found_valid_tgt = 0;
    
    if (!err) {
        err = kim_ccache_get_type (in_ccache, &type);
        printiferr (err, "while getting the ccache type");
    }
    
    if (!err) {
        err = kim_ccache_get_name (in_ccache, &name);
        printiferr (err, "while getting the ccache name");
    }
    
    if (!err) {
        err = kim_ccache_get_client_identity (in_ccache, &ccache_identity);
        printiferr (err, "while getting the ccache principal");
   }
    
    if (!err) {
        err = kim_identity_get_display_string (ccache_identity, 
                                               &ccache_identity_string);
        printiferr (err, "while unparsing the ccache principal name");
    }
    
    if (!err) {
        printmsg ("Kerberos 5 ticket cache: '%s:%s'\nDefault principal: %s\n\n",
                  type, name, ccache_identity_string);
        printmsg ("Valid Starting");
        printfiller (' ', get_timestamp_width () - sizeof ("Valid Starting") + 3);
        printmsg ("Expires");
        printfiller (' ', get_timestamp_width () - sizeof ("Expires") + 3);
        printmsg ("Service Principal\n");
        
        err = kim_credential_iterator_create (&iterator, in_ccache);
    }
    
    while (!err) {
        kim_credential credential = NULL;
        kim_identity client = NULL;
        kim_identity service = NULL;
        kim_string client_string = NULL;
        kim_string service_string = NULL;
        krb5_creds *creds = NULL;
        int extra_field = 0;
        
        err = kim_credential_iterator_next (iterator, &credential);
        if (!err && !credential) { break; }
        
        if (!err) {
            err = kim_credential_get_client_identity (credential, &client);
            printiferr (err, "while getting the client principal");
        }

        if (!err) {
            err = kim_identity_get_display_string (client, &client_string);
            printiferr (err, "while unparsing the client principal name");
        }
        
        if (!err) {
            err = kim_credential_get_service_identity (credential, &service);
            printiferr (err, "while getting the service principal");
        }
        
        if (!err) {
            err = kim_identity_get_display_string (service, &service_string);
            printiferr (err, "while unparsing the service principal name");
        }
        
        if (!err) {
            err = kim_credential_get_krb5_creds (credential, kcontext, &creds);
            printiferr (err, "while getting krb5 creds");
        }
                
	if (!err && krb5_is_config_principal(kcontext, creds->server))
	    goto next;

        if (!err) {
            found_tickets = 1;
            
            printtime (creds->times.starttime ? creds->times.starttime : creds->times.authtime);
            printmsg ("  ");
            printtime (creds->times.endtime);
            printmsg ("  ");
            printmsg ("%s\n", service_string);
            
            if (strcmp (ccache_identity_string, client_string)) {
                if (!extra_field) {
                    printmsg ("\t");
                }
                printmsg ("for client %s", client_string);
                extra_field++;
            }
            
            if (creds->ticket_flags & TKT_FLG_RENEWABLE) {
                printmsg (extra_field ? ", " : "\t");
                printmsg ("renew until ");
                printtime (creds->times.renew_till);
                extra_field += 2;
            }
            
            if (extra_field > 2) {
                printmsg ("\n");
                extra_field = 0;
            }
            
            if (show_flags) {
                printmsg (extra_field ? ", " : "\t");
                printflags (creds->ticket_flags);
                extra_field++;
            }
            
            if (extra_field > 2) {
                printmsg ("\n");
                extra_field = 0;
            }
            
            if (show_enctypes) {
                krb5_ticket *ticket_rep;
                
                if (krb5_decode_ticket (&creds->ticket, &ticket_rep) == 0) {
                    if (!extra_field) {
                        printmsg ("\t");
                    } else {
                        printmsg (", ");
                    }
                    printmsg ("Etype (skey, tkt): %s, ", 
                              enctype_to_string (creds->keyblock.enctype));
                    printmsg ("%s ", 
                              enctype_to_string (ticket_rep->enc_part.enctype));
                    extra_field++;
                    
                    krb5_free_ticket (kcontext, ticket_rep);
                }
            }
            
            if (extra_field) {
                printmsg ("\n");
            }
            
            if (show_address_list) {
                printmsg ("\tAddresses: ");
                if (!creds->addresses || !creds->addresses[0]) {
                    printmsg ("(none)\n");
                } else {
                    int i;
                    
                    for (i = 0; creds->addresses[i]; i++) {
                        if (i > 0) {
                            printmsg (", ");
                        }
                        printaddress (*creds->addresses[i]);
                    }
                    printmsg ("\n");
                }
            }
            if (extra_field) {
                printmsg ("\n");
            }
            
        }
        
        if (!err) {
            kim_boolean is_tgt = 0;
            kim_credential_state state;
            
            err = kim_credential_is_tgt (credential, &is_tgt);
            printiferr (err, "while checking if creds are valid");
           
            if (!err) {
                err = kim_credential_get_state (credential, &state);
            }
            
            if (!err && is_tgt && state == kim_credentials_state_valid) { 
                *out_found_valid_tgt = 1;
            }
        }
        
    next:
        if (creds) { krb5_free_creds (kcontext, creds); }
        kim_string_free (&client_string);
        kim_string_free (&service_string);
        kim_identity_free (&client);
        kim_identity_free (&service);
        kim_credential_free (&credential);
    }
        
    kim_string_free (&type);
    kim_string_free (&name);
    kim_string_free (&ccache_identity_string);
    kim_identity_free (&ccache_identity);
    kim_credential_iterator_free (&iterator);
    
    if (!err) {
        if (!found_tickets) {
            printerr ("No Kerberos 5 tickets in credentials cache\n");
        } else {
            printmsg ("\n");
        }
    }

    return err;
}
Esempio n. 3
0
int print_keytab (const char *in_name)
{
    krb5_error_code err = 0;
    krb5_keytab kt;
    krb5_keytab_entry entry;
    krb5_kt_cursor cursor;
    char keytab_name[BUFSIZ]; /* hopefully large enough for any type */

    if (!err) {
        if (!in_name) {
            err = krb5_kt_default (kcontext, &kt);
            printiferr (err, "while resolving default keytab");
        } else {
            err = krb5_kt_resolve (kcontext, in_name, &kt);
            printiferr (err, "while resolving keytab %s", in_name);
        }
    }

    if (!err) {
        err = krb5_kt_get_name (kcontext, kt, keytab_name, sizeof (keytab_name));
        printiferr (err, "while getting keytab name");
    }

    if (!err) {
        printmsg ("Keytab name: %s\n", keytab_name);
    }

    if (!err) {
        err = krb5_kt_start_seq_get (kcontext, kt, &cursor);
        printiferr (err, "while starting scan of keytab %s", keytab_name);
    }

    if (!err) {
        if (show_entry_timestamps) {
            printmsg ("KVNO Timestamp");
            printfiller (' ', get_timestamp_width () - sizeof ("Timestamp") + 2);
            printmsg ("Principal\n");
            printmsg ("---- ");
            printfiller ('-', get_timestamp_width ());
            printmsg (" ");
            printfiller ('-', 78 - get_timestamp_width () - sizeof ("KVNO"));
            printmsg ("\n");
        } else {
            printmsg("KVNO Principal\n");
            printmsg("---- --------------------------------------------------------------------------\n");
        }
    }

    while (!err) {
        char *principal_name = NULL;

        err = krb5_kt_next_entry (kcontext, kt, &entry, &cursor);
	if (err == KRB5_KT_END) {
	    err = 0;
	    break;
	}
 
        if (!err) {
            err = krb5_unparse_name (kcontext, entry.principal, &principal_name);
            printiferr (err, "while unparsing principal name");
        }
        
        if (!err) {
            printmsg ("%4d ", entry.vno);
            if (show_entry_timestamps) {
                printtime (entry.timestamp);
                printmsg (" ");
            }
            printmsg ("%s", principal_name);
            if (show_enctypes) {
                printmsg (" (%s) ", enctype_to_string (entry.key.enctype));
            }
            if (show_entry_DES_keys) {
                unsigned int i;
                
                printmsg (" (0x");
                for (i = 0; i < entry.key.length; i++) {
                    printmsg ("%02x", entry.key.contents[i]);
                }
                printmsg (")");
            }
            printmsg ("\n");
        }
	printiferr (err, "while scanning keytab %s", keytab_name);

        if (principal_name) { krb5_free_unparsed_name (kcontext, principal_name); }
    }

    if (!err) {
        err = krb5_kt_end_seq_get (kcontext, kt, &cursor);
        printiferr (err, "while ending scan of keytab %s", keytab_name);
    }

    return err ? 1 : 0;
}
Esempio n. 4
0
static int destroy_tickets (void)
{
    krb5_error_code err = 0;
    
    if (cache_name) {
        kim_ccache ccache = NULL;
        
        err = kim_ccache_create_from_display_name (&ccache, cache_name);
        printiferr (err, "while locating credentials cache '%s'", 
                    cache_name);
        
        if (!err) {
            err = kim_ccache_destroy (&ccache);
            printiferr (err, "while destroying credentials cache '%s'", 
                        cache_name);
        }
        
    } else if (all) {
        /* Destroy all ticket caches */
        kim_ccache_iterator iterator = NULL;
        
        err = kim_ccache_iterator_create (&iterator);
        
        while (!err) {
            kim_ccache ccache = NULL;
            
            err = kim_ccache_iterator_next (iterator, &ccache);
            
            if (!err) {
                if (ccache) {
                    err = kim_ccache_destroy (&ccache);
                } else {
                    break; /* no more ccaches */
                }
            }
        }
        
        kim_ccache_iterator_free (&iterator);
        
    } else {
        /* Destroy the tickets by the principal or the default tickets */
        kim_identity identity = KIM_IDENTITY_ANY;
        kim_ccache ccache = NULL;
        
        if (principal_name) {
            err = kim_identity_create_from_string (&identity, principal_name);
            printiferr (err, "while creating identity for '%s'", 
                        principal_name);
        }
        
        if (!err) {
            kim_ccache_create_from_client_identity (&ccache, identity);
            if (identity) {
                printiferr (err, "while getting ccache for '%s'", 
                            principal_name);
            } else {
                printiferr (err, "while getting default ccache");
            }
        }
        
        if (!err) {
            err = kim_ccache_destroy (&ccache);
            printiferr (err, "while destroying tickets");
        }
        
        kim_identity_free (&identity);
    }
    
    return err ? 1 : 0;
}
Esempio n. 5
0
/*
 * 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;
}
Esempio n. 6
0
/*
 * 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;
}