#include "includes.h"
#include "system/kerberos.h"
-#include "system/time.h"
-#include "system/network.h"
#include "auth/kerberos/kerberos.h"
-#include "librpc/gen_ndr/ndr_krb5pac.h"
+#include "librpc/gen_ndr/krb5pac.h"
#include "auth/auth.h"
+#include "lib/ldb/include/ldb.h"
+#include "auth/auth_sam.h"
+#include "system/network.h"
+#include "lib/socket/socket.h"
+#include "librpc/rpc/dcerpc.h"
enum GENSEC_KRB5_STATE {
GENSEC_KRB5_SERVER_START,
krb5_error_code ret;
struct gensec_krb5_state *gensec_krb5_state;
struct cli_credentials *creds;
-
+ const struct socket_address *my_addr, *peer_addr;
+ krb5_address my_krb5_addr, peer_krb5_addr;
+
creds = gensec_get_credentials(gensec_security);
if (!creds) {
return NT_STATUS_INVALID_PARAMETER;
return NT_STATUS_INTERNAL_ERROR;
}
+ my_addr = gensec_get_my_addr(gensec_security);
+ if (my_addr && my_addr->sockaddr) {
+ ret = krb5_sockaddr2address(gensec_krb5_state->smb_krb5_context->krb5_context,
+ my_addr->sockaddr, &my_krb5_addr);
+ if (ret) {
+ DEBUG(1,("gensec_krb5_start: krb5_sockaddr2address (local) failed (%s)\n",
+ smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context,
+ ret, gensec_krb5_state)));
+ talloc_free(gensec_krb5_state);
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ }
+
+ peer_addr = gensec_get_my_addr(gensec_security);
+ if (peer_addr && peer_addr->sockaddr) {
+ ret = krb5_sockaddr2address(gensec_krb5_state->smb_krb5_context->krb5_context,
+ peer_addr->sockaddr, &peer_krb5_addr);
+ if (ret) {
+ DEBUG(1,("gensec_krb5_start: krb5_sockaddr2address (local) failed (%s)\n",
+ smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context,
+ ret, gensec_krb5_state)));
+ talloc_free(gensec_krb5_state);
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ }
+
+ ret = krb5_auth_con_setaddrs(gensec_krb5_state->smb_krb5_context->krb5_context,
+ gensec_krb5_state->auth_context,
+ my_addr ? &my_krb5_addr : NULL,
+ peer_addr ? &peer_krb5_addr : NULL);
+ if (ret) {
+ DEBUG(1,("gensec_krb5_start: krb5_auth_con_setaddrs failed (%s)\n",
+ smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context,
+ ret, gensec_krb5_state)));
+ talloc_free(gensec_krb5_state);
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
return NT_STATUS_OK;
}
const char *hostname;
krb5_flags ap_req_options = AP_OPTS_USE_SUBKEY | AP_OPTS_MUTUAL_REQUIRED;
- char *principal;
+ const char *principal;
krb5_data in_data;
hostname = gensec_get_target_hostname(gensec_security);
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:
}
return nt_status;
}
+
case GENSEC_KRB5_DONE:
- return NT_STATUS_OK;
+ default:
+ /* Asking too many times... */
+ return NT_STATUS_INVALID_PARAMETER;
}
-
- return NT_STATUS_INVALID_PARAMETER;
}
static NTSTATUS gensec_krb5_session_key(struct gensec_security *gensec_security,
} else {
pac = data_blob_talloc(mem_ctx, pac_data.data, pac_data.length);
if (!pac.data) {
+ talloc_free(mem_ctx);
return NT_STATUS_NO_MEMORY;
}
DEBUG(5, ("krb5_ticket_get_client failed to get cleint principal: %s\n",
smb_get_krb5_error_message(context,
ret, mem_ctx)));
+ talloc_free(mem_ctx);
return NT_STATUS_NO_MEMORY;
}
gensec_krb5_state->smb_krb5_context->krb5_context,
NULL, gensec_krb5_state->keyblock,
client_principal,
- gensec_krb5_state->ticket->ticket.authtime);
+ gensec_krb5_state->ticket->ticket.authtime, NULL);
krb5_free_principal(context, client_principal);
if (NT_STATUS_IS_OK(nt_status)) {
union netr_Validation validation;
validation.sam3 = &logon_info->info3;
- nt_status = make_server_info_netlogon_validation(gensec_krb5_state,
+ nt_status = make_server_info_netlogon_validation(mem_ctx,
NULL,
3, &validation,
&server_info);
}
- talloc_free(mem_ctx);
}
DEBUG(5, ("krb5_ticket_get_client failed to get cleint principal: %s\n",
smb_get_krb5_error_message(context,
ret, mem_ctx)));
+ talloc_free(mem_ctx);
return NT_STATUS_NO_MEMORY;
}
client_principal, &principal_string);
krb5_free_principal(context, client_principal);
if (ret) {
+ talloc_free(mem_ctx);
return NT_STATUS_NO_MEMORY;
}
}
/* references the server_info into the session_info */
- nt_status = auth_generate_session_info(gensec_krb5_state, server_info, &session_info);
- talloc_free(mem_ctx);
+ nt_status = auth_generate_session_info(mem_ctx, server_info, &session_info);
- NT_STATUS_NOT_OK_RETURN(nt_status);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(mem_ctx);
+ return nt_status;
+ }
nt_status = gensec_krb5_session_key(gensec_security, &session_info->session_key);
- NT_STATUS_NOT_OK_RETURN(nt_status);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(mem_ctx);
+ return nt_status;
+ }
*_session_info = session_info;
+ talloc_steal(gensec_krb5_state, session_info);
+ talloc_free(mem_ctx);
return NT_STATUS_OK;
}
static const struct gensec_security_ops gensec_fake_gssapi_krb5_security_ops = {
.name = "fake_gssapi_krb5",
+ .sasl_name = "GSSAPI",
.auth_type = DCERPC_AUTH_TYPE_KRB5,
.oid = gensec_krb5_oids,
.client_start = gensec_fake_gssapi_krb5_client_start,
.session_key = gensec_krb5_session_key,
.session_info = gensec_krb5_session_info,
.have_feature = gensec_krb5_have_feature,
- .enabled = False
+ .enabled = False,
+ .kerberos = True
};
static const struct gensec_security_ops gensec_krb5_security_ops = {
.have_feature = gensec_krb5_have_feature,
.wrap = gensec_krb5_wrap,
.unwrap = gensec_krb5_unwrap,
- .enabled = True
+ .enabled = True,
+ .kerberos = True
};
NTSTATUS gensec_krb5_init(void)