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; }
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 }
int do_ccache(krb5_context ctx, krb5_ccache cache, TICKETINFO ***ticketInfoTail) { krb5_cc_cursor cur; krb5_creds creds; krb5_principal princ = NULL; krb5_flags flags; krb5_error_code code; char *defname = NULL; char *functionName = NULL; TicketList **ticketListTail; TICKETINFO *ticketinfo; flags = 0; /* turns off OPENCLOSE mode */ code = pkrb5_cc_set_flags(ctx, cache, flags); if (code) { functionName = "krb5_cc_set_flags"; goto cleanup; } code = pkrb5_cc_get_principal(ctx, cache, &princ); if (code) { functionName = "krb5_cc_get_principal"; goto cleanup; } code = pkrb5_unparse_name(ctx, princ, &defname); if (code) { functionName = "krb5_unparse_name"; goto cleanup; } code = pkrb5_cc_start_seq_get(ctx, cache, &cur); if (code) { functionName = "krb5_cc_start_seq_get"; goto cleanup; } ticketinfo = calloc(1, sizeof(TICKETINFO)); if (ticketinfo == NULL) { functionName = "calloc"; code = ENOMEM; goto cleanup; } ticketinfo->next = NULL; ticketinfo->ticket_list = NULL; ticketinfo->principal = strdup(defname); if (ticketinfo->principal == NULL) { functionName = "strdup"; code = ENOMEM; goto cleanup; } ticketinfo->ccache_name = strdup(pkrb5_cc_get_name(ctx, cache)); if (ticketinfo->ccache_name == NULL) { functionName = "strdup"; code = ENOMEM; goto cleanup; } **ticketInfoTail = ticketinfo; *ticketInfoTail = &ticketinfo->next; ticketListTail = &ticketinfo->ticket_list; while (!(code = pkrb5_cc_next_cred(ctx, cache, &cur, &creds))) { if (pkrb5_is_config_principal(ctx, creds.server)) continue; CredToTicketList(ctx, creds, defname, &ticketListTail); CredToTicketInfo(creds, ticketinfo); pkrb5_free_cred_contents(ctx, &creds); } if (code == KRB5_CC_END) { code = pkrb5_cc_end_seq_get(ctx, cache, &cur); if (code) { functionName = "krb5_cc_end_seq_get"; goto cleanup; } flags = KRB5_TC_OPENCLOSE; /* turns on OPENCLOSE mode */ code = pkrb5_cc_set_flags(ctx, cache, flags); if (code) { functionName = "krb5_cc_set_flags"; goto cleanup; } } else { functionName = "krb5_cc_next_cred"; goto cleanup; } cleanup: if (code) { Leash_krb5_error(code, functionName, 0, NULL, NULL); } if (princ) pkrb5_free_principal(ctx, princ); if (defname) pkrb5_free_unparsed_name(ctx, defname); return code ? 1 : 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; }