summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2007-08-02 17:41:47 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:29:09 -0500
commitcc8d70036477f30c6c9c8a6e37d1e2680107c0a6 (patch)
tree6b38b08a5b2aa33e187883b5844f45b75a7fe12a
parent6c6fed5e656d64df9c9c12d7909f2c2289208bf7 (diff)
downloadsamba-cc8d70036477f30c6c9c8a6e37d1e2680107c0a6.tar.gz
samba-cc8d70036477f30c6c9c8a6e37d1e2680107c0a6.tar.bz2
samba-cc8d70036477f30c6c9c8a6e37d1e2680107c0a6.zip
r24131: - make it more clear what the different min and max fields mean
- with the "GSSAPI" sasl mech the plain, sign or seal negotiation is independed from the req_flags and ret_flags - verify the server supports the wrapping type we want - better handling on negotiated buffer sizes metze (This used to be commit d0ec7323870ca16b28d458ff5f7dacce278b7d54)
-rw-r--r--source3/include/ads.h9
-rw-r--r--source3/libads/sasl.c77
-rw-r--r--source3/libads/sasl_wrapping.c8
3 files changed, 53 insertions, 41 deletions
diff --git a/source3/include/ads.h b/source3/include/ads.h
index 2dc7e277d5..0216f536c9 100644
--- a/source3/include/ads.h
+++ b/source3/include/ads.h
@@ -103,16 +103,17 @@ typedef struct ads_struct {
uint32 ofs;
uint32 needed;
uint32 left;
- uint32 max;
- uint32 min;
+#define ADS_SASL_WRAPPING_IN_MAX_WRAPPED 0x0FFFFFFF
+ uint32 max_wrapped;
+ uint32 min_wrapped;
uint32 size;
uint8 *buf;
} in;
struct {
uint32 ofs;
uint32 left;
- uint32 max;
- uint32 min;
+#define ADS_SASL_WRAPPING_OUT_MAX_WRAPPED 0x00A00000
+ uint32 max_unwrapped;
uint32 sig_size;
uint32 size;
uint8 *buf;
diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c
index c727c8b50a..bcd8833f30 100644
--- a/source3/libads/sasl.c
+++ b/source3/libads/sasl.c
@@ -247,11 +247,10 @@ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
then the state will be kept by the signing engine */
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.max_unwrapped = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED - NTLMSSP_SIG_SIZE;
ads->ldap.out.sig_size = NTLMSSP_SIG_SIZE;
- ads->ldap.in.min = 4;
- ads->ldap.in.max = 0x0FFFFFFF;
+ ads->ldap.in.min_wrapped = ads->ldap.out.sig_size;
+ ads->ldap.in.max_wrapped = ADS_SASL_WRAPPING_IN_MAX_WRAPPED;
status = ads_setup_sasl_wrapping(ads, &ads_sasl_ntlmssp_ops, ntlmssp_state);
if (!ADS_ERR_OK(status)) {
DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
@@ -574,21 +573,20 @@ static ADS_STATUS ads_sasl_spnego_gsskrb5_bind(ADS_STRUCT *ads, const gss_name_t
}
if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
- uint32 max_msg_size = 0x0A000000;
+ uint32 max_msg_size = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED;
gss_rc = gss_wrap_size_limit(&minor_status, context_handle,
(ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_SEAL),
GSS_C_QOP_DEFAULT,
- max_msg_size, &ads->ldap.out.max);
+ max_msg_size, &ads->ldap.out.max_unwrapped);
if (gss_rc) {
status = ADS_ERROR_GSS(gss_rc, minor_status);
goto failed;
}
- ads->ldap.out.min = 4;
- ads->ldap.out.sig_size = max_msg_size - ads->ldap.out.max;
- ads->ldap.in.min = 4;
- ads->ldap.in.max = max_msg_size;
+ ads->ldap.out.sig_size = max_msg_size - ads->ldap.out.max_unwrapped;
+ ads->ldap.in.min_wrapped = 0x2C; /* taken from a capture with LDAP unbind */
+ ads->ldap.in.max_wrapped = max_msg_size;
status = ads_setup_sasl_wrapping(ads, &ads_sasl_gssapi_ops, context_handle);
if (!ADS_ERR_OK(status)) {
DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
@@ -930,23 +928,19 @@ static ADS_STATUS ads_sasl_gssapi_do_bind(ADS_STRUCT *ads, const gss_name_t serv
int i=0;
int gss_rc, rc;
uint8 *p;
- uint32 max_msg_size = 0;
+ uint32 max_msg_size = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED;
+ uint8 wrap_type = ADS_SASLWRAP_TYPE_PLAIN;
ADS_STATUS status;
input_token.value = NULL;
input_token.length = 0;
- req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG;
- switch (ads->ldap.wrap_type) {
- case ADS_SASLWRAP_TYPE_SEAL:
- req_flags |= GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG;
- break;
- case ADS_SASLWRAP_TYPE_SIGN:
- req_flags |= GSS_C_INTEG_FLAG;
- break;
- case ADS_SASLWRAP_TYPE_PLAIN:
- break;
- }
+ /*
+ * Note: here we always ask the gssapi for sign and seal
+ * as this is negotiated later after the mutal
+ * authentication
+ */
+ req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG;
for (i=0; i < MAX_GSS_PASSES; i++) {
gss_rc = gss_init_sec_context(&minor_status,
@@ -1014,20 +1008,37 @@ static ADS_STATUS ads_sasl_gssapi_do_bind(ADS_STRUCT *ads, const gss_name_t serv
#endif
if (p) {
- max_msg_size = (p[1]<<16) | (p[2]<<8) | p[3];
+ wrap_type = CVAL(p,0);
+ SCVAL(p,0,0);
+ max_msg_size = RIVAL(p,0);
}
gss_release_buffer(&minor_status, &output_token);
+ if (!(wrap_type & ads->ldap.wrap_type)) {
+ /*
+ * the server doesn't supports the wrap
+ * type we want :-(
+ */
+ DEBUG(0,("The ldap sasl wrap type doesn't match wanted[%d] server[%d]\n",
+ ads->ldap.wrap_type, wrap_type));
+ DEBUGADD(0,("You may want to set the 'client ldap sasl wrapping' option\n"));
+ status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
+ goto failed;
+ }
+
+ /* 0x58 is the minimum windows accepts */
+ if (max_msg_size < 0x58) {
+ max_msg_size = 0x58;
+ }
+
output_token.length = 4;
output_token.value = SMB_MALLOC(output_token.length);
p = (uint8 *)output_token.value;
- *p++ = ads->ldap.wrap_type;
- /* choose the same size as the server gave us */
- *p++ = max_msg_size>>16;
- *p++ = max_msg_size>>8;
- *p++ = max_msg_size;
+ RSIVAL(p,0,max_msg_size);
+ SCVAL(p,0,ads->ldap.wrap_type);
+
/*
* we used to add sprintf("dn:%s", ads->config.bind_path) here.
* but using ads->config.bind_path is the wrong! It should be
@@ -1062,16 +1073,15 @@ static ADS_STATUS ads_sasl_gssapi_do_bind(ADS_STRUCT *ads, const gss_name_t serv
gss_rc = gss_wrap_size_limit(&minor_status, context_handle,
(ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_SEAL),
GSS_C_QOP_DEFAULT,
- max_msg_size, &ads->ldap.out.max);
+ max_msg_size, &ads->ldap.out.max_unwrapped);
if (gss_rc) {
status = ADS_ERROR_GSS(gss_rc, minor_status);
goto failed;
}
- ads->ldap.out.min = 4;
- ads->ldap.out.sig_size = max_msg_size - ads->ldap.out.max;
- ads->ldap.in.min = 4;
- ads->ldap.in.max = max_msg_size;
+ ads->ldap.out.sig_size = max_msg_size - ads->ldap.out.max_unwrapped;
+ ads->ldap.in.min_wrapped = 0x2C; /* taken from a capture with LDAP unbind */
+ ads->ldap.in.max_wrapped = max_msg_size;
status = ads_setup_sasl_wrapping(ads, &ads_sasl_gssapi_ops, context_handle);
if (!ADS_ERR_OK(status)) {
DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
@@ -1081,6 +1091,7 @@ static ADS_STATUS ads_sasl_gssapi_do_bind(ADS_STRUCT *ads, const gss_name_t serv
/* make sure we don't free context_handle */
context_handle = GSS_C_NO_CONTEXT;
}
+
failed:
if (context_handle != GSS_C_NO_CONTEXT)
diff --git a/source3/libads/sasl_wrapping.c b/source3/libads/sasl_wrapping.c
index c620aae7ac..2bfa079235 100644
--- a/source3/libads/sasl_wrapping.c
+++ b/source3/libads/sasl_wrapping.c
@@ -42,7 +42,7 @@ static ber_slen_t ads_saslwrap_prepare_inbuf(ADS_STRUCT *ads)
ads->ldap.in.ofs = 0;
ads->ldap.in.needed = 0;
ads->ldap.in.left = 0;
- ads->ldap.in.size = 4 + ads->ldap.in.min;
+ ads->ldap.in.size = 4 + ads->ldap.in.min_wrapped;
ads->ldap.in.buf = talloc_array(ads->ldap.mem_ctx,
uint8, ads->ldap.in.size);
if (!ads->ldap.in.buf) {
@@ -99,11 +99,11 @@ static ber_slen_t ads_saslwrap_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t
if (ads->ldap.in.ofs < 4) goto eagain;
ads->ldap.in.needed = RIVAL(ads->ldap.in.buf, 0);
- if (ads->ldap.in.needed > ads->ldap.in.max) {
+ if (ads->ldap.in.needed > ads->ldap.in.max_wrapped) {
errno = EINVAL;
return -1;
}
- if (ads->ldap.in.needed < ads->ldap.in.min) {
+ if (ads->ldap.in.needed < ads->ldap.in.min_wrapped) {
errno = EINVAL;
return -1;
}
@@ -208,7 +208,7 @@ static ber_slen_t ads_saslwrap_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_
return -1;
}
- rlen = MIN(len, ads->ldap.out.max);
+ rlen = MIN(len, ads->ldap.out.max_unwrapped);
ret = ads_saslwrap_prepare_outbuf(ads, rlen);
if (ret < 0) return ret;