summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2011-07-26 15:11:47 +1000
committerAndrew Bartlett <abartlet@samba.org>2011-08-03 18:48:04 +1000
commitd3524f2eaeef06059fcdc7af5b742cd46064fd20 (patch)
tree6dca681b7d39f74d78e2ce51bf67e2c77aaff365
parent9f663270fd7d40dbaf258fe6818685d42249a827 (diff)
downloadsamba-d3524f2eaeef06059fcdc7af5b742cd46064fd20.tar.gz
samba-d3524f2eaeef06059fcdc7af5b742cd46064fd20.tar.bz2
samba-d3524f2eaeef06059fcdc7af5b742cd46064fd20.zip
s3-auth use auth_generic_start to get full GENSEC in Samba3 session setup
This tests if the auth_generic_start() hook is available on the auth context during the negprot, and if so it uses auth_generic_start() to hook to GENSEC to handle the full SPNEGO blob. Andrew Bartlett Signed-off-by: Andrew Tridgell <tridge@samba.org>
-rw-r--r--source3/smbd/globals.h3
-rw-r--r--source3/smbd/negprot.c28
-rw-r--r--source3/smbd/sesssetup.c54
-rw-r--r--source3/smbd/smb2_sesssetup.c25
4 files changed, 80 insertions, 30 deletions
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 9e8059be19..26125ce805 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -474,6 +474,9 @@ struct smbd_server_connection {
unsigned long file_gen_counter;
int first_file;
+ /* Try GENSEC hook */
+ bool use_gensec_hook;
+
/* number of open connections (tcons) */
int num_tcons_open;
diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c
index f1d2fc2545..a58744281c 100644
--- a/source3/smbd/negprot.c
+++ b/source3/smbd/negprot.c
@@ -24,8 +24,10 @@
#include "../libcli/auth/spnego.h"
#include "serverid.h"
#include "auth.h"
+#include "ntlmssp_wrap.h"
#include "messages.h"
#include "smbprofile.h"
+#include "auth/gensec/gensec.h"
extern fstring remote_proto;
@@ -187,6 +189,7 @@ DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbd_server_connection *sconn)
DATA_BLOB blob_out = data_blob_null;
nstring dos_name;
fstring unix_name;
+ NTSTATUS status;
#ifdef DEVELOPER
size_t slen;
#endif
@@ -195,8 +198,29 @@ DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbd_server_connection *sconn)
OID_NTLMSSP,
NULL};
const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
+ struct auth_ntlmssp_state *auth_ntlmssp_state;
+
+ sconn->use_gensec_hook = false;
+
+ /* See if we can get an SPNEGO blob out of the gensec hook (if auth_samba4 is loaded) */
+ status = auth_ntlmssp_prepare(sconn->remote_address,
+ &auth_ntlmssp_state);
+ if (NT_STATUS_IS_OK(status)) {
+ status = auth_generic_start(auth_ntlmssp_state, GENSEC_OID_SPNEGO);
+ if (NT_STATUS_IS_OK(status)) {
+ status = auth_ntlmssp_update(auth_ntlmssp_state, ctx,
+ data_blob_null, &blob);
+ /* If we get the list of OIDs, the 'OK' answer
+ * is NT_STATUS_MORE_PROCESSING_REQUIRED */
+ if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ sconn->use_gensec_hook = true;
+ }
+ }
+ TALLOC_FREE(auth_ntlmssp_state);
+ }
sconn->smb1.negprot.spnego = true;
+
/* strangely enough, NT does not sent the single OID NTLMSSP when
not a ADS member, it sends no OIDs at all
@@ -210,7 +234,9 @@ DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbd_server_connection *sconn)
*/
- if (lp_security() != SEC_ADS && !USE_KERBEROS_KEYTAB) {
+ if (sconn->use_gensec_hook) {
+ /* blob initialised above */
+ } else if (lp_security() != SEC_ADS && !USE_KERBEROS_KEYTAB) {
#if 0
/* Code for PocketPC client */
blob = data_blob(guid, 16);
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index 2f3bbd6171..020c62cad8 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -36,6 +36,7 @@
#include "messages.h"
#include "smbprofile.h"
#include "../libcli/security/security.h"
+#include "auth/gensec/gensec.h"
/* For split krb5 SPNEGO blobs. */
struct pending_auth_data {
@@ -1134,27 +1135,12 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
return;
}
- if (blob1.data[0] == ASN1_APPLICATION(0)) {
-
- /* its a negTokenTarg packet */
-
- reply_spnego_negotiate(req, vuid, blob1,
- &vuser->auth_ntlmssp_state);
- data_blob_free(&blob1);
- return;
- }
-
- if (blob1.data[0] == ASN1_CONTEXT(1)) {
-
- /* its a auth packet */
-
- reply_spnego_auth(req, vuid, blob1,
- &vuser->auth_ntlmssp_state);
- data_blob_free(&blob1);
- return;
- }
-
- if (blob1.length > 7 && strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
+ /* Handle either raw NTLMSSP or hand off the whole blob to
+ * GENSEC. The processing at this layer is essentially
+ * identical regardless. In particular, both rely only on the
+ * status code (not the contents of the packet) and do not
+ * wrap the result */
+ if (sconn->use_gensec_hook || (blob1.length > 7 && strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0)) {
DATA_BLOB chal;
if (!vuser->auth_ntlmssp_state) {
@@ -1170,7 +1156,11 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
auth_ntlmssp_want_feature(vuser->auth_ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
- status = auth_ntlmssp_start(vuser->auth_ntlmssp_state);
+ if (sconn->use_gensec_hook) {
+ status = auth_generic_start(vuser->auth_ntlmssp_state, GENSEC_OID_SPNEGO);
+ } else {
+ status = auth_ntlmssp_start(vuser->auth_ntlmssp_state);
+ }
if (!NT_STATUS_IS_OK(status)) {
/* Kill the intermediate vuid */
invalidate_vuid(sconn, vuid);
@@ -1193,6 +1183,26 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
return;
}
+ if (blob1.data[0] == ASN1_APPLICATION(0)) {
+
+ /* its a negTokenTarg packet */
+
+ reply_spnego_negotiate(req, vuid, blob1,
+ &vuser->auth_ntlmssp_state);
+ data_blob_free(&blob1);
+ return;
+ }
+
+ if (blob1.data[0] == ASN1_CONTEXT(1)) {
+
+ /* its a auth packet */
+
+ reply_spnego_auth(req, vuid, blob1,
+ &vuser->auth_ntlmssp_state);
+ data_blob_free(&blob1);
+ return;
+ }
+
/* what sort of packet is this? */
DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c
index a3283117b4..d1022cd2cf 100644
--- a/source3/smbd/smb2_sesssetup.c
+++ b/source3/smbd/smb2_sesssetup.c
@@ -25,6 +25,7 @@
#include "../libcli/smb/smb_common.h"
#include "../libcli/auth/spnego.h"
#include "../libcli/auth/ntlmssp.h"
+#include "../auth/gensec/gensec.h"
#include "ntlmssp_wrap.h"
#include "../librpc/gen_ndr/krb5pac.h"
#include "libads/kerberos_proto.h"
@@ -649,7 +650,11 @@ static NTSTATUS smbd_smb2_raw_ntlmssp_auth(struct smbd_smb2_session *session,
auth_ntlmssp_want_feature(session->auth_ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
- status = auth_ntlmssp_start(session->auth_ntlmssp_state);
+ if (session->sconn->use_gensec_hook) {
+ status = auth_generic_start(session->auth_ntlmssp_state, GENSEC_OID_SPNEGO);
+ } else {
+ status = auth_ntlmssp_start(session->auth_ntlmssp_state);
+ }
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(session);
return status;
@@ -742,24 +747,30 @@ static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *smb2req,
return NT_STATUS_REQUEST_NOT_ACCEPTED;
}
- if (in_security_buffer.data[0] == ASN1_APPLICATION(0)) {
- return smbd_smb2_spnego_negotiate(session,
+ /* Handle either raw NTLMSSP or hand off the whole blob to
+ * GENSEC. The processing at this layer is essentially
+ * identical regardless. In particular, both rely only on the
+ * status code (not the contents of the packet) and do not
+ * wrap the result */
+ if (session->sconn->use_gensec_hook
+ || (in_security_buffer.length > 7 && strncmp((char *)(in_security_buffer.data), "NTLMSSP", 7) == 0)) {
+ return smbd_smb2_raw_ntlmssp_auth(session,
smb2req,
in_security_mode,
in_security_buffer,
out_session_flags,
out_security_buffer,
out_session_id);
- } else if (in_security_buffer.data[0] == ASN1_CONTEXT(1)) {
- return smbd_smb2_spnego_auth(session,
+ } else if (in_security_buffer.data[0] == ASN1_APPLICATION(0)) {
+ return smbd_smb2_spnego_negotiate(session,
smb2req,
in_security_mode,
in_security_buffer,
out_session_flags,
out_security_buffer,
out_session_id);
- } else if (in_security_buffer.length > 7 && strncmp((char *)(in_security_buffer.data), "NTLMSSP", 7) == 0) {
- return smbd_smb2_raw_ntlmssp_auth(session,
+ } else if (in_security_buffer.data[0] == ASN1_CONTEXT(1)) {
+ return smbd_smb2_spnego_auth(session,
smb2req,
in_security_mode,
in_security_buffer,