summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/libcli/auth/gensec.c41
-rw-r--r--source4/libcli/auth/gensec.h6
-rw-r--r--source4/libcli/auth/gensec_ntlmssp.c26
-rw-r--r--source4/libcli/auth/ntlmssp.c22
-rw-r--r--source4/libcli/auth/ntlmssp_sign.c10
-rw-r--r--source4/libcli/raw/clisession.c2
-rw-r--r--source4/librpc/rpc/dcerpc.c18
-rw-r--r--source4/librpc/rpc/dcerpc_auth.c27
-rw-r--r--source4/librpc/rpc/dcerpc_ntlm.c5
-rw-r--r--source4/librpc/rpc/dcerpc_schannel.c4
-rw-r--r--source4/librpc/rpc/dcerpc_spnego.c4
-rw-r--r--source4/rpc_server/dcesrv_auth.c3
-rw-r--r--source4/smb_server/sesssetup.c2
13 files changed, 126 insertions, 44 deletions
diff --git a/source4/libcli/auth/gensec.c b/source4/libcli/auth/gensec.c
index 24c2c18877..8188701558 100644
--- a/source4/libcli/auth/gensec.c
+++ b/source4/libcli/auth/gensec.c
@@ -145,6 +145,7 @@ static NTSTATUS gensec_start(struct gensec_security **gensec_security)
(*gensec_security)->default_user.realm = talloc_strdup(mem_ctx, lp_realm());
(*gensec_security)->subcontext = False;
+ (*gensec_security)->want_features = 0;
return NT_STATUS_OK;
}
@@ -232,13 +233,20 @@ static NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
*/
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);
}
@@ -308,6 +316,10 @@ NTSTATUS gensec_check_packet(struct gensec_security *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);
}
@@ -319,6 +331,10 @@ NTSTATUS gensec_seal_packet(struct gensec_security *gensec_security,
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);
}
@@ -330,6 +346,10 @@ NTSTATUS gensec_sign_packet(struct gensec_security *gensec_security,
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);
}
@@ -339,6 +359,10 @@ NTSTATUS gensec_session_key(struct gensec_security *gensec_security,
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);
}
@@ -393,6 +417,17 @@ void gensec_end(struct gensec_security **gensec_security)
}
/**
+ * 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
*
*/
diff --git a/source4/libcli/auth/gensec.h b/source4/libcli/auth/gensec.h
index 880ee45265..73a5f6b463 100644
--- a/source4/libcli/auth/gensec.h
+++ b/source4/libcli/auth/gensec.h
@@ -36,7 +36,10 @@ struct gensec_target {
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
@@ -86,6 +89,7 @@ struct gensec_security {
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 */
diff --git a/source4/libcli/auth/gensec_ntlmssp.c b/source4/libcli/auth/gensec_ntlmssp.c
index 99247fb626..ae03bc88e6 100644
--- a/source4/libcli/auth/gensec_ntlmssp.c
+++ b/source4/libcli/auth/gensec_ntlmssp.c
@@ -179,6 +179,13 @@ static NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_secur
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;
@@ -211,6 +218,25 @@ static NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_secur
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)) {
diff --git a/source4/libcli/auth/ntlmssp.c b/source4/libcli/auth/ntlmssp.c
index 893e8520c2..4d2dd6b576 100644
--- a/source4/libcli/auth/ntlmssp.c
+++ b/source4/libcli/auth/ntlmssp.c
@@ -375,6 +375,14 @@ static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state,
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;
}
@@ -933,9 +941,7 @@ NTSTATUS ntlmssp_server_start(struct ntlmssp_state **ntlmssp_state)
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;
}
@@ -1289,16 +1295,6 @@ NTSTATUS ntlmssp_client_start(struct ntlmssp_state **ntlmssp_state)
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;
diff --git a/source4/libcli/auth/ntlmssp_sign.c b/source4/libcli/auth/ntlmssp_sign.c
index 80ce1cccc0..6c770b87b9 100644
--- a/source4/libcli/auth/ntlmssp_sign.c
+++ b/source4/libcli/auth/ntlmssp_sign.c
@@ -178,6 +178,11 @@ NTSTATUS ntlmssp_sign_packet(struct ntlmssp_state *ntlmssp_state,
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);
@@ -268,6 +273,11 @@ NTSTATUS ntlmssp_seal_packet(struct ntlmssp_state *ntlmssp_state,
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) {
diff --git a/source4/libcli/raw/clisession.c b/source4/libcli/raw/clisession.c
index af8a63328c..32be6b68ed 100644
--- a/source4/libcli/raw/clisession.c
+++ b/source4/libcli/raw/clisession.c
@@ -399,6 +399,8 @@ static NTSTATUS smb_raw_session_setup_generic_spnego(struct smbcli_session *sess
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",
diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c
index 31db6df738..b605b4d110 100644
--- a/source4/librpc/rpc/dcerpc.c
+++ b/source4/librpc/rpc/dcerpc.c
@@ -942,3 +942,21 @@ const char *dcerpc_server_name(struct dcerpc_pipe *p)
}
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;
+}
diff --git a/source4/librpc/rpc/dcerpc_auth.c b/source4/librpc/rpc/dcerpc_auth.c
index 43b2212d60..6ae6a80596 100644
--- a/source4/librpc/rpc/dcerpc_auth.c
+++ b/source4/librpc/rpc/dcerpc_auth.c
@@ -44,7 +44,7 @@ NTSTATUS dcerpc_bind_auth_none(struct dcerpc_pipe *p,
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;
@@ -63,7 +63,7 @@ NTSTATUS dcerpc_bind_auth3(struct dcerpc_pipe *p, uint8_t auth_type,
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;
@@ -77,19 +77,12 @@ NTSTATUS dcerpc_bind_auth3(struct dcerpc_pipe *p, uint8_t auth_type,
}
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);
@@ -126,7 +119,7 @@ done:
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;
@@ -145,7 +138,8 @@ NTSTATUS dcerpc_bind_alter(struct dcerpc_pipe *p, uint8_t auth_type,
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;
@@ -159,19 +153,12 @@ NTSTATUS dcerpc_bind_alter(struct dcerpc_pipe *p, uint8_t auth_type,
}
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);
diff --git a/source4/librpc/rpc/dcerpc_ntlm.c b/source4/librpc/rpc/dcerpc_ntlm.c
index 1f8dbc993e..eab80a333b 100644
--- a/source4/librpc/rpc/dcerpc_ntlm.c
+++ b/source4/librpc/rpc/dcerpc_ntlm.c
@@ -60,7 +60,7 @@ NTSTATUS dcerpc_bind_auth_ntlm(struct dcerpc_pipe *p,
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)));
@@ -68,7 +68,8 @@ NTSTATUS dcerpc_bind_auth_ntlm(struct dcerpc_pipe *p,
}
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)));
diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c
index b3d7048501..e7b1d08988 100644
--- a/source4/librpc/rpc/dcerpc_schannel.c
+++ b/source4/librpc/rpc/dcerpc_schannel.c
@@ -469,7 +469,7 @@ NTSTATUS dcerpc_bind_auth_schannel(struct dcerpc_pipe *p,
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)));
@@ -477,7 +477,7 @@ NTSTATUS dcerpc_bind_auth_schannel(struct dcerpc_pipe *p,
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)) {
diff --git a/source4/librpc/rpc/dcerpc_spnego.c b/source4/librpc/rpc/dcerpc_spnego.c
index 7ccc0cf422..f5e2be0da4 100644
--- a/source4/librpc/rpc/dcerpc_spnego.c
+++ b/source4/librpc/rpc/dcerpc_spnego.c
@@ -67,14 +67,14 @@ NTSTATUS dcerpc_bind_auth_spnego(struct dcerpc_pipe *p,
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)) {
diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c
index 84a5460d68..85c7916df7 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -53,7 +53,8 @@ NTSTATUS dcesrv_crypto_select_type(struct dcesrv_connection *dce_conn,
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",
diff --git a/source4/smb_server/sesssetup.c b/source4/smb_server/sesssetup.c
index a87db0ecc4..1c33686407 100644
--- a/source4/smb_server/sesssetup.c
+++ b/source4/smb_server/sesssetup.c
@@ -213,6 +213,8 @@ static NTSTATUS sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup
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)));