r24131: - make it more clear what the different min and max fields mean
authorStefan Metzmacher <metze@samba.org>
Thu, 2 Aug 2007 17:41:47 +0000 (17:41 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:29:09 +0000 (12:29 -0500)
- 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)

source3/include/ads.h
source3/libads/sasl.c
source3/libads/sasl_wrapping.c

index 2dc7e277d5efb80aa8f909fb9a3a95ee6c6f219a..0216f536c98b8654cc48bcdfff07c9685acda9b1 100644 (file)
@@ -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;
index c727c8b50ac1c31892e6e91604594b54e2b08447..bcd8833f30c55d745fe4aeb5fdde201d107f1a45 100644 (file)
@@ -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)
index c620aae7ac37a5687b1371376de23cf86cda6b85..2bfa07923502dad5600d3ba4a776424d893e8c60 100644 (file)
@@ -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;