From a69d2a85d19bf76aec74ddb17cdde82fc4eef7f6 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Wed, 2 Oct 2013 17:26:11 -0400
Subject: [PATCH] Ticket 47531 - Mozldap - need to rewrite sasl_io_recv

Bug Description:  Mozldap does not have some "ber" functions (ber_skip_element) that
                  are in openldap.  This causes the build to fail.

Fix Description:  To parse the ber we need a local copy of the ber structure(which I
                  called MozElement), so that the ber_ptr can be manipulated.  I had to
                  use a new header file(mozldap.h), because the mozldap BerElement typedef's
                  caused build failures.

                  There is also a mozldap version check, and if the verison is newer than
                  what was used for mozldap.h, the build will fail.  The current internal
                  version is 604, even though the rpm says 605.

https://fedorahosted.org/389/ticket/47531

Reviewed by: ?
---
 ldap/servers/slapd/mozldap.h |   45 ++++++++++++++++++++++++++++++++++++++++++
 ldap/servers/slapd/sasl_io.c |   39 +++++++++++++++++++++++++++++++++--
 2 files changed, 81 insertions(+), 3 deletions(-)
 create mode 100644 ldap/servers/slapd/mozldap.h

diff --git a/ldap/servers/slapd/mozldap.h b/ldap/servers/slapd/mozldap.h
new file mode 100644
index 0000000..cd3cb2e
--- /dev/null
+++ b/ldap/servers/slapd/mozldap.h
@@ -0,0 +1,45 @@
+/*
+ * mozldap does not have all the openldap "ber" functions, like ber_skip_element.
+ * So we need to directly parse the ber element, and see inside the ber struct.
+ * From lber-int.h
+ */
+typedef struct seqorset {
+   ber_len_t    sos_clen;
+   ber_tag_t    sos_tag;
+   char         *sos_first;
+   char         *sos_ptr;
+   struct seqorset      *sos_next;
+} Seqorset;
+
+#define SOS_STACK_SIZE 8 /* depth of the pre-allocated sos structure stack */
+#define MAX_TAG_SIZE (1 + sizeof(ber_int_t)) /* One byte for the length of the tag */
+#define MAX_LEN_SIZE (1 + sizeof(ber_int_t)) /* One byte for the length of the length */
+#define MAX_VALUE_PREFIX_SIZE (2 + sizeof(ber_int_t)) /* 1 byte for the tag and 1 for the len (msgid) */
+#define BER_ARRAY_QUANTITY 7 /* 0:Tag   1:Length   2:Value-prefix   3:Value   4:Value-suffix  */
+
+struct berelement {
+    ldap_x_iovec  ber_struct[BER_ARRAY_QUANTITY];   /* See above */
+    char          ber_tag_contents[MAX_TAG_SIZE];
+    char          ber_len_contents[MAX_LEN_SIZE];
+    char          ber_pre_contents[MAX_VALUE_PREFIX_SIZE];
+    char          ber_suf_contents[MAX_LEN_SIZE+1];
+    char          *ber_buf; /* update the value value when writing in case realloc is called */
+    char          *ber_ptr;
+    char          *ber_end;
+    struct seqorset       *ber_sos;
+    ber_len_t ber_tag_len_read;
+    ber_tag_t     ber_tag; /* Remove me someday */
+    ber_len_t     ber_len; /* Remove me someday */
+    int           ber_usertag;
+    char          ber_options;
+    char          *ber_rwptr;
+    BERTranslateProc ber_encode_translate_proc;
+    BERTranslateProc ber_decode_translate_proc;
+    int           ber_flags;
+#define LBER_FLAG_NO_FREE_BUFFER        1       /* don't free ber_buf */
+    unsigned  int ber_buf_reallocs;              /* realloc counter */
+    int           ber_sos_stack_posn;
+    Seqorset      ber_sos_stack[SOS_STACK_SIZE];
+};
+typedef struct berelement MozElement;
+
diff --git a/ldap/servers/slapd/sasl_io.c b/ldap/servers/slapd/sasl_io.c
index b39f22d..3fe9057 100644
--- a/ldap/servers/slapd/sasl_io.c
+++ b/ldap/servers/slapd/sasl_io.c
@@ -45,6 +45,14 @@
 #include "fe.h"
 #include <sasl.h>
 #include <arpa/inet.h>
+#ifndef USE_OPENLDAP
+#include "mozldap.h"
+#if LDAP_VENDOR_VERSION > 604
+/* garbage to cause build to fail */
+MOZLDAP is newer than expected, if the ber structure has not changed
+(see ldap/server/slapd/mozldap.h), please bump the version number(604 -> new version)
+#endif
+#endif
 
 /*
  * I/O Shim Layer for SASL Encryption
@@ -261,11 +269,16 @@ sasl_io_start_packet(PRFileDesc *fd, PRIntn flags, PRIntervalTime timeout, PRInt
      * Check if an LDAP operation was sent unencrypted
      */
     if(!sp->send_encrypted && *sp->encrypted_buffer == LDAP_TAG_MESSAGE){
-        struct berval bv, tmp_bv;
+        struct berval bv;
+#ifdef USE_OPENLDAP
         BerElement *ber = NULL;
+        struct berval tmp_bv;
+#else
+        MozElement *ber = NULL;
+#endif
         ber_len_t maxbersize = config_get_maxbersize();
         ber_len_t ber_len = 0;
-        ber_tag_t tag;
+        ber_tag_t tag = 0;
 
         slapi_log_error( SLAPI_LOG_CONNS, "sasl_io_start_packet", "conn=%" NSPRIu64 " fd=%d "
                 "Sent an LDAP message that was not encrypted.\n", (long long unsigned int)c->c_connid,
@@ -340,7 +353,12 @@ sasl_io_start_packet(PRFileDesc *fd, PRIntn flags, PRIntervalTime timeout, PRInt
          */
         bv.bv_val = sp->encrypted_buffer;
         bv.bv_len = sp->encrypted_buffer_offset;
+
+#ifdef USE_OPENLDAP
         if ( (ber = ber_init(&bv)) == NULL){
+#else
+        if ( (ber = (MozElement *)ber_init(&bv)) == NULL){
+#endif
             goto done;
         }
 
@@ -348,16 +366,27 @@ sasl_io_start_packet(PRFileDesc *fd, PRIntn flags, PRIntervalTime timeout, PRInt
          * Start parsing the berElement.  First skip this tag, and move on to the
          * tag msgid
          */
+#ifdef USE_OPENLDAP
         ber_skip_tag(ber, &ber_len);
         if( ber_peek_tag( ber, &ber_len ) == LDAP_TAG_MSGID) {
+#else
+        ber_skip_tag((BerElement*)ber, &ber_len);
+        if( ber_peek_tag( (BerElement*)ber, &ber_len ) == LDAP_TAG_MSGID) {
+#endif
             /*
              * Skip the entire msgid element, so we can get to the LDAP op tag
              */
+#ifdef USE_OPENLDAP
             if(ber_skip_element(ber, &tmp_bv) == LDAP_TAG_MSGID) {
                 /*
                  * We only allow unbind operations to be processed for unencrypted operations
                  */
                 if (( tag = ber_peek_tag( ber, &ber_len )) == LDAP_REQ_UNBIND ) {
+#else
+            {
+                tag = *ber->ber_ptr++;
+                if (*ber->ber_ptr == LDAP_REQ_UNBIND){
+#endif
                     slapi_log_error( SLAPI_LOG_CONNS, "sasl_io_start_packet", "conn=%" NSPRIu64 " fd=%d "
                             "Received unencrypted UNBIND operation.\n", (long long unsigned int)c->c_connid,
                             c->c_sd);
@@ -368,7 +397,11 @@ sasl_io_start_packet(PRFileDesc *fd, PRIntn flags, PRIntervalTime timeout, PRInt
                 }
                 slapi_log_error( SLAPI_LOG_CONNS, "sasl_io_start_packet", "conn=%" NSPRIu64 " fd=%d "
                         "Error: received an LDAP message (tag 0x%lx) that was not encrypted.\n",
-                        (long long unsigned int)c->c_connid, c->c_sd, tag);
+#ifdef USE_OPENLDAP
+                        (long long unsigned int)c->c_connid, c->c_sd, (long unsigned int)tag);
+#else
+                        (long long unsigned int)c->c_connid, c->c_sd, (long unsigned int)*ber->ber_ptr);
+#endif
             }
         }
 
-- 
1.7.1

