(*gensec_security)->default_user.realm = talloc_strdup(mem_ctx, lp_realm());
(*gensec_security)->subcontext = False;
+ (*gensec_security)->want_features = 0;
return NT_STATUS_OK;
}
*/
NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
- uint8_t authtype)
+ uint8_t auth_type, uint8_t auth_level)
{
- gensec_security->ops = gensec_security_by_authtype(authtype);
+ gensec_security->ops = gensec_security_by_authtype(auth_type);
if (!gensec_security->ops) {
- DEBUG(3, ("Could not find GENSEC backend for authtype=%d\n", (int)authtype));
+ DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
return NT_STATUS_INVALID_PARAMETER;
}
+ if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
+ gensec_want_feature(gensec_security, GENSEC_WANT_SIGN);
+ }
+ if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
+ gensec_want_feature(gensec_security, GENSEC_WANT_SIGN);
+ gensec_want_feature(gensec_security, GENSEC_WANT_SEAL);
+ }
return gensec_start_mech(gensec_security);
}
if (!gensec_security->ops->check_packet) {
return NT_STATUS_NOT_IMPLEMENTED;
}
+ if (!(gensec_security->want_features & GENSEC_WANT_SIGN)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
return gensec_security->ops->check_packet(gensec_security, mem_ctx, data, length, sig);
}
if (!gensec_security->ops->seal_packet) {
return NT_STATUS_NOT_IMPLEMENTED;
}
+ if (!(gensec_security->want_features & GENSEC_WANT_SEAL)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
return gensec_security->ops->seal_packet(gensec_security, mem_ctx, data, length, sig);
}
if (!gensec_security->ops->sign_packet) {
return NT_STATUS_NOT_IMPLEMENTED;
}
+ if (!(gensec_security->want_features & GENSEC_WANT_SIGN)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
return gensec_security->ops->sign_packet(gensec_security, mem_ctx, data, length, sig);
}
if (!gensec_security->ops->session_key) {
return NT_STATUS_NOT_IMPLEMENTED;
}
+ if (!(gensec_security->want_features & GENSEC_WANT_SESSION_KEY)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
return gensec_security->ops->session_key(gensec_security, session_key);
}
gensec_security = NULL;
}
+/**
+ * Set the requirement for a certain feature on the connection
+ *
+ */
+
+void gensec_want_feature(struct gensec_security *gensec_security,
+ uint32 feature)
+{
+ gensec_security->want_features |= feature;
+}
+
/**
* Set a username on a GENSEC context - ensures it is talloc()ed
*
const struct sock_addr *addr;
const char *service;
};
-
+
+#define GENSEC_WANT_SESSION_KEY 0x1
+#define GENSEC_WANT_SIGN 0x2
+#define GENSEC_WANT_SEAL 0x4
/* GENSEC mode */
enum gensec_role
struct gensec_target target;
enum gensec_role gensec_role;
BOOL subcontext;
+ uint32 want_features;
};
/* this structure is used by backends to determine the size of some critical types */
return nt_status;
}
+ if (gensec_security->want_features & GENSEC_WANT_SIGN) {
+ gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
+ }
+ if (gensec_security->want_features & GENSEC_WANT_SEAL) {
+ gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
+ }
+
ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state;
if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&gensec_ntlmssp_state->auth_context))) {
return nt_status;
return status;
}
+ if (gensec_security->want_features & GENSEC_WANT_SESSION_KEY) {
+ /*
+ * We need to set this to allow a later SetPassword
+ * via the SAMR pipe to succeed. Strange.... We could
+ * also add NTLMSSP_NEGOTIATE_SEAL here. JRA.
+ *
+ * Without this, Windows will not create the master key
+ * that it thinks is only used for NTLMSSP signing and
+ * sealing. (It is actually pulled out and used directly)
+ */
+ gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
+ }
+ if (gensec_security->want_features & GENSEC_WANT_SIGN) {
+ gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
+ }
+ if (gensec_security->want_features & GENSEC_WANT_SEAL) {
+ gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
+ }
+
status = ntlmssp_set_domain(gensec_ntlmssp_state->ntlmssp_state,
gensec_security->user.domain);
if (!NT_STATUS_IS_OK(status)) {
ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
}
+ if (!(neg_flags & NTLMSSP_NEGOTIATE_SIGN)) {
+ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SIGN;
+ }
+
+ if (!(neg_flags & NTLMSSP_NEGOTIATE_SEAL)) {
+ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SEAL;
+ }
+
if (!(neg_flags & NTLMSSP_NEGOTIATE_NTLM2)) {
ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
}
NTLMSSP_NEGOTIATE_128 |
NTLMSSP_NEGOTIATE_NTLM |
/* NTLMSSP_NEGOTIATE_NTLM2 | */
- NTLMSSP_NEGOTIATE_KEY_EXCH |
- NTLMSSP_NEGOTIATE_SIGN |
- NTLMSSP_NEGOTIATE_SEAL;
+ NTLMSSP_NEGOTIATE_KEY_EXCH;
return NT_STATUS_OK;
}
NTLMSSP_NEGOTIATE_NTLM |
/* NTLMSSP_NEGOTIATE_NTLM2 |*/
NTLMSSP_NEGOTIATE_KEY_EXCH |
- /*
- * We need to set this to allow a later SetPassword
- * via the SAMR pipe to succeed. Strange.... We could
- * also add NTLMSSP_NEGOTIATE_SEAL here. JRA.
- *
- * Without this, Windows will not create the master key
- * that it thinks is only used for NTLMSSP signing and
- * sealing. (It is actually pulled out and used directly)
- */
- NTLMSSP_NEGOTIATE_SIGN |
NTLMSSP_REQUEST_TARGET;
return NT_STATUS_OK;
return NT_STATUS_NO_USER_SESSION_KEY;
}
+ if (!ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) {
+ DEBUG(3, ("NTLMSSP Signing not negotiated - cannot sign packet!\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
nt_status = ntlmssp_make_packet_signature(ntlmssp_state, sig_mem_ctx,
data, length, NTLMSSP_SEND, sig);
return NT_STATUS_NO_USER_SESSION_KEY;
}
+ if (!ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
+ DEBUG(3, ("NTLMSSP Sealing not negotiated - cannot seal packet!\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
DEBUG(10,("ntlmssp_seal_data: seal\n"));
dump_data_pw("ntlmssp clear data\n", data, length);
if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
goto done;
}
+ gensec_want_feature(session->gensec, GENSEC_WANT_SESSION_KEY);
+
status = gensec_set_domain(session->gensec, parms->generic.in.domain);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to start set GENSEC client domain to %s: %s\n",
}
return p->transport.peer_name(p);
}
+
+/*
+ a useful function to get the auth_level
+*/
+
+uint32 dcerpc_auth_level(struct dcerpc_pipe *p)
+{
+ uint8_t auth_level;
+
+ if (p->flags & DCERPC_SEAL) {
+ auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
+ } else if (p->flags & DCERPC_SIGN) {
+ auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
+ } else {
+ auth_level = DCERPC_AUTH_LEVEL_NONE;
+ }
+ return auth_level;
+}
return status;
}
-NTSTATUS dcerpc_bind_auth3(struct dcerpc_pipe *p, uint8_t auth_type,
+NTSTATUS dcerpc_bind_auth3(struct dcerpc_pipe *p, uint8_t auth_type, uint8_t auth_level,
const char *uuid, uint_t version)
{
NTSTATUS status;
return status;
}
- status = gensec_start_mech_by_authtype(p->security_state.generic_state, auth_type);
+ status = gensec_start_mech_by_authtype(p->security_state.generic_state, auth_type, auth_level);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
p->security_state.auth_info->auth_type = auth_type;
+ p->security_state.auth_info->auth_level = auth_level;
p->security_state.auth_info->auth_pad_length = 0;
p->security_state.auth_info->auth_reserved = 0;
p->security_state.auth_info->auth_context_id = random();
p->security_state.auth_info->credentials = null_data_blob;
- if (p->flags & DCERPC_SEAL) {
- p->security_state.auth_info->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
- } else if (p->flags & DCERPC_SIGN) {
- p->security_state.auth_info->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
- } else {
- p->security_state.auth_info->auth_level = DCERPC_AUTH_LEVEL_NONE;
- }
-
status = gensec_update(p->security_state.generic_state, mem_ctx,
null_data_blob,
&credentials);
return status;
}
-NTSTATUS dcerpc_bind_alter(struct dcerpc_pipe *p, uint8_t auth_type,
+NTSTATUS dcerpc_bind_alter(struct dcerpc_pipe *p, uint8_t auth_type, uint8_t auth_level,
const char *uuid, uint_t version)
{
NTSTATUS status;
return status;
}
- status = gensec_start_mech_by_authtype(p->security_state.generic_state, auth_type);
+ status = gensec_start_mech_by_authtype(p->security_state.generic_state,
+ auth_type, auth_level);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
p->security_state.auth_info->auth_type = auth_type;
+ p->security_state.auth_info->auth_level = auth_level;
p->security_state.auth_info->auth_pad_length = 0;
p->security_state.auth_info->auth_reserved = 0;
p->security_state.auth_info->auth_context_id = random();
p->security_state.auth_info->credentials = null_data_blob;
- if (p->flags & DCERPC_SEAL) {
- p->security_state.auth_info->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
- } else if (p->flags & DCERPC_SIGN) {
- p->security_state.auth_info->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
- } else {
- p->security_state.auth_info->auth_level = DCERPC_AUTH_LEVEL_NONE;
- }
-
status = gensec_update(p->security_state.generic_state, mem_ctx,
null_data_blob,
&credentials);
return status;
}
- status = gensec_start_mech_by_authtype(p->security_state.generic_state, DCERPC_AUTH_TYPE_NTLMSSP);
+ status = gensec_start_mech_by_authtype(p->security_state.generic_state, DCERPC_AUTH_TYPE_NTLMSSP, dcerpc_auth_level(p));
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to start set GENSEC client NTLMSSP mechanism: %s\n",
nt_errstr(status)));
}
status = dcerpc_bind_auth3(p, DCERPC_AUTH_TYPE_NTLMSSP,
- uuid, version);
+ dcerpc_auth_level(p),
+ uuid, version);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(2, ("Failed to bind to pipe with NTLMSSP: %s\n", nt_errstr(status)));
return status;
}
- status = gensec_start_mech_by_authtype(p->security_state.generic_state, DCERPC_AUTH_TYPE_SCHANNEL);
+ status = gensec_start_mech_by_authtype(p->security_state.generic_state, DCERPC_AUTH_TYPE_SCHANNEL, dcerpc_auth_level(p));
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to start SCHANNEL GENSEC backend: %s\n", nt_errstr(status)));
return status;
}
- status = dcerpc_bind_auth3(p, DCERPC_AUTH_TYPE_SCHANNEL,
+ status = dcerpc_bind_auth3(p, DCERPC_AUTH_TYPE_SCHANNEL, dcerpc_auth_level(p),
uuid, version);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- status = gensec_start_mech_by_authtype(p->security_state.generic_state, DCERPC_AUTH_TYPE_SPNEGO);
+ status = gensec_start_mech_by_authtype(p->security_state.generic_state, DCERPC_AUTH_TYPE_SPNEGO, dcerpc_auth_level(p));
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to start set GENSEC client SPNEGO mechanism: %s\n",
nt_errstr(status)));
return status;
}
- status = dcerpc_bind_alter(p, DCERPC_AUTH_TYPE_SPNEGO,
+ status = dcerpc_bind_alter(p, DCERPC_AUTH_TYPE_SPNEGO, dcerpc_auth_level(p),
uuid, version);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- status = gensec_start_mech_by_authtype(auth->gensec_security, auth->auth_info->auth_type);
+ status = gensec_start_mech_by_authtype(auth->gensec_security, auth->auth_info->auth_type,
+ auth->auth_info->auth_level);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to start GENSEC mech-specific server code (%d): %s\n",
return status;
}
+ gensec_want_feature(gensec_ctx, GENSEC_WANT_SESSION_KEY);
+
status = gensec_start_mech_by_oid(gensec_ctx, OID_SPNEGO);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to start GENSEC SPNEGO server code: %s\n", nt_errstr(status)));