Example #1
0
krb5_error_code
Leash_krb5_cc_default(krb5_context *ctx, krb5_ccache *cache)
{
    krb5_error_code rc;
    krb5_flags flags;

    char *functionName = NULL;
    if (*cache == 0) {
        rc = pkrb5_cc_default(*ctx, cache);
        if (rc) {
            functionName = "krb5_cc_default()";
            goto on_error;
        }
    }
#ifdef KRB5_TC_NOTICKET
    flags = KRB5_TC_NOTICKET;
#endif
    rc = pkrb5_cc_set_flags(*ctx, *cache, flags);
    if (rc) {
        if (rc == KRB5_FCC_NOFILE || rc == KRB5_CC_NOTFOUND) {
            if (*cache != NULL && *ctx != NULL)
                pkrb5_cc_close(*ctx, *cache);
        } else {
            functionName = "krb5_cc_set_flags()";
            goto on_error;
        }
    }
on_error:
    if (rc && functionName) {
        Leash_krb5_error(rc, functionName, 0, ctx, cache);
    }
    return rc;
}
Example #2
0
//
// Returns 0 for success, 1 for failure
//
int
do_all_ccaches(krb5_context ctx, TICKETINFO **ticketinfotail)
{
    krb5_error_code code;
    krb5_ccache cache;
    krb5_cccol_cursor cursor;
    int retval = 0;
    char *functionName = NULL;

    code = pkrb5_cccol_cursor_new(ctx, &cursor);
    if (code) {
        functionName = "krb5_cccol_cursor_new";
        goto cleanup;
    }
    retval = 0;
    while (!(code = pkrb5_cccol_cursor_next(ctx, cursor, &cache)) &&
           cache != NULL) {
        // Note that ticketList will be updated here to point to the tail
        // of the list but the caller of this function will remain with a
        // pointer to the head.
        do_ccache(ctx, cache, &ticketinfotail);
        pkrb5_cc_close(ctx, cache);
    }
    if (code)
         functionName = "krb5_cccol_cursor_next";
    pkrb5_cccol_cursor_free(ctx, &cursor);
cleanup:
    if (code) {
        Leash_krb5_error(code, functionName, 0, NULL, NULL);
    }
    return retval;
}
Example #3
0
long
not_an_API_LeashKRB5GetTickets(TICKETINFO *ticketinfo,
                               krb5_context *krbv5Context)
{
    krb5_error_code code;
    krb5_principal me = 0;
    krb5_context ctx = 0;
    krb5_ccache cache = 0;
    char *PrincipalName = NULL;

    code = Leash_krb5_initialize(krbv5Context);
    if (code)
        return code;

    ctx = *krbv5Context;

    // @TEMP fixme; shouldn't be necessary
    // save default principal name in ticketinfo
    if (ticketinfo != NULL) {
        ticketinfo->btickets = NO_TICKETS;
        ticketinfo->principal = NULL;
        ticketinfo->ccache_name = NULL;
        ticketinfo->next = NULL;
        ticketinfo->ticket_list = NULL;

        code = pkrb5_cc_default(ctx, &cache);
        if (code)
            goto cleanup;
        ticketinfo->ccache_name = strdup(pkrb5_cc_get_name(ctx, cache));
        if (ticketinfo->ccache_name == NULL) {
            code = ENOMEM;
            goto cleanup;
        }
        if (!pkrb5_cc_get_principal(ctx, cache, &me)) {
            code = (*pkrb5_unparse_name)(ctx, me, &PrincipalName);
            if (code)
                goto cleanup;
            if (PrincipalName) {
                ticketinfo->principal = strdup(PrincipalName);
                pkrb5_free_unparsed_name(ctx, PrincipalName);
            }
        }
    }

    do_all_ccaches(*krbv5Context, &ticketinfo->next);
    // @TEMP aggregate ticket info here?

cleanup:
    if (code)
        not_an_API_LeashKRB5FreeTickets(ticketinfo);
    if (cache)
        pkrb5_cc_close(ctx, cache);
    if (me)
        pkrb5_free_principal(ctx, me);
    return code;
}
Example #4
0
int 
khm_krb5_error(krb5_error_code rc, LPCSTR FailedFunctionName, 
                 int FreeContextFlag, krb5_context * ctx, 
                 krb5_ccache * cache)
{
#ifdef NO_KRB5
    return 0;
#else

#ifdef SHOW_MESSAGE_IN_AN_ANNOYING_WAY
    char message[256];
    const char *errText;
    int krb5Error = ((int)(rc & 255));  

    errText = perror_message(rc);   
    _snprintf(message, sizeof(message), 
        "%s\n(Kerberos error %ld)\n\n%s failed", 
        errText, 
        krb5Error, 
        FailedFunctionName);

    MessageBoxA(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR | 
        MB_TASKMODAL | 
        MB_SETFOREGROUND);
#endif

    if (FreeContextFlag == 1)
    {
        if (*ctx != NULL)
        {
            if (*cache != NULL) {
                pkrb5_cc_close(*ctx, *cache);
                *cache = NULL;
            }

            pkrb5_free_context(*ctx);
            *ctx = NULL;
        }
    }

    return rc;

#endif //!NO_KRB5
}
Example #5
0
int
Leash_krb5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
                 int FreeContextFlag, krb5_context * ctx,
                 krb5_ccache * cache)
{
#ifdef NO_KRB5
    return 0;
#else
#ifdef USE_MESSAGE_BOX
    char message[256];
    const char *errText;

    errText = perror_message(rc);
    _snprintf(message, sizeof(message),
              "%s\n(Kerberos error %ld)\n\n%s failed",
              errText,
              rc,
              FailedFunctionName);
    message[sizeof(message)-1] = 0;

    MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
               MB_TASKMODAL |
               MB_SETFOREGROUND);
#endif /* USE_MESSAGE_BOX */

    if (ctx != NULL && *ctx != NULL) {
        if (cache != NULL && *cache != NULL) {
            pkrb5_cc_close(*ctx, *cache);
            *cache = NULL;
        }

        if (FreeContextFlag) {
            pkrb5_free_context(*ctx);
            *ctx = NULL;
        }
    }

    return rc;

#endif //!NO_KRB5
}
Example #6
0
long
Leash_convert524(
     krb5_context alt_ctx
     )
{
#if defined(NO_KRB5) || defined(NO_KRB4)
    return(0);
#else
    krb5_context ctx = 0;
    krb5_error_code code = 0;
    int icode = 0;
    krb5_principal me = 0;
    krb5_principal server = 0;
    krb5_creds *v5creds = 0;
    krb5_creds increds;
    krb5_ccache cc = 0;
    CREDENTIALS * v4creds = NULL;
    static int init_ets = 1;

    if (!pkrb5_init_context ||
        !pkrb_in_tkt ||
	!pkrb524_init_ets ||
	!pkrb524_convert_creds_kdc)
        return 0;

	v4creds = (CREDENTIALS *) malloc(sizeof(CREDENTIALS));
	memset((char *) v4creds, 0, sizeof(CREDENTIALS));

    memset((char *) &increds, 0, sizeof(increds));
    /*
      From this point on, we can goto cleanup because increds is
      initialized.
    */

    if (alt_ctx)
    {
        ctx = alt_ctx;
    }
    else
    {
        code = pkrb5_init_context(&ctx);
        if (code) goto cleanup;
    }

    code = pkrb5_cc_default(ctx, &cc);
    if (code) goto cleanup;

    if ( init_ets ) {
        pkrb524_init_ets(ctx);
        init_ets = 0;
    }

    if (code = pkrb5_cc_get_principal(ctx, cc, &me))
        goto cleanup;

    if ((code = pkrb5_build_principal(ctx,
                                     &server,
                                     krb5_princ_realm(ctx, me)->length,
                                     krb5_princ_realm(ctx, me)->data,
                                     "krbtgt",
                                     krb5_princ_realm(ctx, me)->data,
                                     NULL))) {
        goto cleanup;
    }

    increds.client = me;
    increds.server = server;
    increds.times.endtime = 0;
    increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
    if ((code = pkrb5_get_credentials(ctx, 0,
                                     cc,
                                     &increds,
                                     &v5creds))) {
        goto cleanup;
    }

    if ((icode = pkrb524_convert_creds_kdc(ctx,
                                          v5creds,
                                          v4creds))) {
        goto cleanup;
    }

    /* initialize ticket cache */
    if ((icode = pkrb_in_tkt(v4creds->pname, v4creds->pinst, v4creds->realm)
         != KSUCCESS)) {
        goto cleanup;
    }
    /* stash ticket, session key, etc. for future use */
    if ((icode = pkrb_save_credentials(v4creds->service,
                                      v4creds->instance,
                                      v4creds->realm,
                                      v4creds->session,
                                      v4creds->lifetime,
                                      v4creds->kvno,
                                      &(v4creds->ticket_st),
                                      v4creds->issue_date))) {
        goto cleanup;
    }

 cleanup:
    memset(v4creds, 0, sizeof(v4creds));
    free(v4creds);

    if (v5creds) {
        pkrb5_free_creds(ctx, v5creds);
    }
    if (increds.client == me)
        me = 0;
    if (increds.server == server)
        server = 0;
    pkrb5_free_cred_contents(ctx, &increds);
    if (server) {
        pkrb5_free_principal(ctx, server);
    }
    if (me) {
        pkrb5_free_principal(ctx, me);
    }
    pkrb5_cc_close(ctx, cc);

    if (ctx && (ctx != alt_ctx)) {
        pkrb5_free_context(ctx);
    }
    return !(code || icode);
#endif /* NO_KRB5 */
}
Example #7
0
int
Leash_krb5_kinit(
krb5_context alt_ctx,
HWND hParent,
char *principal_name,
char *password,
krb5_deltat lifetime,
DWORD                       forwardable,
DWORD                       proxiable,
krb5_deltat                 renew_life,
DWORD                       addressless,
DWORD                       publicIP
)
{
#ifdef NO_KRB5
    return(0);
#else
    krb5_error_code		        code = 0;
    krb5_context		        ctx = 0;
    krb5_ccache			        cc = 0, defcache = 0;
    krb5_principal		        me = 0;
    char*                       name = 0;
    krb5_creds			        my_creds;
    krb5_get_init_creds_opt *   options = NULL;
    krb5_address **             addrs = NULL;
    int                         i = 0, addr_count = 0;
    int                         cc_new = 0;
    const char *                deftype = NULL;

    if (!pkrb5_init_context)
        return 0;

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

    if (alt_ctx)
    {
        ctx = alt_ctx;
    }
    else
    {
        code = pkrb5_init_context(&ctx);
        if (code) goto cleanup;
    }

    code = pkrb5_get_init_creds_opt_alloc(ctx, &options);
    if (code) goto cleanup;

    code = pkrb5_cc_default(ctx, &defcache);
    if (code) goto cleanup;

    code = pkrb5_parse_name(ctx, principal_name, &me);
    if (code) goto cleanup;

    deftype = pkrb5_cc_get_type(ctx, defcache);
    if (me != NULL && pkrb5_cc_support_switch(ctx, deftype)) {
        /* Use an existing cache for the specified principal if we can. */
        code = pkrb5_cc_cache_match(ctx, me, &cc);
        if (code != 0 && code != KRB5_CC_NOTFOUND)
            goto cleanup;
        if (code == KRB5_CC_NOTFOUND) {
            code = pkrb5_cc_new_unique(ctx, deftype, NULL, &cc);
            if (code)
                goto cleanup;
            cc_new = 1;
        }
        pkrb5_cc_close(ctx, defcache);
    } else {
        cc = defcache;
    }

    code = pkrb5_unparse_name(ctx, me, &name);
    if (code) goto cleanup;

    if (lifetime == 0)
        lifetime = Leash_get_default_lifetime();
    else
        lifetime *= 5*60;

	if (renew_life > 0)
		renew_life *= 5*60;

    if (lifetime)
        pkrb5_get_init_creds_opt_set_tkt_life(options, lifetime);
	pkrb5_get_init_creds_opt_set_forwardable(options,
                                             forwardable ? 1 : 0);
	pkrb5_get_init_creds_opt_set_proxiable(options,
                                           proxiable ? 1 : 0);
	pkrb5_get_init_creds_opt_set_renew_life(options,
                                            renew_life);
    if (addressless)
        pkrb5_get_init_creds_opt_set_address_list(options,NULL);
    else {
		if (publicIP)
        {
            // we are going to add the public IP address specified by the user
            // to the list provided by the operating system
            krb5_address ** local_addrs=NULL;
            DWORD           netIPAddr;

            pkrb5_os_localaddr(ctx, &local_addrs);
            while ( local_addrs[i++] );
            addr_count = i + 1;

            addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
            if ( !addrs ) {
                pkrb5_free_addresses(ctx, local_addrs);
                assert(0);
            }
            memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
            i = 0;
            while ( local_addrs[i] ) {
                addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
                if (addrs[i] == NULL) {
                    pkrb5_free_addresses(ctx, local_addrs);
                    assert(0);
                }

                addrs[i]->magic = local_addrs[i]->magic;
                addrs[i]->addrtype = local_addrs[i]->addrtype;
                addrs[i]->length = local_addrs[i]->length;
                addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
                if (!addrs[i]->contents) {
                    pkrb5_free_addresses(ctx, local_addrs);
                    assert(0);
                }

                memcpy(addrs[i]->contents,local_addrs[i]->contents,
                        local_addrs[i]->length);        /* safe */
                i++;
            }
            pkrb5_free_addresses(ctx, local_addrs);

            addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
            if (addrs[i] == NULL)
                assert(0);

            addrs[i]->magic = KV5M_ADDRESS;
            addrs[i]->addrtype = AF_INET;
            addrs[i]->length = 4;
            addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
            if (!addrs[i]->contents)
                assert(0);

            netIPAddr = htonl(publicIP);
            memcpy(addrs[i]->contents,&netIPAddr,4);

            pkrb5_get_init_creds_opt_set_address_list(options,addrs);

        }
    }

    code = pkrb5_get_init_creds_opt_set_out_ccache(ctx, options, cc);
    if (code)
        goto cleanup;

    code = pkrb5_get_init_creds_password(ctx,
                                       &my_creds,
                                       me,
                                       password, // password
                                       leash_krb5_prompter, // prompter
                                       hParent, // prompter data
                                       0, // start time
                                       0, // service name
                                       options);
    // @TODO: make this an option
    if ((!code) && (cc != defcache)) {
        code = pkrb5_cc_switch(ctx, cc);
        if (!code) {
            const char *cctype = pkrb5_cc_get_type(ctx, cc);
            if (cctype != NULL) {
                char defname[20];
                sprintf_s(defname, sizeof(defname), "%s:", cctype);
                pkrb5int_cc_user_set_default_name(ctx, defname);
            }
        }
    }
 cleanup:
    if (code && cc_new) {
        // don't leave newly-generated empty ccache lying around on failure
        pkrb5_cc_destroy(ctx, cc);
        cc = NULL;
    }
    if ( addrs ) {
        for ( i=0;i<addr_count;i++ ) {
            if ( addrs[i] ) {
                if ( addrs[i]->contents )
                    free(addrs[i]->contents);
                free(addrs[i]);
            }
        }
    }
    if (my_creds.client == me)
	my_creds.client = 0;
    pkrb5_free_cred_contents(ctx, &my_creds);
    if (name)
	pkrb5_free_unparsed_name(ctx, name);
    if (me)
	pkrb5_free_principal(ctx, me);
    if (cc)
	pkrb5_cc_close(ctx, cc);
    if (options)
        pkrb5_get_init_creds_opt_free(ctx, options);
    if (ctx && (ctx != alt_ctx))
	pkrb5_free_context(ctx);
    return(code);
#endif //!NO_KRB5
}
Example #8
0
int
LeashKRB5_renew(void)
{
#ifdef NO_KRB5
    return(0);
#else
    krb5_error_code		        code = 0;
    krb5_context		        ctx = 0;
    krb5_ccache			        cc = 0;
    krb5_principal		        me = 0;
    krb5_principal              server = 0;
    krb5_creds			        my_creds;
    krb5_data                   *realm = 0;

    if ( !pkrb5_init_context )
        goto cleanup;

	memset(&my_creds, 0, sizeof(krb5_creds));

    code = pkrb5_init_context(&ctx);
    if (code) goto cleanup;

    code = pkrb5_cc_default(ctx, &cc);
    if (code) goto cleanup;

    code = pkrb5_cc_get_principal(ctx, cc, &me);
    if (code) goto cleanup;

    realm = krb5_princ_realm(ctx, me);

    code = pkrb5_build_principal_ext(ctx, &server,
                                    realm->length,realm->data,
                                    KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
                                    realm->length,realm->data,
                                    0);
    if ( code ) goto cleanup;

    my_creds.client = me;
    my_creds.server = server;

#ifdef KRB5_TC_NOTICKET
    pkrb5_cc_set_flags(ctx, cc, 0);
#endif
    code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
#ifdef KRB5_TC_NOTICKET
    pkrb5_cc_set_flags(ctx, cc, KRB5_TC_NOTICKET);
#endif
    if (code) {
        if ( code != KRB5KDC_ERR_ETYPE_NOSUPP ||
             code != KRB5_KDC_UNREACH)
            Leash_krb5_error(code, "krb5_get_renewed_creds()", 0, &ctx, &cc);
        goto cleanup;
    }

    code = pkrb5_cc_initialize(ctx, cc, me);
    if (code) goto cleanup;

    code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
    if (code) goto cleanup;

  cleanup:
    if (my_creds.client == me)
        my_creds.client = 0;
    if (my_creds.server == server)
        my_creds.server = 0;
    pkrb5_free_cred_contents(ctx, &my_creds);
    if (me)
        pkrb5_free_principal(ctx, me);
    if (server)
        pkrb5_free_principal(ctx, server);
    if (cc)
        pkrb5_cc_close(ctx, cc);
    if (ctx)
        pkrb5_free_context(ctx);
    return(code);
#endif /* NO_KRB5 */
}
Example #9
0
BOOL
Leash_ms2mit(BOOL save_creds)
{
#ifdef NO_KRB5
    return(FALSE);
#else /* NO_KRB5 */
    krb5_context kcontext = 0;
    krb5_error_code code;
    krb5_ccache ccache=0;
    krb5_ccache mslsa_ccache=0;
    krb5_creds creds;
    krb5_cc_cursor cursor=0;
    krb5_principal princ = 0;
    BOOL rc = FALSE;

    if ( !pkrb5_init_context )
        goto cleanup;

    if (code = pkrb5_init_context(&kcontext))
        goto cleanup;

    if (code = pkrb5_cc_resolve(kcontext, "MSLSA:", &mslsa_ccache))
        goto cleanup;

    if ( save_creds ) {
        if (code = pkrb5_cc_get_principal(kcontext, mslsa_ccache, &princ))
            goto cleanup;

        if (code = pkrb5_cc_default(kcontext, &ccache))
            goto cleanup;

        if (code = pkrb5_cc_initialize(kcontext, ccache, princ))
            goto cleanup;

        if (code = pkrb5_cc_copy_creds(kcontext, mslsa_ccache, ccache))
            goto cleanup;

        rc = TRUE;
    } else {
        /* Enumerate tickets from cache looking for an initial ticket */
        if ((code = pkrb5_cc_start_seq_get(kcontext, mslsa_ccache, &cursor)))
            goto cleanup;

        while (!(code = pkrb5_cc_next_cred(kcontext, mslsa_ccache, &cursor, &creds)))
        {
            if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
                rc = TRUE;
                pkrb5_free_cred_contents(kcontext, &creds);
                break;
            }
            pkrb5_free_cred_contents(kcontext, &creds);
        }
        pkrb5_cc_end_seq_get(kcontext, mslsa_ccache, &cursor);
    }

  cleanup:
    if (princ)
        pkrb5_free_principal(kcontext, princ);
    if (ccache)
        pkrb5_cc_close(kcontext, ccache);
    if (mslsa_ccache)
        pkrb5_cc_close(kcontext, mslsa_ccache);
    if (kcontext)
        pkrb5_free_context(kcontext);
    return(rc);
#endif /* NO_KRB5 */
}
Example #10
0
int
Leash_afs_klog(
    char *service,
    char *cell,
    char *realm,
    int LifeTime
    )
{
/////#ifdef NO_AFS
#if defined(NO_AFS) || defined(NO_KRB4)
    return(0);
#else
    long	rc;
////This is defined in krb.h:
    CREDENTIALS	creds;
    KTEXT_ST	ticket;
    struct ktc_principal	aserver;
    struct ktc_principal	aclient;
    char	realm_of_user[REALM_SZ]; /* Kerberos realm of user */
    char	realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
    char	local_cell[MAXCELLCHARS+1];
    char	Dmycell[MAXCELLCHARS+1];
    struct ktc_token	atoken;
    struct ktc_token	btoken;
    afsconf_cell	ak_cellconfig; /* General information about the cell */
    char	RealmName[128];
    char	CellName[128];
    char	ServiceName[128];
    DWORD       CurrentState;
    char        HostName[64];
    BOOL        try_krb5 = 0;
    int         retry = 0;
    int         len;
#ifndef NO_KRB5
    krb5_context  context = 0;
    krb5_ccache  _krb425_ccache = 0;
    krb5_creds increds;
    krb5_creds * k5creds = 0;
    krb5_error_code r;
    krb5_principal client_principal = 0;
    krb5_flags		flags = 0;
#endif /* NO_KRB5 */

    if (!AfsAvailable || GetAfsStatus(&AfsOnLine) && !AfsOnLine)
        return(0);

    if ( !realm ) realm = "";
    if ( !cell )  cell = "";
    if ( !service ) service = "";

    CurrentState = 0;
    memset(HostName, '\0', sizeof(HostName));
    gethostname(HostName, sizeof(HostName));
    if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
        return(0);
    if (CurrentState != SERVICE_RUNNING)
        return(0);

    memset(RealmName, '\0', sizeof(RealmName));
    memset(CellName, '\0', sizeof(CellName));
    memset(ServiceName, '\0', sizeof(ServiceName));
    memset(realm_of_user, '\0', sizeof(realm_of_user));
    memset(realm_of_cell, '\0', sizeof(realm_of_cell));
    memset(Dmycell, '\0', sizeof(Dmycell));

    // NULL or empty cell returns information on local cell
    if (cell && cell[0])
        strcpy(Dmycell, cell);
    rc = get_cellconfig(Dmycell, &ak_cellconfig, local_cell);
    if (rc && cell && cell[0]) {
        memset(Dmycell, '\0', sizeof(Dmycell));
        rc = get_cellconfig(Dmycell, &ak_cellconfig, local_cell);
    }
    if (rc)
        return(rc);

#ifndef NO_KRB5
    if (!(r = Leash_krb5_initialize(&context, &_krb425_ccache))) {
        int i;

        memset((char *)&increds, 0, sizeof(increds));

        (*pkrb5_cc_get_principal)(context, _krb425_ccache, &client_principal);
        i = krb5_princ_realm(context, client_principal)->length;
        if (i > REALM_SZ-1)
            i = REALM_SZ-1;
        strncpy(realm_of_user,krb5_princ_realm(context, client_principal)->data,i);
        realm_of_user[i] = 0;
        try_krb5 = 1;
    }
#endif /* NO_KRB5 */

#ifndef NO_KRB4
    if ( !try_krb5 || !realm_of_user[0] ) {
        if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
        {
            return(rc);
        }
    }
#endif
    strcpy(realm_of_cell, afs_realm_of_cell(&ak_cellconfig));

    if (strlen(service) == 0)
        strcpy(ServiceName, "afs");
    else
        strcpy(ServiceName, service);

    if (strlen(cell) == 0)
        strcpy(CellName, local_cell);
    else
        strcpy(CellName, cell);

    if (strlen(realm) == 0)
        strcpy(RealmName, realm_of_cell);
    else
        strcpy(RealmName, realm);

    memset(&creds, '\0', sizeof(creds));

#ifndef NO_KRB5
    if ( try_krb5 ) {
        /* First try Service/Cell@REALM */
        if (r = (*pkrb5_build_principal)(context, &increds.server,
                                      strlen(RealmName),
                                      RealmName,
                                      ServiceName,
                                      CellName,
                                      0))
        {
            try_krb5 = 0;
            goto use_krb4;
        }

        increds.client = client_principal;
        increds.times.endtime = 0;
        /* Ask for DES since that is what V4 understands */
        increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;

#ifdef KRB5_TC_NOTICKET
        flags = 0;
        r = pkrb5_cc_set_flags(context, _krb425_ccache, flags);
#endif
        if (r == 0)
            r = pkrb5_get_credentials(context, 0, _krb425_ccache, &increds, &k5creds);
        if (r == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
			r == KRB5KRB_ERR_GENERIC /* Heimdal */) {
            /* Next try Service@REALM */
            pkrb5_free_principal(context, increds.server);
            r = pkrb5_build_principal(context, &increds.server,
                                      strlen(RealmName),
                                      RealmName,
                                      ServiceName,
                                      0);
            if (r == 0)
                r = pkrb5_get_credentials(context, 0, _krb425_ccache, &increds, &k5creds);
        }

        pkrb5_free_principal(context, increds.server);
        pkrb5_free_principal(context, client_principal);
#ifdef KRB5_TC_NOTICKET
        flags = KRB5_TC_NOTICKET;
        pkrb5_cc_set_flags(context, _krb425_ccache, flags);
#endif
        (void) pkrb5_cc_close(context, _krb425_ccache);
        _krb425_ccache = 0;

        if (r || k5creds == 0) {
            pkrb5_free_context(context);
            try_krb5 = 0;
            goto use_krb4;
        }

        /* This code inserts the entire K5 ticket into the token
         * No need to perform a krb524 translation which is
         * commented out in the code below
         */
        if ( use_krb524() || k5creds->ticket.length > MAXKTCTICKETLEN )
            goto try_krb524d;

        memset(&aserver, '\0', sizeof(aserver));
        strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
        strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);

        memset(&atoken, '\0', sizeof(atoken));
        atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
        atoken.startTime = k5creds->times.starttime;
        atoken.endTime = k5creds->times.endtime;
        memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length);
        atoken.ticketLen = k5creds->ticket.length;
        memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen);

      retry_gettoken5:
        rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
        if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
            if ( rc == KTC_NOCM && retry < 20 ) {
                Sleep(500);
                retry++;
                goto retry_gettoken5;
            }
            goto try_krb524d;
        }

        if (atoken.kvno == btoken.kvno &&
             atoken.ticketLen == btoken.ticketLen &&
             !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
             !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
        {
            /* Success */
            pkrb5_free_creds(context, k5creds);
            pkrb5_free_context(context);
            return(0);
        }

        // * Reset the "aclient" structure before we call ktc_SetToken.
        // * This structure was first set by the ktc_GetToken call when
        // * we were comparing whether identical tokens already existed.

        len = min(k5creds->client->data[0].length,MAXKTCNAMELEN - 1);
        strncpy(aclient.name, k5creds->client->data[0].data, len);
        aclient.name[len] = '\0';

        if ( k5creds->client->length > 1 ) {
            char * p;
            strcat(aclient.name, ".");
            p = aclient.name + strlen(aclient.name);
            len = min(k5creds->client->data[1].length,MAXKTCNAMELEN - strlen(aclient.name) - 1);
            strncpy(p, k5creds->client->data[1].data, len);
            p[len] = '\0';
        }
        aclient.instance[0] = '\0';

        strcpy(aclient.cell, realm_of_cell);

        len = min(k5creds->client->realm.length,strlen(realm_of_cell));
        if ( strncmp(realm_of_cell, k5creds->client->realm.data, len) ) {
            char * p;
            strcat(aclient.name, "@");
            p = aclient.name + strlen(aclient.name);
            len = min(k5creds->client->realm.length,MAXKTCNAMELEN - strlen(aclient.name) - 1);
            strncpy(p, k5creds->client->realm.data, len);
            p[len] = '\0';
        }

        rc = ktc_SetToken(&aserver, &atoken, &aclient, 0);
        if (!rc) {
            /* Success */
            pkrb5_free_creds(context, k5creds);
            pkrb5_free_context(context);
            return(0);
        }

      try_krb524d:
        /* This requires krb524d to be running with the KDC */
        r = pkrb524_convert_creds_kdc(context, k5creds, &creds);
        pkrb5_free_creds(context, k5creds);
		pkrb5_free_context(context);
        if (r) {
            try_krb5 = 0;
            goto use_krb4;
        }
        rc = KSUCCESS;
    } else
#endif /* NO_KRB5 */
    {
      use_krb4:
	rc = KFAILURE;
    }
    if (rc != KSUCCESS)
    {
            return(rc);
    }

	memset(&aserver, '\0', sizeof(aserver));
    strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
    strncpy(aserver.cell, CellName, MAXKTCNAMELEN - 1);

    memset(&atoken, '\0', sizeof(atoken));
    atoken.kvno = creds.kvno;
    atoken.startTime = creds.issue_date;
    atoken.endTime = (*pkrb_life_to_time)(creds.issue_date,creds.lifetime);
    memcpy(&atoken.sessionKey, creds.session, 8);
    atoken.ticketLen = creds.ticket_st.length;
    memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);

    if (!(rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient)) &&
        atoken.kvno == btoken.kvno &&
        atoken.ticketLen == btoken.ticketLen &&
        !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
        !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
    {
        return(0);
    }

    // * Reset the "aclient" structure before we call ktc_SetToken.
    // * This structure was first set by the ktc_GetToken call when
    // * we were comparing whether identical tokens already existed.

    strncpy(aclient.name, creds.pname, MAXKTCNAMELEN - 1);
    aclient.name[MAXKTCNAMELEN - 1] = '\0';
    if (creds.pinst[0])
    {
        strncat(aclient.name, ".", MAXKTCNAMELEN - 1 - strlen(aclient.name));
        aclient.name[MAXKTCNAMELEN - 1] = '\0';
        strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1 - strlen(aclient.name));
        aclient.name[MAXKTCNAMELEN - 1] = '\0';
    }
    strcpy(aclient.instance, "");

    if ( strcmp(realm_of_cell, creds.realm) )
    {
        strncat(aclient.name, "@", MAXKTCNAMELEN - 1 - strlen(aclient.name));
        aclient.name[MAXKTCNAMELEN - 1] = '\0';
        strncat(aclient.name, creds.realm, MAXKTCNAMELEN - 1 - strlen(aclient.name));
        aclient.name[MAXKTCNAMELEN - 1] = '\0';
    }
    aclient.name[MAXKTCNAMELEN-1] = '\0';

    strcpy(aclient.cell, CellName);

    // * NOTE: On WIN32, the order of SetToken params changed...
    // * to   ktc_SetToken(&aserver, &aclient, &atoken, 0)
    // * from ktc_SetToken(&aserver, &atoken, &aclient, 0) on Unix...
    // * The afscompat ktc_SetToken provides the Unix order

    if (rc = ktc_SetToken(&aserver, &atoken, &aclient, 0))
    {
        Leash_afs_error(rc, "ktc_SetToken()");
        return(rc);
    }

    return(0);
#endif
}