static int kvno5(krb5_context ctx, const char *host, int socktype, krb5_principal princ, krb5_principal sprinc, krb5_ccache ccache) { krb5_error_code kerr = 0; krb5_creds increds; krb5_creds *outcreds = NULL; krb5_ticket *ticket = NULL; VERBOSE(1, (stderr, "initiating kvno5/%s ping to %s\n", socktype == SOCK_DGRAM ? "udp" : "tcp", host)); memset(&increds, 0x0, sizeof(increds)); increds.client = princ; increds.server = sprinc; kerr = krb5_get_credentials(ctx, 0, ccache, &increds, &outcreds); if (kerr) goto bail; kerr = krb5_decode_ticket(&outcreds->ticket, &ticket); if (kerr) goto bail; VERBOSE(2, (stderr, "kvno5 says kvno = %d\n", ticket->enc_part.kvno)); bail: if (kerr) fail_msg("kvno5", socktype, host, error_message(kerr)); if (ticket) krb5_free_ticket(ctx, ticket); if (outcreds) krb5_free_creds(ctx, outcreds); return kerr; }
static void copy_realm_of_ticket(krb5_context context, char * dest, size_t destlen, krb5_creds *v5cred) { krb5_error_code code; krb5_ticket *ticket; size_t len; code = krb5_decode_ticket(&v5cred->ticket, &ticket); if (code == 0) { len = krb5_princ_realm(context, ticket->server)->length; if (len > destlen - 1) len = destlen - 1; strncpy(dest, krb5_princ_realm(context, ticket->server)->data, len); dest[len] = '\0'; krb5_free_ticket(context, ticket); } }
int print_ccache (kim_ccache in_ccache, int *out_found_valid_tgt) { kim_error err = 0; kim_credential_iterator iterator = NULL; kim_identity ccache_identity = NULL; kim_string type = NULL; kim_string name = NULL; kim_string ccache_identity_string = NULL; int found_tickets = 0; *out_found_valid_tgt = 0; if (!err) { err = kim_ccache_get_type (in_ccache, &type); printiferr (err, "while getting the ccache type"); } if (!err) { err = kim_ccache_get_name (in_ccache, &name); printiferr (err, "while getting the ccache name"); } if (!err) { err = kim_ccache_get_client_identity (in_ccache, &ccache_identity); printiferr (err, "while getting the ccache principal"); } if (!err) { err = kim_identity_get_display_string (ccache_identity, &ccache_identity_string); printiferr (err, "while unparsing the ccache principal name"); } if (!err) { printmsg ("Kerberos 5 ticket cache: '%s:%s'\nDefault principal: %s\n\n", type, name, ccache_identity_string); printmsg ("Valid Starting"); printfiller (' ', get_timestamp_width () - sizeof ("Valid Starting") + 3); printmsg ("Expires"); printfiller (' ', get_timestamp_width () - sizeof ("Expires") + 3); printmsg ("Service Principal\n"); err = kim_credential_iterator_create (&iterator, in_ccache); } while (!err) { kim_credential credential = NULL; kim_identity client = NULL; kim_identity service = NULL; kim_string client_string = NULL; kim_string service_string = NULL; krb5_creds *creds = NULL; int extra_field = 0; err = kim_credential_iterator_next (iterator, &credential); if (!err && !credential) { break; } if (!err) { err = kim_credential_get_client_identity (credential, &client); printiferr (err, "while getting the client principal"); } if (!err) { err = kim_identity_get_display_string (client, &client_string); printiferr (err, "while unparsing the client principal name"); } if (!err) { err = kim_credential_get_service_identity (credential, &service); printiferr (err, "while getting the service principal"); } if (!err) { err = kim_identity_get_display_string (service, &service_string); printiferr (err, "while unparsing the service principal name"); } if (!err) { err = kim_credential_get_krb5_creds (credential, kcontext, &creds); printiferr (err, "while getting krb5 creds"); } if (!err && krb5_is_config_principal(kcontext, creds->server)) goto next; if (!err) { found_tickets = 1; printtime (creds->times.starttime ? creds->times.starttime : creds->times.authtime); printmsg (" "); printtime (creds->times.endtime); printmsg (" "); printmsg ("%s\n", service_string); if (strcmp (ccache_identity_string, client_string)) { if (!extra_field) { printmsg ("\t"); } printmsg ("for client %s", client_string); extra_field++; } if (creds->ticket_flags & TKT_FLG_RENEWABLE) { printmsg (extra_field ? ", " : "\t"); printmsg ("renew until "); printtime (creds->times.renew_till); extra_field += 2; } if (extra_field > 2) { printmsg ("\n"); extra_field = 0; } if (show_flags) { printmsg (extra_field ? ", " : "\t"); printflags (creds->ticket_flags); extra_field++; } if (extra_field > 2) { printmsg ("\n"); extra_field = 0; } if (show_enctypes) { krb5_ticket *ticket_rep; if (krb5_decode_ticket (&creds->ticket, &ticket_rep) == 0) { if (!extra_field) { printmsg ("\t"); } else { printmsg (", "); } printmsg ("Etype (skey, tkt): %s, ", enctype_to_string (creds->keyblock.enctype)); printmsg ("%s ", enctype_to_string (ticket_rep->enc_part.enctype)); extra_field++; krb5_free_ticket (kcontext, ticket_rep); } } if (extra_field) { printmsg ("\n"); } if (show_address_list) { printmsg ("\tAddresses: "); if (!creds->addresses || !creds->addresses[0]) { printmsg ("(none)\n"); } else { int i; for (i = 0; creds->addresses[i]; i++) { if (i > 0) { printmsg (", "); } printaddress (*creds->addresses[i]); } printmsg ("\n"); } } if (extra_field) { printmsg ("\n"); } } if (!err) { kim_boolean is_tgt = 0; kim_credential_state state; err = kim_credential_is_tgt (credential, &is_tgt); printiferr (err, "while checking if creds are valid"); if (!err) { err = kim_credential_get_state (credential, &state); } if (!err && is_tgt && state == kim_credentials_state_valid) { *out_found_valid_tgt = 1; } } next: if (creds) { krb5_free_creds (kcontext, creds); } kim_string_free (&client_string); kim_string_free (&service_string); kim_identity_free (&client); kim_identity_free (&service); kim_credential_free (&credential); } kim_string_free (&type); kim_string_free (&name); kim_string_free (&ccache_identity_string); kim_identity_free (&ccache_identity); kim_credential_iterator_free (&iterator); if (!err) { if (!found_tickets) { printerr ("No Kerberos 5 tickets in credentials cache\n"); } else { printmsg ("\n"); } } return err; }
/* * call-seq: * list_cache([cache_name]) -> array * * Call krb5_cc_next_cred to fetch credentials from a cachefile. With no parameters, it fetches the credentials in the default cachefile. With one parameter, it fetches the credentials in the named cachefile. Returns a list of Krb5Auth::Krb5::Cred objects on success, raises Krb5Auth::Krb5::Exception on failure. */ static VALUE Krb5_list_cache_creds(int argc, VALUE *argv, VALUE self) { VALUE cache_val; struct ruby_krb5 *kerb; krb5_error_code krbret; char *cache_name; krb5_ccache cc; krb5_cc_cursor cur; krb5_creds creds; char *name; char *sname; krb5_ticket *tkt; VALUE result; VALUE line; rb_scan_args(argc, argv, "01", &cache_val); cache_name = get_string_or_nil(cache_val); Data_Get_Struct(self, struct ruby_krb5, kerb); if (!kerb) { NOSTRUCT_EXCEPT(); return Qfalse; } if (cache_name == NULL) { krbret = krb5_cc_default(kerb->ctx, &cc); } else { krbret = krb5_cc_resolve(kerb->ctx, cache_name, &cc); } if (krbret) { goto cache_fail_raise; } krbret = krb5_cc_start_seq_get(kerb->ctx, cc, &cur); if (krbret) { goto cache_fail_close; } result = rb_ary_new(); while (!(krbret = krb5_cc_next_cred(kerb->ctx, cc, &cur, &creds))) { krbret = krb5_unparse_name(kerb->ctx, creds.client, &name); if (krbret) { krb5_free_cred_contents(kerb->ctx, &creds); break; } krbret = krb5_unparse_name(kerb->ctx, creds.server, &sname); if (krbret) { free(name); krb5_free_cred_contents(kerb->ctx, &creds); break; } krbret = krb5_decode_ticket(&creds.ticket, &tkt); if (krbret) { free(sname); free(name); krb5_free_cred_contents(kerb->ctx, &creds); break; } line = rb_class_new_instance(0, NULL, cCred); rb_iv_set(line, "@client", rb_str_new2(name)); rb_iv_set(line, "@server", rb_str_new2(sname)); rb_iv_set(line, "@starttime", INT2NUM(creds.times.starttime)); rb_iv_set(line, "@authtime", INT2NUM(creds.times.authtime)); rb_iv_set(line, "@endtime", INT2NUM(creds.times.endtime)); rb_iv_set(line, "@ticket_flags", INT2NUM(creds.ticket_flags)); rb_iv_set(line, "@cred_enctype", INT2NUM(creds.keyblock.enctype)); rb_iv_set(line, "@ticket_enctype", INT2NUM(tkt->enc_part.enctype)); rb_ary_push(result, line); krb5_free_ticket(kerb->ctx, tkt); free(sname); free(name); krb5_free_cred_contents(kerb->ctx, &creds); } if (krbret != KRB5_CC_END) { // FIXME: do we need to free up "result" here? There will be no // references to it, so I think the garbage collector will pick it up, // but I'm not sure. goto cache_fail_close; } krbret = krb5_cc_end_seq_get(kerb->ctx, cc, &cur); krb5_cc_close(kerb->ctx, cc); return result; cache_fail_close: krb5_cc_close(kerb->ctx, cc); cache_fail_raise: Krb5_register_error(krbret); return Qfalse; }
krb5_error_code sss_extract_pac(krb5_context ctx, krb5_ccache ccache, krb5_principal server_principal, krb5_principal client_principal, krb5_keytab keytab, krb5_authdata ***_pac_authdata) { #ifdef HAVE_PAC_RESPONDER krb5_error_code kerr; krb5_creds mcred; krb5_creds cred; krb5_authdata **pac_authdata = NULL; krb5_pac pac = NULL; int ret; krb5_ticket *ticket = NULL; krb5_keytab_entry entry; memset(&entry, 0, sizeof(entry)); memset(&mcred, 0, sizeof(mcred)); memset(&cred, 0, sizeof(mcred)); mcred.server = server_principal; mcred.client = client_principal; kerr = krb5_cc_retrieve_cred(ctx, ccache, 0, &mcred, &cred); if (kerr != 0) { DEBUG(SSSDBG_OP_FAILURE, "krb5_cc_retrieve_cred failed.\n"); goto done; } kerr = krb5_decode_ticket(&cred.ticket, &ticket); if (kerr != 0) { DEBUG(SSSDBG_OP_FAILURE, "krb5_decode_ticket failed.\n"); goto done; } kerr = krb5_server_decrypt_ticket_keytab(ctx, keytab, ticket); if (kerr != 0) { DEBUG(SSSDBG_OP_FAILURE, "krb5_server_decrypt_ticket_keytab failed.\n"); goto done; } kerr = sss_krb5_find_authdata(ctx, ticket->enc_part2->authorization_data, NULL, KRB5_AUTHDATA_WIN2K_PAC, &pac_authdata); if (kerr != 0) { DEBUG(SSSDBG_OP_FAILURE, "krb5_find_authdata failed.\n"); goto done; } if (pac_authdata == NULL || pac_authdata[0] == NULL) { DEBUG(SSSDBG_OP_FAILURE, "No PAC authdata available.\n"); kerr = ENOENT; goto done; } if (pac_authdata[1] != NULL) { DEBUG(SSSDBG_OP_FAILURE, "More than one PAC autdata found.\n"); kerr = EINVAL; goto done; } kerr = krb5_pac_parse(ctx, pac_authdata[0]->contents, pac_authdata[0]->length, &pac); if (kerr != 0) { DEBUG(SSSDBG_OP_FAILURE, "krb5_pac_parse failed.\n"); goto done; } kerr = krb5_kt_get_entry(ctx, keytab, ticket->server, ticket->enc_part.kvno, ticket->enc_part.enctype, &entry); if (kerr != 0) { DEBUG(SSSDBG_OP_FAILURE, "krb5_kt_get_entry failed.\n"); goto done; } kerr = krb5_pac_verify(ctx, pac, 0, NULL, &entry.key, NULL); if (kerr != 0) { DEBUG(SSSDBG_OP_FAILURE, "krb5_pac_verify failed.\n"); goto done; } ret = unsetenv("_SSS_LOOPS"); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to unset _SSS_LOOPS, " "sss_pac_make_request will most certainly fail.\n"); } *_pac_authdata = pac_authdata; kerr = 0; done: if (kerr != 0) { krb5_free_authdata(ctx, pac_authdata); } if (entry.magic != 0) { krb5_free_keytab_entry_contents(ctx, &entry); } krb5_pac_free(ctx, pac); if (ticket != NULL) { krb5_free_ticket(ctx, ticket); } krb5_free_cred_contents(ctx, &cred); return kerr; #else return ENOTSUP; #endif }
DWORD LwKrb5InitializeUserLoginCredentials( IN PCSTR pszUserPrincipalName, IN PCSTR pszPassword, IN uid_t uid, IN gid_t gid, IN LW_KRB5_LOGIN_FLAGS Flags, IN PCSTR pszServicePrincipal, IN PCSTR pszServiceRealm, IN PCSTR pszServicePassword, OUT PVOID* ppNdrPacInfo, OUT size_t* pNdrPacInfoSize, OUT PDWORD pdwGoodUntilTime ) { DWORD dwError = 0; krb5_error_code ret = 0; krb5_context ctx = NULL; krb5_ccache cc = NULL; // Free with krb5_free_cred_contents krb5_creds credsRequest = {0}; krb5_creds *pTgsCreds = NULL; krb5_ticket *pTgsTicket = NULL; krb5_ticket *pDecryptedTgs = NULL; krb5_auth_context authContext = NULL; krb5_data apReqPacket = {0}; krb5_keyblock serviceKey = {0}; krb5_data salt = {0}; // Do not free krb5_data machinePassword = {0}; krb5_flags flags = 0; krb5_int32 authcon_flags = 0; BOOLEAN bInLock = FALSE; PCSTR pszTempCacheName = NULL; PSTR pszTempCachePath = NULL; PVOID pNdrPacInfo = NULL; size_t ndrPacInfoSize = 0; DWORD dwGoodUntilTime = 0; ret = krb5_init_context(&ctx); BAIL_ON_KRB_ERROR(ctx, ret); /* Generates a new filed based credentials cache in /tmp. The file will * be owned by root and only accessible by root. */ ret = krb5_cc_new_unique( ctx, "FILE", "hint", &cc); BAIL_ON_KRB_ERROR(ctx, ret); if (Flags & LW_KRB5_LOGIN_FLAG_SMART_CARD) { dwError = LwKrb5GetTgtWithSmartCard( pszUserPrincipalName, pszPassword, krb5_cc_get_name(ctx, cc), &dwGoodUntilTime); } else { dwError = LwKrb5GetTgt( pszUserPrincipalName, pszPassword, krb5_cc_get_name(ctx, cc), &dwGoodUntilTime); } BAIL_ON_LW_ERROR(dwError); ret = krb5_parse_name(ctx, pszServicePrincipal, &credsRequest.server); BAIL_ON_KRB_ERROR(ctx, ret); ret = krb5_cc_get_principal(ctx, cc, &credsRequest.client); BAIL_ON_KRB_ERROR(ctx, ret); /* Get a TGS for our service using the tgt in the cache */ ret = krb5_get_credentials( ctx, 0, /*no options (not user to user encryption, and not only cached) */ cc, &credsRequest, &pTgsCreds); // Don't trust pTgsCreds on an unsuccessful return // This may be non-zero due to the krb5 libs following referrals // but has been freed in the krb5 libs themselves and any useful // tickets have already been cached. if (ret != 0) { pTgsCreds = NULL; } BAIL_ON_KRB_ERROR(ctx, ret); //No need to store the tgs in the cc. Kerberos does that automatically /* Generate an ap_req message, but don't send it anywhere. Just decode it * immediately. This is the only way to get kerberos to decrypt the tgs * using public APIs */ ret = krb5_mk_req_extended( ctx, &authContext, 0, /* no options necessary */ NULL, /* since this isn't a real ap_req, we don't have any supplemental data to send with it. */ pTgsCreds, &apReqPacket); BAIL_ON_KRB_ERROR(ctx, ret); /* Decode (but not decrypt) the tgs ticket so that we can figure out * which encryption type was used in it. */ ret = krb5_decode_ticket(&pTgsCreds->ticket, &pTgsTicket); /* The TGS ticket is encrypted with the machine password and salted with * the service principal. pszServicePrincipal could probably be used * directly, but it's safer to unparse pTgsCreds->server, because the KDC * sent that to us. */ salt.magic = KV5M_DATA; ret = krb5_unparse_name( ctx, pTgsCreds->server, &salt.data); BAIL_ON_KRB_ERROR(ctx, ret); salt.length = strlen(salt.data); machinePassword.magic = KV5M_DATA; machinePassword.data = (PSTR)pszServicePassword, machinePassword.length = strlen(pszServicePassword), /* Generate a key to decrypt the TGS */ ret = krb5_c_string_to_key( ctx, pTgsTicket->enc_part.enctype, &machinePassword, &salt, &serviceKey); BAIL_ON_KRB_ERROR(ctx, ret); /* Typically krb5_rd_req would decode the AP_REQ using the keytab, but * we don't want to depend on the keytab. As a side effect of kerberos' * user to user authentication support, if a key is explictly set on the * auth context, that key will be used to decrypt the TGS instead of the * keytab. * * By manually generating the key and setting it, we don't require * a keytab. */ if (authContext != NULL) { ret = krb5_auth_con_free(ctx, authContext); BAIL_ON_KRB_ERROR(ctx, ret); } ret = krb5_auth_con_init(ctx, &authContext); BAIL_ON_KRB_ERROR(ctx, ret); ret = krb5_auth_con_setuseruserkey( ctx, authContext, &serviceKey); BAIL_ON_KRB_ERROR(ctx, ret); /* Disable replay detection which is unnecessary and * can fail when authenticating large numbers of users. */ krb5_auth_con_getflags(ctx, authContext, &authcon_flags); krb5_auth_con_setflags(ctx, authContext, authcon_flags & ~KRB5_AUTH_CONTEXT_DO_TIME); if (pszServiceRealm) { ret = krb5_set_default_realm(ctx, pszServiceRealm); BAIL_ON_KRB_ERROR(ctx, ret); } /* This decrypts the TGS. As a side effect it ensures that the KDC that * the user's TGT came from is in the same realm that the machine was * joined to (this prevents users from spoofing the KDC). */ ret = krb5_rd_req( ctx, &authContext, &apReqPacket, pTgsCreds->server, NULL, /* we're not using the keytab */ &flags, &pDecryptedTgs); BAIL_ON_KRB_ERROR(ctx, ret); dwError = LwKrb5FindPac( ctx, pDecryptedTgs, &serviceKey, &pNdrPacInfo, &ndrPacInfoSize); BAIL_ON_LW_ERROR(dwError); if (Flags & LW_KRB5_LOGIN_FLAG_UPDATE_CACHE) { /* 1. Copy old credentials from the existing user creds cache to * the temporary cache. * 2. Delete the existing creds cache. * 3. Move the temporary cache file into the final path. */ dwError = pthread_mutex_lock(&gLwKrb5State.UserCacheMutex); BAIL_ON_LW_ERROR(dwError); bInLock = TRUE; dwError = LwKrb5CopyFromUserCache( ctx, cc, uid ); BAIL_ON_LW_ERROR(dwError); pszTempCacheName = krb5_cc_get_name(ctx, cc); if (!strncasecmp(pszTempCacheName, "FILE:", sizeof("FILE:")-1)) { pszTempCacheName += sizeof("FILE:") - 1; } dwError = LwAllocateString(pszTempCacheName, &pszTempCachePath); BAIL_ON_LW_ERROR(dwError); krb5_cc_close(ctx, cc); // Just to make sure no one accesses this now invalid pointer cc = NULL; dwError = LwKrb5MoveCCacheToUserPath( ctx, pszTempCachePath, uid, gid); if (dwError != LW_ERROR_SUCCESS) { /* Let the user login, even if we couldn't create the ccache for * them. Possible causes are: * 1. /tmp is readonly * 2. Another user maliciously setup a weird file (such as a * directory) where the ccache would go. * 3. Someone created a ccache in the small window after we delete * the old one and before we move in the new one. */ LW_LOG_WARNING("Unable to set up credentials cache with tgt for uid %ld", (long)uid); dwError = LwRemoveFile(pszTempCachePath); BAIL_ON_LW_ERROR(dwError); } } error: if (dwError) { LW_SAFE_FREE_MEMORY(pNdrPacInfo); ndrPacInfoSize = 0; dwGoodUntilTime = 0; } if (ctx) { // This function skips fields which are NULL krb5_free_cred_contents(ctx, &credsRequest); if (pTgsCreds != NULL) { krb5_free_creds(ctx, pTgsCreds); } if (pTgsTicket != NULL) { krb5_free_ticket(ctx, pTgsTicket); } if (pDecryptedTgs != NULL) { krb5_free_ticket(ctx, pDecryptedTgs); } if (authContext != NULL) { krb5_auth_con_free(ctx, authContext); } krb5_free_data_contents(ctx, &apReqPacket); krb5_free_data_contents(ctx, &salt); krb5_free_keyblock_contents(ctx, &serviceKey); if (cc != NULL) { krb5_cc_destroy(ctx, cc); } krb5_free_context(ctx); } if (bInLock) { pthread_mutex_unlock(&gLwKrb5State.UserCacheMutex); } LW_SAFE_FREE_STRING(pszTempCachePath); *ppNdrPacInfo = pNdrPacInfo; *pNdrPacInfoSize = ndrPacInfoSize; *pdwGoodUntilTime = dwGoodUntilTime; return dwError; }
static void show_credential(krb5_creds *cred) { krb5_error_code ret; krb5_ticket *tkt; char *name, *sname, *flags; int extra_field = 0, ccol = 0, i; ret = krb5_unparse_name(context, cred->client, &name); if (ret) { com_err(progname, ret, _("while unparsing client name")); return; } ret = krb5_unparse_name(context, cred->server, &sname); if (ret) { com_err(progname, ret, _("while unparsing server name")); krb5_free_unparsed_name(context, name); return; } if (!cred->times.starttime) cred->times.starttime = cred->times.authtime; if (!krb5_is_config_principal(context, cred->server)) { printtime(cred->times.starttime); putchar(' '); putchar(' '); printtime(cred->times.endtime); putchar(' '); putchar(' '); printf("%s\n", sname); } else { fputs("config: ", stdout); ccol = 8; for (i = 1; i < cred->server->length; i++) { ccol += printf("%s%.*s%s", i > 1 ? "(" : "", (int)cred->server->data[i].length, cred->server->data[i].data, i > 1 ? ")" : ""); } fputs(" = ", stdout); ccol += 3; } if (strcmp(name, defname)) { printf(_("\tfor client %s"), name); extra_field++; } if (krb5_is_config_principal(context, cred->server)) print_config_data(ccol, &cred->ticket); if (cred->times.renew_till) { if (!extra_field) fputs("\t",stdout); else fputs(", ",stdout); fputs(_("renew until "), stdout); printtime(cred->times.renew_till); extra_field += 2; } if (extra_field > 3) { fputs("\n", stdout); extra_field = 0; } if (show_flags) { flags = flags_string(cred); if (flags && *flags) { if (!extra_field) fputs("\t",stdout); else fputs(", ",stdout); printf(_("Flags: %s"), flags); extra_field++; } } if (extra_field > 2) { fputs("\n", stdout); extra_field = 0; } if (show_etype) { ret = krb5_decode_ticket(&cred->ticket, &tkt); if (ret) goto err_tkt; if (!extra_field) fputs("\t",stdout); else fputs(", ",stdout); printf(_("Etype (skey, tkt): %s, "), etype_string(cred->keyblock.enctype)); printf("%s ", etype_string(tkt->enc_part.enctype)); extra_field++; err_tkt: if (tkt != NULL) krb5_free_ticket(context, tkt); } if (show_adtype) { if (cred->authdata != NULL) { if (!extra_field) fputs("\t",stdout); else fputs(", ",stdout); printf(_("AD types: ")); for (i = 0; cred->authdata[i] != NULL; i++) { if (i) printf(", "); printf("%d", cred->authdata[i]->ad_type); } extra_field++; } } /* If any additional info was printed, extra_field is non-zero. */ if (extra_field) putchar('\n'); if (show_addresses) { if (cred->addresses == NULL || cred->addresses[0] == NULL) { printf(_("\tAddresses: (none)\n")); } else { printf(_("\tAddresses: ")); one_addr(cred->addresses[0]); for (i = 1; cred->addresses[i] != NULL; i++) { printf(", "); one_addr(cred->addresses[i]); } printf("\n"); } } krb5_free_unparsed_name(context, name); krb5_free_unparsed_name(context, sname); }
tkt_test_1() { krb5_data *data; krb5_ticket tk_in, *tk_out; krb5_keyblock sess_k, serv_k, *nsess; krb5_enc_tkt_part tk_in_enc; int code; krb5_address *addr_list[2]; krb5_address addr_1; static krb5_octet ip_addr_1[4] = { 18, 72, 0, 122 }; char *out; /* * fill in some values on the "in" side of the ticket */ code = krb5_parse_name ("server/test/[email protected]", &tk_in.server); if (code != 0) { com_err("tkt_test_1", code, " parsing server principal"); return; } serv_k.enctype = 1; /* XXX symbolic constant */ serv_k.length = 8; /* XXX symbolic constant */ serv_k.contents = key_one; sess_k.enctype = 1; /* XXX symbolic constant */ sess_k.length = 8; /* XXX symbolic constant */ sess_k.contents = key_two; tk_in.etype = 1; /* XXX symbolic constant here */ tk_in.skvno = 4; tk_in.enc_part2 = &tk_in_enc; tk_in_enc.flags = 0x11; tk_in_enc.session = &sess_k; tk_in_enc.times.authtime = 42; tk_in_enc.times.starttime = 43; tk_in_enc.times.endtime = 44; code = krb5_parse_name ("client/test/[email protected]", &tk_in_enc.client); if (code != 0) { com_err("tkt_test_1", code, " parsing client principal"); return; } tk_in_enc.transited.length = 0; addr_1.addrtype = ADDRTYPE_INET; /* XXX should be KRB5_ADDR... */ addr_1.length = 4; addr_1.contents = ip_addr_1; addr_list[0] = &addr_1; addr_list[1] = 0; tk_in_enc.caddrs = addr_list; tk_in_enc.authorization_data = 0; code = krb5_encrypt_tkt_part(&serv_k, &tk_in); if (code != 0) { com_err ("tkt_test_1", code, " encrypting ticket"); return; } data = 0; code = krb5_encode_ticket (&tk_in, &data); if (code != 0) { com_err ("tkt_test_1", code, " encoding ticket"); return; } dump_data(data); tk_out = 0; code = krb5_decode_ticket (data, &tk_out); if (code != 0) { com_err ("tkt_test_1", code, "decoding ticket"); return; } /* check the plaintext values */ if (tk_out->etype != 1) { com_err ("tkt_test_1", 0, "wrong etype"); return; } if (tk_out->skvno != 4) { com_err ("tkt_test_1", 0, "wrong kvno"); return; } code = krb5_unparse_name(tk_out->server, &out); if (code != 0) { com_err ("tkt_test_1", code, "couldn't unparse server principal"); return; } if (strcmp (out, "server/test/[email protected]") != 0) { com_err("tkt_test_1", 0, "wrong server principal"); return; } free(out); out = 0; /* decode the ciphertext */ code = krb5_decrypt_tkt_part (&serv_k, tk_out); if (code != 0) { com_err ("tkt_test_1", code, "while decrypting ticket"); return; } /* check the contents */ if (tk_out->enc_part2->flags != 0x11) { com_err("tkt_test_1", 0, "wrong flags"); return; } nsess = tk_out->enc_part2->session; if (nsess->enctype != 1) { com_err("tkt_test_1", 0, "wrong session key type"); return; } if (nsess->length != 8) { com_err("tkt_test_1", 0, "wrong session key length"); return; } if (memcmp(nsess->contents, key_two, 8) != 0) { com_err("tkt_test_1", 0, "wrong session key contents"); return; } code = krb5_unparse_name(tk_out->enc_part2->client, &out); if (code != 0) { com_err ("tkt_test_1", code, "couldn't unparse client principal"); return; } if (strcmp (out, "client/test/[email protected]") != 0) { com_err("tkt_test_1", 0, "wrong client principal"); return; } free(out); out = 0; if (tk_out->enc_part2->transited.length != 0) { com_err("tkt_test_1", 0, "wrong transited length"); return; } /* XXX should check address here, too */ /* XXX should check times here */ /* XXX should check auth. data here */ printf("test 1 passed\n"); }
static void do_v5_kvno (int count, char *names[], char * ccachestr, char *etypestr, char *keytab_name, char *sname, int canon, int unknown) { krb5_error_code ret; int i, errors; krb5_enctype etype; krb5_ccache ccache; krb5_principal me; krb5_creds in_creds, *out_creds; krb5_ticket *ticket; char *princ; krb5_keytab keytab = NULL; ret = krb5_init_context(&context); if (ret) { com_err(prog, ret, "while initializing krb5 library"); exit(1); } if (etypestr) { ret = krb5_string_to_enctype(etypestr, &etype); if (ret) { com_err(prog, ret, "while converting etype"); exit(1); } } else { etype = 0; } if (ccachestr) ret = krb5_cc_resolve(context, ccachestr, &ccache); else ret = krb5_cc_default(context, &ccache); if (ret) { com_err(prog, ret, "while opening ccache"); exit(1); } if (keytab_name) { ret = krb5_kt_resolve(context, keytab_name, &keytab); if (ret) { com_err(prog, ret, "resolving keytab %s", keytab_name); exit(1); } } ret = krb5_cc_get_principal(context, ccache, &me); if (ret) { com_err(prog, ret, "while getting client principal name"); exit(1); } errors = 0; for (i = 0; i < count; i++) { memset(&in_creds, 0, sizeof(in_creds)); in_creds.client = me; if (sname != NULL) { ret = krb5_sname_to_principal(context, names[i], sname, KRB5_NT_SRV_HST, &in_creds.server); } else { ret = krb5_parse_name(context, names[i], &in_creds.server); } if (ret) { if (!quiet) com_err(prog, ret, "while parsing principal name %s", names[i]); errors++; continue; } if (unknown == 1) { krb5_princ_type(context, in_creds.server) = KRB5_NT_UNKNOWN; } ret = krb5_unparse_name(context, in_creds.server, &princ); if (ret) { com_err(prog, ret, "while formatting parsed principal name for '%s'", names[i]); errors++; continue; } in_creds.keyblock.enctype = etype; ret = krb5_get_credentials(context, canon ? KRB5_GC_CANONICALIZE : 0, ccache, &in_creds, &out_creds); krb5_free_principal(context, in_creds.server); if (ret) { com_err(prog, ret, "while getting credentials for %s", princ); krb5_free_unparsed_name(context, princ); errors++; continue; } /* we need a native ticket */ ret = krb5_decode_ticket(&out_creds->ticket, &ticket); if (ret) { com_err(prog, ret, "while decoding ticket for %s", princ); krb5_free_creds(context, out_creds); krb5_free_unparsed_name(context, princ); errors++; continue; } if (keytab) { ret = krb5_server_decrypt_ticket_keytab(context, keytab, ticket); if (ret) { if (!quiet) printf("%s: kvno = %d, keytab entry invalid", princ, ticket->enc_part.kvno); com_err(prog, ret, "while decrypting ticket for %s", princ); krb5_free_ticket(context, ticket); krb5_free_creds(context, out_creds); krb5_free_unparsed_name(context, princ); errors++; continue; } if (!quiet) printf("%s: kvno = %d, keytab entry valid\n", princ, ticket->enc_part.kvno); } else { if (!quiet) printf("%s: kvno = %d\n", princ, ticket->enc_part.kvno); } krb5_free_creds(context, out_creds); krb5_free_unparsed_name(context, princ); } if (keytab) krb5_kt_close(context, keytab); krb5_free_principal(context, me); krb5_cc_close(context, ccache); krb5_free_context(context); if (errors) exit(1); exit(0); }