mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
r1475: More kerberos work
- We can now connect to hosts that follow the SPNEGO RFC, and *do not*
give us their principal name in the mechListMIC.
- The client code now remembers the hostname it connects to
- We now kinit for a user, if there is not valid ticket already
- Re-introduce clock skew compensation
TODO:
- See if the username in the ccache matches the username specified
- Use a private ccache, rather then the global one, for a 'new' kinit
- Determine 'default' usernames.
- The default for Krb5 is the one in the ccache, then $USER
- For NTLMSSP, it's just $USER
Andrew Bartlett
(This used to be commit de5da66939
)
This commit is contained in:
parent
39b1201584
commit
ed03516c91
@ -79,6 +79,8 @@ struct cli_socket {
|
||||
int reference_count;
|
||||
|
||||
struct in_addr dest_ip;
|
||||
/* dest hostname (which may or may not be a DNS name) */
|
||||
char *hostname;
|
||||
|
||||
/* the port used */
|
||||
int port;
|
||||
|
@ -106,6 +106,14 @@ static NTSTATUS gensec_start(struct gensec_security **gensec_security)
|
||||
(*gensec_security)->mem_ctx = mem_ctx;
|
||||
(*gensec_security)->ops = NULL;
|
||||
|
||||
ZERO_STRUCT((*gensec_security)->user);
|
||||
ZERO_STRUCT((*gensec_security)->target);
|
||||
ZERO_STRUCT((*gensec_security)->default_user);
|
||||
|
||||
(*gensec_security)->default_user.name = "";
|
||||
(*gensec_security)->default_user.domain = talloc_strdup(mem_ctx, lp_workgroup());
|
||||
(*gensec_security)->default_user.realm = talloc_strdup(mem_ctx, lp_realm());
|
||||
|
||||
(*gensec_security)->subcontext = False;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
@ -163,6 +171,9 @@ NTSTATUS gensec_server_start(struct gensec_security **gensec_security)
|
||||
static NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
|
||||
{
|
||||
NTSTATUS status;
|
||||
DEBUG(5, ("Starting GENSEC %smechanism %s\n",
|
||||
gensec_security->subcontext ? "sub" : "",
|
||||
gensec_security->ops->name));
|
||||
switch (gensec_security->gensec_role) {
|
||||
case GENSEC_CLIENT:
|
||||
if (gensec_security->ops->client_start) {
|
||||
@ -337,6 +348,61 @@ void gensec_end(struct gensec_security **gensec_security)
|
||||
gensec_security = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a username on a GENSEC context - ensures it is talloc()ed
|
||||
*
|
||||
*/
|
||||
|
||||
NTSTATUS gensec_set_unparsed_username(struct gensec_security *gensec_security, const char *user)
|
||||
{
|
||||
char *p;
|
||||
char *u = talloc_strdup(gensec_security->mem_ctx, user);
|
||||
if (!u) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
p = strchr_m(user, '@');
|
||||
|
||||
if (p) {
|
||||
*p = '\0';
|
||||
gensec_security->user.name = talloc_strdup(gensec_security->mem_ctx, u);
|
||||
if (!gensec_security->user.name) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
gensec_security->user.realm = talloc_strdup(gensec_security->mem_ctx, p+1);
|
||||
if (!gensec_security->user.realm) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
p = strchr_m(user, '\\');
|
||||
if (!p) {
|
||||
p = strchr_m(user, '/');
|
||||
}
|
||||
|
||||
if (p) {
|
||||
*p = '\0';
|
||||
gensec_security->user.domain = talloc_strdup(gensec_security->mem_ctx, u);
|
||||
if (!gensec_security->user.domain) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
gensec_security->user.name = talloc_strdup(gensec_security->mem_ctx, p+1);
|
||||
if (!gensec_security->user.name) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
gensec_security->user.name = u;
|
||||
if (!gensec_security->user.name) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a username on a GENSEC context - ensures it is talloc()ed
|
||||
*
|
||||
@ -351,6 +417,19 @@ NTSTATUS gensec_set_username(struct gensec_security *gensec_security, const char
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a username on a GENSEC context - ensures it is talloc()ed
|
||||
*
|
||||
*/
|
||||
|
||||
const char *gensec_get_username(struct gensec_security *gensec_security)
|
||||
{
|
||||
if (gensec_security->user.name) {
|
||||
return gensec_security->user.name;
|
||||
}
|
||||
return gensec_security->default_user.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a domain on a GENSEC context - ensures it is talloc()ed
|
||||
*
|
||||
@ -365,6 +444,67 @@ NTSTATUS gensec_set_domain(struct gensec_security *gensec_security, const char *
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the NT domain for this GENSEC context
|
||||
*
|
||||
*/
|
||||
|
||||
const char *gensec_get_domain(struct gensec_security *gensec_security)
|
||||
{
|
||||
if (gensec_security->user.domain) {
|
||||
return gensec_security->user.domain;
|
||||
} else if (gensec_security->user.realm) {
|
||||
return gensec_security->user.realm;
|
||||
}
|
||||
return gensec_security->default_user.domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a kerberos realm on a GENSEC context - ensures it is talloc()ed
|
||||
*
|
||||
*/
|
||||
|
||||
NTSTATUS gensec_set_realm(struct gensec_security *gensec_security, const char *realm)
|
||||
{
|
||||
gensec_security->user.realm = talloc_strdup(gensec_security->mem_ctx, realm);
|
||||
if (!gensec_security->user.realm) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Krb5 realm for this context
|
||||
*
|
||||
*/
|
||||
|
||||
const char *gensec_get_realm(struct gensec_security *gensec_security)
|
||||
{
|
||||
if (gensec_security->user.realm) {
|
||||
return gensec_security->user.realm;
|
||||
} else if (gensec_security->user.domain) {
|
||||
return gensec_security->user.domain;
|
||||
}
|
||||
return gensec_security->default_user.realm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a kerberos principal for this context, if one has been set
|
||||
*
|
||||
*/
|
||||
|
||||
char *gensec_get_client_principal(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
const char *realm = gensec_get_realm(gensec_security);
|
||||
if (realm) {
|
||||
return talloc_asprintf(mem_ctx, "%s@%s",
|
||||
gensec_get_username(gensec_security),
|
||||
gensec_get_realm(gensec_security));
|
||||
} else {
|
||||
return talloc_strdup(mem_ctx, gensec_get_username(gensec_security));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the password outright on GENSEC context - ensures it is talloc()ed, and that we will
|
||||
* not do a callback
|
||||
@ -381,20 +521,6 @@ NTSTATUS gensec_set_password(struct gensec_security *gensec_security,
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a kerberos realm on a GENSEC context - ensures it is talloc()ed
|
||||
*
|
||||
*/
|
||||
|
||||
NTSTATUS gensec_set_realm(struct gensec_security *gensec_security, const char *realm)
|
||||
{
|
||||
gensec_security->user.realm = talloc_strdup(gensec_security->mem_ctx, realm);
|
||||
if (!gensec_security->user.realm) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the target principal name (if already known) on a GENSEC context - ensures it is talloc()ed
|
||||
*
|
||||
@ -409,6 +535,53 @@ NTSTATUS gensec_set_target_principal(struct gensec_security *gensec_security, co
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the target service (such as 'http' or 'host') on a GENSEC context - ensures it is talloc()ed
|
||||
*
|
||||
*/
|
||||
|
||||
NTSTATUS gensec_set_target_service(struct gensec_security *gensec_security, const char *service)
|
||||
{
|
||||
gensec_security->target.service = talloc_strdup(gensec_security->mem_ctx, service);
|
||||
if (!gensec_security->target.service) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the target hostname (suitable for kerberos resolutation) on a GENSEC context - ensures it is talloc()ed
|
||||
*
|
||||
*/
|
||||
|
||||
NTSTATUS gensec_set_target_hostname(struct gensec_security *gensec_security, const char *hostname)
|
||||
{
|
||||
gensec_security->target.hostname = talloc_strdup(gensec_security->mem_ctx, hostname);
|
||||
if (!gensec_security->target.hostname) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
const char *gensec_get_target_hostname(struct gensec_security *gensec_security)
|
||||
{
|
||||
if (gensec_security->target.hostname) {
|
||||
return gensec_security->target.hostname;
|
||||
}
|
||||
|
||||
/* TODO: Add a 'set sockaddr' call, and do a reverse lookup */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *gensec_get_target_service(struct gensec_security *gensec_security)
|
||||
{
|
||||
if (gensec_security->target.service) {
|
||||
return gensec_security->target.service;
|
||||
}
|
||||
|
||||
return "host";
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a password callback, if the gensec module we use demands a password
|
||||
*/
|
||||
|
@ -34,6 +34,7 @@ struct gensec_target {
|
||||
const char *principal;
|
||||
const char *hostname;
|
||||
const struct sock_addr *addr;
|
||||
const char *service;
|
||||
};
|
||||
|
||||
|
||||
@ -79,6 +80,7 @@ struct gensec_security {
|
||||
const struct gensec_security_ops *ops;
|
||||
void *private_data;
|
||||
struct gensec_user user;
|
||||
struct gensec_user default_user;
|
||||
struct gensec_target target;
|
||||
enum gensec_role gensec_role;
|
||||
BOOL subcontext;
|
||||
|
@ -43,6 +43,7 @@ struct gensec_krb5_state {
|
||||
krb5_context krb5_context;
|
||||
krb5_auth_context krb5_auth_context;
|
||||
krb5_ccache krb5_ccache;
|
||||
krb5_data ticket;
|
||||
};
|
||||
|
||||
static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security)
|
||||
@ -68,6 +69,7 @@ static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security)
|
||||
gensec_krb5_state->krb5_context = NULL;
|
||||
gensec_krb5_state->krb5_auth_context = NULL;
|
||||
gensec_krb5_state->krb5_ccache = NULL;
|
||||
ZERO_STRUCT(gensec_krb5_state->ticket);
|
||||
gensec_krb5_state->session_key = data_blob(NULL, 0);
|
||||
|
||||
ret = krb5_init_context(&gensec_krb5_state->krb5_context);
|
||||
@ -114,6 +116,7 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security
|
||||
struct gensec_krb5_state *gensec_krb5_state;
|
||||
krb5_error_code ret;
|
||||
NTSTATUS nt_status;
|
||||
|
||||
nt_status = gensec_krb5_start(gensec_security);
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
return nt_status;
|
||||
@ -122,6 +125,7 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security
|
||||
gensec_krb5_state = gensec_security->private_data;
|
||||
gensec_krb5_state->state_position = GENSEC_KRB5_CLIENT_START;
|
||||
|
||||
/* TODO: This is effecivly a static/global variable... */
|
||||
ret = krb5_cc_default(gensec_krb5_state->krb5_context, &gensec_krb5_state->krb5_ccache);
|
||||
if (ret) {
|
||||
DEBUG(1,("krb5_cc_default failed (%s)\n",
|
||||
@ -129,13 +133,101 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security
|
||||
return NT_STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
while (1) {
|
||||
if (gensec_security->target.principal) {
|
||||
DEBUG(5, ("Finding ticket for target [%s]\n", gensec_security->target.principal));
|
||||
ret = ads_krb5_mk_req(gensec_krb5_state->krb5_context,
|
||||
&gensec_krb5_state->krb5_auth_context,
|
||||
AP_OPTS_USE_SUBKEY | AP_OPTS_MUTUAL_REQUIRED,
|
||||
gensec_security->target.principal,
|
||||
gensec_krb5_state->krb5_ccache,
|
||||
&gensec_krb5_state->ticket);
|
||||
if (ret) {
|
||||
DEBUG(1,("ads_krb5_mk_req failed (%s)\n",
|
||||
error_message(ret)));
|
||||
}
|
||||
} else {
|
||||
krb5_data in_data;
|
||||
in_data.length = 0;
|
||||
const char *hostname = gensec_get_target_hostname(gensec_security);
|
||||
if (!hostname) {
|
||||
DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n"));
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
ret = krb5_mk_req(gensec_krb5_state->krb5_context,
|
||||
&gensec_krb5_state->krb5_auth_context,
|
||||
AP_OPTS_USE_SUBKEY | AP_OPTS_MUTUAL_REQUIRED,
|
||||
gensec_get_target_service(gensec_security),
|
||||
hostname,
|
||||
&in_data, gensec_krb5_state->krb5_ccache,
|
||||
&gensec_krb5_state->ticket);
|
||||
if (ret) {
|
||||
DEBUG(1,("krb5_mk_req failed (%s)\n",
|
||||
error_message(ret)));
|
||||
}
|
||||
|
||||
}
|
||||
switch (ret) {
|
||||
case 0:
|
||||
return NT_STATUS_OK;
|
||||
case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN:
|
||||
DEBUG(3, ("Server is not registered with our KDC: %s\n",
|
||||
error_message(ret)));
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
case KRB5KDC_ERR_PREAUTH_FAILED:
|
||||
case KRB5KRB_AP_ERR_TKT_EXPIRED:
|
||||
case KRB5_CC_END:
|
||||
case KRB5_FCC_NOFILE:
|
||||
case KRB5_CC_NOTFOUND:
|
||||
{
|
||||
char *password;
|
||||
time_t kdc_time;
|
||||
DEBUG(3, ("kerberos: %s\n",
|
||||
error_message(ret)));
|
||||
nt_status = gensec_get_password(gensec_security,
|
||||
gensec_security->mem_ctx,
|
||||
&password);
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
return nt_status;
|
||||
}
|
||||
|
||||
ret = kerberos_kinit_password_cc(gensec_krb5_state->krb5_context, gensec_krb5_state->krb5_ccache,
|
||||
gensec_get_client_principal(gensec_security, gensec_security->mem_ctx),
|
||||
password, NULL, &kdc_time);
|
||||
|
||||
/* cope with ticket being in the future due to clock skew */
|
||||
if ((unsigned)kdc_time > time(NULL)) {
|
||||
time_t t = time(NULL);
|
||||
int time_offset =(unsigned)kdc_time-t;
|
||||
DEBUG(4,("Advancing clock by %d seconds to cope with clock skew\n", time_offset));
|
||||
krb5_set_real_time(gensec_krb5_state->krb5_context, t + time_offset + 1, 0);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
DEBUG(1,("kinit failed (%s)\n",
|
||||
error_message(ret)));
|
||||
return NT_STATUS_WRONG_PASSWORD;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
DEBUG(0, ("kerberos: %s\n",
|
||||
error_message(ret)));
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gensec_krb5_end(struct gensec_security *gensec_security)
|
||||
{
|
||||
struct gensec_krb5_state *gensec_krb5_state = gensec_security->private_data;
|
||||
|
||||
if (gensec_krb5_state->ticket.length) {
|
||||
/* Hmm, heimdal dooesn't have this - what's the correct call? */
|
||||
#ifdef HAVE_KRB5_FREE_DATA_CONTENTS
|
||||
krb5_free_data_contents(gensec_krb5_state->krb5_context, &gensec_krb5_state->ticket);
|
||||
#endif
|
||||
}
|
||||
if (gensec_krb5_state->krb5_ccache) {
|
||||
/* Removed by jra. They really need to fix their kerberos so we don't leak memory.
|
||||
JERRY -- disabled since it causes heimdal 0.6.1rc3 to die
|
||||
@ -182,33 +274,17 @@ static NTSTATUS gensec_krb5_update(struct gensec_security *gensec_security, TALL
|
||||
switch (gensec_krb5_state->state_position) {
|
||||
case GENSEC_KRB5_CLIENT_START:
|
||||
{
|
||||
krb5_data packet;
|
||||
|
||||
#if 0 /* When we get some way to input the time offset */
|
||||
if (time_offset != 0) {
|
||||
krb5_set_real_time(context, time(NULL) + time_offset, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = ads_krb5_mk_req(gensec_krb5_state->krb5_context,
|
||||
&gensec_krb5_state->krb5_auth_context,
|
||||
AP_OPTS_USE_SUBKEY | AP_OPTS_MUTUAL_REQUIRED,
|
||||
gensec_security->target.principal,
|
||||
gensec_krb5_state->krb5_ccache, &packet);
|
||||
if (ret) {
|
||||
DEBUG(1,("ads_krb5_mk_req (request ticket) failed (%s)\n",
|
||||
error_message(ret)));
|
||||
nt_status = NT_STATUS_LOGON_FAILURE;
|
||||
} else {
|
||||
DATA_BLOB unwrapped_out;
|
||||
unwrapped_out = data_blob_talloc(out_mem_ctx, packet.data, packet.length);
|
||||
unwrapped_out = data_blob_talloc(out_mem_ctx, gensec_krb5_state->ticket.data, gensec_krb5_state->ticket.length);
|
||||
|
||||
/* wrap that up in a nice GSS-API wrapping */
|
||||
*out = gensec_gssapi_gen_krb5_wrap(out_mem_ctx, &unwrapped_out, TOK_ID_KRB_AP_REQ);
|
||||
/* Hmm, heimdal dooesn't have this - what's the correct call? */
|
||||
#ifdef HAVE_KRB5_FREE_DATA_CONTENTS
|
||||
krb5_free_data_contents(gensec_krb5_state->krb5_context, &packet);
|
||||
#endif
|
||||
|
||||
gensec_krb5_state->state_position = GENSEC_KRB5_CLIENT_MUTUAL_AUTH;
|
||||
nt_status = NT_STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
@ -54,13 +54,59 @@ kerb_prompter(krb5_context ctx, void *data,
|
||||
simulate a kinit, putting the tgt in the default cache location
|
||||
remus@snapserver.com
|
||||
*/
|
||||
int kerberos_kinit_password(const char *principal, const char *password, int time_offset, time_t *expire_time)
|
||||
int kerberos_kinit_password_cc(krb5_context ctx, krb5_ccache cc, const char *principal, const char *password, time_t *expire_time, time_t *kdc_time)
|
||||
{
|
||||
krb5_error_code code = 0;
|
||||
krb5_principal me;
|
||||
krb5_creds my_creds;
|
||||
|
||||
if ((code = krb5_parse_name(ctx, principal, &me))) {
|
||||
return code;
|
||||
}
|
||||
|
||||
if ((code = krb5_get_init_creds_password(ctx, &my_creds, me, password,
|
||||
kerb_prompter,
|
||||
NULL, 0, NULL, NULL))) {
|
||||
krb5_free_principal(ctx, me);
|
||||
return code;
|
||||
}
|
||||
|
||||
if ((code = krb5_cc_initialize(ctx, cc, me))) {
|
||||
krb5_free_cred_contents(ctx, &my_creds);
|
||||
krb5_free_principal(ctx, me);
|
||||
return code;
|
||||
}
|
||||
|
||||
if ((code = krb5_cc_store_cred(ctx, cc, &my_creds))) {
|
||||
krb5_free_cred_contents(ctx, &my_creds);
|
||||
krb5_free_principal(ctx, me);
|
||||
return code;
|
||||
}
|
||||
|
||||
if (expire_time) {
|
||||
*expire_time = (time_t) my_creds.times.endtime;
|
||||
}
|
||||
|
||||
if (kdc_time) {
|
||||
*kdc_time = (time_t) my_creds.times.starttime;
|
||||
}
|
||||
|
||||
krb5_free_cred_contents(ctx, &my_creds);
|
||||
krb5_free_principal(ctx, me);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
simulate a kinit, putting the tgt in the default cache location
|
||||
remus@snapserver.com
|
||||
*/
|
||||
int kerberos_kinit_password(const char *principal, const char *password, int time_offset, time_t *expire_time, time_t *kdc_time)
|
||||
{
|
||||
krb5_context ctx = NULL;
|
||||
krb5_error_code code = 0;
|
||||
krb5_ccache cc = NULL;
|
||||
krb5_principal me;
|
||||
krb5_creds my_creds;
|
||||
|
||||
if ((code = krb5_init_context(&ctx)))
|
||||
return code;
|
||||
@ -73,42 +119,12 @@ int kerberos_kinit_password(const char *principal, const char *password, int tim
|
||||
krb5_free_context(ctx);
|
||||
return code;
|
||||
}
|
||||
|
||||
if ((code = krb5_parse_name(ctx, principal, &me))) {
|
||||
krb5_free_context(ctx);
|
||||
return code;
|
||||
}
|
||||
|
||||
if ((code = krb5_get_init_creds_password(ctx, &my_creds, me, password,
|
||||
kerb_prompter,
|
||||
NULL, 0, NULL, NULL))) {
|
||||
krb5_free_principal(ctx, me);
|
||||
krb5_free_context(ctx);
|
||||
return code;
|
||||
}
|
||||
|
||||
if ((code = krb5_cc_initialize(ctx, cc, me))) {
|
||||
krb5_free_cred_contents(ctx, &my_creds);
|
||||
krb5_free_principal(ctx, me);
|
||||
krb5_free_context(ctx);
|
||||
return code;
|
||||
}
|
||||
|
||||
if ((code = krb5_cc_store_cred(ctx, cc, &my_creds))) {
|
||||
krb5_cc_close(ctx, cc);
|
||||
krb5_free_cred_contents(ctx, &my_creds);
|
||||
krb5_free_principal(ctx, me);
|
||||
krb5_free_context(ctx);
|
||||
return code;
|
||||
}
|
||||
|
||||
if (expire_time)
|
||||
*expire_time = (time_t) my_creds.times.endtime;
|
||||
|
||||
krb5_cc_close(ctx, cc);
|
||||
krb5_free_cred_contents(ctx, &my_creds);
|
||||
krb5_free_principal(ctx, me);
|
||||
krb5_free_context(ctx);
|
||||
if ((code = kerberos_kinit_password_cc(ctx, cc, principal, password, expire_time, kdc_time))) {
|
||||
krb5_cc_close(ctx, cc);
|
||||
krb5_free_context(ctx);
|
||||
return code;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -129,7 +145,7 @@ int ads_kinit_password(ADS_STRUCT *ads)
|
||||
return KRB5_LIBOS_CANTREADPWD;
|
||||
}
|
||||
|
||||
ret = kerberos_kinit_password(s, ads->auth.password, ads->auth.time_offset, &ads->auth.expire);
|
||||
ret = kerberos_kinit_password(s, ads->auth.password, ads->auth.time_offset, &ads->auth.expire, NULL);
|
||||
|
||||
if (ret) {
|
||||
DEBUG(0,("kerberos_kinit_password %s failed: %s\n",
|
||||
|
@ -69,5 +69,6 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
|
||||
const char *realm, const DATA_BLOB *ticket,
|
||||
char **principal, DATA_BLOB *auth_data,
|
||||
DATA_BLOB *ap_rep);
|
||||
int kerberos_kinit_password_cc(krb5_context ctx, krb5_ccache cc, const char *principal, const char *password, time_t *expire_time, time_t *kdc_time);
|
||||
#endif /* HAVE_KRB5 */
|
||||
|
||||
|
@ -256,7 +256,7 @@ static NTSTATUS gensec_spnego_client_netTokenInit(struct gensec_security *gensec
|
||||
return nt_status;
|
||||
}
|
||||
nt_status = gensec_update(spnego_state->sub_sec_security,
|
||||
out_mem_ctx, in, &unwrapped_out);
|
||||
out_mem_ctx, in, &unwrapped_out);
|
||||
if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
|
||||
struct spnego_data spnego_out;
|
||||
spnego_out.type = SPNEGO_NEG_TOKEN_INIT;
|
||||
@ -349,6 +349,7 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
|
||||
}
|
||||
|
||||
if (spnego.negTokenInit.targetPrincipal) {
|
||||
DEBUG(5, ("Server claims it's principal name is %s\n", spnego.negTokenInit.targetPrincipal));
|
||||
nt_status = gensec_set_target_principal(gensec_security,
|
||||
spnego.negTokenInit.targetPrincipal);
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
|
@ -424,6 +424,13 @@ static NTSTATUS smb_raw_session_setup_generic_spnego(struct cli_session *session
|
||||
goto done;
|
||||
}
|
||||
|
||||
status = gensec_set_target_hostname(session->gensec, session->transport->socket->hostname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(1, ("Failed to start set GENSEC target hostname: %s\n",
|
||||
nt_errstr(status)));
|
||||
goto done;
|
||||
}
|
||||
|
||||
status = gensec_start_mech_by_oid(session->gensec, OID_SPNEGO);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(1, ("Failed to start set GENSEC client SPNEGO mechanism: %s\n",
|
||||
|
@ -45,6 +45,8 @@ struct cli_socket *cli_sock_init(void)
|
||||
/* 20 second default timeout */
|
||||
sock->timeout = 20000;
|
||||
|
||||
sock->hostname = NULL;
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
@ -140,6 +142,7 @@ BOOL cli_sock_connect_byname(struct cli_socket *sock, const char *host, int port
|
||||
struct in_addr ip;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
char *name, *p;
|
||||
BOOL ret;
|
||||
|
||||
if (getenv("LIBSMB_PROG")) {
|
||||
sock->fd = sock_exec(getenv("LIBSMB_PROG"));
|
||||
@ -162,7 +165,13 @@ BOOL cli_sock_connect_byname(struct cli_socket *sock, const char *host, int port
|
||||
return False;
|
||||
}
|
||||
|
||||
ret = cli_sock_connect(sock, &ip, port);
|
||||
|
||||
if (ret) {
|
||||
sock->hostname = talloc_steal(mem_ctx, sock->mem_ctx, name);
|
||||
}
|
||||
|
||||
talloc_destroy(mem_ctx);
|
||||
|
||||
return cli_sock_connect(sock, &ip, port);
|
||||
return ret;
|
||||
}
|
||||
|
@ -60,6 +60,13 @@ NTSTATUS dcerpc_bind_auth_spnego(struct dcerpc_pipe *p,
|
||||
return status;
|
||||
}
|
||||
|
||||
status = gensec_set_target_hostname(p->security_state.generic_state, p->transport.peer_name(p));
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(1, ("Failed to start set GENSEC target hostname: %s\n",
|
||||
nt_errstr(status)));
|
||||
return status;
|
||||
}
|
||||
|
||||
status = gensec_start_mech_by_authtype(p->security_state.generic_state, DCERPC_AUTH_TYPE_SPNEGO);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(1, ("Failed to start set GENSEC client SPNEGO mechanism: %s\n",
|
||||
|
Loading…
Reference in New Issue
Block a user