mirror of
https://github.com/samba-team/samba.git
synced 2025-01-03 01:18:10 +03:00
s3:libads: add kerberos_kinit_passwords_ext() helper
This can check more than one password and is designed to support getting a TGT for our machine account also falling back to older passwords... If we don't have a plaintext password it falls back to an nt_hash. Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Andreas Schneider <asn@samba.org>
This commit is contained in:
parent
017e6e1cb1
commit
4dbbfcb004
@ -26,10 +26,13 @@
|
||||
#include "system/filesys.h"
|
||||
#include "smb_krb5.h"
|
||||
#include "../librpc/gen_ndr/ndr_misc.h"
|
||||
#include "../librpc/gen_ndr/samr.h"
|
||||
#include "libads/kerberos_proto.h"
|
||||
#include "libads/netlogon_ping.h"
|
||||
#include "secrets.h"
|
||||
#include "../lib/tsocket/tsocket.h"
|
||||
#include "../libcli/util/tstream.h"
|
||||
#include "../lib/util/tevent_ntstatus.h"
|
||||
#include "lib/util/asn1.h"
|
||||
#include "librpc/gen_ndr/netlogon.h"
|
||||
|
||||
@ -349,6 +352,583 @@ int kerberos_kinit_password_ext(const char *given_principal,
|
||||
ntstatus);
|
||||
}
|
||||
|
||||
struct kerberos_transaction_cache {
|
||||
struct tsocket_address *local_addr;
|
||||
struct tsocket_address *kdc_addr;
|
||||
uint32_t timeout_msec;
|
||||
};
|
||||
|
||||
static NTSTATUS kerberos_transaction_cache_create(
|
||||
const char *explicit_kdc,
|
||||
uint32_t timeout_msec,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct kerberos_transaction_cache **_kc)
|
||||
{
|
||||
struct kerberos_transaction_cache *kc = NULL;
|
||||
int ret;
|
||||
|
||||
kc = talloc_zero(mem_ctx, struct kerberos_transaction_cache);
|
||||
if (kc == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
kc->timeout_msec = timeout_msec;
|
||||
|
||||
/* parse the address of explicit kdc */
|
||||
ret = tsocket_address_inet_from_strings(kc,
|
||||
"ip",
|
||||
explicit_kdc,
|
||||
DEFAULT_KRB5_PORT,
|
||||
&kc->kdc_addr);
|
||||
if (ret != 0) {
|
||||
NTSTATUS status = map_nt_error_from_unix_common(errno);
|
||||
TALLOC_FREE(kc);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* get an address for us to use locally */
|
||||
ret = tsocket_address_inet_from_strings(kc,
|
||||
"ip",
|
||||
NULL,
|
||||
0,
|
||||
&kc->local_addr);
|
||||
if (ret != 0) {
|
||||
NTSTATUS status = map_nt_error_from_unix_common(errno);
|
||||
TALLOC_FREE(kc);
|
||||
return status;
|
||||
}
|
||||
|
||||
*_kc = kc;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
#ifdef HAVE_KRB5_INIT_CREDS_STEP
|
||||
|
||||
struct kerberos_transaction_state {
|
||||
struct tevent_context *ev;
|
||||
struct kerberos_transaction_cache *kc;
|
||||
struct tstream_context *stream;
|
||||
uint8_t in_hdr[4];
|
||||
struct iovec in_iov[2];
|
||||
DATA_BLOB rep_blob;
|
||||
};
|
||||
|
||||
static void kerberos_transaction_connect_done(struct tevent_req *subreq);
|
||||
|
||||
static struct tevent_req *kerberos_transaction_send(
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct kerberos_transaction_cache *kc,
|
||||
const char *realm,
|
||||
const DATA_BLOB req_blob)
|
||||
{
|
||||
struct tevent_req *req = NULL;
|
||||
struct kerberos_transaction_state *state = NULL;
|
||||
struct tevent_req *subreq = NULL;
|
||||
struct timeval end;
|
||||
|
||||
req = tevent_req_create(mem_ctx, &state,
|
||||
struct kerberos_transaction_state);
|
||||
if (req == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
state->ev = ev;
|
||||
state->kc = kc;
|
||||
|
||||
PUSH_BE_U32(state->in_hdr, 0, req_blob.length);
|
||||
state->in_iov[0].iov_base = (char *)state->in_hdr;
|
||||
state->in_iov[0].iov_len = 4;
|
||||
state->in_iov[1].iov_base = (char *)req_blob.data;
|
||||
state->in_iov[1].iov_len = req_blob.length;
|
||||
|
||||
end = timeval_current_ofs_msec(state->kc->timeout_msec);
|
||||
if (!tevent_req_set_endtime(req, state->ev, end)) {
|
||||
return tevent_req_post(req, state->ev);
|
||||
}
|
||||
|
||||
subreq = tstream_inet_tcp_connect_send(state,
|
||||
state->ev,
|
||||
state->kc->local_addr,
|
||||
state->kc->kdc_addr);
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
return tevent_req_post(req, state->ev);
|
||||
}
|
||||
tevent_req_set_callback(subreq, kerberos_transaction_connect_done, req);
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
static void kerberos_transaction_writev_done(struct tevent_req *subreq);
|
||||
static void kerberos_transaction_read_pdu_done(struct tevent_req *subreq);
|
||||
|
||||
static void kerberos_transaction_connect_done(struct tevent_req *subreq)
|
||||
{
|
||||
struct tevent_req *req =
|
||||
tevent_req_callback_data(subreq,
|
||||
struct tevent_req);
|
||||
struct kerberos_transaction_state *state =
|
||||
tevent_req_data(req,
|
||||
struct kerberos_transaction_state);
|
||||
int ret, sys_errno;
|
||||
|
||||
ret = tstream_inet_tcp_connect_recv(subreq,
|
||||
&sys_errno,
|
||||
state,
|
||||
&state->stream,
|
||||
NULL);
|
||||
TALLOC_FREE(subreq);
|
||||
if (ret != 0) {
|
||||
NTSTATUS status = map_nt_error_from_unix_common(sys_errno);
|
||||
tevent_req_nterror(req, status);
|
||||
return;
|
||||
}
|
||||
|
||||
subreq = tstream_writev_send(state,
|
||||
state->ev,
|
||||
state->stream,
|
||||
state->in_iov, 2);
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
return;
|
||||
}
|
||||
tevent_req_set_callback(subreq, kerberos_transaction_writev_done, req);
|
||||
|
||||
subreq = tstream_read_pdu_blob_send(state,
|
||||
state->ev,
|
||||
state->stream,
|
||||
4, /* initial_read_size */
|
||||
tstream_full_request_u32,
|
||||
req);
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
return;
|
||||
}
|
||||
tevent_req_set_callback(subreq, kerberos_transaction_read_pdu_done, req);
|
||||
}
|
||||
|
||||
static void kerberos_transaction_writev_done(struct tevent_req *subreq)
|
||||
{
|
||||
struct tevent_req *req =
|
||||
tevent_req_callback_data(subreq,
|
||||
struct tevent_req);
|
||||
int ret, sys_errno;
|
||||
|
||||
ret = tstream_writev_recv(subreq, &sys_errno);
|
||||
TALLOC_FREE(subreq);
|
||||
if (ret == -1) {
|
||||
NTSTATUS status = map_nt_error_from_unix_common(sys_errno);
|
||||
tevent_req_nterror(req, status);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void kerberos_transaction_read_pdu_done(struct tevent_req *subreq)
|
||||
{
|
||||
struct tevent_req *req =
|
||||
tevent_req_callback_data(subreq,
|
||||
struct tevent_req);
|
||||
struct kerberos_transaction_state *state =
|
||||
tevent_req_data(req,
|
||||
struct kerberos_transaction_state);
|
||||
NTSTATUS status;
|
||||
|
||||
status = tstream_read_pdu_blob_recv(subreq, state, &state->rep_blob);
|
||||
TALLOC_FREE(subreq);
|
||||
if (tevent_req_nterror(req, status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* raw blob has the length in the first 4 bytes,
|
||||
* which we do not need here.
|
||||
*/
|
||||
memmove(state->rep_blob.data,
|
||||
state->rep_blob.data + 4,
|
||||
state->rep_blob.length - 4);
|
||||
state->rep_blob.length -= 4;
|
||||
|
||||
tevent_req_done(req);
|
||||
}
|
||||
|
||||
static NTSTATUS kerberos_transaction_recv(struct tevent_req *req,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
DATA_BLOB *rep_blob)
|
||||
{
|
||||
struct kerberos_transaction_state *state =
|
||||
tevent_req_data(req,
|
||||
struct kerberos_transaction_state);
|
||||
NTSTATUS status;
|
||||
|
||||
if (tevent_req_is_nterror(req, &status)) {
|
||||
tevent_req_received(req);
|
||||
return status;
|
||||
}
|
||||
|
||||
rep_blob->data = talloc_move(mem_ctx, &state->rep_blob.data);
|
||||
rep_blob->length = state->rep_blob.length;
|
||||
|
||||
tevent_req_received(req);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS kerberos_transaction(
|
||||
struct kerberos_transaction_cache *kc,
|
||||
const char *realm,
|
||||
const DATA_BLOB req_blob,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
DATA_BLOB *rep_blob)
|
||||
{
|
||||
TALLOC_CTX *frame = talloc_stackframe();
|
||||
struct tevent_context *ev = NULL;
|
||||
struct tevent_req *req = NULL;
|
||||
NTSTATUS status = NT_STATUS_NO_MEMORY;
|
||||
|
||||
ev = samba_tevent_context_init(frame);
|
||||
if (ev == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
req = kerberos_transaction_send(frame, ev, kc, realm, req_blob);
|
||||
if (req == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
if (!tevent_req_poll_ntstatus(req, ev, &status)) {
|
||||
goto fail;
|
||||
}
|
||||
status = kerberos_transaction_recv(req, mem_ctx, rep_blob);
|
||||
fail:
|
||||
TALLOC_FREE(frame);
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif /* HAVE_KRB5_INIT_CREDS_STEP */
|
||||
|
||||
struct kerberos_kinit_passwords_ext_private {
|
||||
const char *explicit_kdc;
|
||||
uint32_t timeout_msec;
|
||||
struct kerberos_transaction_cache *kc;
|
||||
const char *password;
|
||||
const struct samr_Password *nt_hash;
|
||||
};
|
||||
|
||||
static krb5_error_code kerberos_kinit_passwords_ext_cb(krb5_context context,
|
||||
krb5_creds *creds,
|
||||
krb5_principal client,
|
||||
krb5_get_init_creds_opt *options,
|
||||
void *private_data)
|
||||
{
|
||||
struct kerberos_kinit_passwords_ext_private *ep =
|
||||
(struct kerberos_kinit_passwords_ext_private *)private_data;
|
||||
TALLOC_CTX *frame = talloc_stackframe();
|
||||
krb5_deltat start_time = 0;
|
||||
krb5_init_creds_context ctx = NULL;
|
||||
krb5_keytab keytab = NULL;
|
||||
krb5_error_code ret;
|
||||
#ifdef HAVE_KRB5_INIT_CREDS_STEP
|
||||
DATA_BLOB rep_blob = { .length = 0, };
|
||||
#endif /* HAVE_KRB5_INIT_CREDS_STEP */
|
||||
|
||||
ZERO_STRUCTP(creds);
|
||||
|
||||
ret = krb5_init_creds_init(context,
|
||||
client,
|
||||
NULL, /* prompter */
|
||||
NULL, /* prompter_data */
|
||||
start_time,
|
||||
options,
|
||||
&ctx);
|
||||
if (ret) {
|
||||
TALLOC_FREE(frame);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ep->password != NULL) {
|
||||
ret = krb5_init_creds_set_password(context, ctx, ep->password);
|
||||
if (ret) {
|
||||
krb5_init_creds_free(context, ctx);
|
||||
TALLOC_FREE(frame);
|
||||
return ret;
|
||||
}
|
||||
} else if (ep->nt_hash != NULL) {
|
||||
const char *keytab_name = "MEMORY:kerberos_kinit_passwords_ext_cb";
|
||||
krb5_keytab_entry entry = { .principal = client, };
|
||||
|
||||
ret = krb5_kt_resolve(context, keytab_name, &keytab);
|
||||
if (ret) {
|
||||
krb5_init_creds_free(context, ctx);
|
||||
TALLOC_FREE(frame);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = smb_krb5_keyblock_init_contents(context,
|
||||
ENCTYPE_ARCFOUR_HMAC,
|
||||
ep->nt_hash->hash,
|
||||
ARRAY_SIZE(ep->nt_hash->hash),
|
||||
KRB5_KT_KEY(&entry));
|
||||
if (ret) {
|
||||
krb5_init_creds_free(context, ctx);
|
||||
krb5_kt_close(context, keytab);
|
||||
TALLOC_FREE(frame);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = krb5_kt_add_entry(context, keytab, &entry);
|
||||
krb5_free_keyblock_contents(context, KRB5_KT_KEY(&entry));
|
||||
if (ret) {
|
||||
krb5_init_creds_free(context, ctx);
|
||||
krb5_kt_close(context, keytab);
|
||||
TALLOC_FREE(frame);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = krb5_init_creds_set_keytab(context, ctx, keytab);
|
||||
if (ret) {
|
||||
krb5_init_creds_free(context, ctx);
|
||||
krb5_kt_close(context, keytab);
|
||||
TALLOC_FREE(frame);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
ret = EINVAL;
|
||||
krb5_init_creds_free(context, ctx);
|
||||
TALLOC_FREE(frame);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ep->kc == NULL) {
|
||||
/*
|
||||
* Use the logic from the krb5 libraries
|
||||
* to find the KDC
|
||||
*/
|
||||
ret = krb5_init_creds_get(context, ctx);
|
||||
if (ret) {
|
||||
krb5_init_creds_free(context, ctx);
|
||||
if (keytab != NULL) {
|
||||
krb5_kt_close(context, keytab);
|
||||
}
|
||||
TALLOC_FREE(frame);
|
||||
return ret;
|
||||
}
|
||||
|
||||
goto got_creds;
|
||||
}
|
||||
|
||||
#ifdef HAVE_KRB5_INIT_CREDS_STEP
|
||||
while (true) {
|
||||
#if defined(HAVE_KRB5_REALM_TYPE)
|
||||
/* Heimdal. */
|
||||
krb5_realm krealm = NULL;
|
||||
#else
|
||||
/* MIT */
|
||||
krb5_data krealm = { .length = 0, };
|
||||
#endif
|
||||
unsigned int flags = 0;
|
||||
const char *realm = NULL;
|
||||
krb5_data in = { .length = 0, };
|
||||
krb5_data out = { .length = 0, };
|
||||
DATA_BLOB req_blob = { .length = 0, };
|
||||
NTSTATUS status;
|
||||
|
||||
in.data = (void *)rep_blob.data;
|
||||
in.length = rep_blob.length;
|
||||
|
||||
flags = 0;
|
||||
ret = krb5_init_creds_step(context,
|
||||
ctx,
|
||||
&in,
|
||||
&out,
|
||||
&krealm,
|
||||
&flags);
|
||||
data_blob_free(&rep_blob);
|
||||
in = (krb5_data) { .length = 0, };
|
||||
if (ret) {
|
||||
krb5_init_creds_free(context, ctx);
|
||||
if (keytab != NULL) {
|
||||
krb5_kt_close(context, keytab);
|
||||
}
|
||||
TALLOC_FREE(frame);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((flags & KRB5_INIT_CREDS_STEP_FLAG_CONTINUE) == 0) {
|
||||
smb_krb5_free_data_contents(context, &out);
|
||||
#if defined(HAVE_KRB5_REALM_TYPE)
|
||||
/* Heimdal. */
|
||||
SAFE_FREE(krealm);
|
||||
#else
|
||||
/* MIT */
|
||||
smb_krb5_free_data_contents(context, &krealm);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(HAVE_KRB5_REALM_TYPE)
|
||||
/* Heimdal. */
|
||||
realm = talloc_strdup(frame, krealm);
|
||||
SAFE_FREE(krealm);
|
||||
#else
|
||||
/* MIT */
|
||||
realm = talloc_strndup(frame, krealm.data, krealm.length);
|
||||
smb_krb5_free_data_contents(context, &krealm);
|
||||
#endif
|
||||
if (realm == NULL) {
|
||||
smb_krb5_free_data_contents(context, &out);
|
||||
krb5_init_creds_free(context, ctx);
|
||||
if (keytab != NULL) {
|
||||
krb5_kt_close(context, keytab);
|
||||
}
|
||||
TALLOC_FREE(frame);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
req_blob.data = (uint8_t *)out.data;
|
||||
req_blob.length = out.length;
|
||||
|
||||
status = kerberos_transaction(ep->kc,
|
||||
realm,
|
||||
req_blob,
|
||||
frame,
|
||||
&rep_blob);
|
||||
smb_krb5_free_data_contents(context, &out);
|
||||
req_blob = (DATA_BLOB) { .length = 0, };
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
ret = map_errno_from_nt_status(status);
|
||||
krb5_init_creds_free(context, ctx);
|
||||
if (keytab != NULL) {
|
||||
krb5_kt_close(context, keytab);
|
||||
}
|
||||
TALLOC_FREE(frame);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#else /* HAVE_KRB5_INIT_CREDS_STEP */
|
||||
#ifdef USING_EMBEDDED_HEIMDAL
|
||||
#error missing HAVE_KRB5_INIT_CREDS_STEP
|
||||
#endif /* USING_EMBEDDED_HEIMDAL */
|
||||
/* Caller should already check! */
|
||||
smb_panic("krb5_init_creds_step not available");
|
||||
#endif /* HAVE_KRB5_INIT_CREDS_STEP */
|
||||
|
||||
got_creds:
|
||||
ret = krb5_init_creds_get_creds(context, ctx, creds);
|
||||
if (ret) {
|
||||
krb5_init_creds_free(context, ctx);
|
||||
if (keytab != NULL) {
|
||||
krb5_kt_close(context, keytab);
|
||||
}
|
||||
TALLOC_FREE(frame);
|
||||
return ret;
|
||||
}
|
||||
|
||||
krb5_init_creds_free(context, ctx);
|
||||
if (keytab != NULL) {
|
||||
krb5_kt_close(context, keytab);
|
||||
}
|
||||
TALLOC_FREE(frame);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
simulate a kinit, putting the tgt in the given cache location.
|
||||
cache_name == NULL is not allowed.
|
||||
This tries all given passwords until we don't get
|
||||
KDC_ERR_PREAUTH_FAILED.
|
||||
If passwords[i] is NULL it falls back to nt_hashes[i]
|
||||
*/
|
||||
int kerberos_kinit_passwords_ext(const char *given_principal,
|
||||
uint8_t num_passwords,
|
||||
const char * const *passwords,
|
||||
const struct samr_Password * const *nt_hashes,
|
||||
uint8_t *used_idx,
|
||||
const char *explicit_kdc,
|
||||
const char *cache_name,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
char **_canon_principal,
|
||||
char **_canon_realm,
|
||||
NTSTATUS *ntstatus)
|
||||
{
|
||||
TALLOC_CTX *frame = talloc_stackframe();
|
||||
struct kerberos_kinit_passwords_ext_private ep = {
|
||||
.explicit_kdc = explicit_kdc,
|
||||
.timeout_msec = 15*1000,
|
||||
};
|
||||
NTSTATUS status;
|
||||
krb5_error_code ret;
|
||||
uint8_t i;
|
||||
krb5_error_code first_ret = EINVAL;
|
||||
NTSTATUS first_status = NT_STATUS_UNSUCCESSFUL;
|
||||
|
||||
if (num_passwords == 0) {
|
||||
TALLOC_FREE(frame);
|
||||
return EINVAL;
|
||||
}
|
||||
if (num_passwords >= INT8_MAX) {
|
||||
TALLOC_FREE(frame);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
#ifndef HAVE_KRB5_INIT_CREDS_STEP
|
||||
if (ep.explicit_kdc != NULL) {
|
||||
DBG_ERR("Using explicit_kdc requires krb5_init_creds_step!\n");
|
||||
TALLOC_FREE(frame);
|
||||
return EINVAL;
|
||||
}
|
||||
#endif /* ! HAVE_KRB5_INIT_CREDS_STEP */
|
||||
|
||||
DBG_DEBUG("explicit_kdc[%s] given_principal[%s] "
|
||||
"num_passwords[%u] cache_name[%s]\n",
|
||||
ep.explicit_kdc,
|
||||
given_principal,
|
||||
num_passwords,
|
||||
cache_name);
|
||||
|
||||
if (ep.explicit_kdc != NULL) {
|
||||
status = kerberos_transaction_cache_create(ep.explicit_kdc,
|
||||
ep.timeout_msec,
|
||||
frame,
|
||||
&ep.kc);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
TALLOC_FREE(frame);
|
||||
return map_errno_from_nt_status(status);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < num_passwords; i++) {
|
||||
ep.password = passwords[i];
|
||||
ep.nt_hash = nt_hashes[i];
|
||||
|
||||
ret = kerberos_kinit_generic_once(given_principal,
|
||||
kerberos_kinit_passwords_ext_cb,
|
||||
&ep,
|
||||
0, /* time_offset */
|
||||
0, /* expire_time */
|
||||
0, /* renew_till_time */
|
||||
cache_name,
|
||||
true, /* request_pac */
|
||||
NULL, /* add_netbios_addr */
|
||||
0, /* renewable_time */
|
||||
mem_ctx,
|
||||
_canon_principal,
|
||||
_canon_realm,
|
||||
ntstatus);
|
||||
if (ret == 0) {
|
||||
*used_idx = i;
|
||||
TALLOC_FREE(frame);
|
||||
return 0;
|
||||
}
|
||||
if (i == 0) {
|
||||
first_ret = ret;
|
||||
first_status = *ntstatus;
|
||||
}
|
||||
if (ret != KRB5KDC_ERR_PREAUTH_FAILED) {
|
||||
*used_idx = i;
|
||||
TALLOC_FREE(frame);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
*used_idx = 0;
|
||||
*ntstatus = first_status;
|
||||
TALLOC_FREE(frame);
|
||||
return first_ret;
|
||||
}
|
||||
|
||||
int ads_kdestroy(const char *cc_name)
|
||||
{
|
||||
krb5_error_code code;
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "system/kerberos.h"
|
||||
|
||||
struct PAC_DATA_CTR;
|
||||
struct samr_Password;
|
||||
|
||||
#define DEFAULT_KRB5_PORT 88
|
||||
|
||||
@ -53,6 +54,17 @@ int kerberos_kinit_password_ext(const char *given_principal,
|
||||
char **_canon_principal,
|
||||
char **_canon_realm,
|
||||
NTSTATUS *ntstatus);
|
||||
int kerberos_kinit_passwords_ext(const char *given_principal,
|
||||
uint8_t num_passwords,
|
||||
const char * const *passwords,
|
||||
const struct samr_Password * const *nt_hashes,
|
||||
uint8_t *used_idx,
|
||||
const char *explicit_kdc,
|
||||
const char *cache_name,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
char **_canon_principal,
|
||||
char **_canon_realm,
|
||||
NTSTATUS *ntstatus);
|
||||
int ads_kdestroy(const char *cc_name);
|
||||
|
||||
int kerberos_kinit_password(const char *principal,
|
||||
|
@ -13,3 +13,5 @@ conf.RECURSE('third_party/heimdal_build')
|
||||
# when this will be available also in
|
||||
# system libraries...
|
||||
conf.define('HAVE_CLIENT_GSS_C_CHANNEL_BOUND_FLAG', 1)
|
||||
|
||||
conf.define('HAVE_KRB5_INIT_CREDS_STEP', 1)
|
||||
|
@ -62,6 +62,7 @@ conf.define('USING_SYSTEM_HEIMDAL', 1)
|
||||
conf.CHECK_FUNCS('''
|
||||
krb5_get_init_creds_opt_set_fast_ccache
|
||||
krb5_get_init_creds_opt_set_fast_flags
|
||||
krb5_init_creds_step
|
||||
''',
|
||||
lib='krb5',
|
||||
headers='krb5.h')
|
||||
|
@ -170,6 +170,7 @@ conf.CHECK_FUNCS('''
|
||||
krb5_free_string
|
||||
krb5_get_init_creds_opt_set_fast_ccache
|
||||
krb5_get_init_creds_opt_set_fast_flags
|
||||
krb5_init_creds_step
|
||||
''',
|
||||
lib='krb5 k5crypto',
|
||||
headers='krb5.h')
|
||||
|
Loading…
Reference in New Issue
Block a user