DWORD LwKrb5CopyFromUserCache( krb5_context ctx, krb5_ccache destCC, uid_t uid ) { DWORD dwError = LW_ERROR_SUCCESS; PSTR pszCachePath = NULL; krb5_ccache srcCC = NULL; krb5_cc_cursor srcPos = NULL; krb5_cc_cursor destPos = NULL; // Free with krb5_free_cred_contents krb5_creds srcCreds = {0}; // Free with krb5_free_cred_contents krb5_creds destCreds = {0}; krb5_error_code ret = 0; krb5_principal destClient = 0; BOOLEAN bIncludeTicket = TRUE; DWORD dwTime = 0; ret = krb5_cc_get_principal( ctx, destCC, &destClient); BAIL_ON_KRB_ERROR(ctx, ret); dwError = LwKrb5GetUserCachePath( uid, KRB5_File_Cache, &pszCachePath); BAIL_ON_LW_ERROR(dwError); ret = krb5_cc_resolve( ctx, pszCachePath, &srcCC); BAIL_ON_KRB_ERROR(ctx, ret); ret = krb5_cc_start_seq_get( ctx, srcCC, &srcPos); if (ret == KRB5_FCC_NOFILE) { // The cache file does not exist ret = 0; goto cleanup; } if (ret == KRB5_CC_FORMAT) { // Some other user put a bad cc in place - don't copy anything // from it. ret = 0; goto cleanup; } BAIL_ON_KRB_ERROR(ctx, ret); dwTime = time(NULL); while (1) { krb5_free_cred_contents( ctx, &srcCreds); ret = krb5_cc_next_cred( ctx, srcCC, &srcPos, &srcCreds); if (ret == KRB5_CC_FORMAT) { break; } else if (ret == KRB5_CC_END) { break; } else { BAIL_ON_KRB_ERROR(ctx, ret); } if (!krb5_principal_compare(ctx, destClient, srcCreds.client)) { /* Can't keep these creds. The client principal doesn't * match. */ continue; } if ( srcCreds.times.endtime < dwTime ) { /* Credentials are too old. */ continue; } if (destPos != NULL) { krb5_cc_end_seq_get( ctx, destCC, &destPos); destPos = NULL; } ret = krb5_cc_start_seq_get( ctx, destCC, &destPos); BAIL_ON_KRB_ERROR(ctx, ret); bIncludeTicket = TRUE; while(bIncludeTicket) { krb5_free_cred_contents( ctx, &destCreds); ret = krb5_cc_next_cred( ctx, destCC, &destPos, &destCreds); if (ret == KRB5_CC_END) { break; } else { BAIL_ON_KRB_ERROR(ctx, ret); } if (krb5_principal_compare( ctx, destCreds.server, srcCreds.server)) { /* These credentials are already in the dest cache */ bIncludeTicket = FALSE; } } if (bIncludeTicket) { // These creds can go in the new cache ret = krb5_cc_store_cred(ctx, destCC, &srcCreds); BAIL_ON_KRB_ERROR(ctx, ret); } } cleanup: LW_SAFE_FREE_STRING(pszCachePath); if (ctx != NULL) { if (srcPos != NULL) { krb5_cc_end_seq_get( ctx, srcCC, &srcPos); } if (destPos != NULL) { krb5_cc_end_seq_get( ctx, destCC, &destPos); } if (srcCC != NULL) { krb5_cc_close(ctx, srcCC); } krb5_free_cred_contents(ctx, &srcCreds); krb5_free_cred_contents(ctx, &destCreds); if (destClient != NULL) { krb5_free_principal(ctx, destClient); } } return dwError; error: goto cleanup; }
void main( int argc, char *argv[] ) { krb5_context kcontext; krb5_error_code code; krb5_ccache ccache=NULL; krb5_ccache mslsa_ccache=NULL; krb5_cc_cursor cursor; krb5_creds creds; krb5_principal princ; int initial_ticket = 0; int option; char * ccachestr = 0; prog = strrchr(argv[0], '/'); prog = prog ? (prog + 1) : argv[0]; while ((option = getopt(argc, argv, "c:h")) != -1) { switch (option) { case 'c': ccachestr = optarg; break; case 'h': default: xusage(); break; } } if (code = krb5_init_context(&kcontext)) { com_err(argv[0], code, "while initializing kerberos library"); exit(1); } if (code = krb5_cc_resolve(kcontext, "MSLSA:", &mslsa_ccache)) { com_err(argv[0], code, "while opening MS LSA ccache"); krb5_free_context(kcontext); exit(1); } if (code = krb5_cc_set_flags(kcontext, mslsa_ccache, KRB5_TC_NOTICKET)) { com_err(argv[0], code, "while setting KRB5_TC_NOTICKET flag"); krb5_cc_close(kcontext, mslsa_ccache); krb5_free_context(kcontext); exit(1); } /* Enumerate tickets from cache looking for an initial ticket */ if ((code = krb5_cc_start_seq_get(kcontext, mslsa_ccache, &cursor))) { com_err(argv[0], code, "while initiating the cred sequence of MS LSA ccache"); krb5_cc_close(kcontext, mslsa_ccache); krb5_free_context(kcontext); exit(1); } while (!(code = krb5_cc_next_cred(kcontext, mslsa_ccache, &cursor, &creds))) { if ( creds.ticket_flags & TKT_FLG_INITIAL ) { krb5_free_cred_contents(kcontext, &creds); initial_ticket = 1; break; } krb5_free_cred_contents(kcontext, &creds); } krb5_cc_end_seq_get(kcontext, mslsa_ccache, &cursor); if (code = krb5_cc_set_flags(kcontext, mslsa_ccache, 0)) { com_err(argv[0], code, "while clearing flags"); krb5_cc_close(kcontext, mslsa_ccache); krb5_free_context(kcontext); exit(1); } if ( !initial_ticket ) { fprintf(stderr, "%s: Initial Ticket Getting Tickets are not available from the MS LSA\n", argv[0]); krb5_cc_close(kcontext, mslsa_ccache); krb5_free_context(kcontext); exit(1); } if (code = krb5_cc_get_principal(kcontext, mslsa_ccache, &princ)) { com_err(argv[0], code, "while obtaining MS LSA principal"); krb5_cc_close(kcontext, mslsa_ccache); krb5_free_context(kcontext); exit(1); } if (ccachestr) code = krb5_cc_resolve(kcontext, ccachestr, &ccache); else code = krb5_cc_default(kcontext, &ccache); if (code) { com_err(argv[0], code, "while getting default ccache"); krb5_free_principal(kcontext, princ); krb5_cc_close(kcontext, mslsa_ccache); krb5_free_context(kcontext); exit(1); } if (code = krb5_cc_initialize(kcontext, ccache, princ)) { com_err (argv[0], code, "when initializing ccache"); krb5_free_principal(kcontext, princ); krb5_cc_close(kcontext, mslsa_ccache); krb5_cc_close(kcontext, ccache); krb5_free_context(kcontext); exit(1); } if (code = krb5_cc_copy_creds(kcontext, mslsa_ccache, ccache)) { com_err (argv[0], code, "while copying MS LSA ccache to default ccache"); krb5_free_principal(kcontext, princ); krb5_cc_close(kcontext, ccache); krb5_cc_close(kcontext, mslsa_ccache); krb5_free_context(kcontext); exit(1); } krb5_free_principal(kcontext, princ); krb5_cc_close(kcontext, ccache); krb5_cc_close(kcontext, mslsa_ccache); krb5_free_context(kcontext); return(0); }
static int store_gss_creds(gss_store_state *state, char *princ_name, gss_cred_id_t delegated_cred) { OM_uint32 maj_stat, min_stat; krb5_error_code problem; const char * temp_ccname = "FILE:/tmp/krb5cc_pykerberos_XXXXXX"; int ret = 1; problem = krb5_init_context(&state->context); if (problem) { PyErr_SetObject(BasicAuthException_class, Py_BuildValue("((s:i))", "Cannot initialize Kerberos5 context", problem)); return 0; } int name_len = strlen(temp_ccname); state->ccache_name = (char *)malloc(name_len + 1); strcpy(state->ccache_name, temp_ccname); int fd = mkstemp(state->ccache_name + strlen("FILE:")); if (fd < 0) { PyErr_SetObject(BasicAuthException_class, Py_BuildValue("(s:s)", "Error in mkstemp", strerror(errno))); ret = 0; goto end; } close(fd); problem = krb5_cc_resolve(state->context, state->ccache_name, &state->ccache); if (problem) { set_basicauth_error(state->context, problem); ret = 0; goto end; } problem = krb5_parse_name(state->context, princ_name, &state->client); if (problem) { set_basicauth_error(state->context, problem); goto end; } problem = krb5_cc_initialize(state->context, state->ccache, state->client); if (problem) { set_basicauth_error(state->context, problem); ret = 0; goto end; } maj_stat = gss_krb5_copy_ccache(&min_stat, delegated_cred, state->ccache); if (GSS_ERROR(maj_stat)) { set_gss_error(maj_stat, min_stat); ret = 0; goto end; } ret = 1; return ret; end: if (state->client != NULL) krb5_free_principal(state->context, state->client); if (state->ccache != NULL) krb5_cc_destroy(state->context, state->ccache); krb5_free_context(state->context); return ret; }
int klist(struct klist_options *opt, int argc, char **argv) { krb5_error_code ret; int exit_status = 0; int do_verbose = opt->verbose_flag || opt->a_flag || opt->n_flag; int do_test = opt->test_flag || opt->s_flag; if(opt->version_flag) { print_version(NULL); exit(0); } if (opt->list_all_flag) { exit_status = list_caches(heimtools_context, opt); return exit_status; } if (opt->v5_flag) { krb5_ccache id; if (opt->all_content_flag) { krb5_cc_cache_cursor cursor; int first = 1; ret = krb5_cc_cache_get_first(heimtools_context, NULL, &cursor); if (ret) krb5_err(heimtools_context, 1, ret, "krb5_cc_cache_get_first"); if (opt->json_flag) printf("["); while (krb5_cc_cache_next(heimtools_context, cursor, &id) == 0) { if (opt->json_flag && !first) printf(","); exit_status |= display_v5_ccache(heimtools_context, id, do_test, do_verbose, opt->flags_flag, opt->hidden_flag, opt->json_flag); if (!opt->json_flag) printf("\n\n"); first = 0; } krb5_cc_cache_end_seq_get(heimtools_context, cursor); if (opt->json_flag) printf("]"); } else { if(opt->cache_string) { ret = krb5_cc_resolve(heimtools_context, opt->cache_string, &id); if (ret) krb5_err(heimtools_context, 1, ret, "%s", opt->cache_string); } else { ret = krb5_cc_default(heimtools_context, &id); if (ret) krb5_err(heimtools_context, 1, ret, "krb5_cc_resolve"); } exit_status = display_v5_ccache(heimtools_context, id, do_test, do_verbose, opt->flags_flag, opt->hidden_flag, opt->json_flag); } } if (!do_test) { #ifndef NO_AFS if (opt->tokens_flag && k_hasafs()) { if (opt->v5_flag) printf("\n"); display_tokens(opt->verbose_flag); } #endif } return exit_status; }
void kerberos5_is(Authenticator *ap, unsigned char *data, int cnt) { krb5_error_code ret; krb5_data outbuf; krb5_keyblock *key_block; char *name; krb5_principal server; krb5_authenticator authenticator; int zero = 0; if (cnt-- < 1) return; switch (*data++) { case KRB_AUTH: auth.data = (char *)data; auth.length = cnt; auth_context = NULL; ret = krb5_auth_con_init (context, &auth_context); if (ret) { Data(ap, KRB_REJECT, "krb5_auth_con_init failed", -1); auth_finished(ap, AUTH_REJECT); if (auth_debug_mode) printf("Kerberos V5: krb5_auth_con_init failed (%s)\r\n", krb5_get_err_text(context, ret)); return; } ret = krb5_auth_con_setaddrs_from_fd (context, auth_context, &zero); if (ret) { Data(ap, KRB_REJECT, "krb5_auth_con_setaddrs_from_fd failed", -1); auth_finished(ap, AUTH_REJECT); if (auth_debug_mode) printf("Kerberos V5: " "krb5_auth_con_setaddrs_from_fd failed (%s)\r\n", krb5_get_err_text(context, ret)); return; } ret = krb5_sock_to_principal (context, 0, "host", KRB5_NT_SRV_HST, &server); if (ret) { Data(ap, KRB_REJECT, "krb5_sock_to_principal failed", -1); auth_finished(ap, AUTH_REJECT); if (auth_debug_mode) printf("Kerberos V5: " "krb5_sock_to_principal failed (%s)\r\n", krb5_get_err_text(context, ret)); return; } ret = krb5_rd_req(context, &auth_context, &auth, server, NULL, NULL, &ticket); krb5_free_principal (context, server); if (ret) { char *errbuf; asprintf(&errbuf, "Read req failed: %s", krb5_get_err_text(context, ret)); Data(ap, KRB_REJECT, errbuf, -1); if (auth_debug_mode) printf("%s\r\n", errbuf); free (errbuf); return; } ret = krb5_auth_con_getkey(context, auth_context, &key_block); if (ret) { Data(ap, KRB_REJECT, "krb5_auth_con_getkey failed", -1); auth_finished(ap, AUTH_REJECT); if (auth_debug_mode) printf("Kerberos V5: " "krb5_auth_con_getkey failed (%s)\r\n", krb5_get_err_text(context, ret)); return; } ret = krb5_auth_getauthenticator (context, auth_context, &authenticator); if (ret) { Data(ap, KRB_REJECT, "krb5_auth_getauthenticator failed", -1); auth_finished(ap, AUTH_REJECT); if (auth_debug_mode) printf("Kerberos V5: " "krb5_auth_getauthenticator failed (%s)\r\n", krb5_get_err_text(context, ret)); return; } if (authenticator->cksum) { char foo[2]; foo[0] = ap->type; foo[1] = ap->way; ret = krb5_verify_checksum (context, foo, sizeof(foo), key_block, authenticator->cksum); if (ret) { Data(ap, KRB_REJECT, "No checksum", -1); if (auth_debug_mode) printf ("No checksum\r\n"); krb5_free_authenticator (context, &authenticator); return; } } krb5_free_authenticator (context, &authenticator); ret = krb5_auth_con_getremotesubkey (context, auth_context, &key_block); if (ret) { Data(ap, KRB_REJECT, "krb5_auth_con_getremotesubkey failed", -1); auth_finished(ap, AUTH_REJECT); if (auth_debug_mode) printf("Kerberos V5: " "krb5_auth_con_getremotesubkey failed (%s)\r\n", krb5_get_err_text(context, ret)); return; } if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { ret = krb5_mk_rep(context, &auth_context, &outbuf); if (ret) { Data(ap, KRB_REJECT, "krb5_mk_rep failed", -1); auth_finished(ap, AUTH_REJECT); if (auth_debug_mode) printf("Kerberos V5: " "krb5_mk_rep failed (%s)\r\n", krb5_get_err_text(context, ret)); return; } Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length); } if (krb5_unparse_name(context, ticket->client, &name)) name = 0; if(UserNameRequested && krb5_kuserok(context, ticket->client, UserNameRequested)) { Data(ap, KRB_ACCEPT, name, name ? -1 : 0); if (auth_debug_mode) { printf("Kerberos5 identifies him as ``%s''\r\n", name ? name : ""); } if(key_block->keytype == KEYTYPE_DES) { Session_Key skey; skey.type = SK_DES; skey.length = 8; skey.data = key_block->keyvalue.data; encrypt_session_key(&skey, 0); } } else { char *msg; asprintf (&msg, "user `%s' is not authorized to " "login as `%s'", name ? name : "<unknown>", UserNameRequested ? UserNameRequested : "<nobody>"); if (msg == NULL) Data(ap, KRB_REJECT, NULL, 0); else { Data(ap, KRB_REJECT, (void *)msg, -1); free(msg); } } auth_finished(ap, AUTH_USER); krb5_free_keyblock_contents(context, key_block); break; #ifdef FORWARD case KRB_FORWARD: { struct passwd *pwd; char ccname[1024]; /* XXX */ krb5_data inbuf; krb5_ccache ccache; inbuf.data = (char *)data; inbuf.length = cnt; pwd = getpwnam (UserNameRequested); if (pwd == NULL) break; snprintf (ccname, sizeof(ccname), "FILE:/tmp/krb5cc_%u", pwd->pw_uid); ret = krb5_cc_resolve (context, ccname, &ccache); if (ret) { if (auth_debug_mode) printf ("Kerberos V5: could not get ccache: %s\r\n", krb5_get_err_text(context, ret)); break; } ret = krb5_cc_initialize (context, ccache, ticket->client); if (ret) { if (auth_debug_mode) printf ("Kerberos V5: could not init ccache: %s\r\n", krb5_get_err_text(context, ret)); break; } ret = krb5_rd_cred (context, auth_context, ccache, &inbuf); if(ret) { char *errbuf; asprintf (&errbuf, "Read forwarded creds failed: %s", krb5_get_err_text (context, ret)); if(errbuf == NULL) Data(ap, KRB_FORWARD_REJECT, NULL, 0); else Data(ap, KRB_FORWARD_REJECT, errbuf, -1); if (auth_debug_mode) printf("Could not read forwarded credentials: %s\r\n", errbuf); free (errbuf); } else Data(ap, KRB_FORWARD_ACCEPT, 0, 0); chown (ccname + 5, pwd->pw_uid, -1); if (auth_debug_mode) printf("Forwarded credentials obtained\r\n"); break; } #endif /* FORWARD */ default: if (auth_debug_mode) printf("Unknown Kerberos option %d\r\n", data[-1]); Data(ap, KRB_REJECT, 0, 0); break; } }
static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx, const char *realm_str, const char *princ_str, const char *keytab_name, const krb5_deltat lifetime, const char **ccname_out, time_t *expire_time_out) { char *ccname; char *realm_name = NULL; char *full_princ = NULL; char *default_realm = NULL; char *tmp_str = NULL; krb5_context context = NULL; krb5_keytab keytab = NULL; krb5_ccache ccache = NULL; krb5_principal kprinc; krb5_creds my_creds; krb5_get_init_creds_opt options; krb5_error_code krberr; krb5_timestamp kdc_time_offset; int canonicalize = 0; int kdc_time_offset_usec; int ret; krberr = krb5_init_context(&context); if (krberr) { DEBUG(SSSDBG_OP_FAILURE, "Failed to init kerberos context\n"); return krberr; } DEBUG(SSSDBG_TRACE_INTERNAL, "Kerberos context initialized\n"); krberr = set_child_debugging(context); if (krberr != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, "Cannot set krb5_child debugging\n"); } if (!realm_str) { krberr = krb5_get_default_realm(context, &default_realm); if (krberr) { DEBUG(SSSDBG_OP_FAILURE, "Failed to get default realm name: %s\n", sss_krb5_get_error_message(context, krberr)); goto done; } realm_name = talloc_strdup(memctx, default_realm); krb5_free_default_realm(context, default_realm); if (!realm_name) { krberr = KRB5KRB_ERR_GENERIC; goto done; } } else { realm_name = talloc_strdup(memctx, realm_str); if (!realm_name) { krberr = KRB5KRB_ERR_GENERIC; goto done; } } DEBUG(SSSDBG_TRACE_INTERNAL, "got realm_name: [%s]\n", realm_name); if (princ_str) { if (!strchr(princ_str, '@')) { full_princ = talloc_asprintf(memctx, "%s@%s", princ_str, realm_name); } else { full_princ = talloc_strdup(memctx, princ_str); } } else { char hostname[HOST_NAME_MAX + 1]; ret = gethostname(hostname, HOST_NAME_MAX); if (ret == -1) { krberr = KRB5KRB_ERR_GENERIC; goto done; } hostname[HOST_NAME_MAX] = '\0'; DEBUG(SSSDBG_TRACE_LIBS, "got hostname: [%s]\n", hostname); ret = select_principal_from_keytab(memctx, hostname, realm_name, keytab_name, &full_princ, NULL, NULL); if (ret) { krberr = KRB5_KT_IOERR; goto done; } } if (!full_princ) { krberr = KRB5KRB_ERR_GENERIC; goto done; } DEBUG(SSSDBG_CONF_SETTINGS, "Principal name is: [%s]\n", full_princ); krberr = krb5_parse_name(context, full_princ, &kprinc); if (krberr) { DEBUG(SSSDBG_OP_FAILURE, "Unable to build principal: %s\n", sss_krb5_get_error_message(context, krberr)); goto done; } if (keytab_name) { krberr = krb5_kt_resolve(context, keytab_name, &keytab); } else { krberr = krb5_kt_default(context, &keytab); } DEBUG(SSSDBG_CONF_SETTINGS, "Using keytab [%s]\n", KEYTAB_CLEAN_NAME); if (krberr) { DEBUG(SSSDBG_FATAL_FAILURE, "Failed to read keytab file [%s]: %s\n", KEYTAB_CLEAN_NAME, sss_krb5_get_error_message(context, krberr)); goto done; } /* Verify the keytab */ ret = sss_krb5_verify_keytab_ex(full_princ, keytab_name, context, keytab); if (ret) { DEBUG(SSSDBG_OP_FAILURE, "Unable to verify principal is present in the keytab\n"); krberr = KRB5_KT_IOERR; goto done; } ccname = talloc_asprintf(memctx, "FILE:%s/ccache_%s", DB_PATH, realm_name); if (!ccname) { krberr = KRB5KRB_ERR_GENERIC; goto done; } DEBUG(SSSDBG_TRACE_INTERNAL, "keytab ccname: [%s]\n", ccname); krberr = krb5_cc_resolve(context, ccname, &ccache); if (krberr) { DEBUG(SSSDBG_OP_FAILURE, "Failed to set cache name: %s\n", sss_krb5_get_error_message(context, krberr)); goto done; } memset(&my_creds, 0, sizeof(my_creds)); memset(&options, 0, sizeof(options)); krb5_get_init_creds_opt_set_address_list(&options, NULL); krb5_get_init_creds_opt_set_forwardable(&options, 0); krb5_get_init_creds_opt_set_proxiable(&options, 0); krb5_get_init_creds_opt_set_tkt_life(&options, lifetime); tmp_str = getenv("KRB5_CANONICALIZE"); if (tmp_str != NULL && strcasecmp(tmp_str, "true") == 0) { DEBUG(SSSDBG_CONF_SETTINGS, "Will canonicalize principals\n"); canonicalize = 1; } sss_krb5_get_init_creds_opt_set_canonicalize(&options, canonicalize); krberr = krb5_get_init_creds_keytab(context, &my_creds, kprinc, keytab, 0, NULL, &options); if (krberr) { DEBUG(SSSDBG_FATAL_FAILURE, "Failed to init credentials: %s\n", sss_krb5_get_error_message(context, krberr)); sss_log(SSS_LOG_ERR, "Failed to initialize credentials using keytab [%s]: %s. " "Unable to create GSSAPI-encrypted LDAP connection.", KEYTAB_CLEAN_NAME, sss_krb5_get_error_message(context, krberr)); goto done; } DEBUG(SSSDBG_TRACE_INTERNAL, "credentials initialized\n"); /* Use updated principal if changed due to canonicalization. */ krberr = krb5_cc_initialize(context, ccache, my_creds.client); if (krberr) { DEBUG(SSSDBG_OP_FAILURE, "Failed to init ccache: %s\n", sss_krb5_get_error_message(context, krberr)); goto done; } krberr = krb5_cc_store_cred(context, ccache, &my_creds); if (krberr) { DEBUG(SSSDBG_OP_FAILURE, "Failed to store creds: %s\n", sss_krb5_get_error_message(context, krberr)); goto done; } DEBUG(SSSDBG_TRACE_INTERNAL, "credentials stored\n"); #ifdef HAVE_KRB5_GET_TIME_OFFSETS krberr = krb5_get_time_offsets(context, &kdc_time_offset, &kdc_time_offset_usec); if (krberr) { DEBUG(SSSDBG_OP_FAILURE, "Failed to get KDC time offset: %s\n", sss_krb5_get_error_message(context, krberr)); kdc_time_offset = 0; } else { if (kdc_time_offset_usec > 0) { kdc_time_offset++; } } DEBUG(SSSDBG_TRACE_INTERNAL, "Got KDC time offset\n"); #else /* If we don't have this function, just assume no offset */ kdc_time_offset = 0; #endif krberr = 0; *ccname_out = ccname; *expire_time_out = my_creds.times.endtime - kdc_time_offset; done: if (krberr != 0) KRB5_SYSLOG(krberr); if (keytab) krb5_kt_close(context, keytab); if (context) krb5_free_context(context); return krberr; }
static void do_v5_kvno (int count, char *names[], char * ccache_name, char *etype_str, char *keytab_name, char *sname) { krb5_error_code ret; krb5_context context = 0; int i, errors; krb5_enctype etype; krb5_ccache ccache; krb5_principal me; krb5_creds in_creds, *out_creds = NULL; Ticket ticket; size_t len; char *princ = NULL; krb5_keytab keytab = NULL; ret = krb5_init_context(&context); if (ret) errx(1, "krb5_init_context failed: %d", ret); if (etype_str) { ret = krb5_string_to_enctype(context, etype_str, &etype); if (ret) krb5_err(context, 1, ret, "Failed to convert encryption type %s", etype_str); } else { etype = 0; } if (ccache_name) ret = krb5_cc_resolve(context, ccache_name, &ccache); else ret = krb5_cc_default(context, &ccache); if (ret) krb5_err(context, 1, ret, "Failed to open credentials cache %s", (ccache_name) ? ccache_name : "(Default)"); if (keytab_name) { ret = krb5_kt_resolve(context, keytab_name, &keytab); if (ret) krb5_err(context, 1, ret, "Can't resolve keytab %s", keytab_name); } ret = krb5_cc_get_principal(context, ccache, &me); if (ret) krb5_err(context, 1, ret, "krb5_cc_get_principal"); errors = 0; for (i = 0; i < count; i++) { memset(&in_creds, 0, sizeof(in_creds)); memset(&ticket, 0, sizeof(ticket)); 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_flag) krb5_warn(context, ret, "Couldn't parse principal name %s", names[i]); errors++; continue; } ret = krb5_unparse_name(context, in_creds.server, &princ); if (ret) { krb5_warn(context, ret, "Couldn't format parsed principal name for '%s'", names[i]); errors++; goto next; } in_creds.session.keytype = etype; ret = krb5_get_credentials(context, 0, ccache, &in_creds, &out_creds); if (ret) { krb5_warn(context, ret, "Couldn't get credentials for %s", princ); errors++; goto next; } ret = decode_Ticket(out_creds->ticket.data, out_creds->ticket.length, &ticket, &len); if (ret) { krb5_err(context, 1, ret, "Can't decode ticket for %s", princ); errors++; goto next; continue; } if (keytab) { krb5_keytab_entry kte; krb5_crypto crypto; krb5_data dec_data; EncTicketPart decr_part; ret = krb5_kt_get_entry(context, keytab, in_creds.server, (ticket.enc_part.kvno != NULL)? *ticket.enc_part.kvno : 0, ticket.enc_part.etype, &kte); if (ret) { krb5_warn(context, ret, "Can't decrypt ticket for %s", princ); if (!quiet_flag) printf("%s: kvno = %d, keytab entry invalid", princ, (ticket.enc_part.kvno != NULL)? *ticket.enc_part.kvno : 0); errors ++; goto next; } ret = krb5_crypto_init(context, &kte.keyblock, 0, &crypto); if (ret) { krb5_warn(context, ret, "krb5_crypto_init"); errors ++; krb5_kt_free_entry(context, &kte); goto next; } ret = krb5_decrypt_EncryptedData (context, crypto, KRB5_KU_TICKET, &ticket.enc_part, &dec_data); krb5_crypto_destroy(context, crypto); krb5_kt_free_entry(context, &kte); if (ret) { krb5_warn(context, ret, "krb5_decrypt_EncryptedData"); errors ++; goto next; } ret = decode_EncTicketPart(dec_data.data, dec_data.length, &decr_part, &len); krb5_data_free(&dec_data); if (ret) { krb5_warn(context, ret, "decode_EncTicketPart"); errors ++; goto next; } if (!quiet_flag) printf("%s: kvno = %d, keytab entry valid\n", princ, (ticket.enc_part.kvno != NULL)? *ticket.enc_part.kvno : 0); free_EncTicketPart(&decr_part); } else { if (!quiet_flag) printf("%s: kvno = %d\n", princ, (ticket.enc_part.kvno != NULL)? *ticket.enc_part.kvno : 0); } next: if (out_creds) { krb5_free_creds(context, out_creds); out_creds = NULL; } if (princ) { krb5_free_unparsed_name(context, princ); princ = NULL; } krb5_free_principal(context, in_creds.server); free_Ticket(&ticket); } 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); }
int main (int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_ccache ccache; krb5_principal principal; int optidx = 0; krb5_deltat ticket_life = 0; int parseflags = 0; setprogname (argv[0]); setlocale (LC_ALL, ""); bindtextdomain ("heimdal_kuser", HEIMDAL_LOCALEDIR); textdomain("heimdal_kuser"); ret = krb5_init_context (&context); if (ret == KRB5_CONFIG_BADFORMAT) errx (1, "krb5_init_context failed to parse configuration file"); else if (ret) errx(1, "krb5_init_context failed: %d", ret); if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) usage(1); if (help_flag) usage (0); if(version_flag) { print_version(NULL); exit(0); } argc -= optidx; argv += optidx; if (canonicalize_flag || enterprise_flag) parseflags |= KRB5_PRINCIPAL_PARSE_ENTERPRISE; if (pk_enterprise_flag) { ret = krb5_pk_enterprise_cert(context, pk_user_id, argv[0], &principal, &ent_user_id); if (ret) krb5_err(context, 1, ret, "krb5_pk_enterprise_certs"); pk_user_id = NULL; } else if (anonymous_flag) { ret = krb5_make_principal(context, &principal, argv[0], KRB5_WELLKNOWN_NAME, KRB5_ANON_NAME, NULL); if (ret) krb5_err(context, 1, ret, "krb5_make_principal"); krb5_principal_set_type(context, principal, KRB5_NT_WELLKNOWN); } else { if (argv[0]) { ret = krb5_parse_name_flags (context, argv[0], parseflags, &principal); if (ret) krb5_err (context, 1, ret, "krb5_parse_name"); } else { ret = krb5_get_default_principal (context, &principal); if (ret) krb5_err (context, 1, ret, "krb5_get_default_principal"); } } if(fcache_version) krb5_set_fcache_version(context, fcache_version); if(renewable_flag == -1) /* this seems somewhat pointless, but whatever */ krb5_appdefault_boolean(context, "kinit", krb5_principal_get_realm(context, principal), "renewable", FALSE, &renewable_flag); if(do_afslog == -1) krb5_appdefault_boolean(context, "kinit", krb5_principal_get_realm(context, principal), "afslog", TRUE, &do_afslog); if(cred_cache) ret = krb5_cc_resolve(context, cred_cache, &ccache); else { if(argc > 1) { char s[1024]; ret = krb5_cc_new_unique(context, NULL, NULL, &ccache); if(ret) krb5_err(context, 1, ret, "creating cred cache"); snprintf(s, sizeof(s), "%s:%s", krb5_cc_get_type(context, ccache), krb5_cc_get_name(context, ccache)); setenv("KRB5CCNAME", s, 1); } else { ret = krb5_cc_cache_match(context, principal, &ccache); if (ret) { const char *type; ret = krb5_cc_default (context, &ccache); if (ret) krb5_err (context, 1, ret, N_("resolving credentials cache", "")); /* * Check if the type support switching, and we do, * then do that instead over overwriting the current * default credential */ type = krb5_cc_get_type(context, ccache); if (krb5_cc_support_switch(context, type)) { krb5_cc_close(context, ccache); ret = krb5_cc_new_unique(context, type, NULL, &ccache); } } } } if (ret) krb5_err (context, 1, ret, N_("resolving credentials cache", "")); #ifndef NO_AFS if(argc > 1 && k_hasafs ()) k_setpag(); #endif if (lifetime) { int tmp = parse_time (lifetime, "s"); if (tmp < 0) errx (1, N_("unparsable time: %s", ""), lifetime); ticket_life = tmp; } if(addrs_flag == 0 && extra_addresses.num_strings > 0) krb5_errx(context, 1, N_("specifying both extra addresses and " "no addresses makes no sense", "")); { int i; krb5_addresses addresses; memset(&addresses, 0, sizeof(addresses)); for(i = 0; i < extra_addresses.num_strings; i++) { ret = krb5_parse_address(context, extra_addresses.strings[i], &addresses); if (ret == 0) { krb5_add_extra_addresses(context, &addresses); krb5_free_addresses(context, &addresses); } } free_getarg_strings(&extra_addresses); } if(renew_flag || validate_flag) { ret = renew_validate(context, renew_flag, validate_flag, ccache, server_str, ticket_life); exit(ret != 0); } get_new_tickets(context, principal, ccache, ticket_life, 1); #ifndef NO_AFS if(do_afslog && k_hasafs()) krb5_afslog(context, ccache, NULL, NULL); #endif if(argc > 1) { struct renew_ctx ctx; time_t timeout; timeout = ticket_lifetime(context, ccache, principal, server_str) / 2; ctx.context = context; ctx.ccache = ccache; ctx.principal = principal; ctx.ticket_life = ticket_life; ret = simple_execvp_timed(argv[1], argv+1, renew_func, &ctx, timeout); #define EX_NOEXEC 126 #define EX_NOTFOUND 127 if(ret == EX_NOEXEC) krb5_warnx(context, N_("permission denied: %s", ""), argv[1]); else if(ret == EX_NOTFOUND) krb5_warnx(context, N_("command not found: %s", ""), argv[1]); krb5_cc_destroy(context, ccache); #ifndef NO_AFS if(k_hasafs()) k_unlog(); #endif } else { krb5_cc_close (context, ccache); ret = 0; } krb5_free_principal(context, principal); krb5_free_context (context); return ret; }
static krb5_error_code get_ccache(krb5_context context, int *destroy, krb5_ccache *id) { krb5_principal principal = NULL; krb5_error_code ret; krb5_keytab kt = NULL; *id = NULL; if (!issuid()) { const char *cache; cache = getenv("NTLM_ACCEPTOR_CCACHE"); if (cache) { ret = krb5_cc_resolve(context, cache, id); if (ret) goto out; return 0; } } ret = krb5_sname_to_principal(context, NULL, "host", KRB5_NT_SRV_HST, &principal); if (ret) goto out; ret = krb5_cc_cache_match(context, principal, id); if (ret == 0) return 0; /* did not find in default credcache, lets try default keytab */ ret = krb5_kt_default(context, &kt); if (ret) goto out; /* XXX check in keytab */ { krb5_get_init_creds_opt *opt; krb5_creds cred; memset(&cred, 0, sizeof(cred)); ret = krb5_cc_new_unique(context, "MEMORY", NULL, id); if (ret) goto out; *destroy = 1; ret = krb5_get_init_creds_opt_alloc(context, &opt); if (ret) goto out; ret = krb5_get_init_creds_keytab (context, &cred, principal, kt, 0, NULL, opt); krb5_get_init_creds_opt_free(context, opt); if (ret) goto out; ret = krb5_cc_initialize (context, *id, cred.client); if (ret) { krb5_free_cred_contents (context, &cred); goto out; } ret = krb5_cc_store_cred (context, *id, &cred); krb5_free_cred_contents (context, &cred); if (ret) goto out; } krb5_kt_close(context, kt); return 0; out: if (*id) { if (*destroy) krb5_cc_destroy(context, *id); else krb5_cc_close(context, *id); *id = NULL; } if (kt) krb5_kt_close(context, kt); if (principal) krb5_free_principal(context, principal); return ret; }
/* * Obtain credentials via a key in the keytab given * a keytab handle and a gssd_k5_kt_princ structure. * Checks to see if current credentials are expired, * if not, uses the keytab to obtain new credentials. * * Returns: * 0 => success (or credentials have not expired) * nonzero => error */ static int gssd_get_single_krb5_cred(krb5_context context, krb5_keytab kt, struct gssd_k5_kt_princ *ple, int nocache) { #if HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS krb5_get_init_creds_opt *init_opts = NULL; #else krb5_get_init_creds_opt options; #endif krb5_get_init_creds_opt *opts; krb5_creds my_creds; krb5_ccache ccache = NULL; char kt_name[BUFSIZ]; char cc_name[BUFSIZ]; int code; time_t now = time(0); char *cache_type; char *pname = NULL; char *k5err = NULL; memset(&my_creds, 0, sizeof(my_creds)); if (ple->ccname && ple->endtime > now && !nocache) { printerr(2, "INFO: Credentials in CC '%s' are good until %d\n", ple->ccname, ple->endtime); code = 0; goto out; } code = krb5_kt_get_name(context, kt, kt_name, BUFSIZ); if (code != 0) { printerr(0, "ERROR: Unable to get keytab name in " "gssd_get_single_krb5_cred\n"); goto out; } if ((krb5_unparse_name(context, ple->princ, &pname))) pname = NULL; #if HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS code = krb5_get_init_creds_opt_alloc(context, &init_opts); if (code) { k5err = gssd_k5_err_msg(context, code); printerr(0, "ERROR: %s allocating gic options\n", k5err); goto out; } if (krb5_get_init_creds_opt_set_addressless(context, init_opts, 1)) printerr(1, "WARNING: Unable to set option for addressless " "tickets. May have problems behind a NAT.\n"); #ifdef TEST_SHORT_LIFETIME /* set a short lifetime (for debugging only!) */ printerr(0, "WARNING: Using (debug) short machine cred lifetime!\n"); krb5_get_init_creds_opt_set_tkt_life(init_opts, 5 * 60); #endif opts = init_opts; #else /* HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS */ krb5_get_init_creds_opt_init(&options); krb5_get_init_creds_opt_set_address_list(&options, NULL); #ifdef TEST_SHORT_LIFETIME /* set a short lifetime (for debugging only!) */ printerr(0, "WARNING: Using (debug) short machine cred lifetime!\n"); krb5_get_init_creds_opt_set_tkt_life(&options, 5 * 60); #endif opts = &options; #endif code = krb5_get_init_creds_keytab(context, &my_creds, ple->princ, kt, 0, NULL, opts); if (code != 0) { k5err = gssd_k5_err_msg(context, code); printerr(1, "WARNING: %s while getting initial ticket for " "principal '%s' using keytab '%s'\n", k5err, pname ? pname : "<unparsable>", kt_name); goto out; } /* * Initialize cache file which we're going to be using */ if (use_memcache) cache_type = "MEMORY"; else cache_type = "FILE"; snprintf(cc_name, sizeof(cc_name), "%s:%s/%s%s_%s", cache_type, ccachesearch[0], GSSD_DEFAULT_CRED_PREFIX, GSSD_DEFAULT_MACHINE_CRED_SUFFIX, ple->realm); ple->endtime = my_creds.times.endtime; if (ple->ccname != NULL) gsh_free(ple->ccname); ple->ccname = gsh_strdup(cc_name); if (ple->ccname == NULL) { printerr(0, "ERROR: no storage to duplicate credentials " "cache name '%s'\n", cc_name); code = ENOMEM; goto out; } code = krb5_cc_resolve(context, cc_name, &ccache); if (code != 0) { k5err = gssd_k5_err_msg(context, code); printerr(0, "ERROR: %s while opening credential cache '%s'\n", k5err, cc_name); goto out; } code = krb5_cc_initialize(context, ccache, ple->princ); if (code != 0) { k5err = gssd_k5_err_msg(context, code); printerr(0, "ERROR: %s while initializing credential " "cache '%s'\n", k5err, cc_name); } code = krb5_cc_store_cred(context, ccache, &my_creds); if (code != 0) { k5err = gssd_k5_err_msg(context, code); printerr(0, "ERROR: %s while storing credentials in '%s'\n", k5err, cc_name); goto out; } /* if we get this far, let gss mech know */ gssd_set_krb5_ccache_name(cc_name); code = 0; printerr(2, "Successfully obtained machine credentials for " "principal '%s' stored in ccache '%s'\n", pname, cc_name); out: #if HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS if (init_opts) krb5_get_init_creds_opt_free(context, init_opts); #endif if (pname) k5_free_unparsed_name(context, pname); if (ccache) krb5_cc_close(context, ccache); krb5_free_cred_contents(context, &my_creds); gsh_free(k5err); return code; }
static krb5_error_code get_new_tickets(krb5_context context, krb5_principal principal, krb5_ccache ccache, krb5_deltat ticket_life, int interactive) { krb5_error_code ret; krb5_get_init_creds_opt *opt; krb5_creds cred; char passwd[256]; krb5_deltat start_time = 0; krb5_deltat renew = 0; const char *renewstr = NULL; krb5_enctype *enctype = NULL; krb5_ccache tempccache; krb5_keytab kt = NULL; krb5_init_creds_context ctx; #ifndef NO_NTLM struct ntlm_buf ntlmkey; memset(&ntlmkey, 0, sizeof(ntlmkey)); #endif passwd[0] = '\0'; if (password_file) { FILE *f; if (strcasecmp("STDIN", password_file) == 0) f = stdin; else f = fopen(password_file, "r"); if (f == NULL) krb5_errx(context, 1, "Failed to open the password file %s", password_file); if (fgets(passwd, sizeof(passwd), f) == NULL) krb5_errx(context, 1, N_("Failed to read password from file %s", ""), password_file); if (f != stdin) fclose(f); passwd[strcspn(passwd, "\n")] = '\0'; } #ifdef __APPLE__ if (passwd[0] == '\0') { const char *realm; OSStatus osret; UInt32 length; void *buffer; char *name; realm = krb5_principal_get_realm(context, principal); ret = krb5_unparse_name_flags(context, principal, KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name); if (ret) goto nopassword; osret = SecKeychainFindGenericPassword(NULL, strlen(realm), realm, strlen(name), name, &length, &buffer, NULL); free(name); if (osret == noErr && length < sizeof(passwd) - 1) { memcpy(passwd, buffer, length); passwd[length] = '\0'; } nopassword: do { } while(0); } #endif memset(&cred, 0, sizeof(cred)); ret = krb5_get_init_creds_opt_alloc (context, &opt); if (ret) krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc"); krb5_get_init_creds_opt_set_default_flags(context, "kinit", krb5_principal_get_realm(context, principal), opt); if(forwardable_flag != -1) krb5_get_init_creds_opt_set_forwardable (opt, forwardable_flag); if(proxiable_flag != -1) krb5_get_init_creds_opt_set_proxiable (opt, proxiable_flag); if(anonymous_flag) krb5_get_init_creds_opt_set_anonymous (opt, anonymous_flag); if (pac_flag != -1) krb5_get_init_creds_opt_set_pac_request(context, opt, pac_flag ? TRUE : FALSE); if (canonicalize_flag) krb5_get_init_creds_opt_set_canonicalize(context, opt, TRUE); if (pk_enterprise_flag || enterprise_flag || canonicalize_flag || windows_flag) krb5_get_init_creds_opt_set_win2k(context, opt, TRUE); if (pk_user_id || ent_user_id || anonymous_flag) { ret = krb5_get_init_creds_opt_set_pkinit(context, opt, principal, pk_user_id, pk_x509_anchors, NULL, NULL, pk_use_enckey ? 2 : 0 | anonymous_flag ? 4 : 0, krb5_prompter_posix, NULL, passwd); if (ret) krb5_err(context, 1, ret, "krb5_get_init_creds_opt_set_pkinit"); if (ent_user_id) krb5_get_init_creds_opt_set_pkinit_user_certs(context, opt, ent_user_id); } if (addrs_flag != -1) krb5_get_init_creds_opt_set_addressless(context, opt, addrs_flag ? FALSE : TRUE); if (renew_life == NULL && renewable_flag) renewstr = "1 month"; if (renew_life) renewstr = renew_life; if (renewstr) { renew = parse_time (renewstr, "s"); if (renew < 0) errx (1, "unparsable time: %s", renewstr); krb5_get_init_creds_opt_set_renew_life (opt, renew); } if(ticket_life != 0) krb5_get_init_creds_opt_set_tkt_life (opt, ticket_life); if(start_str) { int tmp = parse_time (start_str, "s"); if (tmp < 0) errx (1, N_("unparsable time: %s", ""), start_str); start_time = tmp; } if(etype_str.num_strings) { int i; enctype = malloc(etype_str.num_strings * sizeof(*enctype)); if(enctype == NULL) errx(1, "out of memory"); for(i = 0; i < etype_str.num_strings; i++) { ret = krb5_string_to_enctype(context, etype_str.strings[i], &enctype[i]); if(ret) errx(1, "unrecognized enctype: %s", etype_str.strings[i]); } krb5_get_init_creds_opt_set_etype_list(opt, enctype, etype_str.num_strings); } ret = krb5_init_creds_init(context, principal, krb5_prompter_posix, NULL, start_time, opt, &ctx); if (ret) krb5_err(context, 1, ret, "krb5_init_creds_init"); if (server_str) { ret = krb5_init_creds_set_service(context, ctx, server_str); if (ret) krb5_err(context, 1, ret, "krb5_init_creds_set_service"); } if (fast_armor_cache_string) { krb5_ccache fastid; ret = krb5_cc_resolve(context, fast_armor_cache_string, &fastid); if (ret) krb5_err(context, 1, ret, "krb5_cc_resolve(FAST cache)"); ret = krb5_init_creds_set_fast_ccache(context, ctx, fastid); if (ret) krb5_err(context, 1, ret, "krb5_init_creds_set_fast_ccache"); } if(use_keytab || keytab_str) { if(keytab_str) ret = krb5_kt_resolve(context, keytab_str, &kt); else ret = krb5_kt_default(context, &kt); if (ret) krb5_err(context, 1, ret, "resolving keytab"); ret = krb5_init_creds_set_keytab(context, ctx, kt); if (ret) krb5_err(context, 1, ret, "krb5_init_creds_set_keytab"); } else if (pk_user_id || ent_user_id || anonymous_flag) { } else if (!interactive) { krb5_warnx(context, "Not interactive, failed to get initial ticket"); krb5_get_init_creds_opt_free(context, opt); return 0; } else { if (passwd[0] == '\0') { char *p, *prompt; krb5_unparse_name (context, principal, &p); asprintf (&prompt, N_("%s's Password: "******""), p); free (p); if (UI_UTIL_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0)){ memset(passwd, 0, sizeof(passwd)); errx(1, "failed to read password"); } free (prompt); } if (passwd[0]) { ret = krb5_init_creds_set_password(context, ctx, passwd); if (ret) krb5_err(context, 1, ret, "krb5_init_creds_set_password"); } } ret = krb5_init_creds_get(context, ctx); #ifndef NO_NTLM if (ntlm_domain && passwd[0]) heim_ntlm_nt_key(passwd, &ntlmkey); #endif memset(passwd, 0, sizeof(passwd)); switch(ret){ case 0: break; case KRB5_LIBOS_PWDINTR: /* don't print anything if it was just C-c:ed */ exit(1); case KRB5KRB_AP_ERR_BAD_INTEGRITY: case KRB5KRB_AP_ERR_MODIFIED: case KRB5KDC_ERR_PREAUTH_FAILED: krb5_errx(context, 1, N_("Password incorrect", "")); break; case KRB5KRB_AP_ERR_V4_REPLY: krb5_errx(context, 1, N_("Looks like a Kerberos 4 reply", "")); break; default: krb5_err(context, 1, ret, "krb5_get_init_creds"); } krb5_process_last_request(context, opt, ctx); if(ticket_life != 0) { if(abs(cred.times.endtime - cred.times.starttime - ticket_life) > 30) { char life[64]; unparse_time_approx(cred.times.endtime - cred.times.starttime, life, sizeof(life)); krb5_warnx(context, N_("NOTICE: ticket lifetime is %s", ""), life); } } if(renew_life) { if(abs(cred.times.renew_till - cred.times.starttime - renew) > 30) { char life[64]; unparse_time_approx(cred.times.renew_till - cred.times.starttime, life, sizeof(life)); krb5_warnx(context, N_("NOTICE: ticket renewable lifetime is %s", ""), life); } } ret = krb5_cc_new_unique(context, krb5_cc_get_type(context, ccache), NULL, &tempccache); if (ret) krb5_err (context, 1, ret, "krb5_cc_new_unique"); ret = krb5_init_creds_store(context, ctx, tempccache); if (ret) krb5_err(context, 1, ret, "krb5_init_creds_store"); krb5_init_creds_free(context, ctx); ret = krb5_cc_move(context, tempccache, ccache); if (ret) krb5_err (context, 1, ret, "krb5_cc_move"); if (switch_cache_flags) krb5_cc_switch(context, ccache); #ifndef NO_NTLM if (ntlm_domain && ntlmkey.data) store_ntlmkey(context, ccache, ntlm_domain, &ntlmkey); #endif if (ok_as_delegate_flag || windows_flag || use_referrals_flag) { unsigned char d = 0; krb5_data data; if (ok_as_delegate_flag || windows_flag) d |= 1; if (use_referrals_flag || windows_flag) d |= 2; data.length = 1; data.data = &d; krb5_cc_set_config(context, ccache, NULL, "realm-config", &data); } krb5_get_init_creds_opt_free(context, opt); if (kt) krb5_kt_close(context, kt); if (enctype) free(enctype); return 0; }
static int create_krb5_tickets (krb5_context context, krb5_keytab kt) { krb5_error_code ret; krb5_keytab_entry entry; krb5_creds cred; krb5_enctype etype; krb5_ccache ccache; memset (&cred, 0, sizeof(cred)); ret = krb5_string_to_enctype (context, enc_type, &etype); if (ret) krb5_err (context, 1, ret, "krb5_string_to_enctype"); ret = krb5_kt_get_entry (context, kt, server_principal, 0, etype, &entry); if (ret) krb5_err (context, 1, ret, "krb5_kt_get_entry"); /* * setup cred */ ret = krb5_copy_principal (context, client_principal, &cred.client); if (ret) krb5_err (context, 1, ret, "krb5_copy_principal"); ret = krb5_copy_principal (context, server_principal, &cred.server); if (ret) krb5_err (context, 1, ret, "krb5_copy_principal"); krb5_generate_random_keyblock(context, etype, &cred.session); cred.times.authtime = time(NULL); cred.times.starttime = time(NULL); cred.times.endtime = time(NULL) + expiration_time; cred.times.renew_till = 0; krb5_data_zero(&cred.second_ticket); ret = krb5_get_all_client_addrs (context, &cred.addresses); if (ret) krb5_err (context, 1, ret, "krb5_get_all_client_addrs"); cred.flags.b = ticket_flags; /* * Encode encrypted part of ticket */ encode_ticket (context, &entry.keyblock, etype, entry.vno, &cred); /* * Write to cc */ if (ccache_str) { ret = krb5_cc_resolve(context, ccache_str, &ccache); if (ret) krb5_err (context, 1, ret, "krb5_cc_resolve"); } else { ret = krb5_cc_default (context, &ccache); if (ret) krb5_err (context, 1, ret, "krb5_cc_default"); } ret = krb5_cc_initialize (context, ccache, cred.client); if (ret) krb5_err (context, 1, ret, "krb5_cc_initialize"); ret = krb5_cc_store_cred (context, ccache, &cred); if (ret) krb5_err (context, 1, ret, "krb5_cc_store_cred"); krb5_free_cred_contents (context, &cred); krb5_cc_close (context, ccache); return 0; }
OM_uint32 GSSAPI_CALLCONV _gsskrb5_add_cred ( OM_uint32 *minor_status, gss_const_cred_id_t input_cred_handle, gss_const_name_t desired_name, const gss_OID desired_mech, gss_cred_usage_t cred_usage, OM_uint32 initiator_time_req, OM_uint32 acceptor_time_req, gss_cred_id_t *output_cred_handle, gss_OID_set *actual_mechs, OM_uint32 *initiator_time_rec, OM_uint32 *acceptor_time_rec) { krb5_context context; OM_uint32 ret, lifetime; gsskrb5_cred cred, handle; krb5_const_principal dname; handle = NULL; cred = (gsskrb5_cred)input_cred_handle; dname = (krb5_const_principal)desired_name; GSSAPI_KRB5_INIT (&context); if (gss_oid_equal(desired_mech, GSS_KRB5_MECHANISM) == 0) { *minor_status = 0; return GSS_S_BAD_MECH; } if (cred == NULL && output_cred_handle == NULL) { *minor_status = 0; return GSS_S_NO_CRED; } if (cred == NULL) { /* XXX standard conformance failure */ *minor_status = 0; return GSS_S_NO_CRED; } /* check if requested output usage is compatible with output usage */ if (output_cred_handle != NULL) { HEIMDAL_MUTEX_lock(&cred->cred_id_mutex); if (cred->usage != cred_usage && cred->usage != GSS_C_BOTH) { HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); *minor_status = GSS_KRB5_S_G_BAD_USAGE; return(GSS_S_FAILURE); } } /* check that we have the same name */ if (dname != NULL && krb5_principal_compare(context, dname, cred->principal) != FALSE) { if (output_cred_handle) HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); *minor_status = 0; return GSS_S_BAD_NAME; } /* make a copy */ if (output_cred_handle) { krb5_error_code kret; handle = calloc(1, sizeof(*handle)); if (handle == NULL) { HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); *minor_status = ENOMEM; return (GSS_S_FAILURE); } handle->usage = cred_usage; handle->lifetime = cred->lifetime; handle->principal = NULL; handle->keytab = NULL; handle->ccache = NULL; handle->mechanisms = NULL; HEIMDAL_MUTEX_init(&handle->cred_id_mutex); ret = GSS_S_FAILURE; kret = krb5_copy_principal(context, cred->principal, &handle->principal); if (kret) { HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); free(handle); *minor_status = kret; return GSS_S_FAILURE; } if (cred->keytab) { char *name = NULL; ret = GSS_S_FAILURE; kret = krb5_kt_get_full_name(context, cred->keytab, &name); if (kret) { *minor_status = kret; goto failure; } kret = krb5_kt_resolve(context, name, &handle->keytab); krb5_xfree(name); if (kret){ *minor_status = kret; goto failure; } } if (cred->ccache) { const char *type, *name; char *type_name = NULL; ret = GSS_S_FAILURE; type = krb5_cc_get_type(context, cred->ccache); if (type == NULL){ *minor_status = ENOMEM; goto failure; } if (strcmp(type, "MEMORY") == 0) { ret = krb5_cc_new_unique(context, type, NULL, &handle->ccache); if (ret) { *minor_status = ret; goto failure; } ret = krb5_cc_copy_cache(context, cred->ccache, handle->ccache); if (ret) { *minor_status = ret; goto failure; } } else { name = krb5_cc_get_name(context, cred->ccache); if (name == NULL) { *minor_status = ENOMEM; goto failure; } kret = asprintf(&type_name, "%s:%s", type, name); if (kret < 0 || type_name == NULL) { *minor_status = ENOMEM; goto failure; } kret = krb5_cc_resolve(context, type_name, &handle->ccache); free(type_name); if (kret) { *minor_status = kret; goto failure; } } } ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms); if (ret) goto failure; ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM, &handle->mechanisms); if (ret) goto failure; } HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); ret = _gsskrb5_inquire_cred(minor_status, (gss_cred_id_t)cred, NULL, &lifetime, NULL, actual_mechs); if (ret) goto failure; if (initiator_time_rec) *initiator_time_rec = lifetime; if (acceptor_time_rec) *acceptor_time_rec = lifetime; if (output_cred_handle) { *output_cred_handle = (gss_cred_id_t)handle; } *minor_status = 0; return ret; failure: if (handle) { if (handle->principal) krb5_free_principal(context, handle->principal); if (handle->keytab) krb5_kt_close(context, handle->keytab); if (handle->ccache) krb5_cc_destroy(context, handle->ccache); if (handle->mechanisms) gss_release_oid_set(NULL, &handle->mechanisms); free(handle); } if (output_cred_handle) HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); return ret; }
krb5_error_code KRB5_CALLCONV krb5_verify_init_creds(krb5_context context, krb5_creds *creds, krb5_principal server_arg, krb5_keytab keytab_arg, krb5_ccache *ccache_arg, krb5_verify_init_creds_opt *options) { krb5_error_code ret; krb5_principal server; krb5_keytab keytab; krb5_ccache ccache; krb5_keytab_entry kte; krb5_creds in_creds, *out_creds; krb5_auth_context authcon; krb5_data ap_req; /* KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN */ server = NULL; keytab = NULL; ccache = NULL; out_creds = NULL; authcon = NULL; ap_req.data = NULL; if (keytab_arg) { keytab = keytab_arg; } else { if ((ret = krb5_kt_default(context, &keytab))) goto cleanup; } if (server_arg) { ret = krb5_copy_principal(context, server_arg, &server); if (ret) goto cleanup; } else { /* Use a principal name from the keytab. */ ret = k5_kt_get_principal(context, keytab, &server); if (ret) { /* There's no keytab, or it's empty, or we can't read it. * Allow this unless configuration demands verification. */ if (!nofail(context, options, creds)) ret = 0; goto cleanup; } } /* first, check if the server is in the keytab. If not, there's no reason to continue. rd_req does all this, but there's no way to know that a given error is caused by a missing keytab or key, and not by some other problem. */ if (krb5_is_referral_realm(&server->realm)) { krb5_free_data_contents(context, &server->realm); ret = krb5_get_default_realm(context, &server->realm.data); if (ret) goto cleanup; server->realm.length = strlen(server->realm.data); } if ((ret = krb5_kt_get_entry(context, keytab, server, 0, 0, &kte))) { /* this means there is no keying material. This is ok, as long as it is not prohibited by the configuration */ if (!nofail(context, options, creds)) ret = 0; goto cleanup; } krb5_kt_free_entry(context, &kte); /* If the creds are for the server principal, we're set, just do a mk_req. * Otherwise, do a get_credentials first. */ if (krb5_principal_compare(context, server, creds->server)) { /* make an ap_req */ if ((ret = krb5_mk_req_extended(context, &authcon, 0, NULL, creds, &ap_req))) goto cleanup; } else { /* this is unclean, but it's the easiest way without ripping the library into very small pieces. store the client's initial cred in a memory ccache, then call the library. Later, we'll copy everything except the initial cred into the ccache we return to the user. A clean implementation would involve library internals with a coherent idea of "in" and "out". */ /* insert the initial cred into the ccache */ if ((ret = krb5_cc_new_unique(context, "MEMORY", NULL, &ccache))) { ccache = NULL; goto cleanup; } if ((ret = krb5_cc_initialize(context, ccache, creds->client))) goto cleanup; if ((ret = krb5_cc_store_cred(context, ccache, creds))) goto cleanup; /* set up for get_creds */ memset(&in_creds, 0, sizeof(in_creds)); in_creds.client = creds->client; in_creds.server = server; if ((ret = krb5_timeofday(context, &in_creds.times.endtime))) goto cleanup; in_creds.times.endtime += 5*60; if ((ret = krb5_get_credentials(context, 0, ccache, &in_creds, &out_creds))) goto cleanup; /* make an ap_req */ if ((ret = krb5_mk_req_extended(context, &authcon, 0, NULL, out_creds, &ap_req))) goto cleanup; } /* wipe the auth context for mk_req */ if (authcon) { krb5_auth_con_free(context, authcon); authcon = NULL; } /* verify the ap_req */ if ((ret = krb5_rd_req(context, &authcon, &ap_req, server, keytab, NULL, NULL))) goto cleanup; /* if we get this far, then the verification succeeded. We can still fail if the library stuff here fails, but that's it */ if (ccache_arg && ccache) { if (*ccache_arg == NULL) { krb5_ccache retcc; retcc = NULL; if ((ret = krb5_cc_resolve(context, "MEMORY:rd_req2", &retcc)) || (ret = krb5_cc_initialize(context, retcc, creds->client)) || (ret = copy_creds_except(context, ccache, retcc, creds->server))) { if (retcc) krb5_cc_destroy(context, retcc); } else { *ccache_arg = retcc; } } else { ret = copy_creds_except(context, ccache, *ccache_arg, server); } } /* if any of the above paths returned an errors, then ret is set accordingly. * Either that, or it's zero, which is fine, too */ cleanup: if ( server) krb5_free_principal(context, server); if (!keytab_arg && keytab) krb5_kt_close(context, keytab); if (ccache) krb5_cc_destroy(context, ccache); if (out_creds) krb5_free_creds(context, out_creds); if (authcon) krb5_auth_con_free(context, authcon); if (ap_req.data) free(ap_req.data); return(ret); }
static kbrccache_t userinitcontext( const char * user, const char * domain, const char * passwd, const char * cachename, int initialize, int * outError ) { krb5_context kcontext = 0; krb5_ccache kcache = 0; krb5_creds kcreds; krb5_principal kme = 0; krb5_error_code kres; char * pPass = strdup( passwd ); char * pName = NULL; char * pCacheName = NULL; int numCreds = 0; memset( &kcreds, 0, sizeof(kcreds) ); kres = krb5_init_context( &kcontext ); if( kres ) goto return_error; if( domain ) kres = krb5_build_principal( kcontext, &kme, strlen(domain), domain, user, (char *) 0 ); else kres = krb5_parse_name( kcontext, user, &kme ); if( kres ) goto fail; krb5_unparse_name( kcontext, kme, &pName ); if( cachename ) { if (asprintf(&pCacheName, "%s%s", cachename, pName) < 0) { kres = KRB5_CC_NOMEM; goto fail; } kres = krb5_cc_resolve( kcontext, pCacheName, &kcache ); if( kres ) { kres = krb5_cc_resolve( kcontext, CCACHE_PREFIX_DEFAULT, &kcache ); if( kres == 0 ) pCacheName = strdup(CCACHE_PREFIX_DEFAULT); } } else { kres = krb5_cc_default( kcontext, &kcache ); pCacheName = strdup( krb5_cc_get_name( kcontext, kcache ) ); } if( kres ) { krb5_free_context(kcontext); goto return_error; } if( initialize ) krb5_cc_initialize( kcontext, kcache, kme ); if( kres == 0 && user && passwd ) { long timeneeded = time(0L) +TKTTIMELEFT; int have_credentials = 0; krb5_cc_cursor cc_curs = NULL; numCreds = 0; if( (kres=krb5_cc_start_seq_get(kcontext, kcache, &cc_curs)) >= 0 ) { while( (kres=krb5_cc_next_cred(kcontext, kcache, &cc_curs, &kcreds))== 0) { numCreds++; if( krb5_principal_compare( kcontext, kme, kcreds.client ) ) { if( kcreds.ticket_flags & TKT_FLG_INITIAL && kcreds.times.endtime>timeneeded ) have_credentials = 1; } krb5_free_cred_contents( kcontext, &kcreds ); if( have_credentials ) break; } krb5_cc_end_seq_get( kcontext, kcache, &cc_curs ); } else { const char * errmsg = error_message(kres); fprintf( stderr, "%s user init(%s): %s\n", "setpass", pName, errmsg ); } if( kres != 0 || have_credentials == 0 ) { krb5_get_init_creds_opt *options = NULL; kres = krb5_get_init_creds_opt_alloc(kcontext, &options); if ( kres == 0 ) { get_init_creds_opt_init(options); /* ** no valid credentials - get new ones */ kres = krb5_get_init_creds_password( kcontext, &kcreds, kme, pPass, NULL /*prompter*/, NULL /*data*/, 0 /*starttime*/, 0 /*in_tkt_service*/, options /*options*/ ); } if( kres == 0 ) { if( numCreds <= 0 ) kres = krb5_cc_initialize( kcontext, kcache, kme ); if( kres == 0 ) kres = krb5_cc_store_cred( kcontext, kcache, &kcreds ); if( kres == 0 ) have_credentials = 1; } krb5_get_init_creds_opt_free(kcontext, options); } #ifdef NOTUSED if( have_credentials ) { int mstat; kres = gss_krb5_ccache_name( &mstat, pCacheName, NULL ); if( getenv( ENV_DEBUG_LDAPKERB ) ) fprintf( stderr, "gss credentials cache set to %s(%d)\n", pCacheName, kres ); } #endif krb5_cc_close( kcontext, kcache ); } fail: if( kres ) { const char * errmsg = error_message(kres); fprintf( stderr, "%s user init(%s): %s\n", "setpass", pName, errmsg ); } krb5_free_principal( kcontext, kme ); krb5_free_cred_contents( kcontext, &kcreds ); if( pName ) free( pName ); free(pPass); krb5_free_context(kcontext); return_error: if( kres ) { if( pCacheName ) { free(pCacheName); pCacheName = NULL; } } if( outError ) *outError = kres; return pCacheName; }
static void eval_kinit(heim_dict_t o) { heim_string_t user, password, keytab, fast_armor_cc, pk_user_id, ccache; krb5_get_init_creds_opt *opt; krb5_init_creds_context ctx; krb5_principal client; krb5_keytab ktmem = NULL; krb5_ccache fast_cc = NULL; krb5_error_code ret; if (ptop) ptop->as_req++; user = heim_dict_get_value(o, HSTR("client")); if (user == NULL) krb5_errx(kdc_context, 1, "no client"); password = heim_dict_get_value(o, HSTR("password")); keytab = heim_dict_get_value(o, HSTR("keytab")); pk_user_id = heim_dict_get_value(o, HSTR("pkinit-user-cert-id")); if (password == NULL && keytab == NULL && pk_user_id == NULL) krb5_errx(kdc_context, 1, "password, keytab, nor PKINIT user cert ID"); ccache = heim_dict_get_value(o, HSTR("ccache")); ret = krb5_parse_name(kdc_context, heim_string_get_utf8(user), &client); if (ret) krb5_err(kdc_context, 1, ret, "krb5_unparse_name"); /* PKINIT parts */ ret = krb5_get_init_creds_opt_alloc (kdc_context, &opt); if (ret) krb5_err(kdc_context, 1, ret, "krb5_get_init_creds_opt_alloc"); if (pk_user_id) { heim_bool_t rsaobj = heim_dict_get_value(o, HSTR("pkinit-use-rsa")); int use_rsa = rsaobj ? heim_bool_val(rsaobj) : 0; ret = krb5_get_init_creds_opt_set_pkinit(kdc_context, opt, client, heim_string_get_utf8(pk_user_id), NULL, NULL, NULL, use_rsa ? 2 : 0, NULL, NULL, NULL); if (ret) krb5_err(kdc_context, 1, ret, "krb5_get_init_creds_opt_set_pkinit"); } ret = krb5_init_creds_init(kdc_context, client, NULL, NULL, 0, opt, &ctx); if (ret) krb5_err(kdc_context, 1, ret, "krb5_init_creds_init"); fast_armor_cc = heim_dict_get_value(o, HSTR("fast-armor-cc")); if (fast_armor_cc) { ret = krb5_cc_resolve(kdc_context, heim_string_get_utf8(fast_armor_cc), &fast_cc); if (ret) krb5_err(kdc_context, 1, ret, "krb5_cc_resolve"); ret = krb5_init_creds_set_fast_ccache(kdc_context, ctx, fast_cc); if (ret) krb5_err(kdc_context, 1, ret, "krb5_init_creds_set_fast_ccache"); } if (password) { ret = krb5_init_creds_set_password(kdc_context, ctx, heim_string_get_utf8(password)); if (ret) krb5_err(kdc_context, 1, ret, "krb5_init_creds_set_password"); } if (keytab) { krb5_keytab kt = NULL; ret = krb5_kt_resolve(kdc_context, heim_string_get_utf8(keytab), &kt); if (ret) krb5_err(kdc_context, 1, ret, "krb5_kt_resolve"); ret = krb5_kt_resolve(kdc_context, "MEMORY:keytab", &ktmem); if (ret) krb5_err(kdc_context, 1, ret, "krb5_kt_resolve(MEMORY)"); ret = copy_keytab(kdc_context, kt, ktmem); if (ret) krb5_err(kdc_context, 1, ret, "copy_keytab"); krb5_kt_close(kdc_context, kt); ret = krb5_init_creds_set_keytab(kdc_context, ctx, ktmem); if (ret) krb5_err(kdc_context, 1, ret, "krb5_init_creds_set_keytab"); } ret = krb5_init_creds_get(kdc_context, ctx); if (ret) krb5_err(kdc_context, 1, ret, "krb5_init_creds_get"); if (ccache) { const char *name = heim_string_get_utf8(ccache); krb5_creds cred; krb5_ccache cc; ret = krb5_init_creds_get_creds(kdc_context, ctx, &cred); if (ret) krb5_err(kdc_context, 1, ret, "krb5_init_creds_get_creds"); ret = krb5_cc_resolve(kdc_context, name, &cc); if (ret) krb5_err(kdc_context, 1, ret, "krb5_cc_resolve"); krb5_init_creds_store(kdc_context, ctx, cc); ret = krb5_cc_close(kdc_context, cc); if (ret) krb5_err(kdc_context, 1, ret, "krb5_cc_close"); krb5_free_cred_contents(kdc_context, &cred); } krb5_init_creds_free(kdc_context, ctx); if (ktmem) krb5_kt_close(kdc_context, ktmem); if (fast_cc) krb5_cc_close(kdc_context, fast_cc); }
int main (int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_principal principal; krb5_get_init_creds_opt *opt; krb5_ccache id = NULL; int exit_value; int optidx = 0; setprogname(argv[0]); if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) usage(1, args, sizeof(args) / sizeof(args[0])); if (help_flag) usage(0, args, sizeof(args) / sizeof(args[0])); if (version_flag) { print_version(NULL); return 0; } argc -= optidx; argv += optidx; ret = krb5_init_context (&context); if (ret) errx (1, "krb5_init_context failed: %d", ret); ret = krb5_get_init_creds_opt_alloc (context, &opt); if (ret) krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc"); krb5_get_init_creds_opt_set_tkt_life (opt, 300); krb5_get_init_creds_opt_set_forwardable (opt, FALSE); krb5_get_init_creds_opt_set_proxiable (opt, FALSE); if (cred_cache_str) { ret = krb5_cc_resolve(context, cred_cache_str, &id); if (ret) krb5_err (context, 1, ret, "krb5_cc_resolve"); } else { ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &id); if (ret) krb5_err (context, 1, ret, "krb5_cc_new_unique"); } if (cred_cache_str == NULL) { krb5_principal admin_principal = NULL; krb5_creds cred; if (admin_principal_str) { ret = krb5_parse_name (context, admin_principal_str, &admin_principal); if (ret) krb5_err (context, 1, ret, "krb5_parse_name"); } else if (argc == 1) { ret = krb5_parse_name (context, argv[0], &admin_principal); if (ret) krb5_err (context, 1, ret, "krb5_parse_name"); } else { ret = krb5_get_default_principal (context, &admin_principal); if (ret) krb5_err (context, 1, ret, "krb5_get_default_principal"); } ret = krb5_get_init_creds_password (context, &cred, admin_principal, NULL, krb5_prompter_posix, NULL, 0, "kadmin/changepw", opt); switch (ret) { case 0: break; case KRB5_LIBOS_PWDINTR : return 1; case KRB5KRB_AP_ERR_BAD_INTEGRITY : case KRB5KRB_AP_ERR_MODIFIED : krb5_errx(context, 1, "Password incorrect"); break; default: krb5_err(context, 1, ret, "krb5_get_init_creds"); } krb5_get_init_creds_opt_free(context, opt); ret = krb5_cc_initialize(context, id, admin_principal); krb5_free_principal(context, admin_principal); if (ret) krb5_err(context, 1, ret, "krb5_cc_initialize"); ret = krb5_cc_store_cred(context, id, &cred); if (ret) krb5_err(context, 1, ret, "krb5_cc_store_cred"); krb5_free_cred_contents (context, &cred); } if (argc == 0) { exit_value = change_password(context, NULL, id); } else { exit_value = 0; while (argc-- > 0) { ret = krb5_parse_name (context, argv[0], &principal); if (ret) krb5_err (context, 1, ret, "krb5_parse_name"); ret = change_password(context, principal, id); if (ret) exit_value = 1; krb5_free_principal(context, principal); argv++; } } if (cred_cache_str == NULL) { ret = krb5_cc_destroy(context, id); if (ret) krb5_err (context, 1, ret, "krb5_cc_destroy"); } else { ret = krb5_cc_close(context, id); if (ret) krb5_err (context, 1, ret, "krb5_cc_close"); } krb5_free_context (context); return exit_value; }
static ADS_STATUS ads_init_gssapi_cred(ADS_STRUCT *ads, gss_cred_id_t *cred) { ADS_STATUS status; krb5_context kctx; krb5_error_code kerr; krb5_ccache kccache = NULL; uint32_t maj, min; *cred = GSS_C_NO_CREDENTIAL; if (!ads->auth.ccache_name) { return ADS_SUCCESS; } kerr = krb5_init_context(&kctx); if (kerr) { return ADS_ERROR_KRB5(kerr); } #ifdef HAVE_GSS_KRB5_IMPORT_CRED kerr = krb5_cc_resolve(kctx, ads->auth.ccache_name, &kccache); if (kerr) { status = ADS_ERROR_KRB5(kerr); goto done; } maj = gss_krb5_import_cred(&min, kccache, NULL, NULL, cred); if (maj != GSS_S_COMPLETE) { status = ADS_ERROR_GSS(maj, min); goto done; } #else /* We need to fallback to overriding the default creds. * This operation is not thread safe as it changes the process * environment variable, but we do not have any better option * with older kerberos libraries */ { const char *oldccname = NULL; oldccname = getenv("KRB5CCNAME"); setenv("KRB5CCNAME", ads->auth.ccache_name, 1); maj = gss_acquire_cred(&min, GSS_C_NO_NAME, GSS_C_INDEFINITE, NULL, GSS_C_INITIATE, cred, NULL, NULL); if (oldccname) { setenv("KRB5CCNAME", oldccname, 1); } else { unsetenv("KRB5CCNAME"); } if (maj != GSS_S_COMPLETE) { status = ADS_ERROR_GSS(maj, min); goto done; } } #endif status = ADS_SUCCESS; done: if (!ADS_ERR_OK(status) && kccache != NULL) { krb5_cc_close(kctx, kccache); } krb5_free_context(kctx); return status; }
static int proto (int sock, const char *svc) { krb5_auth_context auth_context; krb5_error_code status; krb5_principal server; krb5_ticket *ticket; char *name; char ret_string[10]; char hostname[MAXHOSTNAMELEN]; krb5_data data; krb5_data remotename; krb5_data tk_file; krb5_ccache ccache; char ccname[MAXPATHLEN]; struct passwd *pwd; status = krb5_auth_con_init (context, &auth_context); if (status) krb5_err(context, 1, status, "krb5_auth_con_init"); status = krb5_auth_con_setaddrs_from_fd (context, auth_context, &sock); if (status) krb5_err(context, 1, status, "krb5_auth_con_setaddr"); if(gethostname (hostname, sizeof(hostname)) < 0) krb5_err(context, 1, errno, "gethostname"); status = krb5_sname_to_principal (context, hostname, svc, KRB5_NT_SRV_HST, &server); if (status) krb5_err(context, 1, status, "krb5_sname_to_principal"); status = krb5_recvauth_match_version (context, &auth_context, &sock, kfd_match_version, NULL, server, 0, NULL, &ticket); if (status) krb5_err(context, 1, status, "krb5_recvauth"); status = krb5_unparse_name (context, ticket->client, &name); if (status) krb5_err(context, 1, status, "krb5_unparse_name"); if(protocol_version == 0) { data.data = "old clnt"; /* XXX old clients only had room for 10 bytes of message, and also didn't show it to the user */ data.length = strlen(data.data) + 1; krb5_write_message(context, &sock, &data); sleep(2); /* XXX give client time to finish */ krb5_errx(context, 1, "old client; exiting"); } status=krb5_read_priv_message (context, auth_context, &sock, &remotename); if (status) krb5_err(context, 1, status, "krb5_read_message"); status=krb5_read_priv_message (context, auth_context, &sock, &tk_file); if (status) krb5_err(context, 1, status, "krb5_read_message"); krb5_data_zero (&data); if(((char*)remotename.data)[remotename.length-1] != '\0') krb5_errx(context, 1, "unterminated received"); if(((char*)tk_file.data)[tk_file.length-1] != '\0') krb5_errx(context, 1, "unterminated received"); status = krb5_read_priv_message(context, auth_context, &sock, &data); if (status) { krb5_err(context, 1, errno, "krb5_read_priv_message"); goto out; } pwd = getpwnam ((char *)(remotename.data)); if (pwd == NULL) { status=1; krb5_warnx(context, "getpwnam: %s failed",(char *)(remotename.data)); goto out; } if(!krb5_kuserok (context, ticket->client, (char *)(remotename.data))) { status=1; krb5_warnx(context, "krb5_kuserok: permission denied"); goto out; } if (setgid(pwd->pw_gid) < 0) { krb5_warn(context, errno, "setgid"); goto out; } if (setuid(pwd->pw_uid) < 0) { krb5_warn(context, errno, "setuid"); goto out; } if (tk_file.length != 1) snprintf (ccname, sizeof(ccname), "%s", (char *)(tk_file.data)); else snprintf (ccname, sizeof(ccname), "FILE:/tmp/krb5cc_%lu", (unsigned long)pwd->pw_uid); status = krb5_cc_resolve (context, ccname, &ccache); if (status) { krb5_warn(context, status, "krb5_cc_resolve"); goto out; } status = krb5_cc_initialize (context, ccache, ticket->client); if (status) { krb5_warn(context, status, "krb5_cc_initialize"); goto out; } status = krb5_rd_cred2 (context, auth_context, ccache, &data); krb5_cc_close (context, ccache); if (status) { krb5_warn(context, status, "krb5_rd_cred"); goto out; } strlcpy(krb5_tkfile,ccname,sizeof(krb5_tkfile)); krb5_warnx(context, "%s forwarded ticket to %s,%s", name, (char *)(remotename.data),ccname); out: if (status) { strlcpy(ret_string, "no", sizeof(ret_string)); krb5_warnx(context, "failed"); } else { strlcpy(ret_string, "ok", sizeof(ret_string)); } krb5_data_free (&tk_file); krb5_data_free (&remotename); krb5_data_free (&data); free(name); data.data = ret_string; data.length = strlen(ret_string) + 1; status = krb5_write_priv_message(context, auth_context, &sock, &data); krb5_auth_con_free(context, auth_context); return status; }
/* * 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; }
static int CommandProc(struct cmd_syndesc *as, void *arock) { krb5_principal princ = 0; char *cell, *pname, **hrealms, *service; char service_temp[MAXKTCREALMLEN + 20]; krb5_creds incred[1], mcred[1], *outcred = 0, *afscred; krb5_ccache cc = 0; #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC krb5_get_init_creds_opt *gic_opts; #else krb5_get_init_creds_opt gic_opts[1]; #endif char *tofree = NULL, *outname; int code; char *what; int i, dosetpag, evil, noprdb, id; #ifdef AFS_RXK5 int authtype; #endif krb5_data enc_part[1]; time_t lifetime; /* requested ticket lifetime */ krb5_prompter_fct pf = NULL; char *pass = 0; void *pa = 0; struct kp_arg klog_arg[1]; char passwd[BUFSIZ]; struct afsconf_cell cellconfig[1]; static char rn[] = "klog"; /*Routine name */ static int Pipe = 0; /* reading from a pipe */ static int Silent = 0; /* Don't want error messages */ int writeTicketFile = 0; /* write ticket file to /tmp */ service = 0; memset(incred, 0, sizeof *incred); /* blow away command line arguments */ for (i = 1; i < zero_argc; i++) memset(zero_argv[i], 0, strlen(zero_argv[i])); zero_argc = 0; memset(klog_arg, 0, sizeof *klog_arg); /* first determine quiet flag based on -silent switch */ Silent = (as->parms[aSILENT].items ? 1 : 0); if (Silent) { afs_set_com_err_hook(silent_errors); } if ((code = krb5_init_context(&k5context))) { afs_com_err(rn, code, "while initializing Kerberos 5 library"); KLOGEXIT(code); } if ((code = rx_Init(0))) { afs_com_err(rn, code, "while initializing rx"); KLOGEXIT(code); } initialize_U_error_table(); /*initialize_krb5_error_table();*/ initialize_RXK_error_table(); initialize_KTC_error_table(); initialize_ACFG_error_table(); /* initialize_rx_error_table(); */ if (!(tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH))) { afs_com_err(rn, 0, "can't get afs configuration (afsconf_Open(%s))", AFSDIR_CLIENT_ETC_DIRPATH); KLOGEXIT(1); } /* * Enable DES enctypes, which are currently still required for AFS. * krb5_allow_weak_crypto is MIT Kerberos 1.8. krb5_enctype_enable is * Heimdal. */ #if defined(HAVE_KRB5_ENCTYPE_ENABLE) i = krb5_enctype_valid(k5context, ETYPE_DES_CBC_CRC); if (i) krb5_enctype_enable(k5context, ETYPE_DES_CBC_CRC); #elif defined(HAVE_KRB5_ALLOW_WEAK_CRYPTO) krb5_allow_weak_crypto(k5context, 1); #endif /* Parse remaining arguments. */ dosetpag = !! as->parms[aSETPAG].items; Pipe = !! as->parms[aPIPE].items; writeTicketFile = !! as->parms[aTMP].items; noprdb = !! as->parms[aNOPRDB].items; evil = (always_evil&1) || !! as->parms[aUNWRAP].items; #ifdef AFS_RXK5 authtype = 0; if (as->parms[aK5].items) authtype |= FORCE_RXK5; if (as->parms[aK4].items) authtype |= FORCE_RXKAD; if (!authtype) authtype |= env_afs_rxk5_default(); #endif cell = as->parms[aCELL].items ? as->parms[aCELL].items->data : 0; if ((code = afsconf_GetCellInfo(tdir, cell, "afsprot", cellconfig))) { if (cell) afs_com_err(rn, code, "Can't get cell information for '%s'", cell); else afs_com_err(rn, code, "Can't get determine local cell!"); KLOGEXIT(code); } if (as->parms[aKRBREALM].items) { code = krb5_set_default_realm(k5context, as->parms[aKRBREALM].items->data); if (code) { afs_com_err(rn, code, "Can't make <%s> the default realm", as->parms[aKRBREALM].items->data); KLOGEXIT(code); } } else if ((code = krb5_get_host_realm(k5context, cellconfig->hostName[0], &hrealms))) { afs_com_err(rn, code, "Can't get realm for host <%s> in cell <%s>\n", cellconfig->hostName[0], cellconfig->name); KLOGEXIT(code); } else { if (hrealms && *hrealms) { code = krb5_set_default_realm(k5context, *hrealms); if (code) { afs_com_err(rn, code, "Can't make <%s> the default realm", *hrealms); KLOGEXIT(code); } } if (hrealms) krb5_free_host_realm(k5context, hrealms); } id = getuid(); if (as->parms[aPRINCIPAL].items) { pname = as->parms[aPRINCIPAL].items->data; } else { /* No explicit name provided: use Unix uid. */ struct passwd *pw; pw = getpwuid(id); if (pw == 0) { afs_com_err(rn, 0, "Can't figure out your name from your user id (%d).", id); if (!Silent) fprintf(stderr, "%s: Try providing the user name.\n", rn); KLOGEXIT(1); } pname = pw->pw_name; } code = krb5_parse_name(k5context, pname, &princ); if (code) { afs_com_err(rn, code, "Can't parse principal <%s>", pname); KLOGEXIT(code); } if (as->parms[aPASSWORD].items) { /* * Current argument is the desired password string. Remember it in * our local buffer, and zero out the argument string - anyone can * see it there with ps! */ strncpy(passwd, as->parms[aPASSWORD].items->data, sizeof(passwd)); memset(as->parms[aPASSWORD].items->data, 0, strlen(as->parms[aPASSWORD].items->data)); pass = passwd; } if (as->parms[aLIFETIME].items) { char *life = as->parms[aLIFETIME].items->data; char *sp; /* string ptr to rest of life */ lifetime = 3600 * strtol(life, &sp, 0); /* hours */ if (sp == life) { bad_lifetime: if (!Silent) fprintf(stderr, "%s: translating '%s' to lifetime failed\n", rn, life); return 1; } if (*sp == ':') { life = sp + 1; /* skip the colon */ lifetime += 60 * strtol(life, &sp, 0); /* minutes */ if (sp == life) goto bad_lifetime; if (*sp == ':') { life = sp + 1; lifetime += strtol(life, &sp, 0); /* seconds */ if (sp == life) goto bad_lifetime; if (*sp) goto bad_lifetime; } else if (*sp) goto bad_lifetime; } else if (*sp) goto bad_lifetime; } else lifetime = 0; /* Get the password if it wasn't provided. */ if (!pass) { if (Pipe) { strncpy(passwd, getpipepass(), sizeof(passwd)); pass = passwd; } else { pf = klog_prompter; pa = klog_arg; } } service = 0; #ifdef AFS_RXK5 if (authtype & FORCE_RXK5) { tofree = get_afs_krb5_svc_princ(cellconfig); snprintf(service_temp, sizeof service_temp, "%s", tofree); } else #endif snprintf (service_temp, sizeof service_temp, "afs/%s", cellconfig->name); klog_arg->pp = &pass; klog_arg->pstore = passwd; klog_arg->allocated = sizeof(passwd); /* XXX should allow k5 to prompt in most cases -- what about expired pw?*/ #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC code = krb5_get_init_creds_opt_alloc(k5context, &gic_opts); if (code) { afs_com_err(rn, code, "Can't allocate get_init_creds options"); KLOGEXIT(code); } #else krb5_get_init_creds_opt_init(gic_opts); #endif for (;;) { code = krb5_get_init_creds_password(k5context, incred, princ, pass, pf, /* prompter */ pa, /* data */ 0, /* start_time */ 0, /* in_tkt_service */ gic_opts); if (code != KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) break; } memset(passwd, 0, sizeof(passwd)); if (code) { char *r = 0; if (krb5_get_default_realm(k5context, &r)) r = 0; if (r) afs_com_err(rn, code, "Unable to authenticate in realm %s", r); else afs_com_err(rn, code, "Unable to authenticate to use cell %s", cellconfig->name); if (r) free(r); KLOGEXIT(code); } for (;;writeTicketFile = 0) { if (writeTicketFile) { what = "getting default ccache"; code = krb5_cc_default(k5context, &cc); } else { what = "krb5_cc_resolve"; code = krb5_cc_resolve(k5context, "MEMORY:core", &cc); if (code) goto Failed; } what = "initializing ccache"; code = krb5_cc_initialize(k5context, cc, princ); if (code) goto Failed; what = "writing Kerberos ticket file"; code = krb5_cc_store_cred(k5context, cc, incred); if (code) goto Failed; if (writeTicketFile) fprintf(stderr, "Wrote ticket file to %s\n", krb5_cc_get_name(k5context, cc)); break; Failed: if (code) afs_com_err(rn, code, "%s", what); if (writeTicketFile) { if (cc) { krb5_cc_close(k5context, cc); cc = 0; } continue; } KLOGEXIT(code); } for (service = service_temp;;service = "afs") { memset(mcred, 0, sizeof *mcred); mcred->client = princ; code = krb5_parse_name(k5context, service, &mcred->server); if (code) { afs_com_err(rn, code, "Unable to parse service <%s>\n", service); KLOGEXIT(code); } if (tofree) { free(tofree); tofree = 0; } if (!(code = krb5_unparse_name(k5context, mcred->server, &outname))) tofree = outname; else outname = service; code = krb5_get_credentials(k5context, 0, cc, mcred, &outcred); krb5_free_principal(k5context, mcred->server); if (code != KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || service != service_temp) break; #ifdef AFS_RXK5 if (authtype & FORCE_RXK5) break; #endif } afscred = outcred; if (code) { afs_com_err(rn, code, "Unable to get credentials to use %s", outname); KLOGEXIT(code); } #ifdef AFS_RXK5 if (authtype & FORCE_RXK5) { struct ktc_principal aserver[1]; int viceid = 555; memset(aserver, 0, sizeof *aserver); strncpy(aserver->cell, cellconfig->name, MAXKTCREALMLEN-1); code = ktc_SetK5Token(k5context, aserver, afscred, viceid, dosetpag); if (code) { afs_com_err(rn, code, "Unable to store tokens for cell %s\n", cellconfig->name); KLOGEXIT(1); } } else #endif { struct ktc_principal aserver[1], aclient[1]; struct ktc_token atoken[1]; memset(atoken, 0, sizeof *atoken); if (evil) { size_t elen = enc_part->length; atoken->kvno = RXKAD_TKT_TYPE_KERBEROS_V5_ENCPART_ONLY; if (afs_krb5_skip_ticket_wrapper(afscred->ticket.data, afscred->ticket.length, (char **) &enc_part->data, &elen)) { afs_com_err(rn, 0, "Can't unwrap %s AFS credential", cellconfig->name); KLOGEXIT(1); } } else { atoken->kvno = RXKAD_TKT_TYPE_KERBEROS_V5; *enc_part = afscred->ticket; } atoken->startTime = afscred->times.starttime; atoken->endTime = afscred->times.endtime; if (tkt_DeriveDesKey(get_creds_enctype(afscred), get_cred_keydata(afscred), get_cred_keylen(afscred), &atoken->sessionKey)) { afs_com_err(rn, 0, "Cannot derive DES key from enctype %i of length %u", get_creds_enctype(afscred), (unsigned)get_cred_keylen(afscred)); KLOGEXIT(1); } memcpy(atoken->ticket, enc_part->data, atoken->ticketLen = enc_part->length); memset(aserver, 0, sizeof *aserver); strncpy(aserver->name, "afs", 4); strncpy(aserver->cell, cellconfig->name, MAXKTCREALMLEN-1); memset(aclient, 0, sizeof *aclient); i = realm_len(k5context, afscred->client); if (i > MAXKTCREALMLEN-1) i = MAXKTCREALMLEN-1; memcpy(aclient->cell, realm_data(k5context, afscred->client), i); if (!noprdb) { int viceid = 0; k5_to_k4_name(k5context, afscred->client, aclient); code = whoami(atoken, cellconfig, aclient, &viceid); if (code) { afs_com_err(rn, code, "Can't get your viceid for cell %s", cellconfig->name); *aclient->name = 0; } else snprintf(aclient->name, MAXKTCNAMELEN-1, "AFS ID %d", viceid); } if (!*aclient->name) k5_to_k4_name(k5context, afscred->client, aclient); code = ktc_SetToken(aserver, atoken, aclient, dosetpag); if (code) { afs_com_err(rn, code, "Unable to store tokens for cell %s\n", cellconfig->name); KLOGEXIT(1); } } krb5_free_principal(k5context, princ); krb5_free_cred_contents(k5context, incred); if (outcred) krb5_free_creds(k5context, outcred); if (cc) krb5_cc_close(k5context, cc); if (tofree) free(tofree); return 0; }
int auks_krb5_cred_get(char *ccachefilename,char **pbuffer, size_t * plength) { int fstatus = AUKS_ERROR ; /* kerberos related variables */ krb5_error_code err_code; krb5_context context; krb5_auth_context auth_context; krb5_ccache ccache; krb5_creds read_cred; krb5_cc_cursor cc_cursor; krb5_data *p_outbuf; krb5_replay_data krdata; int read_cred_was_used = 0; int read_cred_is_tgt = 0; char *buffer; size_t length; /* initialize kerberos context */ err_code = krb5_init_context(&context); if (err_code) { auks_error("unable to initialize kerberos context : %s", error_message(err_code)); fstatus = AUKS_ERROR_KRB5_CRED_INIT_CTX ; goto exit; } auks_log("kerberos context successfully initialized"); /* initialize kerberos credential cache structure */ if (ccachefilename == NULL) err_code = krb5_cc_default(context, &ccache); else err_code = krb5_cc_resolve(context, ccachefilename,&ccache); if (err_code) { auks_error("unable to resolve credential cache : %s", error_message(err_code)); fstatus = AUKS_ERROR_KRB5_CRED_OPEN_CC ; goto ctx_exit ; } auks_log("credential cache successfully resolved"); /* start credential cache sequential reading */ err_code = krb5_cc_start_seq_get(context, ccache,&cc_cursor); if (err_code) { auks_error("unable to start credential cache sequential " "read : %s",error_message(err_code)); fstatus = AUKS_ERROR_KRB5_CRED_READ_CC ; goto cc_exit; } auks_log("credential cache sequential read successfully started"); /* look for the first TGT of the cache */ do { err_code = krb5_cc_next_cred(context,ccache, &cc_cursor,&read_cred); if (!err_code) { /* mark read_cred variable as used */ read_cred_was_used = 1; /* just check initial or forwarded tickets (TGTs) */ if ((read_cred.ticket_flags & TKT_FLG_INITIAL) || (read_cred.ticket_flags & TKT_FLG_FORWARDED)) { read_cred_is_tgt = 1 ; break; } } } while (!err_code); /* stop credential cache sequential reading */ err_code = krb5_cc_end_seq_get(context,ccache,&cc_cursor); if (err_code) { auks_error("unable to stop credential cache sequential " "read : %s",error_message(err_code)); } else auks_log("credential cache sequential read " "successfully stopped"); /* extract credential if a TGT was found */ if (!read_cred_is_tgt) { auks_error("no TGT found in credential cache"); fstatus = AUKS_ERROR_KRB5_CRED_NO_TGT_FOUND ; goto seq_exit; } auks_log("TGT found in credential cache"); /* initialize a nullified kerberos authentication context in order */ /* to serialize credential into buffer */ err_code = krb5_auth_con_init(context,&auth_context); if (err_code) { auks_error("unable to initialize kerberos authentication " "context : %s",error_message(err_code)); fstatus = AUKS_ERROR_KRB5_CRED_INIT_AUTH_CTX ; goto seq_exit; } auks_log("kerberos authentication context successfully initialized"); /* clear kerberos authentication context flags */ krb5_auth_con_setflags(context,auth_context,0); /* extract credential data */ err_code = krb5_mk_1cred(context,auth_context,&read_cred, &p_outbuf,&krdata); if (err_code) { auks_error("unable to dump credential into working buffer : %s", error_message(err_code)); fstatus = AUKS_ERROR_KRB5_CRED_MK_CRED ; goto auth_ctx_exit; } auks_log("credential successfully dumped into buffer"); /* allocate output buffer */ length = p_outbuf->length; buffer = (char *) malloc(length * sizeof(char)); if (buffer == NULL) { auks_error("unable to allocate memory for credential data " "storage"); fstatus = AUKS_ERROR_KRB5_CRED_MALLOC ; goto cred_exit; } /* copy credential data into output buffer */ memcpy(buffer,p_outbuf->data,length); *pbuffer = buffer; *plength = length; auks_log("credential successfully stored in output buffer"); fstatus = AUKS_SUCCESS ; cred_exit: krb5_free_data(context,p_outbuf); auth_ctx_exit: /* free kerberos authentication context */ krb5_auth_con_free(context,auth_context); seq_exit: /* free credential contents */ if (read_cred_was_used) krb5_free_cred_contents(context,&read_cred); cc_exit: krb5_cc_close(context, ccache); ctx_exit: krb5_free_context(context); exit: return fstatus; }
int main (int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_ccache ccache; int optidx = 0; int exit_val = 0; setprogname (argv[0]); if(getarg(args, num_args, argc, argv, &optidx)) usage(1); if (help_flag) usage (0); if(version_flag){ print_version(NULL); exit(0); } argc -= optidx; argv += optidx; if (argc != 0) usage (1); ret = krb5_init_context (&context); if (ret) errx (1, "krb5_init_context failed: %d", ret); if (all_flag) { krb5_cccol_cursor cursor; ret = krb5_cccol_cursor_new (context, &cursor); if (ret) krb5_err(context, 1, ret, "krb5_cccol_cursor_new"); while (krb5_cccol_cursor_next (context, cursor, &ccache) == 0 && ccache != NULL) { ret = krb5_cc_destroy (context, ccache); if (ret) { krb5_warn(context, ret, "krb5_cc_destroy"); exit_val = 1; } } krb5_cccol_cursor_free(context, &cursor); } else { if(cache == NULL) { ret = krb5_cc_default(context, &ccache); if (ret) krb5_err(context, 1, ret, "krb5_cc_default"); } else { ret = krb5_cc_resolve(context, cache, &ccache); if (ret) krb5_err(context, 1, ret, "krb5_cc_resolve"); } if (ret == 0) { if (credential) { krb5_creds mcred; krb5_cc_clear_mcred(&mcred); ret = krb5_parse_name(context, credential, &mcred.server); if (ret) krb5_err(context, 1, ret, "Can't parse principal %s", credential); ret = krb5_cc_remove_cred(context, ccache, 0, &mcred); if (ret) krb5_err(context, 1, ret, "Failed to remove principal %s", credential); krb5_cc_close(context, ccache); krb5_free_principal(context, mcred.server); krb5_free_context(context); return 0; } ret = krb5_cc_destroy (context, ccache); if (ret) { krb5_warn(context, ret, "krb5_cc_destroy"); exit_val = 1; } } } krb5_free_context (context); #ifndef NO_AFS if (unlog_flag && k_hasafs ()) { if (k_unlog ()) exit_val = 1; } #endif return exit_val; }
int auks_krb5_cred_store(char *cachefilename, char *buffer, size_t buffer_length) { int fstatus = AUKS_ERROR ; /* kerberos related variables */ krb5_error_code err_code; krb5_context context; krb5_auth_context auth_context; krb5_ccache ccache; krb5_creds **creds; krb5_data data; krb5_replay_data krdata; /* initialize kerberos context */ err_code = krb5_init_context(&context); if (err_code) { auks_error("unable to initialize kerberos context : %s", error_message(err_code)); fstatus = AUKS_ERROR_KRB5_CRED_INIT_CTX ; goto exit; } auks_log("kerberos context successfully initialized"); /* initialize a nullified kerberos authentication context in order */ /* to decode credential from buffer */ err_code = krb5_auth_con_init(context, &auth_context); if (err_code) { auks_error("unable to initialize kerberos authentication" " context : %s",error_message(err_code)); fstatus = AUKS_ERROR_KRB5_CRED_INIT_AUTH_CTX ; goto ctx_exit; } auks_log("kerberos authentication context successfully initialized"); /* clear kerberos authentication context flags */ krb5_auth_con_setflags(context, auth_context, 0); /* build a kerberos data structure with input buffer */ data.data = buffer; data.length = buffer_length; /* build kerberos credential structure using this data structure */ err_code = krb5_rd_cred(context, auth_context, &data,&creds,&krdata); if (err_code) { auks_error("unable to deserialize credential data : %s", error_message(err_code)); fstatus = AUKS_ERROR_KRB5_CRED_RD_CRED ; goto auth_ctx_exit; } auks_log("credential data successfully deserialized"); /* resolve kerberos credential cache */ if (cachefilename == NULL) err_code = krb5_cc_default(context,&ccache); else err_code = krb5_cc_resolve(context,cachefilename,&ccache); if (err_code) { auks_error("unable to resolve credential cache : %s", error_message(err_code)); fstatus = AUKS_ERROR_KRB5_CRED_OPEN_CC ; goto cred_exit; } auks_log("credential cache successfully resolved"); /* initialize kerberos credential structure */ err_code = krb5_cc_initialize(context,ccache,(*creds)->client); if (err_code) { auks_error("unable to initialize credential cache : %s", error_message(err_code)); fstatus = AUKS_ERROR_KRB5_CRED_INIT_CC ; goto cc_exit; } auks_log("credential cache successfully initialized",cachefilename); /* store credential in credential cache */ err_code = krb5_cc_store_cred(context,ccache,*creds); if (err_code) { auks_error("unable to store credential in credential " "cache : %s",error_message(err_code)); fstatus = AUKS_ERROR_KRB5_CRED_STORE_CRED ; } else { auks_log("credential successfully stored in credential cache"); fstatus = AUKS_SUCCESS ; } cc_exit: krb5_cc_close(context, ccache); cred_exit: krb5_free_creds(context, *creds); free(creds); auth_ctx_exit: krb5_auth_con_free(context, auth_context); ctx_exit: krb5_free_context(context); exit: return fstatus; }
static DWORD IDMKrbRenewCredentials( PIDM_KRB_CONTEXT pKrbContext ) { DWORD dwError = 0; DWORD dwCleanupError = 0; BOOLEAN bLocked = FALSE; BOOLEAN bRefreshCreds = FALSE; krb5_context pCtx = NULL; PSTR pszPrincipal = NULL; krb5_principal pPrincipal = NULL; krb5_keytab ktid = 0; krb5_ccache pCache = NULL; krb5_creds creds = {0}; IDM_RWMUTEX_LOCK_SHARED(&pKrbContext->mutex_rw, bLocked, dwError); BAIL_ON_ERROR(dwError); if (!pKrbContext->expiryTime) { bRefreshCreds = TRUE; } else { krb5_timestamp now = time(NULL); if (now >= pKrbContext->expiryTime) { bRefreshCreds = TRUE; } else { double threshold = (30 * 60); // 30 minutes double interval = difftime(pKrbContext->expiryTime, now); if (interval <= threshold) { bRefreshCreds = TRUE; } } } if (bRefreshCreds) { krb5_error_code errKrb = 0; krb5_deltat startTime = 0; PSTR pszServiceName = NULL; krb5_get_init_creds_opt options = {0}; krb5_timestamp origExpiryTime = pKrbContext->expiryTime; IDM_RWMUTEX_UNLOCK(&pKrbContext->mutex_rw, bLocked, dwError); BAIL_ON_ERROR(dwError); dwError = IDMKrbGetPrincipal( pKrbContext->pszAccount, pKrbContext->pszDomain, &pszPrincipal); BAIL_ON_ERROR(dwError); errKrb = krb5_init_context(&pCtx); BAIL_ON_KERBEROS_ERROR(NULL, errKrb, dwError); errKrb = krb5_parse_name(pCtx, pszPrincipal, &pPrincipal); BAIL_ON_KERBEROS_ERROR(NULL, errKrb, dwError); errKrb = krb5_kt_default(pCtx, &ktid); BAIL_ON_KERBEROS_ERROR(NULL, errKrb, dwError); krb5_get_init_creds_opt_init(&options); krb5_get_init_creds_opt_set_forwardable(&options, TRUE); errKrb = krb5_get_init_creds_keytab( pCtx, &creds, pPrincipal, ktid, startTime, pszServiceName, &options); BAIL_ON_KERBEROS_ERROR(NULL, errKrb, dwError); IDM_RWMUTEX_LOCK_EXCLUSIVE(&pKrbContext->mutex_rw, bLocked, dwError); BAIL_ON_ERROR(dwError); if (pKrbContext->expiryTime <= origExpiryTime) { errKrb = krb5_cc_resolve(pCtx, pKrbContext->pszCachePath, &pCache); BAIL_ON_KERBEROS_ERROR(NULL, errKrb, dwError); errKrb = krb5_cc_initialize(pCtx, pCache, pPrincipal); BAIL_ON_KERBEROS_ERROR(NULL, errKrb, dwError); errKrb = krb5_cc_store_cred(pCtx, pCache, &creds); BAIL_ON_KERBEROS_ERROR(NULL, errKrb, dwError); pKrbContext->expiryTime = creds.times.endtime; } } cleanup: IDM_RWMUTEX_UNLOCK(&pKrbContext->mutex_rw, bLocked, dwCleanupError); if (pCtx) { if (ktid) { krb5_kt_close(pCtx, ktid); ktid = 0; } if (pPrincipal) { if (creds.client == pPrincipal) { creds.client = NULL; } krb5_free_principal(pCtx, pPrincipal); } krb5_free_cred_contents(pCtx, &creds); if (pCache) { krb5_cc_close(pCtx, pCache); } krb5_free_context(pCtx); } IDM_SAFE_FREE_MEMORY(pszPrincipal); if(!dwError) { dwError = dwCleanupError; } return dwError; error: goto cleanup; }
int auks_krb5_cred_get_fwd(char *ccachefilename, char *serverName, char **p_buffer, size_t * p_buffer_length) { int fstatus = AUKS_ERROR ; /* kerberos related variables */ krb5_error_code err_code; krb5_context context; krb5_ccache ccache; krb5_principal principal; krb5_creds **out_creds_array = NULL; krb5_auth_context auth_context; krb5_flags authopts; krb5_data outbuf; krb5_data *p_outbuf; krb5_replay_data krdata; authopts = AP_OPTS_MUTUAL_REQUIRED; authopts &= (~OPTS_FORWARD_CREDS); authopts &= (~OPTS_FORWARDABLE_CREDS); if ( serverName == NULL ) { auks_error("no host specified"); fstatus = AUKS_ERROR_KRB5_CRED_NO_HOST_SPECIFIED ; goto exit; } /* initialize kerberos context */ err_code = krb5_init_context(&context); if (err_code) { auks_error("unable to initialize kerberos context : %s", error_message(err_code)); fstatus = AUKS_ERROR_KRB5_CRED_INIT_CTX ; goto exit; } auks_log("kerberos context successfully initialized"); /* initialize kerberos credential cache structure */ if (ccachefilename == NULL) err_code = krb5_cc_default(context, &ccache); else err_code = krb5_cc_resolve(context,ccachefilename,&ccache); if (err_code) { auks_error("unable to resolve credential cache : %s", error_message(err_code)); fstatus = AUKS_ERROR_KRB5_CRED_OPEN_CC ; goto ctx_exit ; } auks_log("credential cache successfully resolved"); /* get principal using credential cache */ err_code = krb5_cc_get_principal(context,ccache,&principal); if (err_code) { auks_error("unable to get principal from credential cache : %s", error_message(err_code)); fstatus = AUKS_ERROR_KRB5_CRED_GET_PRINC ; goto cc_exit ; } auks_log("principal successfully extracted from credential cache"); /* initialize kerberos authentication context */ err_code = krb5_auth_con_init(context,&auth_context); if (err_code) { auks_error("unable to initialize kerberos authentication " "context : %s",error_message(err_code)); fstatus = AUKS_ERROR_KRB5_CRED_INIT_AUTH_CTX ; goto princ_exit; } auks_log("kerberos authentication context successfully initialized"); /* do replay detection using timestamps */ krb5_auth_con_setflags(context,auth_context,KRB5_AUTH_CONTEXT_RET_TIME); /* get forwarded credential for server */ err_code = krb5_fwd_tgt_creds(context,auth_context,serverName, principal,NULL,NULL,authopts,&outbuf); if (err_code) { auks_error("unable to get serialized and crypted forwarded " "credential for %s from KDC : %s", serverName,error_message(err_code)); fstatus = AUKS_ERROR_KRB5_CRED_GET_FWD_CRED ; goto auth_ctx_exit; } auks_log("serialized and crypted forwarded credential for %s " "successfully got from KDC",serverName); /* desactive replay detection */ krb5_auth_con_setflags(context,auth_context,0); /* decrypt (using session key stored in auth context) and */ /* unserialized forwarded credential in a kerberos credential */ /* structure */ err_code = krb5_rd_cred(context,auth_context,&outbuf,&out_creds_array, &krdata); if (err_code) { auks_error("unable to unserialize and decrypt forwarded " "credential for %s : %s",serverName, error_message(err_code)); fstatus = AUKS_ERROR_KRB5_CRED_RD_CRED ; goto fwd_exit; } auks_log("unserialization and decryption of forwarded " "credential for %s succesfully done",serverName); /* Reinitialize kerberos authentication context in order to */ /* write credential to output buffer */ krb5_auth_con_free(context,auth_context); err_code = krb5_auth_con_init(context,&auth_context); if (err_code) { auks_error("unable to reinitialize kerberos connection " "authentication context : %s",error_message (err_code)); fstatus = AUKS_ERROR_KRB5_CRED_INIT_AUTH_CTX ; goto rd_cred_exit; } auks_log("kerberos connection authentication context " "reinitialization successfully done"); /* no flags */ krb5_auth_con_setflags(context,auth_context,0); /* serialize forwarded credential (no encryption because auth */ /* context session key is nullified) */ err_code = krb5_mk_1cred(context,auth_context,*out_creds_array, &p_outbuf,&krdata); if (err_code) { auks_error("unable to serialize forwarded credential for " "%s : %s",serverName,error_message(err_code)); fstatus = AUKS_ERROR_KRB5_CRED_MK_CRED ; goto rd_cred_exit; } auks_log("forwarded credential for %s successfully serialized", serverName); /* allocate output buffer and store serialized credential */ (*p_buffer) = (char *) malloc(p_outbuf->length * sizeof(char)); if ((*p_buffer) == NULL) { auks_error("unable to allocate serialized credential output " "buffer for %s",serverName); *p_buffer_length = 0 ; fstatus = AUKS_ERROR_KRB5_CRED_MALLOC ; } else { /* copy data */ memcpy(*p_buffer,p_outbuf->data,p_outbuf->length); *p_buffer_length = p_outbuf->length; auks_log("forwarded credential successfully stored " "in output buffer"); fstatus = AUKS_SUCCESS ; } krb5_free_data(context,p_outbuf); rd_cred_exit: krb5_free_creds(context,*out_creds_array); free(out_creds_array); fwd_exit: krb5_free_data_contents(context, &outbuf); auth_ctx_exit: krb5_auth_con_free(context,auth_context); princ_exit: krb5_free_principal(context, principal); cc_exit: krb5_cc_close(context, ccache); ctx_exit: krb5_free_context(context); exit: return fstatus; }
static NTSTATUS LwIoCredentialCacheToTgt( PIO_CREDS pCacheToken, PIO_CREDS* ppCreds ) { NTSTATUS Status = STATUS_SUCCESS; krb5_context pContext = NULL; krb5_error_code krb5Error = 0; krb5_ccache pCache = NULL; PSTR pszClientPrincipalName = NULL; PSTR pszServerPrincipalName = NULL; PSTR pszDesiredPrincipal = NULL; PSTR pszCredCachePath = NULL; PIO_CREDS pCreds = NULL; BOOLEAN bFoundTgt = FALSE; BOOLEAN bStartSeq = FALSE; krb5_creds creds; krb5_cc_cursor cursor; Status = LwRtlCStringAllocateFromWC16String( &pszDesiredPrincipal, pCacheToken->payload.krb5Ccache.pwszPrincipal); BAIL_ON_NT_STATUS(Status); Status = LwRtlCStringAllocateFromWC16String( &pszCredCachePath, pCacheToken->payload.krb5Ccache.pwszCachePath); BAIL_ON_NT_STATUS(Status); /* Open credentials cache */ krb5Error = krb5_init_context(&pContext); if (krb5Error) { Status = STATUS_INSUFFICIENT_RESOURCES; BAIL_ON_NT_STATUS(Status); } krb5Error = krb5_cc_resolve(pContext, pszCredCachePath, &pCache); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } /* Look for a TGT */ krb5Error = krb5_cc_start_seq_get(pContext, pCache, &cursor); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } bStartSeq = TRUE; while ((krb5Error = krb5_cc_next_cred(pContext, pCache, &cursor, &creds)) == 0) { /* Look tickets with the intial flag set */ if (creds.ticket_flags & TKT_FLG_INITIAL) { /* Extract and compare client principal with desired principal */ krb5Error = krb5_unparse_name(pContext, creds.client, &pszClientPrincipalName); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } if (!strcmp(pszClientPrincipalName, pszDesiredPrincipal)) { bFoundTgt = TRUE; break; } krb5_free_unparsed_name(pContext, pszClientPrincipalName); pszClientPrincipalName = NULL; } krb5_free_cred_contents(pContext, &creds); } if (!bFoundTgt) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } /* Extract server principal name */ krb5Error = krb5_unparse_name(pContext, creds.server, &pszServerPrincipalName); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } /* Construct token from krb5 credential data */ Status = LwIoAllocateMemory(sizeof(*pCreds), OUT_PPVOID(&pCreds)); BAIL_ON_NT_STATUS(Status); pCreds->type = IO_CREDS_TYPE_KRB5_TGT; /* Copy principal names */ Status = LwRtlWC16StringAllocateFromCString( &pCreds->payload.krb5Tgt.pwszClientPrincipal, pszClientPrincipalName); BAIL_ON_NT_STATUS(Status); Status = LwRtlWC16StringAllocateFromCString( &pCreds->payload.krb5Tgt.pwszServerPrincipal, pszServerPrincipalName); BAIL_ON_NT_STATUS(Status); /* Set time fields */ pCreds->payload.krb5Tgt.authTime = creds.times.authtime; pCreds->payload.krb5Tgt.startTime = creds.times.starttime; pCreds->payload.krb5Tgt.endTime = creds.times.endtime; pCreds->payload.krb5Tgt.renewTillTime = creds.times.renew_till; /* Copy encryption key */ pCreds->payload.krb5Tgt.keyType = creds.keyblock.enctype; pCreds->payload.krb5Tgt.ulKeySize = creds.keyblock.length; Status = LwIoAllocateMemory( creds.keyblock.length, OUT_PPVOID(&pCreds->payload.krb5Tgt.pKeyData)); BAIL_ON_NT_STATUS(Status); memcpy( pCreds->payload.krb5Tgt.pKeyData, creds.keyblock.contents, creds.keyblock.length); /* Copy tgt */ pCreds->payload.krb5Tgt.tgtFlags = creds.ticket_flags; pCreds->payload.krb5Tgt.ulTgtSize = creds.ticket.length; Status = LwIoAllocateMemory( creds.ticket.length, OUT_PPVOID(&pCreds->payload.krb5Tgt.pTgtData)); BAIL_ON_NT_STATUS(Status); memcpy( pCreds->payload.krb5Tgt.pTgtData, creds.ticket.data, creds.ticket.length); *ppCreds = pCreds; cleanup: LWIO_SAFE_FREE_MEMORY(pszDesiredPrincipal); LWIO_SAFE_FREE_MEMORY(pszCredCachePath); if (pszClientPrincipalName) { krb5_free_unparsed_name(pContext, pszClientPrincipalName); } if (pszServerPrincipalName) { krb5_free_unparsed_name(pContext, pszServerPrincipalName); } if (bFoundTgt) { krb5_free_cred_contents(pContext, &creds); } if (bStartSeq) { krb5_cc_end_seq_get(pContext, pCache, &cursor); } if (pCache) { krb5_cc_close(pContext, pCache); } if (pContext) { krb5_free_context(pContext); } return Status; error: *ppCreds = NULL; if (pCreds) { LwIoDeleteCreds(pCreds); } goto cleanup; }
int auks_krb5_cred_renew(char *ccachefilename) { int fstatus = AUKS_ERROR ; int read_cred_is_tgt = 0; int read_cred_is_renewable = 0; /* kerberos related variables */ krb5_context context; krb5_error_code err_code; krb5_ccache ccache; krb5_creds *p_cred_out = NULL; krb5_creds read_cred; krb5_creds renew_cred; krb5_cc_cursor cc_cursor; /* initialize kerberos context */ err_code = krb5_init_context(&context); if (err_code) { auks_error("unable to initialize kerberos context : %s", error_message(err_code)); fstatus = AUKS_ERROR_KRB5_CRED_INIT_CTX ; goto exit; } auks_log("kerberos context successfully initialized"); /* initialize kerberos credential cache structure */ if (ccachefilename == NULL) err_code = krb5_cc_default(context,&ccache); else err_code = krb5_cc_resolve(context,ccachefilename,&ccache); if (err_code) { auks_error("unable to resolve credential cache : %s", error_message(err_code)); fstatus = AUKS_ERROR_KRB5_CRED_OPEN_CC ; goto ctx_exit ; } auks_log("credential cache successfully resolved"); /* start credential cache sequential reading */ err_code = krb5_cc_start_seq_get(context, ccache,&cc_cursor); if (err_code) { auks_error("unable to start credential cache sequential " "read : %s",error_message(err_code)); fstatus = AUKS_ERROR_KRB5_CRED_READ_CC ; goto cc_exit; } auks_log("credential cache sequential read successfully started"); /* try to get the first renewable TGT of the cache */ do { err_code = krb5_cc_next_cred(context,ccache, &cc_cursor,&read_cred); if (!err_code) { /* just check initial or forwarded tickets (TGTs) */ if ((read_cred.ticket_flags & TKT_FLG_INITIAL) || (read_cred.ticket_flags & TKT_FLG_FORWARDED)) { read_cred_is_tgt = 1; if (read_cred.ticket_flags & TKT_FLG_RENEWABLE) { read_cred_is_renewable = 1; break; } } } } while (!err_code); /* stop credential cache sequential reading */ err_code = krb5_cc_end_seq_get(context, ccache,&cc_cursor); if (err_code) { auks_error("unable to stop credential cache sequential " "read : %s",error_message(err_code)); } else auks_log("credential cache sequential read " "successfully stopped"); /* try to do renewal if a TGT was found */ if (!read_cred_is_tgt) { auks_error("no TGT found in credential cache"); fstatus = AUKS_ERROR_KRB5_CRED_NO_TGT_FOUND ; goto seq_exit; } /* try to do renewal if a renewable TGT was found */ if (!read_cred_is_renewable) { auks_error("no renewable TGT found in credential cache"); fstatus = AUKS_ERROR_KRB5_CRED_TGT_NOT_RENEWABLE ; goto seq_exit; } auks_log("renewable TGT found in credential cache"); /* test if renewal is possible */ if (read_cred.times.endtime >= read_cred.times.renew_till) { auks_error("TGT can't be renew anymore"); fstatus = AUKS_ERROR_KRB5_CRED_TGT_HAS_EXPIRED ; goto seq_exit; } auks_log("TGT is still renewable"); /* renew credential cache TGT */ memset(&renew_cred, 0,sizeof(renew_cred)); /* copy client principal in futur credential */ err_code = krb5_copy_principal(context,read_cred.client, &renew_cred.client); if (err_code) { auks_error("unable to put client principal into " "request cred : %s",error_message(err_code)); fstatus = AUKS_ERROR_KRB5_CRED_CP_PRINC ; goto cred_exit; } auks_log("client principal successfully put into request cred"); /* copy krbtgt/... principal in futur credential as required */ /* server principal for TGS */ err_code = krb5_copy_principal(context,read_cred.server, &renew_cred.server); if (err_code) { auks_error("unable to put server principal into " "request cred : %s",error_message(err_code)); fstatus = AUKS_ERROR_KRB5_CRED_CP_PRINC ; goto cred_exit; } auks_log("server principal successfully put into request cred"); /* renew credential cache TGT */ /* err_code = krb5_get_credentials_renew(context,KDC_OPT_RENEW,ccache, */ /* &renew_cred,&p_cred_out); */ err_code = krb5_get_cred_via_tkt(context,&read_cred,KDC_OPT_RENEW, NULL,&renew_cred,&p_cred_out); if (err_code) { auks_error("unable to renew credential cache TGT : %s", error_message(err_code)); fstatus = AUKS_ERROR_KRB5_CRED_TGT_RENEW ; } else { auks_log("credential cache TGT successfully renewed"); krb5_free_creds(context,p_cred_out); fstatus = AUKS_SUCCESS ; } cred_exit: /* potential bug to check */ krb5_free_cred_contents(context,&renew_cred); seq_exit: krb5_free_cred_contents(context,&read_cred); cc_exit: krb5_cc_close(context, ccache); ctx_exit: krb5_free_context(context); exit: return fstatus; }
char * /* R: allocated response string */ auth_krb5 ( /* PARAMETERS */ const char *user, /* I: plaintext authenticator */ const char *password, /* I: plaintext password */ const char *service, /* I: service authenticating to */ const char *realm /* I: user's realm */ /* END PARAMETERS */ ) { /* VARIABLES */ krb5_context context; krb5_ccache ccache = NULL; krb5_keytab kt = NULL; krb5_principal auth_user; krb5_verify_opt opt; char * result; char tfname[2048]; char principalbuf[2048]; /* END VARIABLES */ if (!user || !password) { syslog(LOG_ERR, "auth_krb5: NULL password or username?"); return strdup("NO saslauthd internal NULL password or username"); } if (krb5_init_context(&context)) { syslog(LOG_ERR, "auth_krb5: krb5_init_context"); return strdup("NO saslauthd internal krb5_init_context error"); } if (form_principal_name(user, service, realm, principalbuf, sizeof (principalbuf))) { syslog(LOG_ERR, "auth_krb5: form_principal_name"); return strdup("NO saslauthd principal name error"); } if (krb5_parse_name (context, principalbuf, &auth_user)) { krb5_free_context(context); syslog(LOG_ERR, "auth_krb5: krb5_parse_name"); return strdup("NO saslauthd internal krb5_parse_name error"); } if (krbtf_name(tfname, sizeof (tfname)) != 0) { syslog(LOG_ERR, "auth_krb5: could not generate ccache name"); return strdup("NO saslauthd internal error"); } if (krb5_cc_resolve(context, tfname, &ccache)) { krb5_free_principal(context, auth_user); krb5_free_context(context); syslog(LOG_ERR, "auth_krb5: krb5_cc_resolve"); return strdup("NO saslauthd internal error"); } if (keytabname) { if (krb5_kt_resolve(context, keytabname, &kt)) { krb5_free_principal(context, auth_user); krb5_cc_destroy(context, ccache); krb5_free_context(context); syslog(LOG_ERR, "auth_krb5: krb5_kt_resolve"); return strdup("NO saslauthd internal error"); } } krb5_verify_opt_init(&opt); krb5_verify_opt_set_secure(&opt, 1); krb5_verify_opt_set_ccache(&opt, ccache); if (kt) krb5_verify_opt_set_keytab(&opt, kt); krb5_verify_opt_set_service(&opt, verify_principal); if (krb5_verify_user_opt(context, auth_user, password, &opt)) { result = strdup("NO krb5_verify_user_opt failed"); } else { result = strdup("OK"); } krb5_free_principal(context, auth_user); krb5_cc_destroy(context, ccache); if (kt) krb5_kt_close(context, kt); krb5_free_context(context); return result; }
char * /* R: allocated response string */ auth_krb5 ( /* PARAMETERS */ const char *user, /* I: plaintext authenticator */ const char *password, /* I: plaintext password */ const char *service, /* I: service authenticating to */ const char *realm /* I: user's realm */ /* END PARAMETERS */ ) { /* VARIABLES */ krb5_context context; krb5_ccache ccache = NULL; krb5_principal auth_user; krb5_creds creds; krb5_get_init_creds_opt opts; char * result; char tfname[2048]; char principalbuf[2048]; krb5_error_code code; /* END VARIABLES */ if (!user|| !password) { syslog(LOG_ERR, "auth_krb5: NULL password or username?"); return strdup("NO saslauthd internal error"); } if (krb5_init_context(&context)) { syslog(LOG_ERR, "auth_krb5: krb5_init_context"); return strdup("NO saslauthd internal error"); } if (form_principal_name(user, service, realm, principalbuf, sizeof (principalbuf))) { syslog(LOG_ERR, "auth_krb5: form_principal_name"); return strdup("NO saslauthd principal name error"); } if (krb5_parse_name (context, principalbuf, &auth_user)) { krb5_free_context(context); syslog(LOG_ERR, "auth_krb5: krb5_parse_name"); return strdup("NO saslauthd internal error"); } if (krbtf_name(tfname, sizeof (tfname)) != 0) { syslog(LOG_ERR, "auth_krb5: could not generate ticket file name"); return strdup("NO saslauthd internal error"); } if (krb5_cc_resolve(context, tfname, &ccache)) { krb5_free_principal(context, auth_user); krb5_free_context(context); syslog(LOG_ERR, "auth_krb5: krb5_cc_resolve"); return strdup("NO saslauthd internal error"); } if (krb5_cc_initialize (context, ccache, auth_user)) { krb5_free_principal(context, auth_user); krb5_free_context(context); syslog(LOG_ERR, "auth_krb5: krb5_cc_initialize"); return strdup("NO saslauthd internal error"); } krb5_get_init_creds_opt_init(&opts); /* 15 min should be more than enough */ krb5_get_init_creds_opt_set_tkt_life(&opts, 900); if (code = krb5_get_init_creds_password(context, &creds, auth_user, password, NULL, NULL, 0, NULL, &opts)) { krb5_cc_destroy(context, ccache); krb5_free_principal(context, auth_user); krb5_free_context(context); syslog(LOG_ERR, "auth_krb5: krb5_get_init_creds_password: %d", code); return strdup("NO saslauthd internal error"); } /* at this point we should have a TGT. Let's make sure it is valid */ if (krb5_cc_store_cred(context, ccache, &creds)) { krb5_free_principal(context, auth_user); krb5_cc_destroy(context, ccache); krb5_free_context(context); syslog(LOG_ERR, "auth_krb5: krb5_cc_store_cred"); return strdup("NO saslauthd internal error"); } if (!k5support_verify_tgt(context, ccache)) { syslog(LOG_ERR, "auth_krb5: k5support_verify_tgt"); result = strdup("NO saslauthd internal error"); goto fini; } /* * fall through -- user is valid beyond this point */ result = strdup("OK"); fini: /* destroy any tickets we had */ krb5_free_cred_contents(context, &creds); krb5_free_principal(context, auth_user); krb5_cc_destroy(context, ccache); krb5_free_context(context); return result; }