Esempio n. 1
0
void 
khm_cred_end_dialog(khui_new_creds * nc) {
    dialog_sync_init();

    EnterCriticalSection(&cs_dialog);
    if (in_dialog) {
        in_dialog = FALSE;
        SetEvent(in_dialog_evt);
    }
    dialog_result = nc->result;
#ifdef DEBUG
    assert(dialog_nc == nc);
#endif
    dialog_nc = NULL;
    if (nc->subtype == KMSG_CRED_NEW_CREDS &&
        nc->n_identities > 0 &&
        nc->identities[0]) {
        khm_size cb;

        cb = sizeof(dialog_identity);
        if (KHM_FAILED(kcdb_identity_get_name(nc->identities[0],
                                              dialog_identity,
                                              &cb)))
            dialog_identity[0] = 0;
    } else {
        dialog_identity[0] = 0;
    }
    LeaveCriticalSection(&cs_dialog);
}
Esempio n. 2
0
void khm_cred_destroy_identity(khm_handle identity)
{
    khui_action_context * pctx;
    wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
    khm_size cb;

    if (identity == NULL)
        return;

    pctx = PMALLOC(sizeof(*pctx));
#ifdef DEBUG
    assert(pctx);
#endif

    khui_context_create(pctx,
                        KHUI_SCOPE_IDENT,
                        identity,
                        KCDB_CREDTYPE_INVALID,
                        NULL);

    cb = sizeof(idname);
    kcdb_identity_get_name(identity, idname, &cb);

    _begin_task(KHERR_CF_TRANSITIVE);
    _report_sr1(KHERR_NONE, IDS_CTX_DESTROY_ID, _dupstr(idname));
    _describe();

    kmq_post_message(KMSG_CRED,
                     KMSG_CRED_DESTROY_CREDS,
                     0,
                     (void *) pctx);

    _end_task();
}
Esempio n. 3
0
khm_int32
krb4_msg_newcred(khm_int32 msg_type, khm_int32 msg_subtype,
                 khm_ui_4 uparam, void * vparam) {

    switch(msg_subtype) {
    case KMSG_CRED_NEW_CREDS:
        {
            khui_new_creds * nc;
            khui_new_creds_by_type * nct;
            khm_size cbsize;
            wchar_t wbuf[256];

            nc = (khui_new_creds *) vparam;

            nct = PMALLOC(sizeof(*nct));
#ifdef DEBUG
            assert(nct);
#endif
            ZeroMemory(nct, sizeof(*nct));

            nct->type = credtype_id_krb4;
            nct->ordinal = 3;
            LoadString(hResModule, IDS_NC_K4_SHORT,
                       wbuf, ARRAYLENGTH(wbuf));
            StringCbLength(wbuf, sizeof(wbuf), &cbsize);
            cbsize += sizeof(wchar_t);

            nct->name = PMALLOC(cbsize);
            StringCbCopy(nct->name, cbsize, wbuf);

            nct->type_deps[nct->n_type_deps++] = credtype_id_krb5;

            nct->h_module = hResModule;
            nct->dlg_proc = k4_nc_dlg_proc;
            nct->dlg_template = MAKEINTRESOURCE(IDD_NC_KRB4);

            khui_cw_add_type(nc, nct);
        }
        break;

    case KMSG_CRED_RENEW_CREDS:
        {
            khui_new_creds * nc;
            khui_new_creds_by_type * nct;
            khm_size cbsize;
            wchar_t wbuf[256];
            khui_action_context * pctx = NULL;

            nc = (khui_new_creds *) vparam;
            pctx = khui_cw_get_ctx(nc);
            if (!pctx->identity)
                break;

            nct = PMALLOC(sizeof(*nct));
#ifdef DEBUG
            assert(nct);
#endif

            ZeroMemory(nct, sizeof(*nct));

            nct->type = credtype_id_krb4;
            nct->ordinal = 3;
            LoadString(hResModule, IDS_NC_K4_SHORT,
                       wbuf, ARRAYLENGTH(wbuf));
            StringCbLength(wbuf, sizeof(wbuf), &cbsize);
            cbsize += sizeof(wchar_t);

            nct->name = PMALLOC(cbsize);
            StringCbCopy(nct->name, cbsize, wbuf);

            nct->type_deps[nct->n_type_deps++] = credtype_id_krb5;

            khui_cw_add_type(nc, nct);
        }
        break;

    case KMSG_CRED_DIALOG_SETUP:
        break;

    case KMSG_CRED_PROCESS:
        {
            khui_new_creds * nc;
            khui_new_creds_by_type * nct = NULL;
            khm_handle ident = NULL;
            khui_action_context * pctx = NULL;
            k4_dlg_data * d = NULL;
            long code = 0;
            wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
            khm_size cb;
            khm_int32 subtype;

            nc = (khui_new_creds *) vparam;
            if (KHM_FAILED(khui_cw_find_type(nc, credtype_id_krb4, &nct)))
                break;

            subtype = khui_cw_get_subtype(nc);
            if (subtype == KMSG_CRED_NEW_CREDS ||
                subtype == KMSG_CRED_RENEW_CREDS) {
                khm_int32 method;

                if (subtype == KMSG_CRED_NEW_CREDS) {

                    d = (k4_dlg_data *) nct->aux;

                    if (KHM_FAILED(khui_cw_get_primary_id(nc, &ident)))
                        break;

                    if (!d ||
                        khui_cw_get_result(nc) != KHUI_NC_RESULT_PROCESS) {
                        khui_cw_set_response(nc, credtype_id_krb4,
                                             KHUI_NC_RESPONSE_SUCCESS |
                                             KHUI_NC_RESPONSE_EXIT);
                        kcdb_identity_release(ident);
                        break;
                    }

                    if (!d->k4_enabled) {
                        k4_write_identity_data(d);
                        khui_cw_set_response(nc, credtype_id_krb4,
                                             KHUI_NC_RESPONSE_SUCCESS |
                                             KHUI_NC_RESPONSE_EXIT);
                        kcdb_identity_release(ident);
                        break;
                    }

                    method = d->method;

                    cb = sizeof(idname);
                    kcdb_identity_get_name(ident, idname, &cb);
                    _begin_task(0);
                    _report_sr0(KHERR_NONE, IDS_MSG_K4NEW);
                    _resolve();
                    _describe();

                } else if (subtype == KMSG_CRED_RENEW_CREDS) {

                    pctx = khui_cw_get_ctx(nc);

                    if ((pctx->scope == KHUI_SCOPE_IDENT &&
                         pctx->identity != NULL) ||

                        (pctx->scope == KHUI_SCOPE_CREDTYPE &&
                         pctx->cred_type == credtype_id_krb4 &&
                         pctx->identity != NULL) ||

                        (pctx->scope == KHUI_SCOPE_CRED &&
                         pctx->cred_type == credtype_id_krb4 &&
                         pctx->identity != NULL &&
                         pctx->cred != NULL)) {

                        ident = pctx->identity;
                        kcdb_identity_hold(ident);

                        if (!k4_should_identity_get_k4(ident)) {

                            _reportf(L"Kerberos 4 is not enabled for this identity.  Skipping");

                            khui_cw_set_response(nc, credtype_id_krb4,
                                                 KHUI_NC_RESPONSE_FAILED |
                                                 KHUI_NC_RESPONSE_EXIT);
                            kcdb_identity_release(ident);
                            break;
                        }

                    } else {

                        _reportf(L"Kerberos 4 is not within renewal scope. Skipping");

                        khui_cw_set_response(nc, credtype_id_krb4,
                                             KHUI_NC_RESPONSE_FAILED |
                                             KHUI_NC_RESPONSE_EXIT);
                        break;
                    }

                    method = K4_METHOD_K524; /* only k524 is supported
                                                for renewals */

                    _begin_task(0);
                    cb = sizeof(idname);
                    kcdb_identity_get_name(ident, idname, &cb);
                    _report_sr0(KHERR_NONE, IDS_MSG_K4RENEW);
                    _resolve();
                    _describe();
                } else {
                    assert(FALSE);
                    break;
                }

                _progress(0,1);

                if ((method == K4_METHOD_AUTO ||
                     method == K4_METHOD_K524) &&
                    khui_cw_type_succeeded(nc, credtype_id_krb5)) {

                    khm_handle tgt;
                    FILETIME ft_prev;
                    FILETIME ft_new;
                    khm_size cb;

                    _report_cs0(KHERR_INFO, L"Trying K524...");

                    tgt = khm_krb4_find_tgt(NULL, ident);
                    _progress(1,3);

                    if (tgt) {
                        cb = sizeof(ft_prev);
                        if (KHM_FAILED(kcdb_cred_get_attr(tgt,
                                                          KCDB_ATTR_EXPIRE,
                                                          NULL,
                                                          &ft_prev,
                                                          &cb)))
                            ZeroMemory(&ft_prev, sizeof(ft_prev));
                        kcdb_cred_release(tgt);
                    }

                    code = khm_convert524(ident);
                    _progress(2,3);

                    _reportf(L"khm_convert524 returns code %d", code);

                    if (code == 0) {
                        khui_cw_set_response(nc, credtype_id_krb4,
                                             KHUI_NC_RESPONSE_SUCCESS |
                                             KHUI_NC_RESPONSE_EXIT);

                        if (subtype == KMSG_CRED_NEW_CREDS) {
                            assert(d != NULL);

                            k4_write_identity_data(d);

                        } else if (subtype == KMSG_CRED_RENEW_CREDS &&
                                   (pctx->scope == KHUI_SCOPE_CREDTYPE ||
                                    pctx->scope == KHUI_SCOPE_CRED)) {

                            khm_krb4_list_tickets();

                            tgt = khm_krb4_find_tgt(NULL, ident);

                            if (tgt) {
                                cb = sizeof(ft_new);
                                ZeroMemory(&ft_new, sizeof(ft_new));

                                kcdb_cred_get_attr(tgt, KCDB_ATTR_EXPIRE,
                                                   NULL, &ft_new, &cb);

                                kcdb_cred_release(tgt);
                            }

                            if (!tgt ||
                                CompareFileTime(&ft_new, &ft_prev) <= 0) {
                                /* The new TGT wasn't much of an
                                   improvement over what we already
                                   had.  We should go out and try to
                                   renew the identity now. */

                                khui_action_context ctx;

                                _reportf(L"Renewal of Krb4 creds failed to get a longer TGT.  Triggering identity renewal");

                                khui_context_create(&ctx,
                                                    KHUI_SCOPE_IDENT,
                                                    pctx->identity,
                                                    KCDB_CREDTYPE_INVALID,
                                                    NULL);
                                khui_action_trigger(KHUI_ACTION_RENEW_CRED,
                                                    &ctx);

                                khui_context_release(&ctx);
                            }
                        }

                        _progress(1,1);

                        _end_task();
                        if (ident)
                            kcdb_identity_release(ident);
                        break;

                    } else if (method == K4_METHOD_K524) {
                        khui_cw_set_response(nc, credtype_id_krb4,
                                             KHUI_NC_RESPONSE_FAILED |
                                             KHUI_NC_RESPONSE_EXIT);

			if (subtype == KMSG_CRED_RENEW_CREDS &&
			    (pctx->scope == KHUI_SCOPE_CREDTYPE ||
			     pctx->scope == KHUI_SCOPE_CRED)) {
			    /* We were trying to get a new Krb4 TGT
			       for this identity.  Sometimes this
			       fails because of restrictions placed on
			       K524d regarding the lifetime of the
			       issued K4 TGT.  In this case, we
			       trigger a renewal of the identity in
			       the hope that the new K5 TGT will allow
			       us to successfully get a new K4 TGT
			       next time over using the new K5 TGT. */

			    khui_action_context ctx;

                            _reportf(L"Renewal of Krb4 creds failed using k524.  Triggerring identity renewal.");

			    khui_context_create(&ctx,
						KHUI_SCOPE_IDENT,
						pctx->identity,
						KCDB_CREDTYPE_INVALID,
						NULL);

			    khui_action_trigger(KHUI_ACTION_RENEW_CRED,
						&ctx);

			    khui_context_release(&ctx);
			}

                        _progress(1,1);
                        _end_task();

                        if (ident)
                            kcdb_identity_release(ident);
                        break;

                    }
                }

                /* only supported for new credentials */
                if (method == K4_METHOD_AUTO ||
                    method == K4_METHOD_PASSWORD) {

                    khm_size n_prompts = 0;
                    khm_size idx;
                    khm_size cb;
                    wchar_t wpwd[KHUI_MAXCCH_PROMPT_VALUE];
                    char pwd[KHUI_MAXCCH_PROMPT_VALUE];
                    wchar_t widname[KCDB_IDENT_MAXCCH_NAME];
                    char idname[KCDB_IDENT_MAXCCH_NAME];

                    char * aname = NULL;
                    char * inst = NULL;
                    char * realm = NULL;

                    assert(subtype == KMSG_CRED_NEW_CREDS);

                    _report_cs0(KHERR_INFO, L"Trying password ...");

                    code = TRUE; /* just has to be non-zero */

                    khui_cw_get_prompt_count(nc, &n_prompts);

                    if (n_prompts == 0)
                        goto _skip_pwd;

                    for (idx = 0; idx < n_prompts; idx++) {
                        khui_new_creds_prompt * p;

                        if (KHM_FAILED(khui_cw_get_prompt(nc, idx, &p)))
                            continue;

                        if (p->type == KHUI_NCPROMPT_TYPE_PASSWORD)
                            break;
                    }

                    if (idx >= n_prompts) {
                        _reportf(L"Password prompt not found");
                        goto _skip_pwd;
                    }

                    khui_cw_sync_prompt_values(nc);

                    cb = sizeof(wpwd);
                    if (KHM_FAILED(khui_cw_get_prompt_value(nc, idx,
                                                            wpwd,
                                                            &cb))) {
                        _reportf(L"Failed to obtain password value");
                        goto _skip_pwd;
                    }

                    UnicodeStrToAnsi(pwd, sizeof(pwd), wpwd);

                    cb = sizeof(widname);
                    kcdb_identity_get_name(ident,
                                           widname,
                                           &cb);

                    UnicodeStrToAnsi(idname, sizeof(idname), widname);

                    {
                        char * atsign;

                        atsign = strchr(idname, '@');
                        if (atsign == NULL) {
                            _reportf(L"Identity name does not contain an '@'");
                            goto _skip_pwd;
                        }

                        *atsign++ = 0;

                        realm = atsign;
                    }

                    {
                        char * slash;

                        slash = strchr(idname, '/');
                        if (slash != NULL) {
                            *slash++ = 0;
                            inst = slash;
                        } else {
                            inst = "";
                        }
                    }

                    aname = idname;

                    code = khm_krb4_kinit(aname, inst, realm,
                                          (long) d->lifetime, pwd);

                    _progress(2,3);

                    _reportf(L"khm_krb4_kinit returns code %d", code);

                _skip_pwd:

                    if (code) {
                        khui_cw_set_response(nc, credtype_id_krb4,
                                             KHUI_NC_RESPONSE_EXIT |
                                             KHUI_NC_RESPONSE_FAILED);

                    } else {
                        khui_cw_set_response(nc, credtype_id_krb4,
                                             KHUI_NC_RESPONSE_EXIT |
                                             KHUI_NC_RESPONSE_SUCCESS);

                        if (subtype == KMSG_CRED_NEW_CREDS) {

                            assert(d != NULL);
                            k4_write_identity_data(d);

                        }
                    }
                }

                _progress(1,1);

                _end_task();
            }

            if (ident)
                kcdb_identity_release(ident);
        }
        break;

    case KMSG_CRED_END:
        {
            khui_new_creds * nc;
            khui_new_creds_by_type * nct = NULL;

            nc = (khui_new_creds *) vparam;
            if (KHM_FAILED(khui_cw_find_type(nc, credtype_id_krb4, &nct)))
                break;

            khui_cw_del_type(nc, credtype_id_krb4);

            if (nct->name)
                PFREE(nct->name);

            if (nct->credtext)
                PFREE(nct->credtext);

            PFREE(nct);
        }
        break;
    }

    return KHM_ERROR_SUCCESS;
}
Esempio n. 4
0
/* dialog box procedure for the "Add new identity" dialog */
INT_PTR CALLBACK
khm_cfg_add_ident_proc(HWND hwnd,
                       UINT umsg,
                       WPARAM wParam,
                       LPARAM lParam) {
    add_ident_data * d;

    switch(umsg) {
    case WM_INITDIALOG:
        /* we create a new credentials blob and pull in the identity
           selectors from the identity provider. */
        d = PMALLOC(sizeof(*d));
        ZeroMemory(d, sizeof(*d));

        khui_cw_create_cred_blob(&d->nc);
#ifdef DEBUG
        assert(d->nc != NULL);
#endif
        if (d->nc == NULL) {
            PFREE(d);
            break;
        }

        if (KHM_FAILED(kcdb_identpro_get_ui_cb(&d->nc->ident_cb))) {
            /* this should have worked.  The only reason it would fail
               is if there is no identity provider or if the identity
               provider does not support providing idnetity
               selectors. */
            khui_cw_destroy_cred_blob(d->nc);
            PFREE(d);
            break;
        }

#pragma warning(push)
#pragma warning(disable: 4244)
        SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
#pragma warning(pop)

        /* get metrics for dynamic controls */
        get_ctrl_row_metrics(&d->dim_small,
                             GetDlgItem(hwnd, IDC_SM_LBL),
                             GetDlgItem(hwnd, IDC_SM_CTL));
        get_ctrl_row_metrics(&d->dim_medium,
                             GetDlgItem(hwnd, IDC_MED_LBL),
                             GetDlgItem(hwnd, IDC_MED_CTL));
        get_ctrl_row_metrics(&d->dim_large,
                             GetDlgItem(hwnd, IDC_LG_LBL),
                             GetDlgItem(hwnd, IDC_LG_CTL));

        {
            RECT rlbl;
            RECT rctl;
            RECT rwnd;

            GetWindowRect(GetDlgItem(hwnd, IDC_SM_LBL),
                          &rlbl);
            GetWindowRect(GetDlgItem(hwnd, IDC_SM_CTL),
                          &rctl);
            GetWindowRect(hwnd, &rwnd);

            OffsetRect(&rlbl, -rwnd.left, -rwnd.top);
            OffsetRect(&rctl, -rwnd.left, -rwnd.top);

            d->current_x = rlbl.left;
            d->current_y = rctl.top - GetSystemMetrics(SM_CYCAPTION);

            GetWindowRect(GetDlgItem(hwnd, IDC_MED_CTL),
                          &rlbl);
            OffsetRect(&rlbl, -rwnd.left, -rwnd.top);

            d->row_gap = rlbl.top - rctl.bottom;
        }

        d->nc->hwnd = hwnd;

        /* now call the UI callback and make it create the
           controls. */
        d->nc->ident_cb(d->nc, WMNC_IDENT_INIT, NULL, 0, 0,
                        (LPARAM) hwnd);

        break;

    case WM_DESTROY:
        d = (add_ident_data *)(LONG_PTR)
            GetWindowLongPtr(hwnd, DWLP_USER);
        if (d == NULL)
            break;

        d->nc->ident_cb(d->nc, WMNC_IDENT_EXIT, NULL, 0, 0, 0);

        khui_cw_destroy_cred_blob(d->nc);
        PFREE(d);
        break;

    case KHUI_WM_NC_NOTIFY:
        d = (add_ident_data *)(LONG_PTR)
            GetWindowLongPtr(hwnd, DWLP_USER);

        switch(HIWORD(wParam)) {
        case WMNC_ADD_CONTROL_ROW:
            {
                khui_control_row * row;
                RECT r_lbl, r_inp, r_enc;
                struct ctrl_row_dimensions * dim;
                HFONT hf;

                row = (khui_control_row *) lParam;

#ifdef DEBUG
                assert(row->label);
                assert(row->input);
                assert(d);
#endif

                if (row->size == KHUI_CTRLSIZE_SMALL) {
                    dim = &d->dim_small;
                } else if (row->size == KHUI_CTRLSIZE_HALF) {
                    dim = &d->dim_medium;
                } else {
                    dim = &d->dim_large;
#ifdef DEBUG
                    assert(row->size == KHUI_CTRLSIZE_FULL);
#endif
                }

                CopyRect(&r_enc, &dim->enclosure);
                CopyRect(&r_lbl, &dim->label);
                CopyRect(&r_inp, &dim->control);

                OffsetRect(&r_enc, d->current_x, d->current_y);
                OffsetRect(&r_lbl, r_enc.left, r_enc.top);
                OffsetRect(&r_inp, r_enc.left, r_enc.top);

                d->current_y += r_enc.bottom - r_enc.top;

                hf = (HFONT) SendDlgItemMessage(hwnd, IDOK, WM_GETFONT, 0, 0);

                if (row->label) {
                    SetWindowPos(row->label,
                                 ((d->hwnd_last_ctrl != NULL)?
                                  d->hwnd_last_ctrl :
                                  HWND_TOP),
                                 r_lbl.left, r_lbl.top,
                                 r_lbl.right - r_lbl.left,
                                 r_lbl.bottom - r_lbl.top,
                                 SWP_DEFERERASE | SWP_NOACTIVATE |
                                 SWP_NOOWNERZORDER);
                    if (hf)
                        SendMessage(row->label, WM_SETFONT,
                                    (WPARAM) hf,
                                    TRUE);
                    d->hwnd_last_ctrl = row->label;
                }

                if (row->input) {
                    SetWindowPos(row->input,
                                 ((d->hwnd_last_ctrl != NULL)?
                                  d->hwnd_last_ctrl :
                                  HWND_TOP),
                                 r_inp.left, r_inp.top,
                                 r_inp.right - r_inp.left,
                                 r_inp.bottom - r_inp.top,
                                 SWP_DEFERERASE | SWP_NOACTIVATE |
                                 SWP_NOOWNERZORDER);
                    if (hf)
                        SendMessage(row->input, WM_SETFONT,
                                    (WPARAM) hf,
                                    TRUE);
                    d->hwnd_last_ctrl = row->input;
                }
            }
            break;

        case WMNC_IDENTITY_CHANGE:
            break;
        }
        return TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK) {
            wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
            wchar_t err_msg[1024];
            khm_handle ident = NULL;
            khm_handle csp_ident = NULL;
            khm_size cb;
            khm_int32 rv = KHM_ERROR_SUCCESS;

            d = (add_ident_data *)(LONG_PTR)
                GetWindowLongPtr(hwnd, DWLP_USER);

            if (!d || !d->nc)
                break;

            /* check if there was an identity selected */
            if (d->nc->n_identities == 0 ||
                d->nc->identities[0] == NULL) {

                StringCbCopy(idname, sizeof(idname), L"");

                LoadString(khm_hInstance, IDS_CFG_IDNAME_NON,
                           err_msg, ARRAYLENGTH(err_msg));

                goto show_failure;
            }

            ident = d->nc->identities[0];
            kcdb_identity_hold(ident);

            cb = sizeof(idname);
            kcdb_identity_get_name(ident, idname, &cb);

            /* now we have to create the identity configuration. */
            if (KHM_FAILED(rv = kcdb_identity_get_config(ident,
                                                         KHM_FLAG_CREATE,
                                                         &csp_ident))) {
                wchar_t fmt[256];

                LoadString(khm_hInstance, IDS_CFG_IDNAME_CCC,
                           fmt, ARRAYLENGTH(fmt));
                StringCbPrintf(err_msg, sizeof(err_msg), fmt, rv);

                kcdb_identity_release(ident);

                goto show_failure;
            }

            /* create a value so that the configuration space will
               actually be created in the registry.  We don't want
               this new identity to be sticky. */
            khc_write_int32(csp_ident, L"Sticky", 0);

            khm_refresh_config();

            kcdb_identity_release(ident);
            khc_close_space(csp_ident);

            EndDialog(hwnd, 0);
            break;

        show_failure:
            {
                wchar_t title[512];
                wchar_t fmt[256];

                if (!err_msg[0])
                    break;

                LoadString(khm_hInstance, IDS_CFG_IDNAME_PRB,
                           fmt, ARRAYLENGTH(fmt));
                StringCbPrintf(title, sizeof(title), fmt, idname);

                MessageBox(hwnd, err_msg, title, MB_OK | MB_ICONSTOP);

                /* don't end the dialog yet */
                break;
            }
            break;
            
        } else if (LOWORD(wParam) == IDCANCEL) {
            EndDialog(hwnd, 1);
        } else {
            d = (add_ident_data *)(LONG_PTR)
                GetWindowLongPtr(hwnd, DWLP_USER);

            if (d && d->nc && d->nc->ident_cb) {
                return d->nc->ident_cb(d->nc, WMNC_IDENT_WMSG,
                                       hwnd, umsg, wParam, lParam);
            }
        }
        break;
    }

    return FALSE;
}
Esempio n. 5
0
k5_kinit_task *
k5_kinit_task_create(khui_new_creds * nc)
{
    k5_kinit_task * kt;
    k5_dlg_data   * d;

    wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
    khm_size cbbuf;

    LPNETID_DLGINFO pdlginfo;
    khui_action_context * pctx = NULL;

    khm_handle hsub = NULL;

    khui_cw_find_type(nc, credtype_id_krb5, (khui_new_creds_by_type **) &d);
    if (!d)
	return NULL;

    kt = (k5_kinit_task *) PMALLOC(sizeof(*kt));
    memset(kt, 0, sizeof(*kt));
    kt->magic = K5_KINIT_TASK_MAGIC;
    kt->nc = nc;
    kt->dlg_data = d;
    kt->nct = &d->nct;
    kt->context = 0;

    khui_cw_get_primary_id(nc, &kt->identity);
    cbbuf = sizeof(idname);
    kcdb_identity_get_name(kt->identity, idname, &cbbuf);
    cbbuf = (cbbuf * sizeof(char)) / sizeof(wchar_t);

    kt->principal = PMALLOC(cbbuf);
    UnicodeStrToAnsi(kt->principal, cbbuf, idname);
    kt->password = NULL;
    kt->params = d->params;
    kt->params.lifetime = (krb5_deltat) d->tc_lifetime.current;
    kt->params.renew_life = (krb5_deltat) d->tc_renew.current;

    /* if we have external parameters, we should use them as well */
    pctx = khui_cw_get_ctx(nc);
    if (pctx && pctx->cb_vparam == sizeof(NETID_DLGINFO) &&
        (pdlginfo = pctx->vparam) != NULL &&
        pdlginfo->size == NETID_DLGINFO_V1_SZ) {

        wchar_t * t;
        size_t size;

        if (pdlginfo->in.ccache[0] &&
            SUCCEEDED(StringCchLength(pdlginfo->in.ccache,
                                      NETID_CCACHE_NAME_SZ,
                                      &size))) {
            kt->ccache = PMALLOC(sizeof(char) * (size + 1));
            UnicodeStrToAnsi(kt->ccache, size + 1,
                             pdlginfo->in.ccache);

            /* this is the same as the output cache */

            StringCbCopy(pdlginfo->out.ccache, sizeof(pdlginfo->out.ccache),
                         pdlginfo->in.ccache);
        } else {
            wchar_t ccache[KRB5_MAXCCH_CCNAME];

            size = sizeof(ccache);

            khm_krb5_get_identity_default_ccache(kt->identity, ccache, &size);

            StringCbCopy(pdlginfo->out.ccache, sizeof(pdlginfo->out.ccache),
                         ccache);
        }

        t = khm_get_realm_from_princ(idname);

        if (t) {
            StringCbCopy(pdlginfo->out.realm,
                         sizeof(pdlginfo->out.realm),
                         t);

            if ((t - idname) > 1) {
                StringCchCopyN(pdlginfo->out.username,
                               ARRAYLENGTH(pdlginfo->out.username),
                               idname,
                               (t - idname) - 1);
            } else {
                StringCbCopy(pdlginfo->out.username,
                             sizeof(pdlginfo->out.username),
                             L"");
            }
        } else {
            StringCbCopy(pdlginfo->out.username,
                         sizeof(pdlginfo->out.username),
                         idname);
            StringCbCopy(pdlginfo->out.realm,
                         sizeof(pdlginfo->out.realm),
                         L"");
        }
    }

    kt->state = K5_KINIT_STATE_PREP;
    InitializeCriticalSection(&kt->cs);
    kt->h_task_wait = CreateEvent(NULL, FALSE, FALSE, NULL);
    kt->h_parent_wait = CreateEvent(NULL, FALSE, FALSE, NULL);

    kt->refcount = 2;           /* One hold for the caller, one hold
                                   for the thread */

    kmq_create_subscription(k5_msg_callback, &hsub);

    kt->task = task_create(NULL, 32 * 4096, kinit_task_proc, kt, hsub, 0);

    return kt;
}
Esempio n. 6
0
void k4_handle_wmnc_notify(k4_dlg_data * d,
                           WPARAM wParam,
                           LPARAM lParam) {
    switch(HIWORD(wParam)) {
    case WMNC_UPDATE_CREDTEXT:
        {
            if (d->nct->credtext) {
                PFREE(d->nct->credtext);
                d->nct->credtext = NULL;
            }

            if (d->nc->n_identities > 0 &&
                d->nc->identities[0]) {

                khm_int32 flags = 0;
                wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
                wchar_t * atsign;
                wchar_t * realm;
                khm_size cb;

                kcdb_identity_get_flags(d->nc->identities[0], &flags);

                if (!(flags & KCDB_IDENT_FLAG_VALID)) {
                    break;
                }

                cb = sizeof(idname);
                kcdb_identity_get_name(d->nc->identities[0], idname,
                                       &cb);

                atsign = wcsrchr(idname, L'@');

                if (atsign == NULL || !atsign[1])
                    break;

                realm = ++atsign;

                if (d->k4_enabled) {
                    wchar_t wmethod[128];
                    wchar_t wfmt[128];
                    wchar_t wct[512];

                    LoadString(hResModule, IDS_CT_TGTFOR,
                               wfmt, ARRAYLENGTH(wfmt));

                    if (d->method == K4_METHOD_AUTO)
                        LoadString(hResModule, IDS_METHOD_AUTO, wmethod,
                                   ARRAYLENGTH(wmethod));
                    else if (d->method == K4_METHOD_PASSWORD)
                        LoadString(hResModule, IDS_METHOD_PWD, wmethod,
                                   ARRAYLENGTH(wmethod));
                    else if (d->method == K4_METHOD_K524)
                        LoadString(hResModule, IDS_METHOD_K524, wmethod,
                                   ARRAYLENGTH(wmethod));
                    else {
                        assert(FALSE);
                    }

                    StringCbPrintf(wct, sizeof(wct), wfmt, realm, wmethod);

                    StringCbLength(wct, sizeof(wct), &cb);
                    cb += sizeof(wchar_t);

                    d->nct->credtext = PMALLOC(cb);

                    StringCbCopy(d->nct->credtext, cb, wct);
                } else {
                    wchar_t wct[256];

                    LoadString(hResModule, IDS_CT_DISABLED,
                               wct, ARRAYLENGTH(wct));

                    StringCbLength(wct, sizeof(wct), &cb);
                    cb += sizeof(wchar_t);

                    d->nct->credtext = PMALLOC(cb);

                    StringCbCopy(d->nct->credtext, cb, wct);
                }
            }
            /* no identities were selected.  it is not the
               responsibility of krb4 to complain about this. */
        }
        break;

    case WMNC_IDENTITY_CHANGE:
        k4_read_identity_data(d);
        k4_update_display(d, TRUE);
        break;

    case WMNC_CREDTEXT_LINK:
        {
            wchar_t wid[KHUI_MAXCCH_HTLINK_FIELD];
            wchar_t * wids;
            khui_htwnd_link * l;

            l = (khui_htwnd_link *) lParam;

            StringCchCopyN(wid, ARRAYLENGTH(wid), l->id, l->id_len);
            wids = wcschr(wid, L':');

            if (!wids)
                break;
            else
                wids++;

            if (!wcscmp(wids, L"Enable")) {
                d->k4_enabled = TRUE;

                k4_update_display(d, TRUE);
                khui_cw_enable_type(d->nc, credtype_id_krb4, TRUE);
            }
        }
        break;
    }
}
Esempio n. 7
0
/* Completion handler for KMSG_CRED messages.  We control the overall
   logic of credentials acquisition and other operations here.  Once a
   credentials operation is triggered, each successive message
   completion notification will be used to dispatch the messages for
   the next step in processing the operation. */
void KHMAPI 
kmsg_cred_completion(kmq_message *m)
{
    khui_new_creds * nc;

#ifdef DEBUG
    assert(m->type == KMSG_CRED);
#else
    if(m->type != KMSG_CRED)
        return; /* huh? */
#endif

    switch(m->subtype) {
    case KMSG_CRED_PASSWORD:
        /* fallthrough */
    case KMSG_CRED_NEW_CREDS:
        /* Cred types have attached themselves.  Trigger the next
           phase. */
        kmq_post_message(KMSG_CRED, KMSG_CRED_DIALOG_SETUP, 0, 
                         m->vparam);
        break;

    case KMSG_CRED_RENEW_CREDS:
        nc = (khui_new_creds *) m->vparam;

        /* khm_cred_dispatch_process_message() deals with the case
           where there are no credential types that wants to
           participate in this operation. */
        khm_cred_dispatch_process_message(nc);
        break;

    case KMSG_CRED_DIALOG_SETUP:
        nc = (khui_new_creds *) m->vparam;

        khm_prep_newcredwnd(nc->hwnd);
            
        /* all the controls have been created.  Now initialize them */
        if (nc->n_types > 0) {
            kmq_post_subs_msg(nc->type_subs, 
                              nc->n_types, 
                              KMSG_CRED, 
                              KMSG_CRED_DIALOG_PRESTART, 
                              0, 
                              m->vparam);
        } else {
            PostMessage(nc->hwnd, KHUI_WM_NC_NOTIFY, 
                        MAKEWPARAM(0, WMNC_DIALOG_PROCESS_COMPLETE), 0);
        }
        break;

    case KMSG_CRED_DIALOG_PRESTART:
        /* all prestart stuff is done.  Now to activate the dialog */
        nc = (khui_new_creds *) m->vparam;
        khm_show_newcredwnd(nc->hwnd);
        
        kmq_post_subs_msg(nc->type_subs,
                          nc->n_types,
                          KMSG_CRED, 
                          KMSG_CRED_DIALOG_START, 
                          0, 
                          m->vparam);
        /* at this point, the dialog window takes over.  We let it run
           the show until KMSG_CRED_DIALOG_END is posted by the dialog
           procedure. */
        break;

    case KMSG_CRED_PROCESS:
        /* a wave of these messages have completed.  We should check
           if there's more */
        nc = (khui_new_creds *) m->vparam;

        /* if we are done processing all the plug-ins, then check if
           there were any errors reported.  Otherwise we dispatch
           another set of messages. */
        if(!khm_cred_dispatch_process_level(nc)) {

            if(kherr_is_error()) {
                khui_alert * alert;
                kherr_event * evt;
                kherr_context * ctx;
                wchar_t ws_tfmt[512];
                wchar_t w_idname[KCDB_IDENT_MAXCCH_NAME];
                wchar_t ws_title[ARRAYLENGTH(ws_tfmt) + KCDB_IDENT_MAXCCH_NAME];
                khm_size cb;

                /* For renewals, we suppress the error message for the
                   following case:

                   - The renewal was for an identity

                   - There are no identity credentials for the
                     identity (no credentials that have the same type
                     as the identity provider). */

                if (nc->subtype == KMSG_CRED_RENEW_CREDS &&
                    nc->ctx.scope == KHUI_SCOPE_IDENT &&
                    nc->ctx.identity != NULL) {
                    khm_handle tcs = NULL; /* credential set */
                    khm_size count = 0;
                    khm_int32 id_ctype = KCDB_CREDTYPE_INVALID;
                    khm_int32 delta = 0;

                    kcdb_identity_get_type(&id_ctype);
                    kcdb_credset_create(&tcs);
                    kcdb_credset_collect(tcs, NULL,
                                         nc->ctx.identity,
                                         id_ctype,
                                         &delta);
                    kcdb_credset_get_size(tcs, &count);
                    kcdb_credset_delete(tcs);

                    if (count == 0) {
                        goto done_with_op;
                    }
                }

                ctx = kherr_peek_context();
                evt = kherr_get_err_event(ctx);
                kherr_evaluate_event(evt);

                khui_alert_create_empty(&alert);

                if (nc->subtype == KMSG_CRED_NEW_CREDS) {

                    khui_alert_set_type(alert, KHUI_ALERTTYPE_ACQUIREFAIL);

                    cb = sizeof(w_idname);
                    if (nc->n_identities == 0 ||
                        KHM_FAILED(kcdb_identity_get_name(nc->identities[0],
                                                          w_idname, &cb))) {
                        /* an identity could not be determined */
                        LoadString(khm_hInstance, IDS_NC_FAILED_TITLE,
                                   ws_title, ARRAYLENGTH(ws_title));
                    } else {
                        LoadString(khm_hInstance, IDS_NC_FAILED_TITLE_I,
                                   ws_tfmt, ARRAYLENGTH(ws_tfmt));
                        StringCbPrintf(ws_title, sizeof(ws_title),
                                       ws_tfmt, w_idname);
                        khui_alert_set_ctx(alert,
                                           KHUI_SCOPE_IDENT,
                                           nc->identities[0],
                                           KCDB_CREDTYPE_INVALID,
                                           NULL);
                    }

                } else if (nc->subtype == KMSG_CRED_PASSWORD) {

                    khui_alert_set_type(alert, KHUI_ALERTTYPE_CHPW);

                    cb = sizeof(w_idname);
                    if (nc->n_identities == 0 ||
                        KHM_FAILED(kcdb_identity_get_name(nc->identities[0],
                                                          w_idname, &cb))) {
                        LoadString(khm_hInstance, IDS_NC_PWD_FAILED_TITLE,
                                   ws_title, ARRAYLENGTH(ws_title));
                    } else {
                        LoadString(khm_hInstance, IDS_NC_PWD_FAILED_TITLE_I,
                                   ws_tfmt, ARRAYLENGTH(ws_tfmt));
                        StringCbPrintf(ws_title, sizeof(ws_title),
                                       ws_tfmt, w_idname);
                        khui_alert_set_ctx(alert,
                                           KHUI_SCOPE_IDENT,
                                           nc->identities[0],
                                           KCDB_CREDTYPE_INVALID,
                                           NULL);
                    }

                } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) {

                    khui_alert_set_type(alert, KHUI_ALERTTYPE_RENEWFAIL);

                    cb = sizeof(w_idname);
                    if (nc->ctx.identity == NULL ||
                        KHM_FAILED(kcdb_identity_get_name(nc->ctx.identity,
                                                          w_idname, &cb))) {
                        LoadString(khm_hInstance, IDS_NC_REN_FAILED_TITLE,
                                   ws_title, ARRAYLENGTH(ws_title));
                    } else {
                        LoadString(khm_hInstance, IDS_NC_REN_FAILED_TITLE_I,
                                   ws_tfmt, ARRAYLENGTH(ws_tfmt));
                        StringCbPrintf(ws_title, sizeof(ws_title),
                                       ws_tfmt, w_idname);
                        khui_alert_set_ctx(alert,
                                           KHUI_SCOPE_IDENT,
                                           nc->ctx.identity,
                                           KCDB_CREDTYPE_INVALID,
                                           NULL);
                    }

                } else {
#ifdef DEBUG
                    assert(FALSE);
#endif
                }

                khui_alert_set_title(alert, ws_title);
                khui_alert_set_severity(alert, evt->severity);

                if(!evt->long_desc)
                    khui_alert_set_message(alert, evt->short_desc);
                else
                    khui_alert_set_message(alert, evt->long_desc);

                if(evt->suggestion)
                    khui_alert_set_suggestion(alert, evt->suggestion);

                if (nc->subtype == KMSG_CRED_RENEW_CREDS &&
                    nc->ctx.identity != NULL) {

                    khm_int32 n_cmd;

                    n_cmd = khm_get_identity_new_creds_action(nc->ctx.identity);

                    if (n_cmd != 0) {
                        khui_alert_add_command(alert, n_cmd);
                        khui_alert_add_command(alert, KHUI_PACTION_CLOSE);

                        khui_alert_set_flags(alert, KHUI_ALERT_FLAG_DISPATCH_CMD,
                                             KHUI_ALERT_FLAG_DISPATCH_CMD);
                    }
                }

                khui_alert_show(alert);
                khui_alert_release(alert);

                kherr_release_context(ctx);

                kherr_clear_error();
            }

        done_with_op:

            if (nc->subtype == KMSG_CRED_RENEW_CREDS) {
                kmq_post_message(KMSG_CRED, KMSG_CRED_END, 0, 
                                 m->vparam);
            } else {
                PostMessage(nc->hwnd, KHUI_WM_NC_NOTIFY, 
                            MAKEWPARAM(0, WMNC_DIALOG_PROCESS_COMPLETE),
                            0);
            }
        }
        break;

    case KMSG_CRED_END:
        /* all is done. */
        {
            khui_new_creds * nc;
            khm_boolean continue_cmdline = TRUE;

            nc = (khui_new_creds *) m->vparam;

            if (nc->subtype == KMSG_CRED_NEW_CREDS ||
                nc->subtype == KMSG_CRED_PASSWORD) {

                khm_cred_end_dialog(nc);

            } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) {

                /* if this is a renewal that was triggered while we
                   were processing the commandline, then we need to
                   update the pending renewal count. */

                if (khm_startup.processing) {
                    LONG renewals;
                    renewals = InterlockedDecrement(&khm_startup.pending_renewals);

                    if (renewals != 0) {
                        continue_cmdline = FALSE;
                    }
                }
            }

            khui_cw_destroy_cred_blob(nc);

            kmq_post_message(KMSG_CRED, KMSG_CRED_REFRESH, 0, 0);

            if (continue_cmdline)
                kmq_post_message(KMSG_ACT, KMSG_ACT_CONTINUE_CMDLINE, 0, 0);
        }
        break;

        /* property sheet stuff */

    case KMSG_CRED_PP_BEGIN:
        /* all the pages should have been added by now.  Just send out
           the precreate message */
        kmq_post_message(KMSG_CRED, KMSG_CRED_PP_PRECREATE, 0, 
                         m->vparam);
        break;

    case KMSG_CRED_PP_END:
        kmq_post_message(KMSG_CRED, KMSG_CRED_PP_DESTROY, 0, 
                         m->vparam);
        break;

    case KMSG_CRED_DESTROY_CREDS:
#ifdef DEBUG
        assert(m->vparam != NULL);
#endif
        khui_context_release((khui_action_context *) m->vparam);
        PFREE(m->vparam);

        kmq_post_message(KMSG_CRED, KMSG_CRED_REFRESH, 0, 0);

        kmq_post_message(KMSG_ACT, KMSG_ACT_CONTINUE_CMDLINE, 0, 0);
        break;

    case KMSG_CRED_IMPORT:
        {
            khm_boolean continue_cmdline = FALSE;
            LONG pending_renewals;

            /* once an import operation ends, we have to trigger a
               renewal so that other plug-ins that didn't participate
               in the import operation can have a chance at getting
               the necessary credentials.

               If we are in the middle of processing the commandline,
               we have to be a little bit careful.  We can't issue a
               commandline conituation message right now because the
               import action is still ongoing (since the renewals are
               part of the action).  Once the renewals have completed,
               the completion handler will automatically issue a
               commandline continuation message.  However, if there
               were no identities to renew, then we have to issue the
               message ourselves.
            */

            InterlockedIncrement(&khm_startup.pending_renewals);

            khm_cred_renew_all_identities();

            pending_renewals = InterlockedDecrement(&khm_startup.pending_renewals);

            if (pending_renewals == 0 && khm_startup.processing)
                kmq_post_message(KMSG_ACT, KMSG_ACT_CONTINUE_CMDLINE, 0, 0);
        }
        break;

    case KMSG_CRED_REFRESH:
        kcdb_identity_refresh_all();
        break;
    }
}
Esempio n. 8
0
void 
khm_cred_dispatch_process_message(khui_new_creds *nc)
{
    khm_size i;
    BOOL pending;
    wchar_t wsinsert[512];
    khm_size cbsize;

    /* see if there's anything to do.  We can check this without
       obtaining a lock */
    if(nc->n_types == 0 ||
       (nc->subtype == KMSG_CRED_NEW_CREDS &&
        nc->n_identities == 0) ||
       (nc->subtype == KMSG_CRED_PASSWORD &&
        nc->n_identities == 0))
        goto _terminate_job;

    /* check dependencies and stuff first */
    EnterCriticalSection(&nc->cs);
    for(i=0; i<nc->n_types; i++) {
        nc->types[i]->flags &= ~ KHUI_NCT_FLAG_PROCESSED;
    }
    LeaveCriticalSection(&nc->cs);

    /* Consindering all that can go wrong here and the desire to
       handle errors here separately from others, we create a new task
       for the purpose of tracking the credentials acquisition
       process. */
    _begin_task(KHERR_CF_TRANSITIVE);

    /* Describe the context */
    if(nc->subtype == KMSG_CRED_NEW_CREDS) {
        cbsize = sizeof(wsinsert);
        kcdb_identity_get_name(nc->identities[0], wsinsert, &cbsize);

        _report_sr1(KHERR_NONE,  IDS_CTX_PROC_NEW_CREDS,
                    _cstr(wsinsert));
        _resolve();
    } else if (nc->subtype == KMSG_CRED_RENEW_CREDS) {
        cbsize = sizeof(wsinsert);

        if (nc->ctx.scope == KHUI_SCOPE_IDENT)
            kcdb_identity_get_name(nc->ctx.identity, wsinsert, &cbsize);
        else if (nc->ctx.scope == KHUI_SCOPE_CREDTYPE) {
            if (nc->ctx.identity != NULL)
                kcdb_identity_get_name(nc->ctx.identity, wsinsert, 
                                       &cbsize);
            else
                kcdb_credtype_get_name(nc->ctx.cred_type, wsinsert,
                                       &cbsize);
        } else if (nc->ctx.scope == KHUI_SCOPE_CRED) {
            kcdb_cred_get_name(nc->ctx.cred, wsinsert, &cbsize);
        } else {
            StringCbCopy(wsinsert, sizeof(wsinsert), L"(?)");
        }

        _report_sr1(KHERR_NONE, IDS_CTX_PROC_RENEW_CREDS, 
                    _cstr(wsinsert));
        _resolve();
    } else if (nc->subtype == KMSG_CRED_PASSWORD) {
        cbsize = sizeof(wsinsert);
        kcdb_identity_get_name(nc->identities[0], wsinsert, &cbsize);

        _report_sr1(KHERR_NONE, IDS_CTX_PROC_PASSWORD,
                    _cstr(wsinsert));
        _resolve();
    } else {
        assert(FALSE);
    }

    _describe();

    pending = khm_cred_dispatch_process_level(nc);

    _end_task();

    if(!pending)
        goto _terminate_job;

    return;

 _terminate_job:
    if (nc->subtype == KMSG_CRED_RENEW_CREDS)
        kmq_post_message(KMSG_CRED, KMSG_CRED_END, 0, (void *) nc);
    else
        PostMessage(nc->hwnd, KHUI_WM_NC_NOTIFY, 
                    MAKEWPARAM(0, WMNC_DIALOG_PROCESS_COMPLETE), 0);
}
Esempio n. 9
0
khm_int32 KHMAPI
khm_get_identity_expiration_time(krb5_context ctx, krb5_ccache cc, 
                                 khm_handle ident, 
                                 krb5_timestamp * pexpiration)
{
    krb5_principal principal = 0;
    char * princ_name = NULL;
    krb5_creds creds;
    krb5_error_code code;
    krb5_error_code cc_code;
    krb5_cc_cursor cur;
    krb5_timestamp now, expiration = 0;

    wchar_t w_ident_name[KCDB_IDENT_MAXCCH_NAME];
    char    ident_name[KCDB_IDENT_MAXCCH_NAME];
    khm_size cb;

    khm_int32 rv = KHM_ERROR_NOT_FOUND;

    if (!ctx || !cc || !ident || !pexpiration)
        return KHM_ERROR_GENERAL;

    code = pkrb5_cc_get_principal(ctx, cc, &principal);

    if ( code )
        return KHM_ERROR_INVALID_PARAM;

    cb = sizeof(w_ident_name);
    kcdb_identity_get_name(ident, w_ident_name, &cb);
    UnicodeStrToAnsi(ident_name, sizeof(ident_name), w_ident_name);

    code = pkrb5_unparse_name(ctx, principal, &princ_name);

    /* compare principal to ident. */

    if ( code || !princ_name ||
         strcmp(princ_name, ident_name) ) {
        if (princ_name)
            pkrb5_free_unparsed_name(ctx, princ_name);
        pkrb5_free_principal(ctx, principal);
        return KHM_ERROR_UNKNOWN;
    }

    pkrb5_free_unparsed_name(ctx, princ_name);
    pkrb5_free_principal(ctx, principal);

    code = pkrb5_timeofday(ctx, &now);

    if (code)
        return KHM_ERROR_UNKNOWN;

    cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);

    while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
        krb5_data * c0 = krb5_princ_name(ctx, creds.server);
        krb5_data * c1  = krb5_princ_component(ctx, creds.server, 1);
        krb5_data * r = krb5_princ_realm(ctx, creds.server);

        if ( c0 && c1 && r && c1->length == r->length && 
             !strncmp(c1->data,r->data,r->length) &&
             !strncmp("krbtgt",c0->data,c0->length) ) {

            /* we have a TGT, check for the expiration time.
             * if it is valid and renewable, use the renew time 
             */

            if (!(creds.ticket_flags & TKT_FLG_INVALID) &&
                creds.times.starttime < (now + TIMET_TOLERANCE) && 
                (creds.times.endtime + TIMET_TOLERANCE) > now) {
                expiration = creds.times.endtime;

                if ((creds.ticket_flags & TKT_FLG_RENEWABLE) && 
                    (creds.times.renew_till > creds.times.endtime)) {
                    expiration = creds.times.renew_till;
                }
            }
        }
    }

    if (cc_code == KRB5_CC_END) {
        cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
        rv = KHM_ERROR_SUCCESS;
        *pexpiration = expiration;
    }

    return rv;
}