summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/ads.h2
-rw-r--r--source3/libads/sasl.c123
2 files changed, 123 insertions, 2 deletions
diff --git a/source3/include/ads.h b/source3/include/ads.h
index 1c02366ed4..56c7023337 100644
--- a/source3/include/ads.h
+++ b/source3/include/ads.h
@@ -36,7 +36,7 @@ struct ads_saslwrap_ops {
const char *name;
ADS_STATUS (*wrap)(struct ads_struct *, uint8 *buf, uint32 len);
ADS_STATUS (*unwrap)(struct ads_struct *);
- ADS_STATUS (*disconnect)(struct ads_struct *);
+ void (*disconnect)(struct ads_struct *);
};
enum ads_saslwrap_type {
diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c
index 94600d7234..08a6765e27 100644
--- a/source3/libads/sasl.c
+++ b/source3/libads/sasl.c
@@ -21,6 +21,95 @@
#ifdef HAVE_LDAP
+static ADS_STATUS ads_sasl_ntlmssp_wrap(ADS_STRUCT *ads, uint8 *buf, uint32 len)
+{
+ struct ntlmssp_state *ntlmssp_state = ads->ldap.wrap_private_data;
+ ADS_STATUS status;
+ NTSTATUS nt_status;
+ DATA_BLOB sig;
+ uint8 *dptr = ads->ldap.out.buf + (4 + NTLMSSP_SIG_SIZE);
+
+ /* copy the data to the right location */
+ memcpy(dptr, buf, len);
+
+ /* create the signature and may encrypt the data */
+ if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
+ nt_status = ntlmssp_seal_packet(ntlmssp_state,
+ dptr, len,
+ dptr, len,
+ &sig);
+ } else {
+ nt_status = ntlmssp_sign_packet(ntlmssp_state,
+ dptr, len,
+ dptr, len,
+ &sig);
+ }
+ status = ADS_ERROR_NT(nt_status);
+ if (!ADS_ERR_OK(status)) return status;
+
+ /* copy the signature to the right location */
+ memcpy(ads->ldap.out.buf + 4,
+ sig.data, NTLMSSP_SIG_SIZE);
+
+ data_blob_free(&sig);
+
+ /* set how many bytes must be written to the underlying socket */
+ ads->ldap.out.left = 4 + NTLMSSP_SIG_SIZE + len;
+
+ return ADS_SUCCESS;
+}
+
+static ADS_STATUS ads_sasl_ntlmssp_unwrap(ADS_STRUCT *ads)
+{
+ struct ntlmssp_state *ntlmssp_state = ads->ldap.wrap_private_data;
+ ADS_STATUS status;
+ NTSTATUS nt_status;
+ DATA_BLOB sig;
+ uint8 *dptr = ads->ldap.in.buf + (4 + NTLMSSP_SIG_SIZE);
+ uint32 dlen = ads->ldap.in.ofs - (4 + NTLMSSP_SIG_SIZE);
+
+ /* wrap the signature into a DATA_BLOB */
+ sig = data_blob_const(ads->ldap.in.buf + 4, NTLMSSP_SIG_SIZE);
+
+ /* verify the signature and maybe decrypt the data */
+ if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
+ nt_status = ntlmssp_unseal_packet(ntlmssp_state,
+ dptr, dlen,
+ dptr, dlen,
+ &sig);
+ } else {
+ nt_status = ntlmssp_check_packet(ntlmssp_state,
+ dptr, dlen,
+ dptr, dlen,
+ &sig);
+ }
+ status = ADS_ERROR_NT(nt_status);
+ if (!ADS_ERR_OK(status)) return status;
+
+ /* set the amount of bytes for the upper layer and set the ofs to the data */
+ ads->ldap.in.left = dlen;
+ ads->ldap.in.ofs = 4 + NTLMSSP_SIG_SIZE;
+
+ return ADS_SUCCESS;
+}
+
+static void ads_sasl_ntlmssp_disconnect(ADS_STRUCT *ads)
+{
+ struct ntlmssp_state *ntlmssp_state = ads->ldap.wrap_private_data;
+
+ ntlmssp_end(&ntlmssp_state);
+
+ ads->ldap.wrap_ops = NULL;
+ ads->ldap.wrap_private_data = NULL;
+}
+
+static const struct ads_saslwrap_ops ads_sasl_ntlmssp_ops = {
+ .name = "ntlmssp",
+ .wrap = ads_sasl_ntlmssp_wrap,
+ .unwrap = ads_sasl_ntlmssp_unwrap,
+ .disconnect = ads_sasl_ntlmssp_disconnect
+};
+
/*
perform a LDAP/SASL/SPNEGO/NTLMSSP bind (just how many layers can
we fit on one socket??)
@@ -35,6 +124,7 @@ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
int rc;
NTSTATUS nt_status;
int turn = 1;
+ uint32 features = 0;
struct ntlmssp_state *ntlmssp_state;
@@ -53,6 +143,28 @@ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
return ADS_ERROR_NT(nt_status);
}
+ switch (ads->ldap.wrap_type) {
+ case ADS_SASLWRAP_TYPE_SEAL:
+ features = NTLMSSP_FEATURE_SIGN | NTLMSSP_FEATURE_SEAL;
+ break;
+ case ADS_SASLWRAP_TYPE_SIGN:
+ if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
+ features = NTLMSSP_FEATURE_SIGN;
+ } else {
+ /*
+ * windows servers are broken with sign only,
+ * so we need to use seal here too
+ */
+ features = NTLMSSP_FEATURE_SIGN | NTLMSSP_FEATURE_SEAL;
+ ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL;
+ }
+ break;
+ case ADS_SASLWRAP_TYPE_PLAIN:
+ break;
+ }
+
+ ntlmssp_want_feature(ntlmssp_state, features);
+
blob_in = data_blob_null;
do {
@@ -130,7 +242,16 @@ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
/* we have a reference conter on ntlmssp_state, if we are signing
then the state will be kept by the signing engine */
- ntlmssp_end(&ntlmssp_state);
+ if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
+ ads->ldap.out.min = 4;
+ ads->ldap.out.max = 0x0FFFFFFF - NTLMSSP_SIG_SIZE;
+ ads->ldap.out.sig_size = NTLMSSP_SIG_SIZE;
+ ads->ldap.in.min = 4;
+ ads->ldap.in.max = 0x0FFFFFFF;
+ ads_setup_sasl_wrapping(ads, &ads_sasl_ntlmssp_ops, ntlmssp_state);
+ } else {
+ ntlmssp_end(&ntlmssp_state);
+ }
return ADS_ERROR(rc);
}