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; 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) perr = "Error parsing principal name"; 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) printf("%s\n", krb5_get_error_message(ctx, ret)); 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); return ret ? (ret - KRB5KDC_ERR_NONE) : 0; }
int main(int argc, char **argv) { int log_level = 0; char *ap_req_str = NULL; char *plain_text_str; unsigned char *plain_text; size_t plain_text_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; krb5_data cipher_text; 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 */ } plain_text_str = argv[0]; { printf("DBG: %s starts arg(%s)\n", prog, plain_text_str); } /* prepare encrypted data */ { { /* stdout */ printf("std:plain_text:%s\n", plain_text_str); } plain_text_len = strlen(plain_text_str); plain_text_len = plain_text_len/2 + plain_text_len%2; plain_text = (unsigned char *)malloc(plain_text_len); memset(plain_text, 0, plain_text_len); plain_text = hex2data(plain_text_str, plain_text); } 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 */ { /** 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 */ /* just only retrieve TGT from credential cache */ { 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); } } /* encrypt */ { krb5_crypto crypto; 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); } ret = krb5_encrypt(context, crypto, 39, /* usage */ plain_text, plain_text_len, &cipher_text); if (ret != 0) { printf("ERR:krb5_encrypt:%s\n", krb5_get_err_text(context, ret)); return(ret); } { /* stdout */ int i = 0; unsigned char *p; p = (unsigned char *)cipher_text.data; printf("std:cipher_text:"); for (i = 0; i < cipher_text.length; i++) { printf("%02x", *p++); } printf("\n"); } krb5_crypto_destroy(context, crypto); } /* clenaup */ { /*free(plain_text);*/ /*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); }
static void do_v5_kvno (int count, char *names[], char * ccachestr, char *etypestr, char *keytab_name, char *sname, int canon, int unknown) { krb5_error_code ret; int i, errors; krb5_enctype etype; krb5_ccache ccache; krb5_principal me; krb5_creds in_creds, *out_creds; krb5_ticket *ticket; char *princ; krb5_keytab keytab = NULL; ret = krb5_init_context(&context); if (ret) { com_err(prog, ret, "while initializing krb5 library"); exit(1); } if (etypestr) { ret = krb5_string_to_enctype(etypestr, &etype); if (ret) { com_err(prog, ret, "while converting etype"); exit(1); } } else { etype = 0; } if (ccachestr) ret = krb5_cc_resolve(context, ccachestr, &ccache); else ret = krb5_cc_default(context, &ccache); if (ret) { com_err(prog, ret, "while opening ccache"); exit(1); } if (keytab_name) { ret = krb5_kt_resolve(context, keytab_name, &keytab); if (ret) { com_err(prog, ret, "resolving keytab %s", keytab_name); exit(1); } } ret = krb5_cc_get_principal(context, ccache, &me); if (ret) { com_err(prog, ret, "while getting client principal name"); exit(1); } errors = 0; for (i = 0; i < count; i++) { memset(&in_creds, 0, sizeof(in_creds)); in_creds.client = me; if (sname != NULL) { ret = krb5_sname_to_principal(context, names[i], sname, KRB5_NT_SRV_HST, &in_creds.server); } else { ret = krb5_parse_name(context, names[i], &in_creds.server); } if (ret) { if (!quiet) com_err(prog, ret, "while parsing principal name %s", names[i]); errors++; continue; } if (unknown == 1) { krb5_princ_type(context, in_creds.server) = KRB5_NT_UNKNOWN; } ret = krb5_unparse_name(context, in_creds.server, &princ); if (ret) { com_err(prog, ret, "while formatting parsed principal name for '%s'", names[i]); errors++; continue; } in_creds.keyblock.enctype = etype; ret = krb5_get_credentials(context, canon ? KRB5_GC_CANONICALIZE : 0, ccache, &in_creds, &out_creds); krb5_free_principal(context, in_creds.server); if (ret) { com_err(prog, ret, "while getting credentials for %s", princ); krb5_free_unparsed_name(context, princ); errors++; continue; } /* we need a native ticket */ ret = krb5_decode_ticket(&out_creds->ticket, &ticket); if (ret) { com_err(prog, ret, "while decoding ticket for %s", princ); krb5_free_creds(context, out_creds); krb5_free_unparsed_name(context, princ); errors++; continue; } if (keytab) { ret = krb5_server_decrypt_ticket_keytab(context, keytab, ticket); if (ret) { if (!quiet) printf("%s: kvno = %d, keytab entry invalid", princ, ticket->enc_part.kvno); com_err(prog, ret, "while decrypting ticket for %s", princ); krb5_free_ticket(context, ticket); krb5_free_creds(context, out_creds); krb5_free_unparsed_name(context, princ); errors++; continue; } if (!quiet) printf("%s: kvno = %d, keytab entry valid\n", princ, ticket->enc_part.kvno); } else { if (!quiet) printf("%s: kvno = %d\n", princ, ticket->enc_part.kvno); } krb5_free_creds(context, out_creds); krb5_free_unparsed_name(context, princ); } if (keytab) krb5_kt_close(context, keytab); krb5_free_principal(context, me); krb5_cc_close(context, ccache); krb5_free_context(context); if (errors) exit(1); exit(0); }
int authenticate_user_krb5pwd(const char *user, const char *pswd, const char *service, const char *default_realm) { krb5_context kcontext = NULL; krb5_error_code code; krb5_principal client = NULL; krb5_principal server = NULL; int ret = 0; char *name = NULL; char *p = NULL; code = krb5_init_context(&kcontext); if (code) { PyErr_SetObject(BasicAuthException_class, Py_BuildValue("((s:i))", "Cannot initialize Kerberos5 context", code)); return 0; } ret = krb5_parse_name (kcontext, service, &server); if (ret) { set_basicauth_error(kcontext, ret); ret = 0; goto end; } code = krb5_unparse_name(kcontext, server, &name); if (code) { set_basicauth_error(kcontext, code); ret = 0; goto end; } #ifdef PRINTFS printf("Using %s as server principal for password verification\n", name); #endif free(name); name = NULL; name = (char *)malloc(256); p = strchr(user, '@'); if (p == NULL) { snprintf(name, 256, "%s@%s", user, default_realm); } else { snprintf(name, 256, "%s", user); } code = krb5_parse_name(kcontext, name, &client); if (code) { set_basicauth_error(kcontext, code); ret = 0; goto end; } code = verify_krb5_user(kcontext, client, pswd, server); if (code) { ret = 0; goto end; } ret = 1; end: #ifdef PRINTFS printf("kerb_authenticate_user_krb5pwd ret=%d user=%s authtype=%s\n", ret, user, "Basic"); #endif if (name) free(name); if (client) krb5_free_principal(kcontext, client); if (server) krb5_free_principal(kcontext, server); krb5_free_context(kcontext); return ret; }
static void test_dh2key(krb5_context context, int i, struct testcase *c) { krb5_error_code ret; krb5_keyblock key; krb5_principal client, server; Ticket ticket; AlgorithmIdentifier ai; size_t size; memset(&ticket, 0, sizeof(&ticket)); ai.algorithm = *c->oid; ai.parameters = NULL; ret = decode_Ticket(c->ticket.data, c->ticket.length, &ticket, &size); if (ret) krb5_errx(context, 1, "decode ticket: %d", ret); ret = krb5_parse_name(context, c->client, &client); if (ret) krb5_err(context, 1, ret, "parse_name: %s", c->client); ret = krb5_parse_name(context, c->server, &server); if (ret) krb5_err(context, 1, ret, "parse_name: %s", c->server); if (verbose_flag) { char *str; hex_encode(c->Z.data, c->Z.length, &str); printf("Z: %s\n", str); free(str); printf("client: %s\n", c->client); printf("server: %s\n", c->server); printf("enctype: %d\n", (int)c->enctype); hex_encode(c->as_req.data, c->as_req.length, &str); printf("as-req: %s\n", str); free(str); hex_encode(c->pk_as_rep.data, c->pk_as_rep.length, &str); printf("pk-as-rep: %s\n", str); free(str); hex_encode(c->ticket.data, c->ticket.length, &str); printf("ticket: %s\n", str); free(str); } ret = _krb5_pk_kdf(context, &ai, c->Z.data, c->Z.length, client, server, c->enctype, &c->as_req, &c->pk_as_rep, &ticket, &key); krb5_free_principal(context, client); krb5_free_principal(context, server); if (ret) krb5_err(context, 1, ret, "_krb5_pk_kdf: %d", i); if (verbose_flag) { char *str; hex_encode(key.keyvalue.data, key.keyvalue.length, &str); printf("key: %s\n", str); free(str); } if (key.keyvalue.length != c->key.length || memcmp(key.keyvalue.data, c->key.data, c->key.length) != 0) krb5_errx(context, 1, "resulting key wrong: %d", i); krb5_free_keyblock_contents(context, &key); free_Ticket(&ticket); }
static NTSTATUS gensec_krb5_common_client_creds(struct gensec_security *gensec_security, struct tevent_context *ev, bool gssapi) { struct gensec_krb5_state *gensec_krb5_state; krb5_error_code ret; struct ccache_container *ccache_container; const char *error_string; const char *principal; const char *hostname; krb5_data in_data; struct tevent_context *previous_ev; gensec_krb5_state = (struct gensec_krb5_state *)gensec_security->private_data; principal = gensec_get_target_principal(gensec_security); hostname = gensec_get_target_hostname(gensec_security); ret = cli_credentials_get_ccache(gensec_get_credentials(gensec_security), ev, gensec_security->settings->lp_ctx, &ccache_container, &error_string); switch (ret) { case 0: break; case KRB5KDC_ERR_PREAUTH_FAILED: case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN: return NT_STATUS_LOGON_FAILURE; case KRB5_KDC_UNREACH: DEBUG(3, ("Cannot reach a KDC we require to contact %s: %s\n", principal, error_string)); return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */ case KRB5_CC_NOTFOUND: case KRB5_CC_END: DEBUG(3, ("Error preparing credentials we require to contact %s : %s\n", principal, error_string)); return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */ default: DEBUG(1, ("gensec_krb5_start: Aquiring initiator credentials failed: %s\n", error_string)); return NT_STATUS_UNSUCCESSFUL; } in_data.length = 0; /* Do this every time, in case we have weird recursive issues here */ ret = smb_krb5_context_set_event_ctx(gensec_krb5_state->smb_krb5_context, ev, &previous_ev); if (ret != 0) { DEBUG(1, ("gensec_krb5_start: Setting event context failed\n")); return NT_STATUS_NO_MEMORY; } if (principal) { krb5_principal target_principal; ret = krb5_parse_name(gensec_krb5_state->smb_krb5_context->krb5_context, principal, &target_principal); if (ret == 0) { ret = krb5_mk_req_exact(gensec_krb5_state->smb_krb5_context->krb5_context, &gensec_krb5_state->auth_context, gensec_krb5_state->ap_req_options, target_principal, &in_data, ccache_container->ccache, &gensec_krb5_state->enc_ticket); krb5_free_principal(gensec_krb5_state->smb_krb5_context->krb5_context, target_principal); } } else { ret = krb5_mk_req(gensec_krb5_state->smb_krb5_context->krb5_context, &gensec_krb5_state->auth_context, gensec_krb5_state->ap_req_options, gensec_get_target_service(gensec_security), hostname, &in_data, ccache_container->ccache, &gensec_krb5_state->enc_ticket); } smb_krb5_context_remove_event_ctx(gensec_krb5_state->smb_krb5_context, previous_ev, ev); switch (ret) { case 0: return NT_STATUS_OK; case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN: DEBUG(3, ("Server [%s] is not registered with our KDC: %s\n", hostname, smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */ case KRB5_KDC_UNREACH: DEBUG(3, ("Cannot reach a KDC we require to contact host [%s]: %s\n", hostname, smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */ case KRB5KDC_ERR_PREAUTH_FAILED: case KRB5KRB_AP_ERR_TKT_EXPIRED: case KRB5_CC_END: /* Too much clock skew - we will need to kinit to re-skew the clock */ case KRB5KRB_AP_ERR_SKEW: case KRB5_KDCREP_SKEW: { DEBUG(3, ("kerberos (mk_req) failed: %s\n", smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); /*fall through*/ } /* just don't print a message for these really ordinary messages */ case KRB5_FCC_NOFILE: case KRB5_CC_NOTFOUND: case ENOENT: return NT_STATUS_UNSUCCESSFUL; break; default: DEBUG(0, ("kerberos: %s\n", smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); return NT_STATUS_UNSUCCESSFUL; } }
int main(int argc, char **argv) { krb5_context context; krb5_principal princ; krb5_salt salt; int optidx; char buf[1024]; krb5_enctype etype; krb5_error_code ret; optidx = krb5_program_setup(&context, argc, argv, args, num_args, NULL); if(help) usage(0); if(version){ print_version (NULL); return 0; } argc -= optidx; argv += optidx; if (argc > 1) usage(1); if(!version5 && !version4 && !afs) version5 = 1; ret = krb5_string_to_enctype(context, keytype_str, &etype); if(ret) krb5_err(context, 1, ret, "krb5_string_to_enctype"); if((etype != ETYPE_DES_CBC_CRC && etype != ETYPE_DES_CBC_MD4 && etype != ETYPE_DES_CBC_MD5) && (afs || version4)) { if(!version5) { etype = ETYPE_DES_CBC_CRC; } else { krb5_errx(context, 1, "DES is the only valid keytype for AFS and Kerberos 4"); } } if(version5 && principal == NULL){ printf("Kerberos v5 principal: "); if(fgets(buf, sizeof(buf), stdin) == NULL) return 1; buf[strcspn(buf, "\r\n")] = '\0'; principal = estrdup(buf); } if(afs && cell == NULL){ printf("AFS cell: "); if(fgets(buf, sizeof(buf), stdin) == NULL) return 1; buf[strcspn(buf, "\r\n")] = '\0'; cell = estrdup(buf); } if(argv[0]) password = argv[0]; if(password == NULL){ if(UI_UTIL_read_pw_string(buf, sizeof(buf), "Password: "******"Kerberos 5 (%s)"); krb5_free_salt(context, salt); } if(version4){ salt.salttype = KRB5_PW_SALT; salt.saltvalue.length = 0; salt.saltvalue.data = NULL; tokey(context, ETYPE_DES_CBC_MD5, password, salt, "Kerberos 4"); } if(afs){ salt.salttype = KRB5_AFS3_SALT; salt.saltvalue.length = strlen(cell); salt.saltvalue.data = cell; tokey(context, ETYPE_DES_CBC_MD5, password, salt, "AFS"); } return 0; }