📄 clikrb5.c
字号:
} DEBUG(10,("ads_krb5_mk_req: Ticket (%s) in ccache (%s) is valid until: (%s - %u)\n", principal, krb5_cc_default_name(context), http_timestring((unsigned)credsp->times.endtime), (unsigned)credsp->times.endtime)); in_data.length = 0; retval = krb5_mk_req_extended(context, auth_context, ap_req_options, &in_data, credsp, outbuf); if (retval) { DEBUG(1,("ads_krb5_mk_req: krb5_mk_req_extended failed (%s)\n", error_message(retval))); } krb5_free_creds(context, credsp);cleanup_creds: krb5_free_cred_contents(context, &creds);cleanup_princ: krb5_free_principal(context, server); return retval;}/* get a kerberos5 ticket for the given service */int cli_krb5_get_ticket(const char *principal, time_t time_offset, DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts){ krb5_error_code retval; krb5_data packet; krb5_context context = NULL; krb5_ccache ccdef = NULL; krb5_auth_context auth_context = NULL; krb5_enctype enc_types[] = {#ifdef ENCTYPE_ARCFOUR_HMAC ENCTYPE_ARCFOUR_HMAC,#endif ENCTYPE_DES_CBC_MD5, ENCTYPE_DES_CBC_CRC, ENCTYPE_NULL}; initialize_krb5_error_table(); retval = krb5_init_context(&context); if (retval) { DEBUG(1,("cli_krb5_get_ticket: krb5_init_context failed (%s)\n", error_message(retval))); goto failed; } if (time_offset != 0) { krb5_set_real_time(context, time(NULL) + time_offset, 0); } if ((retval = krb5_cc_default(context, &ccdef))) { DEBUG(1,("cli_krb5_get_ticket: krb5_cc_default failed (%s)\n", error_message(retval))); goto failed; } if ((retval = krb5_set_default_tgs_ktypes(context, enc_types))) { DEBUG(1,("cli_krb5_get_ticket: krb5_set_default_tgs_ktypes failed (%s)\n", error_message(retval))); goto failed; } if ((retval = ads_krb5_mk_req(context, &auth_context, AP_OPTS_USE_SUBKEY | (krb5_flags)extra_ap_opts, principal, ccdef, &packet))) { goto failed; } get_krb5_smb_session_key(context, auth_context, session_key_krb5, False); *ticket = data_blob(packet.data, packet.length); kerberos_free_data_contents(context, &packet); failed: if ( context ) { if (ccdef) krb5_cc_close(context, ccdef); if (auth_context) krb5_auth_con_free(context, auth_context); krb5_free_context(context); } return retval;} BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, DATA_BLOB *session_key, BOOL remote) { krb5_keyblock *skey; krb5_error_code err; BOOL ret = False; if (remote) err = krb5_auth_con_getremotesubkey(context, auth_context, &skey); else err = krb5_auth_con_getlocalsubkey(context, auth_context, &skey); if (err == 0 && skey != NULL) { DEBUG(10, ("Got KRB5 session key of length %d\n", KRB5_KEY_LENGTH(skey))); *session_key = data_blob(KRB5_KEY_DATA(skey), KRB5_KEY_LENGTH(skey)); dump_data_pw("KRB5 Session Key:\n", session_key->data, session_key->length); ret = True; krb5_free_keyblock(context, skey); } else { DEBUG(10, ("KRB5 error getting session key %d\n", err)); } return ret; }#if defined(HAVE_KRB5_PRINCIPAL_GET_COMP_STRING) && !defined(HAVE_KRB5_PRINC_COMPONENT) const krb5_data *krb5_princ_component(krb5_context context, krb5_principal principal, int i ); const krb5_data *krb5_princ_component(krb5_context context, krb5_principal principal, int i ){ static krb5_data kdata; kdata.data = (char *)krb5_principal_get_comp_string(context, principal, i); kdata.length = strlen(kdata.data); return &kdata;}#endif krb5_error_code smb_krb5_kt_free_entry(krb5_context context, krb5_keytab_entry *kt_entry){#if defined(HAVE_KRB5_KT_FREE_ENTRY) return krb5_kt_free_entry(context, kt_entry);#elif defined(HAVE_KRB5_FREE_KEYTAB_ENTRY_CONTENTS) return krb5_free_keytab_entry_contents(context, kt_entry);#else#error UNKNOWN_KT_FREE_FUNCTION#endif} void smb_krb5_checksum_from_pac_sig(krb5_checksum *cksum, PAC_SIGNATURE_DATA *sig){#ifdef HAVE_CHECKSUM_IN_KRB5_CHECKSUM cksum->cksumtype = (krb5_cksumtype)sig->type; cksum->checksum.length = sig->signature.buf_len; cksum->checksum.data = sig->signature.buffer;#else cksum->checksum_type = (krb5_cksumtype)sig->type; cksum->length = sig->signature.buf_len; cksum->contents = sig->signature.buffer;#endif} krb5_error_code smb_krb5_verify_checksum(krb5_context context, krb5_keyblock *keyblock, krb5_keyusage usage, krb5_checksum *cksum, uint8 *data, size_t length){ krb5_error_code ret; /* verify the checksum */ /* welcome to the wonderful world of samba's kerberos abstraction layer: * * function heimdal 0.6.1rc3 heimdal 0.7 MIT krb 1.4.2 * ----------------------------------------------------------------------------- * krb5_c_verify_checksum - works works * krb5_verify_checksum works (6 args) works (6 args) broken (7 args) */#if defined(HAVE_KRB5_C_VERIFY_CHECKSUM) { krb5_boolean checksum_valid = False; krb5_data input; input.data = (char *)data; input.length = length; ret = krb5_c_verify_checksum(context, keyblock, usage, &input, cksum, &checksum_valid); if (ret) { DEBUG(3,("smb_krb5_verify_checksum: krb5_c_verify_checksum() failed: %s\n", error_message(ret))); return ret; } if (!checksum_valid) ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; }#elif KRB5_VERIFY_CHECKSUM_ARGS == 6 && defined(HAVE_KRB5_CRYPTO_INIT) && defined(HAVE_KRB5_CRYPTO) && defined(HAVE_KRB5_CRYPTO_DESTROY) /* Warning: MIT's krb5_verify_checksum cannot be used as it will use a key * without enctype and it ignores any key_usage types - Guenther */ { krb5_crypto crypto; ret = krb5_crypto_init(context, keyblock, 0, &crypto); if (ret) { DEBUG(0,("smb_krb5_verify_checksum: krb5_crypto_init() failed: %s\n", error_message(ret))); return ret; } ret = krb5_verify_checksum(context, crypto, usage, data, length, cksum); krb5_crypto_destroy(context, crypto); }#else#error UNKNOWN_KRB5_VERIFY_CHECKSUM_FUNCTION#endif return ret;} time_t get_authtime_from_tkt(krb5_ticket *tkt){#if defined(HAVE_KRB5_TKT_ENC_PART2) return tkt->enc_part2->times.authtime;#else return tkt->ticket.authtime;#endif}static int get_kvno_from_ap_req(krb5_ap_req *ap_req){#ifdef HAVE_TICKET_POINTER_IN_KRB5_AP_REQ /* MIT */ if (ap_req->ticket->enc_part.kvno) return ap_req->ticket->enc_part.kvno;#else /* Heimdal */ if (ap_req->ticket.enc_part.kvno) return *ap_req->ticket.enc_part.kvno;#endif return 0;}static krb5_enctype get_enctype_from_ap_req(krb5_ap_req *ap_req){#ifdef HAVE_ETYPE_IN_ENCRYPTEDDATA /* Heimdal */ return ap_req->ticket.enc_part.etype;#else /* MIT */ return ap_req->ticket->enc_part.enctype;#endif}static krb5_error_codeget_key_from_keytab(krb5_context context, krb5_const_principal server, krb5_enctype enctype, krb5_kvno kvno, krb5_keyblock **out_key){ krb5_keytab_entry entry; krb5_error_code ret; krb5_keytab keytab; char *name = NULL; /* We have to open a new keytab handle here, as MIT does an implicit open/getnext/close on krb5_kt_get_entry. We may be in the middle of a keytab enumeration when this is called. JRA. */ ret = krb5_kt_default(context, &keytab); if (ret) { DEBUG(0,("get_key_from_keytab: failed to open keytab: %s\n", error_message(ret))); return ret; } if ( DEBUGLEVEL >= 10 ) { krb5_unparse_name(context, server, &name); DEBUG(10,("get_key_from_keytab: will look for kvno %d, enctype %d and name: %s\n", kvno, enctype, name)); krb5_free_unparsed_name(context, name); } ret = krb5_kt_get_entry(context, keytab, server, kvno, enctype, &entry); if (ret) { DEBUG(0,("get_key_from_keytab: failed to retrieve key: %s\n", error_message(ret))); goto out; }#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK /* Heimdal */ ret = krb5_copy_keyblock(context, &entry.keyblock, out_key);#elif defined(HAVE_KRB5_KEYTAB_ENTRY_KEY) /* MIT */ ret = krb5_copy_keyblock(context, &entry.key, out_key);#else#error UNKNOWN_KRB5_KEYTAB_ENTRY_FORMAT#endif if (ret) { DEBUG(0,("get_key_from_keytab: failed to copy key: %s\n", error_message(ret))); goto out; } smb_krb5_kt_free_entry(context, &entry); out: krb5_kt_close(context, keytab); return ret;} void smb_krb5_free_ap_req(krb5_context context, krb5_ap_req *ap_req){#ifdef HAVE_KRB5_FREE_AP_REQ /* MIT */ krb5_free_ap_req(context, ap_req);#elif defined(HAVE_FREE_AP_REQ) /* Heimdal */ free_AP_REQ(ap_req);#else#error UNKNOWN_KRB5_AP_REQ_FREE_FUNCTION#endif}/* Prototypes */#if defined(HAVE_DECODE_KRB5_AP_REQ) /* MIT */krb5_error_code decode_krb5_ap_req(const krb5_data *code, krb5_ap_req **rep);#endif krb5_error_code smb_krb5_get_keyinfo_from_ap_req(krb5_context context, const krb5_data *inbuf, krb5_kvno *kvno, krb5_enctype *enctype){ krb5_error_code ret;#ifdef HAVE_KRB5_DECODE_AP_REQ /* Heimdal */ { krb5_ap_req ap_req; ret = krb5_decode_ap_req(context, inbuf, &ap_req); if (ret) return ret; *kvno = get_kvno_from_ap_req(&ap_req); *enctype = get_enctype_from_ap_req(&ap_req); smb_krb5_free_ap_req(context, &ap_req); }#elif defined(HAVE_DECODE_KRB5_AP_REQ) /* MIT */ { krb5_ap_req *ap_req = NULL; ret = decode_krb5_ap_req(inbuf, &ap_req); if (ret) return ret; *kvno = get_kvno_from_ap_req(ap_req); *enctype = get_enctype_from_ap_req(ap_req); smb_krb5_free_ap_req(context, ap_req); }#else#error UNKOWN_KRB5_AP_REQ_DECODING_FUNCTION#endif return ret;} krb5_error_code krb5_rd_req_return_keyblock_from_keytab(krb5_context context, krb5_auth_context *auth_context, const krb5_data *inbuf, krb5_const_principal server, krb5_keytab keytab, krb5_flags *ap_req_options, krb5_ticket **ticket, krb5_keyblock **keyblock){ krb5_error_code ret; krb5_ap_req *ap_req = NULL; krb5_kvno kvno; krb5_enctype enctype; krb5_keyblock *local_keyblock; ret = krb5_rd_req(context, auth_context, inbuf, server, keytab, ap_req_options, ticket); if (ret) { return ret; } ret = smb_krb5_get_keyinfo_from_ap_req(context, inbuf, &kvno, &enctype); if (ret) { return ret; } ret = get_key_from_keytab(context, server, enctype, kvno, &local_keyblock); if (ret) { DEBUG(0,("krb5_rd_req_return_keyblock_from_keytab: failed to call get_key_from_keytab\n")); goto out; }out: if (ap_req) { smb_krb5_free_ap_req(context, ap_req); } if (ret && local_keyblock != NULL) { krb5_free_keyblock(context, local_keyblock); } else { *keyblock = local_keyblock; } return ret;} krb5_error_code smb_krb5_parse_name_norealm(krb5_context context, const char *name, krb5_principal *principal){#ifdef HAVE_KRB5_PARSE_NAME_NOREALM return krb5_parse_name_norealm(context, name, principal);#endif /* we are cheating here because parse_name will in fact set the realm. * We don't care as the only caller of smb_krb5_parse_name_norealm * ignores the realm anyway when calling * smb_krb5_principal_compare_any_realm later - Guenther */ return krb5_parse_name(context, name, principal);} BOOL smb_krb5_principal_compare_any_realm(krb5_context context, krb5_const_principal princ1, krb5_const_principal princ2){#ifdef HAVE_KRB5_PRINCIPAL_COMPARE_ANY_REALM return krb5_principal_compare_any_realm(context, princ1, princ2);/* krb5_princ_size is a macro in MIT */#elif defined(HAVE_KRB5_PRINC_SIZE) || defined(krb5_princ_size) int i, len1, len2; const krb5_data *p1, *p2; len1 = krb5_princ_size(context, princ1); len2 = krb5_princ_size(context, princ2); if (len1 != len2) return False; for (i = 0; i < len1; i++) { p1 = krb5_princ_component(context, CONST_DISCARD(krb5_principal, princ1), i); p2 = krb5_princ_component(context, CONST_DISCARD(krb5_principal, princ2), i); if (p1->length != p2->length || memcmp(p1->data, p2->data, p1->length)) return False; } return True;#else#error NO_SUITABLE_PRINCIPAL_COMPARE_FUNCTION#endif}#else /* HAVE_KRB5 */ /* this saves a few linking headaches */ int cli_krb5_get_ticket(const char *principal, time_t time_offset, DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts) { DEBUG(0,("NO KERBEROS SUPPORT\n")); return 1;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -