int mr_krb5_auth(char *prog) { mr_params params, reply; char host[BUFSIZ], *p; char *args[2]; int argl[2]; krb5_ccache ccache = NULL; krb5_data auth; krb5_error_code problem = 0; CHECK_CONNECTED; memset(&auth, 0, sizeof(auth)); if ((problem = mr_host(host, sizeof(host) - 1))) return problem; if (!context) { problem = krb5_init_context(&context); if (problem) goto out; } problem = krb5_auth_con_init(context, &auth_con); if (problem) goto out; problem = krb5_cc_default(context, &ccache); if (problem) goto out; problem = krb5_mk_req(context, &auth_con, 0, MOIRA_SNAME, host, NULL, ccache, &auth); if (problem) goto out; params.u.mr_procno = MR_KRB5_AUTH; params.mr_argc = 2; params.mr_argv = args; params.mr_argl = argl; params.mr_argv[0] = (char *)auth.data; params.mr_argl[0] = auth.length; params.mr_argv[1] = prog; params.mr_argl[1] = strlen(prog) + 1; if ((problem = mr_do_call(¶ms, &reply)) == MR_SUCCESS) problem = reply.u.mr_status; mr_destroy_reply(reply); out: if (ccache) krb5_cc_close(context, ccache); krb5_free_data_contents(context, &auth); if (auth_con) krb5_auth_con_free(context, auth_con); auth_con = NULL; return problem; }
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; }
krb5_error_code _kadm5_c_get_cache_principal(krb5_context context, krb5_ccache *id, krb5_principal *client) { krb5_error_code ret; const char *name, *inst; krb5_principal p1, p2; ret = krb5_cc_default(context, id); if(ret) { *id = NULL; return ret; } ret = krb5_cc_get_principal(context, *id, &p1); if(ret) { krb5_cc_close(context, *id); *id = NULL; return ret; } ret = krb5_make_principal(context, &p2, NULL, "kadmin", "admin", NULL); if (ret) { krb5_cc_close(context, *id); *id = NULL; krb5_free_principal(context, p1); return ret; } { krb5_creds in, *out; krb5_kdc_flags flags; flags.i = 0; memset(&in, 0, sizeof(in)); in.client = p1; in.server = p2; /* check for initial ticket kadmin/admin */ ret = krb5_get_credentials_with_flags(context, KRB5_GC_CACHED, flags, *id, &in, &out); krb5_free_principal(context, p2); if (ret == 0) { if (out->flags.b.initial) { *client = p1; krb5_free_creds(context, out); return 0; } krb5_free_creds(context, out); } } krb5_cc_close(context, *id); *id = NULL; name = krb5_principal_get_comp_string(context, p1, 0); inst = krb5_principal_get_comp_string(context, p1, 1); if(inst == NULL || strcmp(inst, "admin") != 0) { ret = krb5_make_principal(context, &p2, NULL, name, "admin", NULL); krb5_free_principal(context, p1); if(ret != 0) return ret; *client = p2; return 0; } *client = p1; return 0; }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_ccache cache; krb5_creds *out; int optidx = 0; krb5_get_creds_opt opt; krb5_principal server; krb5_principal impersonate = NULL; setprogname (argv[0]); ret = krb5_init_context (&context); 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 (argc != 1) usage (1); if(cache_str) { ret = krb5_cc_resolve(context, cache_str, &cache); if (ret) krb5_err (context, 1, ret, "%s", cache_str); } else { ret = krb5_cc_default (context, &cache); if (ret) krb5_err (context, 1, ret, "krb5_cc_resolve"); } ret = krb5_get_creds_opt_alloc(context, &opt); if (ret) krb5_err (context, 1, ret, "krb5_get_creds_opt_alloc"); if (etype_str) { krb5_enctype enctype; ret = krb5_string_to_enctype(context, etype_str, &enctype); if (ret) krb5_errx (context, 1, "unrecognized enctype: %s", etype_str); krb5_get_creds_opt_set_enctype(context, opt, enctype); } if (impersonate_str) { ret = krb5_parse_name(context, impersonate_str, &impersonate); if (ret) krb5_err (context, 1, ret, "krb5_parse_name %s", impersonate_str); krb5_get_creds_opt_set_impersonate(context, opt, impersonate); krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_STORE); } if (out_cache_str) krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_STORE); if (forwardable_flag) krb5_get_creds_opt_add_options(context, opt, KRB5_GC_FORWARDABLE); if (!transit_flag) krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_TRANSIT_CHECK); if (delegation_cred_str) { krb5_ccache id; krb5_creds c, mc; Ticket ticket; krb5_cc_clear_mcred(&mc); ret = krb5_cc_get_principal(context, cache, &mc.server); if (ret) krb5_err (context, 1, ret, "krb5_cc_get_principal"); ret = krb5_cc_resolve(context, delegation_cred_str, &id); if(ret) krb5_err (context, 1, ret, "krb5_cc_resolve"); ret = krb5_cc_retrieve_cred(context, id, 0, &mc, &c); if(ret) krb5_err (context, 1, ret, "krb5_cc_retrieve_cred"); ret = decode_Ticket(c.ticket.data, c.ticket.length, &ticket, NULL); if (ret) { krb5_clear_error_string(context); krb5_err (context, 1, ret, "decode_Ticket"); } krb5_free_cred_contents(context, &c); ret = krb5_get_creds_opt_set_ticket(context, opt, &ticket); if(ret) krb5_err (context, 1, ret, "krb5_get_creds_opt_set_ticket"); free_Ticket(&ticket); krb5_cc_close (context, id); krb5_free_principal(context, mc.server); krb5_get_creds_opt_add_options(context, opt, KRB5_GC_CONSTRAINED_DELEGATION); } ret = krb5_parse_name(context, argv[0], &server); if (ret) krb5_err (context, 1, ret, "krb5_parse_name %s", argv[0]); if (nametype_str) { ret = krb5_parse_nametype(context, nametype_str, &server->name.name_type); if (ret) krb5_err(context, 1, ret, "krb5_parse_nametype"); } ret = krb5_get_creds(context, opt, cache, server, &out); if (ret) krb5_err (context, 1, ret, "krb5_get_creds"); if (out_cache_str) { krb5_ccache id; ret = krb5_cc_resolve(context, out_cache_str, &id); if(ret) krb5_err (context, 1, ret, "krb5_cc_resolve"); ret = krb5_cc_initialize(context, id, out->client); if(ret) krb5_err (context, 1, ret, "krb5_cc_initialize"); ret = krb5_cc_store_cred(context, id, out); if(ret) krb5_err (context, 1, ret, "krb5_cc_store_cred"); krb5_cc_close (context, id); } krb5_free_creds(context, out); krb5_free_principal(context, server); krb5_get_creds_opt_free(context, opt); krb5_cc_close (context, cache); krb5_free_context (context); return 0; }
static int create_krb5_cred(krb5_context ctx, char *realm, char *user, char *password, char *ktname, krb5_ccache *ccache, gss_cred_id_t *gsscred, char **errmsg) { int rc = 0, len = 0; unsigned int minor_stat = 0, major_stat = 0; const char *errmsg_tmp = NULL; const char *cctype = NULL; char *cname = NULL; krb5_ccache defcc = NULL; krb5_creds creds; krb5_principal princ = NULL; krb5_keytab keytab = NULL; gss_key_value_element_desc elems[2]; gss_key_value_set_desc store; gss_name_t sname = NULL; gss_buffer_desc pr_name; pr_name.value = NULL; pr_name.length = 0; store.count = 0; store.elements = elems; if (user == NULL || realm == NULL) return 1; len = strlen(realm); if (len == 0 || strlen(user) == 0) return 0; DEBUG("create_krb5_cred (ctx:%p, realm:%s, user:%s, password:%s, ktname: %s," " ccache:%p, gsscred:%p)", ctx, realm, user, "****", ktname, ccache, gsscred); rc = krb5_cc_default(ctx, &defcc); if (rc != 0) goto end; cctype = krb5_cc_get_type(ctx, defcc); rc = krb5_cc_new_unique(ctx, cctype, NULL, ccache); if (rc != 0) goto end; rc = krb5_build_principal(ctx, &princ, len, realm, user, NULL); if (rc != 0) goto end; rc = krb5_cc_initialize(ctx, *ccache, princ); if (rc != 0) goto end; if (password != NULL && strlen(password) > 0) { rc = krb5_get_init_creds_password(ctx, &creds, princ, password, 0, NULL, 0, NULL, NULL); if (rc != 0) goto end; rc = krb5_cc_store_cred(ctx, *ccache, &creds); if (rc != 0) goto end; rc = krb5_cc_get_full_name(ctx, *ccache, &cname); if (rc != 0) goto end; store.elements[store.count].key = "ccache"; store.elements[store.count].value = cname; store.count++; } if (ktname != NULL && strlen(ktname) > 0) { rc = krb5_kt_resolve(ctx, ktname, &keytab); if (rc != 0) goto end; rc = krb5_get_init_creds_keytab(ctx, &creds, princ, keytab, 0, NULL, NULL); if (rc != 0) goto end; rc = krb5_cc_store_cred(ctx, *ccache, &creds); if (rc != 0) goto end; rc = krb5_cc_get_full_name(ctx, *ccache, &cname); if (rc != 0) goto end; store.elements[store.count].key = "client_keytab"; store.elements[store.count].value = ktname; store.count++; store.elements[store.count].key = "ccache"; store.elements[store.count].value = cname; store.count++; rc = krb5_unparse_name(ctx, princ, (char**)&pr_name.value); if (rc != 0) goto end; pr_name.length = strlen(pr_name.value); major_stat = gss_import_name(&minor_stat, &pr_name, GSS_KRB5_NT_PRINCIPAL_NAME, &sname); if (major_stat != 0) goto end; } // Does not work with GSS-SPENGO. //major_stat = gss_krb5_import_cred(&minor_stat, *ccache, princ, NULL, gsscred); major_stat = gss_acquire_cred_from(&minor_stat, sname, 0, GSS_C_NO_OID_SET, GSS_C_INITIATE, &store, gsscred, NULL, NULL); end: if (keytab != NULL) krb5_kt_close(ctx, keytab); if (princ != NULL) krb5_free_principal(ctx, princ); if (defcc != NULL) krb5_cc_close(ctx, defcc); if (cname != NULL) free(cname); if (pr_name.value != NULL) krb5_free_unparsed_name(ctx, pr_name.value); if (sname != NULL) { major_stat = gss_release_name(&minor_stat, &sname); } if (rc != 0) { /* Create error message with the error code. */ errmsg_tmp = krb5_get_error_message(ctx, rc); if (errmsg != NULL && errmsg_tmp != NULL) { len = strlen(errmsg_tmp) + 26; *errmsg = (char *)malloc(len); if (*errmsg == NULL) { krb5_free_error_message(ctx, errmsg_tmp); return -1; } snprintf(*errmsg, len,"%s. (KRB5_ERROR 0x%08x)", errmsg_tmp, rc); } krb5_free_error_message(ctx, errmsg_tmp); } if (major_stat != 0) return major_stat; return rc; }
krb5_error_code _kadm5_c_get_cred_cache(krb5_context context, const char *client_name, const char *server_name, const char *password, krb5_prompter_fct prompter, const char *keytab, krb5_ccache ccache, krb5_ccache *ret_cache) { krb5_error_code ret; krb5_ccache id = NULL; krb5_principal default_client = NULL, client = NULL; /* treat empty password as NULL */ if(password && *password == '\0') password = NULL; if(server_name == NULL) server_name = KADM5_ADMIN_SERVICE; if(client_name != NULL) { ret = krb5_parse_name(context, client_name, &client); if(ret) return ret; } if(password != NULL || prompter != NULL) { /* get principal from default cache, ok if this doesn't work */ ret = krb5_cc_default(context, &id); if(ret == 0) { ret = krb5_cc_get_principal(context, id, &default_client); if(ret) { krb5_cc_close(context, id); id = NULL; } else { const char *name, *inst; krb5_principal tmp; name = krb5_principal_get_comp_string(context, default_client, 0); inst = krb5_principal_get_comp_string(context, default_client, 1); if(inst == NULL || strcmp(inst, "admin") != 0) { ret = krb5_make_principal(context, &tmp, NULL, name, "admin", NULL); if(ret != 0) { krb5_free_principal(context, default_client); if (client) krb5_free_principal(context, client); krb5_cc_close(context, id); return ret; } krb5_free_principal(context, default_client); default_client = tmp; krb5_cc_close(context, id); id = NULL; } } } if (client != NULL) { /* A client was specified by the caller. */ if (default_client != NULL) { krb5_free_principal(context, default_client); default_client = NULL; } } else if (default_client != NULL) /* No client was specified by the caller, but we have a * client from the default credentials cache. */ client = default_client; else { /* No client was specified by the caller and we cannot determine * the client from a credentials cache. */ const char *user; user = get_default_username (); if(user == NULL) return KADM5_FAILURE; ret = krb5_make_principal(context, &client, NULL, user, "admin", NULL); if(ret) return ret; if (id != NULL) { krb5_cc_close(context, id); id = NULL; } } } else if(ccache != NULL) { id = ccache; ret = krb5_cc_get_principal(context, id, &client); if(ret) return ret; } if(id && (default_client == NULL || krb5_principal_compare(context, client, default_client))) { ret = get_kadm_ticket(context, id, client, server_name); if(ret == 0) { *ret_cache = id; krb5_free_principal(context, default_client); if (default_client != client) krb5_free_principal(context, client); return 0; } if(ccache != NULL) /* couldn't get ticket from cache */ return -1; } /* get creds via AS request */ if(id && (id != ccache)) krb5_cc_close(context, id); if (client != default_client) krb5_free_principal(context, default_client); ret = get_new_cache(context, client, password, prompter, keytab, server_name, ret_cache); krb5_free_principal(context, client); return ret; }
static int proto (int sock, const char *service) { struct sockaddr_storage remote, local; socklen_t addrlen; krb5_address remote_addr, local_addr; krb5_ccache ccache; krb5_auth_context auth_context; krb5_error_code status; krb5_data packet; krb5_data data; krb5_data client_name; krb5_creds in_creds, *out_creds; addrlen = sizeof(local); if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0 || addrlen > sizeof(local)) err (1, "getsockname)"); addrlen = sizeof(remote); if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0 || addrlen > sizeof(remote)) err (1, "getpeername"); status = krb5_auth_con_init (context, &auth_context); if (status) krb5_err(context, 1, status, "krb5_auth_con_init"); status = krb5_sockaddr2address (context, (struct sockaddr *)&local, &local_addr); if (status) krb5_err(context, 1, status, "krb5_sockaddr2address(local)"); status = krb5_sockaddr2address (context, (struct sockaddr *)&remote, &remote_addr); if (status) krb5_err(context, 1, status, "krb5_sockaddr2address(remote)"); status = krb5_auth_con_setaddrs (context, auth_context, &local_addr, &remote_addr); if (status) krb5_err(context, 1, status, "krb5_auth_con_setaddr"); status = krb5_read_message(context, &sock, &client_name); if(status) krb5_err(context, 1, status, "krb5_read_message"); memset(&in_creds, 0, sizeof(in_creds)); status = krb5_cc_default(context, &ccache); if(status) krb5_err(context, 1, status, "krb5_cc_default"); status = krb5_cc_get_principal(context, ccache, &in_creds.client); if(status) krb5_err(context, 1, status, "krb5_cc_get_principal"); status = krb5_read_message(context, &sock, &in_creds.second_ticket); if(status) krb5_err(context, 1, status, "krb5_read_message"); status = krb5_parse_name(context, client_name.data, &in_creds.server); if(status) krb5_err(context, 1, status, "krb5_parse_name"); status = krb5_get_credentials(context, KRB5_GC_USER_USER, ccache, &in_creds, &out_creds); if(status) krb5_err(context, 1, status, "krb5_get_credentials"); status = krb5_cc_default(context, &ccache); if(status) krb5_err(context, 1, status, "krb5_cc_default"); status = krb5_sendauth(context, &auth_context, &sock, VERSION, in_creds.client, in_creds.server, AP_OPTS_USE_SESSION_KEY, NULL, out_creds, ccache, NULL, NULL, NULL); if (status) krb5_err(context, 1, status, "krb5_sendauth"); { char *str; krb5_unparse_name(context, in_creds.server, &str); printf ("User is `%s'\n", str); free(str); krb5_unparse_name(context, in_creds.client, &str); printf ("Server is `%s'\n", str); free(str); } krb5_data_zero (&data); krb5_data_zero (&packet); status = krb5_read_message(context, &sock, &packet); if(status) krb5_err(context, 1, status, "krb5_read_message"); status = krb5_rd_safe (context, auth_context, &packet, &data, NULL); if (status) krb5_err(context, 1, status, "krb5_rd_safe"); printf ("safe packet: %.*s\n", (int)data.length, (char *)data.data); status = krb5_read_message(context, &sock, &packet); if(status) krb5_err(context, 1, status, "krb5_read_message"); status = krb5_rd_priv (context, auth_context, &packet, &data, NULL); if (status) krb5_err(context, 1, status, "krb5_rd_priv"); printf ("priv packet: %.*s\n", (int)data.length, (char *)data.data); return 0; }
int main(int argc, char **argv) { krb5_context ctx; krb5_ccache in_ccache, out_ccache, armor_ccache; krb5_get_init_creds_opt *opt; char *user, *password, *armor_ccname = NULL, *in_ccname = NULL, *perr; const char *err; krb5_principal client; krb5_creds creds; krb5_flags fast_flags; krb5_error_code ret; int c; while ((c = getopt(argc, argv, "I:A:")) != -1) { switch (c) { case 'A': armor_ccname = optarg; break; case 'I': in_ccname = optarg; break; } } if (argc - optind < 2) { fprintf(stderr, "Usage: %s [-A armor_ccache] [-I in_ccache] " "username password\n", argv[0]); return 1; } user = argv[optind]; password = argv[optind + 1]; bail_on_err(NULL, "Error initializing Kerberos", krb5_init_context(&ctx)); bail_on_err(ctx, "Error allocating space for get_init_creds options", krb5_get_init_creds_opt_alloc(ctx, &opt)); if (in_ccname != NULL) { bail_on_err(ctx, "Error resolving input ccache", krb5_cc_resolve(ctx, in_ccname, &in_ccache)); bail_on_err(ctx, "Error setting input_ccache option", krb5_get_init_creds_opt_set_in_ccache(ctx, opt, in_ccache)); } else { in_ccache = NULL; } if (armor_ccname != NULL) { bail_on_err(ctx, "Error resolving armor ccache", krb5_cc_resolve(ctx, armor_ccname, &armor_ccache)); bail_on_err(ctx, "Error setting fast_ccache option", krb5_get_init_creds_opt_set_fast_ccache(ctx, opt, armor_ccache)); fast_flags = KRB5_FAST_REQUIRED; bail_on_err(ctx, "Error setting option to force use of FAST", krb5_get_init_creds_opt_set_fast_flags(ctx, opt, fast_flags)); } else { armor_ccache = NULL; } bail_on_err(ctx, "Error resolving output (default) ccache", krb5_cc_default(ctx, &out_ccache)); bail_on_err(ctx, "Error setting output ccache option", krb5_get_init_creds_opt_set_out_ccache(ctx, opt, out_ccache)); if (asprintf(&perr, "Error parsing principal name \"%s\"", user) < 0) abort(); bail_on_err(ctx, perr, krb5_parse_name(ctx, user, &client)); ret = krb5_get_init_creds_password(ctx, &creds, client, password, prompter_cb, NULL, 0, NULL, opt); if (ret) { err = krb5_get_error_message(ctx, ret); printf("%s\n", err); krb5_free_error_message(ctx, err); } else { krb5_free_cred_contents(ctx, &creds); } krb5_get_init_creds_opt_free(ctx, opt); krb5_free_principal(ctx, client); krb5_cc_close(ctx, out_ccache); if (armor_ccache != NULL) krb5_cc_close(ctx, armor_ccache); if (in_ccache != NULL) krb5_cc_close(ctx, in_ccache); krb5_free_context(ctx); free(perr); return ret ? (ret - KRB5KDC_ERR_NONE) : 0; }
_PUBLIC_ int cli_credentials_set_ccache(struct cli_credentials *cred, struct loadparm_context *lp_ctx, const char *name, enum credentials_obtained obtained, const char **error_string) { krb5_error_code ret; krb5_principal princ; struct ccache_container *ccc; if (cred->ccache_obtained > obtained) { return 0; } ccc = talloc(cred, struct ccache_container); if (!ccc) { (*error_string) = error_message(ENOMEM); return ENOMEM; } ret = cli_credentials_get_krb5_context(cred, lp_ctx, &ccc->smb_krb5_context); if (ret) { (*error_string) = error_message(ret); talloc_free(ccc); return ret; } if (!talloc_reference(ccc, ccc->smb_krb5_context)) { talloc_free(ccc); (*error_string) = error_message(ENOMEM); return ENOMEM; } if (name) { ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, name, &ccc->ccache); if (ret) { (*error_string) = talloc_asprintf(cred, "failed to read krb5 ccache: %s: %s\n", name, smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc)); talloc_free(ccc); return ret; } } else { ret = krb5_cc_default(ccc->smb_krb5_context->krb5_context, &ccc->ccache); if (ret) { (*error_string) = talloc_asprintf(cred, "failed to read default krb5 ccache: %s\n", smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc)); talloc_free(ccc); return ret; } } talloc_set_destructor(ccc, free_dccache); ret = krb5_cc_get_principal(ccc->smb_krb5_context->krb5_context, ccc->ccache, &princ); if (ret == 0) { krb5_free_principal(ccc->smb_krb5_context->krb5_context, princ); ret = cli_credentials_set_from_ccache(cred, ccc, obtained, error_string); if (ret) { (*error_string) = error_message(ret); return ret; } cred->ccache = ccc; cred->ccache_obtained = obtained; talloc_steal(cred, ccc); cli_credentials_invalidate_client_gss_creds(cred, cred->ccache_obtained); return 0; } return 0; }
/* * Validate user/pass (Heimdal) */ static rlm_rcode_t krb5_auth(void *instance, REQUEST *request) { rlm_krb5_t *inst = instance; rlm_rcode_t rcode; krb5_error_code ret; krb5_principal client; krb5_ccache ccache; krb5_keytab keytab; krb5_verify_opt options; krb5_context *context = NULL; /* * See above in MIT krb5_auth */ ret = krb5_copy_context(*(inst->context), context); if (ret) { radlog(L_ERR, "rlm_krb5 (%s): Error cloning krb5 context: %s", inst->xlat_name, error_message(ret)); return RLM_MODULE_FAIL; } /* * Setup krb5_verify_user options * * Not entirely sure this is necessary, but as we use context * to get the cache handle, we probably do have to do this with * the cloned context. */ krb5_cc_default(*context, &ccache); krb5_verify_opt_init(&options); krb5_verify_opt_set_ccache(&options, ccache); memset(&keytab, 0, sizeof(keytab)); ret = inst->keytabname ? krb5_kt_resolve(*context, inst->keytabname, &keytab) : krb5_kt_default(*context, &keytab); if (ret) { radlog(L_ERR, "rlm_krb5 (%s): Resolving keytab failed: %s", inst->xlat_name, error_message(ret)); goto cleanup; } krb5_verify_opt_set_keytab(&options, keytab); krb5_verify_opt_set_secure(&options, TRUE); if (inst->service) { krb5_verify_opt_set_service(&options, inst->service); } rcode = krb5_parse_user(inst, request, &client); if (rcode != RLM_MODULE_OK) goto cleanup; /* * Verify the user, using the options we set in instantiate */ ret = krb5_verify_user_opt(*context, client, request->password->vp_strvalue, &options); if (ret) { switch (ret) { case KRB5_LIBOS_BADPWDMATCH: case KRB5KRB_AP_ERR_BAD_INTEGRITY: RDEBUG("Provided password was incorrect: %s", error_message(ret)); rcode = RLM_MODULE_REJECT; break; case KRB5KDC_ERR_KEY_EXP: case KRB5KDC_ERR_CLIENT_REVOKED: case KRB5KDC_ERR_SERVICE_REVOKED: RDEBUG("Account has been locked out: %s", error_message(ret)); rcode = RLM_MODULE_USERLOCK; break; case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN: RDEBUG("User not found: %s", error_message(ret)); rcode = RLM_MODULE_NOTFOUND; default: radlog(L_ERR, "rlm_krb5 (%s): Verifying user failed: " "%s", inst->xlat_name, error_message(ret)); rcode = RLM_MODULE_FAIL; break; } goto cleanup; } cleanup: krb5_free_context(*context); krb5_kt_close(*context, keytab); return rcode; }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_ccache src_cc = NULL; krb5_ccache dst_cc = NULL; krb5_cc_cursor cursor; krb5_principal me = NULL; krb5_creds cred; const char *during; Ticket t; size_t len; int make_kvno_absent = 0; int opt; memset(&cred, 0, sizeof (cred)); during = "init_context"; ret = krb5_init_context(&context); if (ret) goto err; while ((opt = getopt(argc, argv, "c:n")) != -1) { switch (opt) { case 'c': during = "cc_resolve of source ccache"; ret = krb5_cc_resolve(context, optarg, &src_cc); if (ret) goto err; break; case 'n': make_kvno_absent++; break; case 'h': default: fprintf(stderr, "Usage: %s [-n] [-c ccache]\n" "\tThis utility edits a ccache, setting all ticket\n" "\tenc_part kvnos to zero or absent (if -n is set).\n", argv[0]); return 1; } } if (!src_cc) { during = "cc_default"; ret = krb5_cc_default(context, &src_cc); if (ret) goto err; } during = "cc_get_principal"; ret = krb5_cc_get_principal(context, src_cc, &me); if (ret) goto err; if (optind != argc) { fprintf(stderr, "Usage: %s [-n] [-c ccache]\n" "\tThis utility edits a ccache, setting all ticket\n" "\tenc_part kvnos to zero or absent (if -n is set).\n", argv[0]); return 1; } during = "cc_new_unique of temporary ccache"; ret = krb5_cc_new_unique(context, krb5_cc_get_type(context, src_cc), NULL, &dst_cc); during = "cc_initialize of temporary ccache"; ret = krb5_cc_initialize(context, dst_cc, me); if (ret) goto err; during = "cc_start_seq_get"; ret = krb5_cc_start_seq_get(context, src_cc, &cursor); if (ret) goto err; while ((ret = krb5_cc_next_cred(context, src_cc, &cursor, &cred)) == 0) { krb5_data data; during = "decode_Ticket"; memset(&t, 0, sizeof (t)); ret = decode_Ticket(cred.ticket.data, cred.ticket.length, &t, &len); if (ret == ASN1_MISSING_FIELD) continue; if (ret) goto err; if (t.enc_part.kvno) { *t.enc_part.kvno = 0; if (make_kvno_absent) { free(t.enc_part.kvno); t.enc_part.kvno = NULL; } /* * The new Ticket has to need less or same space as before, so * we reuse cred->icket.data. */ during = "encode_Ticket"; ASN1_MALLOC_ENCODE(Ticket, data.data, data.length, &t, &len, ret); if (ret) { free_Ticket(&t); goto err; } krb5_data_free(&cred.ticket); cred.ticket = data; } free_Ticket(&t); during = "cc_store_cred"; ret = krb5_cc_store_cred(context, dst_cc, &cred); if (ret) goto err; krb5_free_cred_contents(context, &cred); memset(&cred, 0, sizeof (cred)); } during = "cc_next_cred"; if (ret != KRB5_CC_END) goto err; during = "cc_end_seq_get"; ret = krb5_cc_end_seq_get(context, src_cc, &cursor); if (ret) goto err; during = "cc_move"; ret = krb5_cc_move(context, dst_cc, src_cc); if (ret) goto err; dst_cc = NULL; during = "cc_switch"; ret = krb5_cc_switch(context, src_cc); if (ret) goto err; err: (void) krb5_free_principal(context, me); if (src_cc) (void) krb5_cc_close(context, src_cc); if (dst_cc) (void) krb5_cc_destroy(context, dst_cc); if (ret) { fprintf(stderr, "Failed while doing %s (%d)\n", during, ret); ret = 1; } return (ret); }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointer p_fd, const char *appl_version, krb5_principal client, krb5_principal server, krb5_flags ap_req_options, krb5_data *in_data, krb5_creds *in_creds, krb5_ccache ccache, krb5_error **ret_error, krb5_ap_rep_enc_part **rep_result, krb5_creds **out_creds) { krb5_error_code ret; uint32_t len, net_len; const char *version = KRB5_SENDAUTH_VERSION; u_char repl; krb5_data ap_req, error_data; krb5_creds this_cred; krb5_principal this_client = NULL; krb5_creds *creds; ssize_t sret; krb5_boolean my_ccache = FALSE; len = strlen(version) + 1; net_len = htonl(len); if (krb5_net_write (context, p_fd, &net_len, 4) != 4 || krb5_net_write (context, p_fd, version, len) != len) { ret = errno; krb5_set_error_message (context, ret, "write: %s", strerror(ret)); return ret; } len = strlen(appl_version) + 1; net_len = htonl(len); if (krb5_net_write (context, p_fd, &net_len, 4) != 4 || krb5_net_write (context, p_fd, appl_version, len) != len) { ret = errno; krb5_set_error_message (context, ret, "write: %s", strerror(ret)); return ret; } sret = krb5_net_read (context, p_fd, &repl, sizeof(repl)); if (sret < 0) { ret = errno; krb5_set_error_message (context, ret, "read: %s", strerror(ret)); return ret; } else if (sret != sizeof(repl)) { krb5_clear_error_message (context); return KRB5_SENDAUTH_BADRESPONSE; } if (repl != 0) { krb5_clear_error_message (context); return KRB5_SENDAUTH_REJECTED; } if (in_creds == NULL) { if (ccache == NULL) { ret = krb5_cc_default (context, &ccache); if (ret) return ret; my_ccache = TRUE; } if (client == NULL) { ret = krb5_cc_get_principal (context, ccache, &this_client); if (ret) { if(my_ccache) krb5_cc_close(context, ccache); return ret; } client = this_client; } memset(&this_cred, 0, sizeof(this_cred)); this_cred.client = client; this_cred.server = server; this_cred.times.endtime = 0; this_cred.ticket.length = 0; in_creds = &this_cred; } if (in_creds->ticket.length == 0) { ret = krb5_get_credentials (context, 0, ccache, in_creds, &creds); if (ret) { if(my_ccache) krb5_cc_close(context, ccache); return ret; } } else { creds = in_creds; } if(my_ccache) krb5_cc_close(context, ccache); ret = krb5_mk_req_extended (context, auth_context, ap_req_options, in_data, creds, &ap_req); if (out_creds) *out_creds = creds; else krb5_free_creds(context, creds); if(this_client) krb5_free_principal(context, this_client); if (ret) return ret; ret = krb5_write_message (context, p_fd, &ap_req); if (ret) return ret; krb5_data_free (&ap_req); ret = krb5_read_message (context, p_fd, &error_data); if (ret) return ret; if (error_data.length != 0) { KRB_ERROR error; ret = krb5_rd_error (context, &error_data, &error); krb5_data_free (&error_data); if (ret == 0) { ret = krb5_error_from_rd_error(context, &error, NULL); if (ret_error != NULL) { *ret_error = malloc (sizeof(krb5_error)); if (*ret_error == NULL) { krb5_free_error_contents (context, &error); } else { **ret_error = error; } } else { krb5_free_error_contents (context, &error); } return ret; } else { krb5_clear_error_message(context); return ret; } } else krb5_data_free (&error_data); if (ap_req_options & AP_OPTS_MUTUAL_REQUIRED) { krb5_data ap_rep; krb5_ap_rep_enc_part *ignore = NULL; krb5_data_zero (&ap_rep); ret = krb5_read_message (context, p_fd, &ap_rep); if (ret) return ret; ret = krb5_rd_rep (context, *auth_context, &ap_rep, rep_result ? rep_result : &ignore); krb5_data_free (&ap_rep); if (ret) return ret; if (rep_result == NULL) krb5_free_ap_rep_enc_part (context, ignore); } return 0; }
void kerberos5_forward (TN_Authenticator * ap) { krb5_error_code r; krb5_ccache ccache; krb5_principal client = 0; krb5_principal server = 0; krb5_data forw_creds; forw_creds.data = 0; if ((r = krb5_cc_default (telnet_context, &ccache))) { DEBUG (("Kerberos V5: could not get default ccache - %s\r\n", error_message (r))); return; } for (;;) /* Fake loop */ { if ((r = krb5_cc_get_principal (telnet_context, ccache, &client))) { DEBUG (("Kerberos V5: could not get default principal - %s\r\n", error_message (r))); break; } if ((r = krb5_sname_to_principal (telnet_context, RemoteHostName, "host", KRB5_NT_SRV_HST, &server))) { DEBUG (("Kerberos V5: could not make server principal - %s\r\n", error_message (r))); break; } if ((r = krb5_auth_con_genaddrs (telnet_context, auth_context, net, KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR))) { DEBUG (("Kerberos V5: could not gen local full address - %s\r\n", error_message (r))); break; } if ((r = krb5_fwd_tgt_creds (telnet_context, auth_context, 0, client, server, ccache, forward_flags & OPTS_FORWARDABLE_CREDS, &forw_creds))) { DEBUG (("Kerberos V5: error getting forwarded creds - %s\r\n", error_message (r))); break; } /* Send forwarded credentials */ if (!Data (ap, KRB_FORWARD, forw_creds.data, forw_creds.length)) { DEBUG (("Not enough room for authentication data\r\n")); } else { DEBUG (("Forwarded local Kerberos V5 credentials to server\r\n")); } break; } if (client) krb5_free_principal (telnet_context, client); if (server) krb5_free_principal (telnet_context, server); free (forw_creds.data); krb5_cc_close (telnet_context, ccache); }
int kerberos5_send (TN_Authenticator * ap) { krb5_error_code r; krb5_ccache ccache; krb5_creds creds; krb5_creds *new_creds = 0; int ap_opts; char type_check[2]; krb5_data check_data; if (!UserNameRequested) { DEBUG (("telnet: Kerberos V5: no user name supplied\r\n")); return 0; } if ((r = krb5_cc_default (telnet_context, &ccache))) { DEBUG (("telnet: Kerberos V5: could not get default ccache\r\n")); return 0; } memset (&creds, 0, sizeof (creds)); if ((r = krb5_sname_to_principal (telnet_context, RemoteHostName, "host", KRB5_NT_SRV_HST, &creds.server))) { DEBUG (("telnet: Kerberos V5: error while constructing service name: %s\r\n", error_message (r))); return 0; } if (telnet_krb5_realm) { krb5_data rdata; rdata.length = strlen (telnet_krb5_realm); rdata.data = malloc (rdata.length + 1); assert (rdata.data); strcpy (rdata.data, telnet_krb5_realm); krb5_princ_set_realm (telnet_context, creds.server, &rdata); } if ((r = krb5_cc_get_principal (telnet_context, ccache, &creds.client))) { DEBUG (("telnet: Kerberos V5: failure on principal (%s)\r\n", error_message (r))); krb5_free_cred_contents (telnet_context, &creds); return 0; } creds.keyblock.enctype = ENCTYPE_DES_CBC_CRC; if ((r = krb5_get_credentials (telnet_context, 0, ccache, &creds, &new_creds))) { DEBUG (("telnet: Kerberos V5: failure on credentials(%s)\r\n", error_message (r))); krb5_free_cred_contents (telnet_context, &creds); return 0; } if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ap_opts = AP_OPTS_MUTUAL_REQUIRED; else ap_opts = 0; # ifdef ENCRYPTION ap_opts |= AP_OPTS_USE_SUBKEY; # endif if (auth_context) { krb5_auth_con_free (telnet_context, auth_context); auth_context = 0; } if ((r = krb5_auth_con_init (telnet_context, &auth_context))) { DEBUG (("Kerberos V5: failed to init auth_context (%s)\r\n", error_message (r))); return 0; } krb5_auth_con_setflags (telnet_context, auth_context, KRB5_AUTH_CONTEXT_RET_TIME); type_check[0] = ap->type; type_check[1] = ap->way; check_data.magic = KV5M_DATA; check_data.length = 2; check_data.data = (char *) &type_check; r = krb5_mk_req_extended (telnet_context, &auth_context, ap_opts, &check_data, new_creds, &auth); encryption_init (new_creds); krb5_free_cred_contents (telnet_context, &creds); krb5_free_creds (telnet_context, new_creds); if (r) { DEBUG (("telnet: Kerberos V5: mk_req failed (%s)\r\n", error_message (r))); return 0; } if (!auth_sendname (UserNameRequested, strlen (UserNameRequested))) { DEBUG (("telnet: Not enough room for user name\r\n")); return 0; } if (!Data (ap, KRB_AUTH, auth.data, auth.length)) { DEBUG (("telnet: Not enough room for authentication data\r\n")); return 0; } DEBUG (("telnet: Sent Kerberos V5 credentials to server\r\n")); return 1; }
static char * init_cc_from_keytab(const char *keytab_name, const char *user) { krb5_context context = NULL; krb5_error_code ret; krb5_creds my_creds; krb5_keytab keytab = NULL; krb5_principal me = NULL; krb5_ccache cc = NULL; char *ccname = NULL; memset((char *) &my_creds, 0, sizeof(my_creds)); ret = krb5_init_context(&context); if (ret) { syslog(LOG_DEBUG, "krb5_init_context: %d", (int)ret); goto icfk_cleanup; } ret = krb5_kt_resolve(context, keytab_name, &keytab); if (ret) { syslog(LOG_DEBUG, "krb5_kt_resolve: %d", (int)ret); goto icfk_cleanup; } ret = krb5_parse_name(context, user, &me); if (ret) { syslog(LOG_DEBUG, "krb5_parse_name: %d", (int)ret); goto icfk_cleanup; } ret = krb5_get_init_creds_keytab(context, &my_creds, me, keytab, 0, NULL, NULL); if (ret) { syslog(LOG_DEBUG, "krb5_get_init_creds_keytab: %d", (int)ret); goto icfk_cleanup; } ret = krb5_cc_default(context, &cc); if (ret) { syslog(LOG_DEBUG, "krb5_cc_default: %d", (int)ret); goto icfk_cleanup; } ret = krb5_cc_initialize(context, cc, me); if (ret) { syslog(LOG_DEBUG, "krb5_cc_initialize: %d", (int)ret); goto icfk_cleanup; } ret = krb5_cc_store_cred(context, cc, &my_creds); if (ret) syslog(LOG_DEBUG, "krb5_cc_store_cred: %d", (int)ret); ccname = strdup(krb5_cc_default_name(context)); if (ccname == NULL) syslog(LOG_ERR, "Unable to allocate memory"); icfk_cleanup: my_creds.client = 0; krb5_free_cred_contents(context, &my_creds); if (me) krb5_free_principal(context, me); if (cc) krb5_cc_close(context, cc); if (keytab) krb5_kt_close(context, keytab); if (context) krb5_free_context(context); return ccname; }
static krb5_error_code digest_request(krb5_context context, krb5_realm realm, krb5_ccache ccache, krb5_key_usage usage, const DigestReqInner *ireq, DigestRepInner *irep) { DigestREQ req; DigestREP rep; krb5_error_code ret; krb5_data data, data2; size_t size = 0; krb5_crypto crypto = NULL; krb5_auth_context ac = NULL; krb5_principal principal = NULL; krb5_ccache id = NULL; krb5_realm r = NULL; krb5_data_zero(&data); krb5_data_zero(&data2); memset(&req, 0, sizeof(req)); memset(&rep, 0, sizeof(rep)); if (ccache == NULL) { ret = krb5_cc_default(context, &id); if (ret) goto out; } else id = ccache; if (realm == NULL) { ret = krb5_get_default_realm(context, &r); if (ret) goto out; } else r = realm; /* * */ ret = krb5_make_principal(context, &principal, r, KRB5_DIGEST_NAME, r, NULL); if (ret) goto out; ASN1_MALLOC_ENCODE(DigestReqInner, data.data, data.length, ireq, &size, ret); if (ret) { krb5_set_error_message(context, ret, N_("Failed to encode digest inner request", "")); goto out; } if (size != data.length) krb5_abortx(context, "ASN.1 internal encoder error"); ret = krb5_mk_req_exact(context, &ac, AP_OPTS_USE_SUBKEY|AP_OPTS_MUTUAL_REQUIRED, principal, NULL, id, &req.apReq); if (ret) goto out; { krb5_keyblock *key; ret = krb5_auth_con_getlocalsubkey(context, ac, &key); if (ret) goto out; if (key == NULL) { ret = EINVAL; krb5_set_error_message(context, ret, N_("Digest failed to get local subkey", "")); goto out; } ret = krb5_crypto_init(context, key, 0, &crypto); krb5_free_keyblock (context, key); if (ret) goto out; } ret = krb5_encrypt_EncryptedData(context, crypto, usage, data.data, data.length, 0, &req.innerReq); if (ret) goto out; krb5_data_free(&data); ASN1_MALLOC_ENCODE(DigestREQ, data.data, data.length, &req, &size, ret); if (ret) { krb5_set_error_message(context, ret, N_("Failed to encode DigestREQest", "")); goto out; } if (size != data.length) krb5_abortx(context, "ASN.1 internal encoder error"); ret = krb5_sendto_kdc(context, &data, &r, &data2); if (ret) goto out; ret = decode_DigestREP(data2.data, data2.length, &rep, NULL); if (ret) { krb5_set_error_message(context, ret, N_("Failed to parse digest response", "")); goto out; } { krb5_ap_rep_enc_part *repl; ret = krb5_rd_rep(context, ac, &rep.apRep, &repl); if (ret) goto out; krb5_free_ap_rep_enc_part(context, repl); } { krb5_keyblock *key; ret = krb5_auth_con_getremotesubkey(context, ac, &key); if (ret) goto out; if (key == NULL) { ret = EINVAL; krb5_set_error_message(context, ret, N_("Digest reply have no remote subkey", "")); goto out; } krb5_crypto_destroy(context, crypto); ret = krb5_crypto_init(context, key, 0, &crypto); krb5_free_keyblock (context, key); if (ret) goto out; } krb5_data_free(&data); ret = krb5_decrypt_EncryptedData(context, crypto, usage, &rep.innerRep, &data); if (ret) goto out; ret = decode_DigestRepInner(data.data, data.length, irep, NULL); if (ret) { krb5_set_error_message(context, ret, N_("Failed to decode digest inner reply", "")); goto out; } out: if (ccache == NULL && id) krb5_cc_close(context, id); if (realm == NULL && r) free(r); if (crypto) krb5_crypto_destroy(context, crypto); if (ac) krb5_auth_con_free(context, ac); if (principal) krb5_free_principal(context, principal); krb5_data_free(&data); krb5_data_free(&data2); free_DigestREQ(&req); free_DigestREP(&rep); return ret; }
int main(int argc, const char *argv[]) { static const char *server = NULL; static const char *principal = NULL; static const char *keytab = NULL; static const char *enctypes_string = NULL; static const char *binddn = NULL; static const char *bindpw = NULL; int quiet = 0; int askpass = 0; int permitted_enctypes = 0; int retrieve = 0; struct poptOption options[] = { { "quiet", 'q', POPT_ARG_NONE, &quiet, 0, _("Print as little as possible"), _("Output only on errors")}, { "server", 's', POPT_ARG_STRING, &server, 0, _("Contact this specific KDC Server"), _("Server Name") }, { "principal", 'p', POPT_ARG_STRING, &principal, 0, _("The principal to get a keytab for (ex: ftp/[email protected])"), _("Kerberos Service Principal Name") }, { "keytab", 'k', POPT_ARG_STRING, &keytab, 0, _("File were to store the keytab information"), _("Keytab File Name") }, { "enctypes", 'e', POPT_ARG_STRING, &enctypes_string, 0, _("Encryption types to request"), _("Comma separated encryption types list") }, { "permitted-enctypes", 0, POPT_ARG_NONE, &permitted_enctypes, 0, _("Show the list of permitted encryption types and exit"), _("Permitted Encryption Types") }, { "password", 'P', POPT_ARG_NONE, &askpass, 0, _("Asks for a non-random password to use for the principal"), NULL }, { "binddn", 'D', POPT_ARG_STRING, &binddn, 0, _("LDAP DN"), _("DN to bind as if not using kerberos") }, { "bindpw", 'w', POPT_ARG_STRING, &bindpw, 0, _("LDAP password"), _("password to use if not using kerberos") }, { "retrieve", 'r', POPT_ARG_NONE, &retrieve, 0, _("Retrieve current keys without changing them"), NULL }, POPT_AUTOHELP POPT_TABLEEND }; poptContext pc; char *ktname; char *password = NULL; krb5_context krbctx; krb5_ccache ccache; krb5_principal uprinc = NULL; krb5_principal sprinc; krb5_error_code krberr; struct keys_container keys = { 0 }; krb5_keytab kt; int kvno; int i, ret; char *err_msg; ret = init_gettext(); if (ret) { fprintf(stderr, "Failed to load translations\n"); } krberr = krb5_init_context(&krbctx); if (krberr) { fprintf(stderr, _("Kerberos context initialization failed\n")); exit(1); } pc = poptGetContext("ipa-getkeytab", argc, (const char **)argv, options, 0); ret = poptGetNextOpt(pc); if (ret == -1 && permitted_enctypes && !(server || principal || keytab || quiet)) { krb5_enctype *ktypes; char enc[79]; /* fit std terminal or truncate */ krberr = krb5_get_permitted_enctypes(krbctx, &ktypes); if (krberr) { fprintf(stderr, _("No system preferred enctypes ?!\n")); exit(1); } fprintf(stdout, _("Supported encryption types:\n")); for (i = 0; ktypes[i]; i++) { krberr = krb5_enctype_to_string(ktypes[i], enc, 79); if (krberr) { fprintf(stderr, _("Warning: " "failed to convert type (#%d)\n"), i); continue; } fprintf(stdout, "%s\n", enc); } ipa_krb5_free_ktypes(krbctx, ktypes); exit (0); } if (ret != -1 || !principal || !keytab || permitted_enctypes) { if (!quiet) { poptPrintUsage(pc, stderr, 0); } exit(2); } if (NULL!=binddn && NULL==bindpw) { fprintf(stderr, _("Bind password required when using a bind DN.\n")); if (!quiet) poptPrintUsage(pc, stderr, 0); exit(10); } if (!server) { struct ipa_config *ipacfg = NULL; ret = read_ipa_config(&ipacfg); if (ret == 0) { server = ipacfg->server_name; ipacfg->server_name = NULL; } free(ipacfg); if (!server) { fprintf(stderr, _("Server name not provided and unavailable\n")); exit(2); } } if (askpass && retrieve) { fprintf(stderr, _("Incompatible options provided (-r and -P)\n")); exit(2); } if (askpass) { password = ask_password(krbctx); if (!password) { exit(2); } } else if (enctypes_string && strchr(enctypes_string, ':')) { if (!quiet) { fprintf(stderr, _("Warning: salt types are not honored" " with randomized passwords (see opt. -P)\n")); } } ret = asprintf(&ktname, "WRFILE:%s", keytab); if (ret == -1) { exit(3); } krberr = krb5_parse_name(krbctx, principal, &sprinc); if (krberr) { fprintf(stderr, _("Invalid Service Principal Name\n")); exit(4); } if (NULL == bindpw) { krberr = krb5_cc_default(krbctx, &ccache); if (krberr) { fprintf(stderr, _("Kerberos Credential Cache not found. " "Do you have a Kerberos Ticket?\n")); exit(5); } krberr = krb5_cc_get_principal(krbctx, ccache, &uprinc); if (krberr) { fprintf(stderr, _("Kerberos User Principal not found. " "Do you have a valid Credential Cache?\n")); exit(6); } } krberr = krb5_kt_resolve(krbctx, ktname, &kt); if (krberr) { fprintf(stderr, _("Failed to open Keytab\n")); exit(7); } kvno = -1; ret = ldap_get_keytab(krbctx, (retrieve == 0), password, enctypes_string, server, principal, uprinc, binddn, bindpw, &keys, &kvno, &err_msg); if (ret) { if (!quiet && err_msg != NULL) { fprintf(stderr, "%s", err_msg); } } if (retrieve == 0 && kvno == -1) { if (!quiet) { fprintf(stderr, _("Retrying with pre-4.0 keytab retrieval method...\n")); } /* create key material */ ret = create_keys(krbctx, sprinc, password, enctypes_string, &keys, &err_msg); if (!ret) { if (err_msg != NULL) { fprintf(stderr, "%s", err_msg); } fprintf(stderr, _("Failed to create key material\n")); exit(8); } kvno = ldap_set_keytab(krbctx, server, principal, uprinc, binddn, bindpw, &keys); } if (kvno == -1) { fprintf(stderr, _("Failed to get keytab\n")); exit(9); } for (i = 0; i < keys.nkeys; i++) { krb5_keytab_entry kt_entry; memset((char *)&kt_entry, 0, sizeof(kt_entry)); kt_entry.principal = sprinc; kt_entry.key = keys.ksdata[i].key; kt_entry.vno = kvno; krberr = krb5_kt_add_entry(krbctx, kt, &kt_entry); if (krberr) { fprintf(stderr, _("Failed to add key to the keytab\n")); exit (11); } } free_keys_contents(krbctx, &keys); krberr = krb5_kt_close(krbctx, kt); if (krberr) { fprintf(stderr, _("Failed to close the keytab\n")); exit (12); } if (!quiet) { fprintf(stderr, _("Keytab successfully retrieved and stored in: %s\n"), keytab); } exit(0); }
ADS_STATUS ads_krb5_set_password(const char *kdc_host, const char *princ, const char *newpw, int time_offset) { ADS_STATUS aret; krb5_error_code ret = 0; krb5_context context = NULL; krb5_principal principal = NULL; char *princ_name = NULL; char *realm = NULL; krb5_creds creds, *credsp = NULL; #if KRB5_PRINC_REALM_RETURNS_REALM krb5_realm orig_realm; #else krb5_data orig_realm; #endif krb5_ccache ccache = NULL; ZERO_STRUCT(creds); initialize_krb5_error_table(); ret = krb5_init_context(&context); if (ret) { DEBUG(1,("Failed to init krb5 context (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } if (time_offset != 0) { krb5_set_real_time(context, time(NULL) + time_offset, 0); } ret = krb5_cc_default(context, &ccache); if (ret) { krb5_free_context(context); DEBUG(1,("Failed to get default creds (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } realm = strchr_m(princ, '@'); if (!realm) { krb5_cc_close(context, ccache); krb5_free_context(context); DEBUG(1,("Failed to get realm\n")); return ADS_ERROR_KRB5(-1); } realm++; asprintf(&princ_name, "kadmin/changepw@%s", realm); ret = smb_krb5_parse_name(context, princ_name, &creds.server); if (ret) { krb5_cc_close(context, ccache); krb5_free_context(context); DEBUG(1,("Failed to parse kadmin/changepw (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } /* parse the principal we got as a function argument */ ret = smb_krb5_parse_name(context, princ, &principal); if (ret) { krb5_cc_close(context, ccache); krb5_free_principal(context, creds.server); krb5_free_context(context); DEBUG(1,("Failed to parse %s (%s)\n", princ_name, error_message(ret))); free(princ_name); return ADS_ERROR_KRB5(ret); } free(princ_name); /* The creds.server principal takes ownership of this memory. Remember to set back to original value before freeing. */ orig_realm = *krb5_princ_realm(context, creds.server); krb5_princ_set_realm(context, creds.server, krb5_princ_realm(context, principal)); ret = krb5_cc_get_principal(context, ccache, &creds.client); if (ret) { krb5_cc_close(context, ccache); krb5_princ_set_realm(context, creds.server, &orig_realm); krb5_free_principal(context, creds.server); krb5_free_principal(context, principal); krb5_free_context(context); DEBUG(1,("Failed to get principal from ccache (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } ret = krb5_get_credentials(context, 0, ccache, &creds, &credsp); if (ret) { krb5_cc_close(context, ccache); krb5_free_principal(context, creds.client); krb5_princ_set_realm(context, creds.server, &orig_realm); krb5_free_principal(context, creds.server); krb5_free_principal(context, principal); krb5_free_context(context); DEBUG(1,("krb5_get_credentials failed (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } /* we might have to call krb5_free_creds(...) from now on ... */ aret = do_krb5_kpasswd_request(context, kdc_host, KRB5_KPASSWD_VERS_SETPW, credsp, princ, newpw); krb5_free_creds(context, credsp); krb5_free_principal(context, creds.client); krb5_princ_set_realm(context, creds.server, &orig_realm); krb5_free_principal(context, creds.server); krb5_free_principal(context, principal); krb5_cc_close(context, ccache); krb5_free_context(context); return aret; }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_ccache cache; krb5_creds in, *out; krb5_kdc_flags flags; int optind = 0; flags.i = 0; ret = krb5_init_context (&context); if (ret) errx(1, "krb5_init_context failed: %d", ret); if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind)) usage(1); if (help_flag) usage (0); if(version_flag) { print_version(NULL); exit(0); } argc -= optind; argv += optind; if (argc != 1) usage (1); ret = krb5_cc_default(context, &cache); if (ret) krb5_err (context, 1, ret, "krb5_cc_default"); if(cache_str) { ret = krb5_cc_resolve(context, cache_str, &cache); if (ret) krb5_err (context, 1, ret, "%s", cache_str); } else { ret = krb5_cc_default (context, &cache); if (ret) krb5_err (context, 1, ret, "krb5_cc_resolve"); } memset(&in, 0, sizeof(in)); if (etype_str) { krb5_enctype enctype; ret = krb5_string_to_enctype(context, etype_str, &enctype); if (ret) krb5_errx (context, 1, "unrecognized enctype: %s", etype_str); in.session.keytype = enctype; } ret = krb5_cc_get_principal(context, cache, &in.client); if (ret) krb5_err (context, 1, ret, "krb5_cc_get_principal"); ret = krb5_parse_name(context, argv[0], &in.server); if (ret) krb5_err (context, 1, ret, "krb5_parse_name %s", argv[0]); if (!transit_check) flags.b.disable_transited_check = 1; if (canonicalize) flags.b.canonicalize = 1; in.times.endtime = 0; ret = krb5_get_credentials_with_flags(context, 0, flags, cache, &in, &out); if (ret) krb5_err (context, 1, ret, "krb5_get_credentials"); krb5_free_cred_contents(context, out); return 0; }
int main(int argc, char **argv) { int log_level = 0; char *data_str; char *ap_req_str = NULL; unsigned char *data; size_t data_len; /* krb5 */ krb5_error_code ret; krb5_context context; krb5_auth_context auth_context; char *princ_str_tn = "kink/tn.example.com"; krb5_principal princ_tn; char *princ_str_nut = "kink/nut.example.com"; krb5_principal princ_nut; char *princ_str_krbtgt = "krbtgt/EXAMPLE.COM"; krb5_principal princ_krbtgt; krb5_ccache ccache; krb5_keytab keytab; krb5_creds creds_tgt; krb5_data ap_req; prog = (const char *) basename(argv[0]); if (prog == NULL) { fprintf(stderr, "basename: %s -- %s\n", strerror(errno), argv[0]); return(0); /* NOTREACHED */ } { int ch = 0; while ((ch = getopt(argc, argv, "dq:")) != -1) { switch (ch) { case 'd': log_level++; break; case 'q': ap_req_str = optarg; break; default: usage(); /* NOTREACHED */ break; } } argc -= optind; argv += optind; } if (!argc) { usage(); /* NOTREACHED */ } data_str = argv[0]; { printf("dbg: %s starts arg(%s)\n", prog, data_str); } { { /* stdout */ printf("std:data:%s\n", data_str); } data_len = strlen(data_str); data_len = data_len/2 + data_len%2; data = (unsigned char *)malloc(data_len); memset(data, 0, data_len); data = hex2data(data_str, data); } if (ap_req_str != NULL) { hex2krb5data(ap_req_str, &ap_req); if (log_level) { dump_krb5_data(&ap_req); } { /* stdout */ int i = 0; unsigned char *p; p = (unsigned char *)ap_req.data; printf("std:ap_req:"); for (i = 0; i < ap_req.length; i++) { printf("%02x", *p++); } printf("\n"); } } /* prepare krb5 context */ { /** init context */ ret = krb5_init_context(&context); if (ret != 0) { printf("ERR:krb5_init_context:%s\n", krb5_get_err_text(context, ret)); return(ret); } /** setup principals */ ret = krb5_parse_name(context, princ_str_tn, &princ_tn); if (ret != 0) { printf("ERR:krb5_parse_name:%s\n", krb5_get_err_text(context, ret)); return(ret); } ret = krb5_parse_name(context, princ_str_nut, &princ_nut); if (ret != 0) { printf("ERR:krb5_parse_name:%s\n", krb5_get_err_text(context, ret)); return(ret); } ret = krb5_parse_name(context, princ_str_krbtgt, &princ_krbtgt); if (ret != 0) { printf("ERR:krb5_parse_name:%s\n", krb5_get_err_text(context, ret)); return(ret); } /** prepare credential cache */ ret = krb5_cc_default(context, &ccache); if (ret != 0) { printf("ERR:krb5_cc_default:%s\n", krb5_get_err_text(context, ret)); return(ret); } /** prepare keytab */ /*ret = krb5_kt_resolve(context, "/usr/local/var/krb5kdc/kadm5.keytab", &keytab);*/ ret = krb5_kt_default(context, &keytab); if (ret != 0) { /* printf("ERR:krb5_kt_default:%s", krb5_get_err_text(context, ret)); */ printf("ERR:krb5_kt_resolve:%s", krb5_get_err_text(context, ret)); return(ret); } } /* get TGT */ { krb5_creds mcreds; memset(&mcreds, 0, sizeof(mcreds)); mcreds.client = princ_tn; mcreds.server = princ_krbtgt; ret = krb5_cc_retrieve_cred(context, ccache, 0, &mcreds, &creds_tgt); if (ret != 0) { printf("ERR:krb5_cc_retrieve_cred:%s\n", krb5_get_err_text(context, ret)); return(ret); } } /* prepare authentiation context */ { ret = krb5_auth_con_init(context, &auth_context); if (ret != 0) { printf("ERR:krb5_auth_con_init:%s\n", krb5_get_err_text(context, ret)); return(ret); } ret = krb5_auth_con_setflags(context, auth_context, KRB5_AUTH_CONTEXT_DO_SEQUENCE); if (ret != 0) { printf("ERR:krb5_auth_con_setflags:%s\n", krb5_get_err_text(context, ret)); return(ret); } /* if USE_SKEY */ /* ret = krb5_auth_con_setuserkey(context, auth_context, &creds_tgt.session); if (ret != 0) { printf("ERR:krb5_auth_con_setuseruserkey:%s\n", krb5_get_err_text(context, ret)); return(ret); } */ } /* set keyblock in auth_context */ if (ap_req_str != NULL) { krb5_ticket *ticket; krb5_flags ap_req_options; ap_req_options = AP_OPTS_MUTUAL_REQUIRED; ticket = NULL; ret = krb5_rd_req(context, &auth_context, &ap_req, NULL, keytab, &ap_req_options, &ticket); if (log_level) { printf("info: ticket.ticket.key is SKEYID_d\n"); /*dump_krb5_ticket(context, *ticket);*/ } if (log_level) { printf("ap_req_opt (%d)\n", ap_req_options); } if (ret != 0) { printf("ERR:krb5_rd_req:%s\n", krb5_get_err_text(context, ret)); return(ret); } if (log_level) { dump_krb5_keyblock(auth_context->keyblock); } krb5_free_ticket(context, ticket); } else { krb5_creds mcreds; krb5_creds *cred; krb5_creds cred_copy; memset(&mcreds, 0, sizeof(mcreds)); mcreds.client = princ_tn; mcreds.server = princ_nut; ret = krb5_get_credentials(context, KRB5_GC_CACHED, ccache, &mcreds, &cred); if (ret != 0) { printf("ERR:krb5_get_credentials:%s\n", krb5_get_err_text(context, ret)); return(ret); } /* mk_req_extends reallocate cred, so use a copy */ ret = krb5_copy_creds_contents(context, (const krb5_creds *)cred, &cred_copy); if (ret != 0) { printf("ERR:krb5_copy_creds_contents:%s\n", krb5_get_err_text(context, ret)); return(ret); } /* * If auth_con == NULL, one is allocated. * This is used later. (keyblock is used to decrypt AP_REP) */ ret = krb5_mk_req_extended(context, &auth_context, AP_OPTS_MUTUAL_REQUIRED, NULL /* in_data */, &cred_copy, &ap_req); if (ret != 0) { printf("ERR:krb5_mk_req_extended:%s\n", krb5_get_err_text(context, ret)); return(ret); } } /* create checksum */ { krb5_crypto crypto; krb5_checksum cksum; ret = krb5_crypto_init(context, auth_context->keyblock, auth_context->keyblock->keytype, &crypto); if (ret != 0) { printf("ERR:krb5_crypto_init:%s\n", krb5_get_err_text(context, ret)); return(ret); } if (0) { dump_krb5_keyblock(auth_context->keyblock); } ret = krb5_create_checksum(context, crypto, 40, 0 /* krb5_cksumtype type */, data, data_len, &cksum); if (ret != 0) { printf("ERR:krb5_create_checksum:%s\n", krb5_get_err_text(context, ret)); return(ret); } if (log_level) { dump_krb5_checksum(cksum); } { /* stdout */ int i = 0; unsigned char *p; p = (unsigned char *)cksum.checksum.data; printf("std:cksum:"); for (i = 0; i < cksum.checksum.length; i++) { printf("%02x", *p++); } printf("\n"); } krb5_crypto_destroy(context, crypto); } /* clenaup */ { /*free(data);*/ /*krb5_data_free(&ap_req);*/ krb5_free_cred_contents(context, &creds_tgt); ret = krb5_kt_close(context, keytab); if (ret != 0) { printf("ERR:krb5_kt_close:%s\n", krb5_get_err_text(context, ret)); return(ret); } ret = krb5_cc_close(context, ccache); if (ret != 0) { printf("ERR:krb5_cc_close:%s\n", krb5_get_err_text(context, ret)); return(ret); } krb5_free_principal(context, princ_krbtgt); krb5_free_principal(context, princ_nut); krb5_free_principal(context, princ_tn); krb5_free_context(context); } return(0); }
/* returns boolean */ static int DEFAULT_CC k5_begin(struct k_opts *opts, struct k5_data *k5, struct user_info *u_info) { krb5_error_code code = 0; code = krb5_init_context(&k5->ctx); if (code != 0) { g_printf("krb5_init_context failed in k5_begin\n"); return 0; } if (opts->k5_cache_name) { code = krb5_cc_resolve(k5->ctx, opts->k5_cache_name, &k5->cc); if (code != 0) { g_printf("krb5_cc_resolve failed in k5_begin\n"); return 0; } } else { code = krb5_cc_default(k5->ctx, &k5->cc); if (code != 0) { g_printf("krb5_cc_default failed in k5_begin\n"); return 0; } } if (opts->principal_name) { /* Use specified name */ code = krb5_parse_name(k5->ctx, opts->principal_name, &k5->me); if (code != 0) { g_printf("krb5_parse_name failed in k5_begin\n"); return 0; } } else { /* No principal name specified */ if (opts->action == INIT_KT) { /* Use the default host/service name */ code = krb5_sname_to_principal(k5->ctx, NULL, NULL, KRB5_NT_SRV_HST, &k5->me); if (code != 0) { g_printf("krb5_sname_to_principal failed in k5_begin\n"); return 0; } } else { /* Get default principal from cache if one exists */ code = krb5_cc_get_principal(k5->ctx, k5->cc, &k5->me); if (code != 0) { code = krb5_parse_name(k5->ctx, u_info->name, &k5->me); if (code != 0) { g_printf("krb5_parse_name failed in k5_begin\n"); return 0; } } } } code = krb5_unparse_name(k5->ctx, k5->me, &k5->name); if (code != 0) { g_printf("krb5_unparse_name failed in k5_begin\n"); return 0; } opts->principal_name = k5->name; return 1; }
/* Given krb5 service (typically "kssl") and hostname in kssl_ctx, ** Return encrypted Kerberos ticket for service @ hostname. ** If authenp is non-NULL, also return encrypted authenticator, ** whose data should be freed by caller. ** (Originally was: Create Kerberos AP_REQ message for SSL Client.) ** ** 19990628 VRS Started; Returns Kerberos AP_REQ message. ** 20010409 VRS Modified for RFC2712; Returns enc tkt. ** 20010606 VRS May also return optional authenticator. */ krb5_error_code kssl_cget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, /* OUT */ krb5_data **enc_ticketp, /* UPDATE */ krb5_data *authenp, /* OUT */ KSSL_ERR *kssl_err) { krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; krb5_context krb5context = NULL; krb5_auth_context krb5auth_context = NULL; krb5_ccache krb5ccdef = NULL; krb5_creds krb5creds, *krb5credsp = NULL; krb5_data krb5_app_req; kssl_err_set(kssl_err, 0, ""); memset((char *)&krb5creds, 0, sizeof(krb5creds)); if (!kssl_ctx) { kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, "No kssl_ctx defined.\n"); goto err; } else if (!kssl_ctx->service_host) { kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, "kssl_ctx service_host undefined.\n"); goto err; } if ((krb5rc = krb5_init_context(&krb5context)) != 0) { (void) snprintf(kssl_err->text, KSSL_ERR_MAX, "krb5_init_context() fails: %d\n", krb5rc); kssl_err->reason = SSL_R_KRB5_C_INIT; goto err; } if ((krb5rc = krb5_sname_to_principal(krb5context, kssl_ctx->service_host, (kssl_ctx->service_name) ? kssl_ctx->service_name : KRB5SVC, KRB5_NT_SRV_HST, &krb5creds.server)) != 0) { (void) snprintf(kssl_err->text, KSSL_ERR_MAX, "krb5_sname_to_principal() fails for %s/%s\n", kssl_ctx->service_host, (kssl_ctx->service_name) ? kssl_ctx->service_name : KRB5SVC); kssl_err->reason = SSL_R_KRB5_C_INIT; goto err; } if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0) { kssl_err_set(kssl_err, SSL_R_KRB5_C_CC_PRINC, "krb5_cc_default fails.\n"); goto err; } if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef, &krb5creds.client)) != 0) { kssl_err_set(kssl_err, SSL_R_KRB5_C_CC_PRINC, "krb5_cc_get_principal() fails.\n"); goto err; } if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef, &krb5creds, &krb5credsp)) != 0) { kssl_err_set(kssl_err, SSL_R_KRB5_C_GET_CRED, "krb5_get_credentials() fails.\n"); goto err; } *enc_ticketp = &krb5credsp->ticket; #ifdef KRB5_HEIMDAL kssl_ctx->enctype = krb5credsp->session.keytype; #else kssl_ctx->enctype = krb5credsp->keyblock.enctype; #endif krb5rc = KRB5KRB_ERR_GENERIC; /* caller should free data of krb5_app_req */ /* 20010406 VRS deleted for real KerberosWrapper ** 20010605 VRS reinstated to offer Authenticator to KerberosWrapper */ krb5_app_req.length = 0; if (authenp) { krb5_data krb5in_data; const unsigned char *p; long arlen; KRB5_APREQBODY *ap_req; authenp->length = 0; krb5in_data.data = NULL; krb5in_data.length = 0; if ((krb5rc = krb5_mk_req_extended(krb5context, &krb5auth_context, 0, &krb5in_data, krb5credsp, &krb5_app_req)) != 0) { kssl_err_set(kssl_err, SSL_R_KRB5_C_MK_REQ, "krb5_mk_req_extended() fails.\n"); goto err; } arlen = krb5_app_req.length; p = (unsigned char *)krb5_app_req.data; ap_req = (KRB5_APREQBODY *) d2i_KRB5_APREQ(NULL, &p, arlen); if (ap_req) { authenp->length = i2d_KRB5_ENCDATA( ap_req->authenticator, NULL); if (authenp->length && (authenp->data = malloc(authenp->length))) { unsigned char *adp = (unsigned char *)authenp->data; authenp->length = i2d_KRB5_ENCDATA( ap_req->authenticator, &adp); } } if (ap_req) KRB5_APREQ_free((KRB5_APREQ *) ap_req); if (krb5_app_req.length) kssl_krb5_free_data_contents(krb5context, &krb5_app_req); } #ifdef KRB5_HEIMDAL if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->session)) { kssl_err_set(kssl_err, SSL_R_KRB5_C_INIT, "kssl_ctx_setkey() fails.\n"); } #else if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->keyblock)) { kssl_err_set(kssl_err, SSL_R_KRB5_C_INIT, "kssl_ctx_setkey() fails.\n"); } #endif else krb5rc = 0; err: #ifdef KSSL_DEBUG kssl_ctx_show(kssl_ctx); #endif /* KSSL_DEBUG */ if (krb5creds.client) krb5_free_principal(krb5context, krb5creds.client); if (krb5creds.server) krb5_free_principal(krb5context, krb5creds.server); if (krb5auth_context) krb5_auth_con_free(krb5context, krb5auth_context); if (krb5context) krb5_free_context(krb5context); return (krb5rc); }
static int krb5_forward_cred (krb5_auth_context auth_context, int s, const char *hostname, int forwardable) { krb5_error_code ret; krb5_ccache ccache; krb5_creds creds; krb5_kdc_flags flags; krb5_data out_data; krb5_principal principal; memset (&creds, 0, sizeof(creds)); ret = krb5_cc_default (context, &ccache); if (ret) { warnx ("could not forward creds: krb5_cc_default: %s", krb5_get_err_text (context, ret)); return 1; } ret = krb5_cc_get_principal (context, ccache, &principal); if (ret) { warnx ("could not forward creds: krb5_cc_get_principal: %s", krb5_get_err_text (context, ret)); return 1; } creds.client = principal; ret = krb5_make_principal(context, &creds.server, principal->realm, "krbtgt", principal->realm, NULL); if (ret) { warnx ("could not forward creds: krb5_make_principal: %s", krb5_get_err_text (context, ret)); return 1; } creds.times.endtime = 0; flags.i = 0; flags.b.forwarded = 1; flags.b.forwardable = forwardable; ret = krb5_get_forwarded_creds (context, auth_context, ccache, flags.i, hostname, &creds, &out_data); if (ret) { warnx ("could not forward creds: krb5_get_forwarded_creds: %s", krb5_get_err_text (context, ret)); return 1; } ret = krb5_write_message (context, (void *)&s, &out_data); krb5_data_free (&out_data); if (ret) warnx ("could not forward creds: krb5_write_message: %s", krb5_get_err_text (context, ret)); return 0; }
/* * validate user/pass (Heimdal) */ static int krb5_auth(void *instance, REQUEST *request) { rlm_krb5_t *inst = instance; krb5_error_code ret; krb5_ccache id; krb5_principal userP; krb5_context context = *(inst->context); /* copy data */ const char *user, *pass; char service[SERVICE_NAME_LEN] = "host"; char *server_name = NULL; char *princ_name; krb5_verify_opt krb_verify_options; krb5_keytab keytab; if (inst->service_princ != NULL) { server_name = strchr(inst->service_princ, '/'); if (server_name != NULL) { *server_name = '\0'; } strlcpy(service, inst->service_princ, sizeof(service)); if (server_name != NULL) { *server_name = '/'; server_name++; } } /* * We can only authenticate user requests which HAVE * a User-Name attribute. */ if (!request->username) { radlog(L_AUTH, "rlm_krb5: Attribute \"User-Name\" is required for authentication."); return RLM_MODULE_INVALID; } /* * We can only authenticate user requests which HAVE * a User-Password attribute. */ if (!request->password) { radlog(L_AUTH, "rlm_krb5: Attribute \"User-Password\" is required for authentication."); return RLM_MODULE_INVALID; } /* * Ensure that we're being passed a plain-text password, * and not anything else. */ if (request->password->attribute != PW_USER_PASSWORD) { radlog(L_AUTH, "rlm_krb5: Attribute \"User-Password\" is required for authentication. Cannot use \"%s\".", request->password->name); return RLM_MODULE_INVALID; } user = request->username->vp_strvalue; pass = request->password->vp_strvalue; ret = krb5_parse_name(context, user, &userP); if (ret) { radlog(L_AUTH, "rlm_krb5: [%s] krb5_parse_name failed: %s", user, error_message(ret)); return RLM_MODULE_REJECT; } /* * Heimdal krb5 verification. */ /* * The following bit allows us to also log user/instance@REALM if someone * logs in using an instance. */ ret = krb5_unparse_name(context, userP, &princ_name); if (ret != 0) { radlog(L_AUTH, "rlm_krb5: Unparsable name"); } else { radlog(L_AUTH, "rlm_krb5: Parsed name is: %s", princ_name); free(princ_name); } krb5_cc_default(context, &id); /* * Set up krb5_verify_user options. */ krb5_verify_opt_init(&krb_verify_options); krb5_verify_opt_set_ccache(&krb_verify_options, id); /* * Resolve keytab name. This allows us to use something other than * the default system keytab */ if (inst->keytab != NULL) { ret = krb5_kt_resolve(context, inst->keytab, &keytab); if (ret) { radlog(L_AUTH, "rlm_krb5: unable to resolve keytab %s: %s", inst->keytab, error_message(ret)); krb5_kt_close(context, keytab); return RLM_MODULE_REJECT; } krb5_verify_opt_set_keytab(&krb_verify_options, keytab); } /* * Verify aquired credentials against the keytab. */ krb5_verify_opt_set_secure(&krb_verify_options, 1); /* * Allow us to use an arbitrary service name. */ krb5_verify_opt_set_service(&krb_verify_options, service); /* * Verify the user, using the above set options. */ ret = krb5_verify_user_opt(context, userP, pass, &krb_verify_options); /* * We are done with the keytab, close it. */ krb5_kt_close(context, keytab); if (ret == 0) return RLM_MODULE_OK; radlog(L_AUTH, "rlm_krb5: failed verify_user: %s (%s@%s)", error_message(ret), *userP->name.name_string.val, userP->realm); return RLM_MODULE_REJECT; }
int main(int argc, char **argv) { krb5_context context; krb5_ccache ccache; krb5_get_init_creds_opt *opts; krb5_principal principal; krb5_creds creds; krb5_error_code err; const char *errmsg; char *opt, *val; struct responder_data response; int c; err = krb5_init_context(&context); if (err != 0) { fprintf(stderr, "error starting Kerberos: %s\n", error_message(err)); return err; } err = krb5_get_init_creds_opt_alloc(context, &opts); if (err != 0) { fprintf(stderr, "error initializing options: %s\n", error_message(err)); return err; } err = krb5_cc_default(context, &ccache); if (err != 0) { fprintf(stderr, "error resolving default ccache: %s\n", error_message(err)); return err; } err = krb5_get_init_creds_opt_set_out_ccache(context, opts, ccache); if (err != 0) { fprintf(stderr, "error setting output ccache: %s\n", error_message(err)); return err; } memset(&response, 0, sizeof(response)); while ((c = getopt(argc, argv, "X:x:cr:p:")) != -1) { switch (c) { case 'X': /* Like kinit, set a generic preauth option. */ opt = strdup(optarg); val = opt + strcspn(opt, "="); if (*val != '\0') { *val++ = '\0'; } err = krb5_get_init_creds_opt_set_pa(context, opts, opt, val); if (err != 0) { fprintf(stderr, "error setting option \"%s\": %s\n", opt, error_message(err)); return err; } free(opt); break; case 'x': /* Check that a particular question has a specific challenge. */ response.challenge = optarg; break; case 'c': /* Note that we want a dump of the PKINIT challenge structure. */ response.print_pkinit_challenge = TRUE; break; case 'r': /* Set a verbatim response for a verbatim challenge. */ response.response = optarg; break; case 'p': /* Set a PKINIT answer for a specific PKINIT identity. */ response.pkinit_answer = optarg; break; case 'o': /* Set an OTP answer for a specific OTP tokeninfo. */ response.otp_answer = optarg; break; } } if (argc > optind) { err = krb5_parse_name(context, argv[optind], &principal); if (err != 0) { fprintf(stderr, "error parsing name \"%s\": %s", argv[optind], error_message(err)); return err; } } else { fprintf(stderr, "error: no principal name provided\n"); return -1; } err = krb5_get_init_creds_opt_set_responder(context, opts, responder, &response); if (err != 0) { fprintf(stderr, "error setting responder: %s\n", error_message(err)); return err; } memset(&creds, 0, sizeof(creds)); err = krb5_get_init_creds_password(context, &creds, principal, NULL, NULL, NULL, 0, NULL, opts); if (err == 0) krb5_free_cred_contents(context, &creds); krb5_free_principal(context, principal); krb5_get_init_creds_opt_free(context, opts); krb5_cc_close(context, ccache); if (!response.called) { fprintf(stderr, "error: responder callback wasn't called\n"); err = 1; } else if (err) { errmsg = krb5_get_error_message(context, err); fprintf(stderr, "error: krb5_get_init_creds_password failed: %s\n", errmsg); krb5_free_error_message(context, errmsg); err = 2; } krb5_free_context(context); return err; }
static OM_uint32 acquire_initiator_cred (OM_uint32 * minor_status, krb5_context context, const gss_name_t desired_name, OM_uint32 time_req, const gss_OID_set desired_mechs, gss_cred_usage_t cred_usage, gsskrb5_cred handle, gss_OID_set * actual_mechs, OM_uint32 * time_rec ) { OM_uint32 ret; krb5_creds cred; krb5_principal def_princ; krb5_get_init_creds_opt *opt; krb5_ccache ccache; krb5_keytab keytab; krb5_error_code kret; keytab = NULL; ccache = NULL; def_princ = NULL; ret = GSS_S_FAILURE; memset(&cred, 0, sizeof(cred)); /* * If we have a preferred principal, lets try to find it in all * caches, otherwise, fall back to default cache, ignore all * errors while searching. */ if (handle->principal) { kret = krb5_cc_cache_match (context, handle->principal, &ccache); if (kret == 0) { ret = GSS_S_COMPLETE; goto found; } } if (ccache == NULL) { kret = krb5_cc_default(context, &ccache); if (kret) goto end; } kret = krb5_cc_get_principal(context, ccache, &def_princ); if (kret != 0) { /* we'll try to use a keytab below */ krb5_cc_close(context, ccache); def_princ = NULL; kret = 0; } else if (handle->principal == NULL) { kret = krb5_copy_principal(context, def_princ, &handle->principal); if (kret) goto end; } else if (handle->principal != NULL && krb5_principal_compare(context, handle->principal, def_princ) == FALSE) { krb5_free_principal(context, def_princ); def_princ = NULL; krb5_cc_close(context, ccache); ccache = NULL; } if (def_princ == NULL) { /* We have no existing credentials cache, * so attempt to get a TGT using a keytab. */ if (handle->principal == NULL) { kret = krb5_get_default_principal(context, &handle->principal); if (kret) goto end; } kret = get_keytab(context, &keytab); if (kret) goto end; kret = krb5_get_init_creds_opt_alloc(context, &opt); if (kret) goto end; kret = krb5_get_init_creds_keytab(context, &cred, handle->principal, keytab, 0, NULL, opt); krb5_get_init_creds_opt_free(context, opt); if (kret) goto end; kret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &ccache); if (kret) goto end; kret = krb5_cc_initialize(context, ccache, cred.client); if (kret) { krb5_cc_destroy(context, ccache); goto end; } kret = krb5_cc_store_cred(context, ccache, &cred); if (kret) { krb5_cc_destroy(context, ccache); goto end; } handle->lifetime = cred.times.endtime; handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; } else { ret = __gsskrb5_ccache_lifetime(minor_status, context, ccache, handle->principal, &handle->lifetime); if (ret != GSS_S_COMPLETE) { krb5_cc_close(context, ccache); goto end; } kret = 0; } found: handle->ccache = ccache; ret = GSS_S_COMPLETE; end: if (cred.client != NULL) krb5_free_cred_contents(context, &cred); if (def_princ != NULL) krb5_free_principal(context, def_princ); if (keytab != NULL) krb5_kt_close(context, keytab); if (ret != GSS_S_COMPLETE && kret != 0) *minor_status = kret; return (ret); }
void ccache::destroy(){ kerror=krb5_cc_destroy(ctx(),_cc); if(kerror) return; kerror=krb5_cc_default(ctx(),&_cc); }
static int get_user_ccache(const ntlm_name name, char **username, struct ntlm_buf *key) { krb5_context context = NULL; krb5_principal client; krb5_ccache id = NULL; krb5_error_code ret; char *confname; krb5_data data; *username = NULL; krb5_data_zero(&data); key->length = 0; key->data = NULL; ret = krb5_init_context(&context); if (ret) return ret; ret = krb5_cc_default(context, &id); if (ret) goto out; ret = krb5_cc_get_principal(context, id, &client); if (ret) goto out; ret = krb5_unparse_name_flags(context, client, KRB5_PRINCIPAL_UNPARSE_NO_REALM, username); krb5_free_principal(context, client); if (ret) goto out; asprintf(&confname, "ntlm-key-%s", name->domain); if (confname == NULL) { krb5_clear_error_message(context); ret = ENOMEM; goto out; } ret = krb5_cc_get_config(context, id, NULL, confname, &data); if (ret) goto out; key->data = malloc(data.length); if (key->data == NULL) { ret = ENOMEM; goto out; } key->length = data.length; memcpy(key->data, data.data, data.length); out: krb5_data_free(&data); if (id) krb5_cc_close(context, id); krb5_free_context(context); return ret; }
static void get_princ_kt(krb5_context context, krb5_principal *principal, char *name) { krb5_error_code ret; krb5_principal tmp; krb5_ccache ccache; krb5_kt_cursor cursor; krb5_keytab_entry entry; char *def_realm; if (name == NULL) { /* * If the credential cache exists and specifies a client principal, * use that. */ if (krb5_cc_default(context, &ccache) == 0) { ret = krb5_cc_get_principal(context, ccache, principal); krb5_cc_close(context, ccache); if (ret == 0) return; } } if (name) { /* If the principal specifies an explicit realm, just use that. */ int parseflags = KRB5_PRINCIPAL_PARSE_NO_DEF_REALM; parse_name_realm(context, name, parseflags, NULL, &tmp); if (krb5_principal_get_realm(context, tmp) != NULL) { *principal = tmp; return; } } else { /* Otherwise, search keytab for bare name of the default principal. */ get_default_principal(context, &tmp); set_princ_realm(context, tmp, NULL); } def_realm = get_default_realm(context); ret = krb5_kt_start_seq_get(context, kt, &cursor); if (ret) krb5_err(context, 1, ret, "krb5_kt_start_seq_get"); while (ret == 0 && krb5_kt_next_entry(context, kt, &entry, &cursor) == 0) { const char *realm; if (!krb5_principal_compare_any_realm(context, tmp, entry.principal)) continue; if (*principal && krb5_principal_compare(context, *principal, entry.principal)) continue; /* The default realm takes precedence */ realm = krb5_principal_get_realm(context, entry.principal); if (*principal && strcmp(def_realm, realm) == 0) { krb5_free_principal(context, *principal); ret = krb5_copy_principal(context, entry.principal, principal); break; } if (!*principal) ret = krb5_copy_principal(context, entry.principal, principal); } if (ret != 0 || (ret = krb5_kt_end_seq_get(context, kt, &cursor)) != 0) krb5_err(context, 1, ret, "get_princ_kt"); if (!*principal) { if (name) parse_name_realm(context, name, 0, NULL, principal); else krb5_err(context, 1, KRB5_CC_NOTFOUND, "get_princ_kt"); } krb5_free_principal(context, tmp); free(def_realm); }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_ccache cache; krb5_creds in, *out; int optidx = 0; setprogname (argv[0]); ret = krb5_init_context (&context); 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 (argc != 1) usage (1); ret = krb5_cc_default(context, &cache); if (ret) krb5_err (context, 1, ret, "krb5_cc_default"); memset(&in, 0, sizeof(in)); if (etype_str) { krb5_enctype enctype; ret = krb5_string_to_enctype(context, etype_str, &enctype); if (ret) krb5_errx (context, 1, "unrecognized enctype: %s", etype_str); in.session.keytype = enctype; } ret = krb5_cc_get_principal(context, cache, &in.client); if (ret) krb5_err (context, 1, ret, "krb5_cc_get_principal"); ret = krb5_parse_name(context, argv[0], &in.server); if (ret) krb5_err (context, 1, ret, "krb5_parse_name %s", argv[0]); in.times.endtime = 0; ret = krb5_get_credentials(context, 0, cache, &in, &out); if (ret) krb5_err (context, 1, ret, "krb5_get_credentials"); print_and_decode_tkt (context, &out->ticket, out->server, out->session.keytype); krb5_free_cred_contents(context, out); return 0; }