Przeglądaj źródła

[bugzilla 149539] Use Cyrus SASL instead of our custom one
CYRUS_SASL is undef'ed both in saslbind.c and sasl_io.c, which should be defined once Cyrus sasl library is pushed to /s/b/c.

Noriko Hosoi 21 lat temu
rodzic
commit
370d483a51
2 zmienionych plików z 437 dodań i 372 usunięć
  1. 241 221
      ldap/servers/slapd/sasl_io.c
  2. 196 151
      ldap/servers/slapd/saslbind.c

+ 241 - 221
ldap/servers/slapd/sasl_io.c

@@ -3,6 +3,8 @@
  * All rights reserved.
  * END COPYRIGHT BLOCK **/
 
+#undef CYRUS_SASL
+
 #include "slap.h"
 #include "slapi-plugin.h"
 #include "fe.h"
@@ -26,173 +28,191 @@
  */
  
 struct _sasl_io_private {
-	struct lextiof_socket_private *real_handle;
-	struct lber_x_ext_io_fns *real_iofns;
-	char *decrypted_buffer;
-	size_t decrypted_buffer_size;
-	size_t decrypted_buffer_count;
-	size_t decrypted_buffer_offset;
-	char *encrypted_buffer;
-	size_t encrypted_buffer_size;
-	size_t encrypted_buffer_count;
-	size_t encrypted_buffer_offset;
-	Connection *conn;	
+    struct lextiof_socket_private *real_handle;
+    struct lber_x_ext_io_fns *real_iofns;
+    char *decrypted_buffer;
+    size_t decrypted_buffer_size;
+    size_t decrypted_buffer_count;
+    size_t decrypted_buffer_offset;
+    char *encrypted_buffer;
+    size_t encrypted_buffer_size;
+    size_t encrypted_buffer_count;
+    size_t encrypted_buffer_offset;
+    Connection *conn;    
 };
 
 int
 sasl_io_enable(Connection *c)
 {
-	int ret = 0;
+    int ret = 0;
 
-	LDAPDebug( LDAP_DEBUG_CONNS,
-				"sasl_io_enable for connection %d\n", c->c_connid, 0, 0 );
-	/* Flag that we should enable SASL I/O for the next read operation on this connection */
-	c->c_enable_sasl_io = 1;
-	
-	return ret;
+    LDAPDebug( LDAP_DEBUG_CONNS,
+                "sasl_io_enable for connection %d\n", c->c_connid, 0, 0 );
+    /* Flag that we should enable SASL I/O for the next read operation on this connection */
+    c->c_enable_sasl_io = 1;
+    
+    return ret;
 }
 
 static void
 sasl_io_init_buffers(sasl_io_private *sp)
 {
-	sp->decrypted_buffer = slapi_ch_malloc(SASL_IO_BUFFER_SIZE);
-	sp->decrypted_buffer_size = SASL_IO_BUFFER_SIZE;
-	sp->encrypted_buffer = slapi_ch_malloc(SASL_IO_BUFFER_SIZE);
-	sp->encrypted_buffer_size = SASL_IO_BUFFER_SIZE;
+    sp->decrypted_buffer = slapi_ch_malloc(SASL_IO_BUFFER_SIZE);
+    sp->decrypted_buffer_size = SASL_IO_BUFFER_SIZE;
+    sp->encrypted_buffer = slapi_ch_malloc(SASL_IO_BUFFER_SIZE);
+    sp->encrypted_buffer_size = SASL_IO_BUFFER_SIZE;
 }
 
 /* This function should be called under the connection mutex */
 int
 sasl_io_setup(Connection *c)
 {
-	int ret = 0;
-	struct lber_x_ext_io_fns *func_pointers = NULL;
-	sasl_io_private *sp = (sasl_io_private*) slapi_ch_calloc(1, sizeof(sasl_io_private));
+    int ret = 0;
+    struct lber_x_ext_io_fns *func_pointers = NULL;
+    sasl_io_private *sp = (sasl_io_private*) slapi_ch_calloc(1, sizeof(sasl_io_private));
 
-	LDAPDebug( LDAP_DEBUG_CONNS,
-				"sasl_io_setup for connection %d\n", c->c_connid, 0, 0 );
+    LDAPDebug( LDAP_DEBUG_CONNS,
+                "sasl_io_setup for connection %d\n", c->c_connid, 0, 0 );
     /* Get the current functions and store them for later */
-	ber_sockbuf_get_option( c->c_sb, LBER_SOCKBUF_OPT_EXT_IO_FNS, &func_pointers);
+    ber_sockbuf_get_option( c->c_sb, LBER_SOCKBUF_OPT_EXT_IO_FNS, &func_pointers);
     sp->real_iofns = func_pointers;
     func_pointers = NULL;
 
-	/* Set up the private structure */
-	sp->real_handle = (struct lextiof_socket_private*) c->c_prfd;
-	sp->conn = c;
-	/* Store the private structure in the connection */
-	c->c_sasl_io_private = sp;
-	/* Insert the sasl i/o functions into the ber layer */
-	func_pointers = (struct lber_x_ext_io_fns *) slapi_ch_malloc(LBER_X_EXTIO_FNS_SIZE);
-	func_pointers->lbextiofn_size = LBER_X_EXTIO_FNS_SIZE;
-	func_pointers->lbextiofn_read = sasl_read_function;
-	func_pointers->lbextiofn_write = sasl_write_function;
-	func_pointers->lbextiofn_writev = NULL;
-	func_pointers->lbextiofn_socket_arg = (struct lextiof_socket_private *) sp;
-	ber_sockbuf_set_option( c->c_sb, LBER_SOCKBUF_OPT_EXT_IO_FNS, func_pointers);
-	/* Setup the data buffers for the fast read path */
-	sasl_io_init_buffers(sp);
-	/* Reset the enable flag, so we don't process it again */
-	c->c_enable_sasl_io = 0;
-	/* Mark the connection as having SASL I/O */
-	c->c_sasl_io = 1;
-	return ret;
+    /* Set up the private structure */
+    sp->real_handle = (struct lextiof_socket_private*) c->c_prfd;
+    sp->conn = c;
+    /* Store the private structure in the connection */
+    c->c_sasl_io_private = sp;
+    /* Insert the sasl i/o functions into the ber layer */
+    func_pointers = (struct lber_x_ext_io_fns *) slapi_ch_malloc(LBER_X_EXTIO_FNS_SIZE);
+    func_pointers->lbextiofn_size = LBER_X_EXTIO_FNS_SIZE;
+    func_pointers->lbextiofn_read = sasl_read_function;
+    func_pointers->lbextiofn_write = sasl_write_function;
+    func_pointers->lbextiofn_writev = NULL;
+    func_pointers->lbextiofn_socket_arg = (struct lextiof_socket_private *) sp;
+    ber_sockbuf_set_option( c->c_sb, LBER_SOCKBUF_OPT_EXT_IO_FNS, func_pointers);
+    /* Setup the data buffers for the fast read path */
+    sasl_io_init_buffers(sp);
+    /* Reset the enable flag, so we don't process it again */
+    c->c_enable_sasl_io = 0;
+    /* Mark the connection as having SASL I/O */
+    c->c_sasl_io = 1;
+    return ret;
 }
 
 int
 sasl_io_cleanup(Connection *c)
 {
-	int ret = 0;
-	sasl_io_private *sp = c->c_sasl_io_private;
-	if (sp) {
-		LDAPDebug( LDAP_DEBUG_CONNS,
-				"sasl_io_cleanup for connection %d\n", c->c_connid, 0, 0 );
-		/* Free the buffers */
-		slapi_ch_free((void**)&(sp->encrypted_buffer));
-		slapi_ch_free((void**)&(sp->decrypted_buffer));
-		/* Put the I/O functions back how they were */
-		ber_sockbuf_set_option( c->c_sb, LBER_SOCKBUF_OPT_EXT_IO_FNS, sp->real_iofns);
-		slapi_ch_free((void**)&sp);
-		c->c_sasl_io_private = NULL;
-		c->c_enable_sasl_io = 0;
-		c->c_sasl_io = 0;
-	}
-	return ret;
+    int ret = 0;
+    sasl_io_private *sp = c->c_sasl_io_private;
+    if (sp) {
+        LDAPDebug( LDAP_DEBUG_CONNS,
+                "sasl_io_cleanup for connection %d\n", c->c_connid, 0, 0 );
+        /* Free the buffers */
+        slapi_ch_free((void**)&(sp->encrypted_buffer));
+        slapi_ch_free((void**)&(sp->decrypted_buffer));
+        /* Put the I/O functions back how they were */
+        ber_sockbuf_set_option( c->c_sb, LBER_SOCKBUF_OPT_EXT_IO_FNS, sp->real_iofns);
+        slapi_ch_free((void**)&sp);
+        c->c_sasl_io_private = NULL;
+        c->c_enable_sasl_io = 0;
+        c->c_sasl_io = 0;
+    }
+    return ret;
 }
 
 
 static void sasl_io_resize_encrypted_buffer(sasl_io_private *sp, size_t requested_size)
 {
-	if (requested_size > sp->encrypted_buffer_size) {
-		sp->encrypted_buffer = slapi_ch_realloc(sp->encrypted_buffer, requested_size);
-		sp->encrypted_buffer_size = requested_size;
-	}
+    if (requested_size > sp->encrypted_buffer_size) {
+        sp->encrypted_buffer = slapi_ch_realloc(sp->encrypted_buffer, requested_size);
+        sp->encrypted_buffer_size = requested_size;
+    }
 }
 
 static void sasl_io_resize_decrypted_buffer(sasl_io_private *sp, size_t requested_size)
 {
-	if (requested_size > sp->decrypted_buffer_size) {
-		sp->decrypted_buffer = slapi_ch_realloc(sp->decrypted_buffer, requested_size);
-		sp->decrypted_buffer_size = requested_size;
-	}
+    if (requested_size > sp->decrypted_buffer_size) {
+        sp->decrypted_buffer = slapi_ch_realloc(sp->decrypted_buffer, requested_size);
+        sp->decrypted_buffer_size = requested_size;
+    }
 }
 
 static int
 sasl_io_reading_packet(sasl_io_private *sp)
 {
-	return (sp->encrypted_buffer_count > 0);
+    return (sp->encrypted_buffer_count > 0);
 }
 
 static int
 sasl_io_finished_packet(sasl_io_private *sp)
 {
-	return (sp->encrypted_buffer_count  && (sp->encrypted_buffer_offset == sp->encrypted_buffer_count) );
+    return (sp->encrypted_buffer_count  && (sp->encrypted_buffer_offset == sp->encrypted_buffer_count) );
 }
 
 static int
 sasl_io_start_packet(Connection *c, PRInt32 *err)
 {
-	int ret = 0;
-	unsigned char buffer[4];
-	size_t packet_length = 0;
-	
-	ret = PR_Recv(c->c_prfd,buffer,sizeof(buffer),0,PR_INTERVAL_NO_WAIT);
-	if (ret < 0) {
-		*err = PR_GetError();
-		return -1;
-	}
-	if (ret != 0 && ret < sizeof(buffer)) {
-		LDAPDebug( LDAP_DEBUG_ANY,
-			"failed to read sasl packet length on connection %d\n", c->c_connid, 0, 0 );
-		return -1;
-		
-	}
-	if (ret == sizeof(buffer)) {
-		/* Decode the length (could use ntohl here ??) */
-		packet_length = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
-		LDAPDebug( LDAP_DEBUG_CONNS,
-			"read sasl packet length %ld on connection %d\n", packet_length, c->c_connid, 0 );
-			sasl_io_resize_encrypted_buffer(c->c_sasl_io_private, packet_length);
-			c->c_sasl_io_private->encrypted_buffer_count = packet_length;
-			c->c_sasl_io_private->encrypted_buffer_offset = 0;
-	}
-	return 0;
+    int ret = 0;
+    unsigned char buffer[4];
+    size_t packet_length = 0;
+    
+    ret = PR_Recv(c->c_prfd,buffer,sizeof(buffer),0,PR_INTERVAL_NO_WAIT);
+    if (ret < 0) {
+        *err = PR_GetError();
+        return -1;
+    }
+    if (ret != 0 && ret < sizeof(buffer)) {
+        LDAPDebug( LDAP_DEBUG_ANY,
+            "failed to read sasl packet length on connection %d\n", c->c_connid, 0, 0 );
+        return -1;
+        
+    }
+#ifdef CYRUS_SASL
+    if (ret == sizeof(buffer)) {
+        /* Decode the length (could use ntohl here ??) */
+        packet_length = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
+        /* add length itself (for Cyrus SASL library) */
+        packet_length += 4;
+
+        LDAPDebug( LDAP_DEBUG_CONNS,
+            "read sasl packet length %ld on connection %d\n", packet_length, c->c_connid, 0 );
+        sasl_io_resize_encrypted_buffer(c->c_sasl_io_private, packet_length);
+        /* Cyrus SASL implementation expects to have the length at the first 
+           4 bytes */
+        memcpy(c->c_sasl_io_private->encrypted_buffer, buffer, 4);
+        c->c_sasl_io_private->encrypted_buffer_count = packet_length;
+        c->c_sasl_io_private->encrypted_buffer_offset = 4;
+    }
+#else
+    if (ret == sizeof(buffer)) {
+        /* Decode the length (could use ntohl here ??) */
+        packet_length = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
+        LDAPDebug( LDAP_DEBUG_CONNS,
+            "read sasl packet length %ld on connection %d\n", packet_length, c->c_connid, 0 );
+        sasl_io_resize_encrypted_buffer(c->c_sasl_io_private, packet_length);
+        c->c_sasl_io_private->encrypted_buffer_count = packet_length;
+        c->c_sasl_io_private->encrypted_buffer_offset = 0;
+    }
+#endif
+    return 0;
 }
 static int
 sasl_io_read_packet(Connection *c, PRInt32 *err)
 {
-	size_t ret = 0;
-	sasl_io_private *sp = c->c_sasl_io_private;
-	size_t bytes_remaining_to_read = sp->encrypted_buffer_count - sp->encrypted_buffer_offset;
+    size_t ret = 0;
+    sasl_io_private *sp = c->c_sasl_io_private;
+    size_t bytes_remaining_to_read = sp->encrypted_buffer_count - sp->encrypted_buffer_offset;
 
-	ret = PR_Recv(c->c_prfd,sp->encrypted_buffer + sp->encrypted_buffer_offset,bytes_remaining_to_read,0,PR_INTERVAL_NO_WAIT);
-	if (ret < 0) {
-		*err = PR_GetError();
-		return -1;
-	}
-	if (ret > 0) {
-		sp->encrypted_buffer_offset += ret;
-	}
-	return ret;
+    ret = PR_Recv(c->c_prfd,sp->encrypted_buffer + sp->encrypted_buffer_offset,bytes_remaining_to_read,0,PR_INTERVAL_NO_WAIT);
+    if (ret < 0) {
+        *err = PR_GetError();
+        return -1;
+    }
+    if (ret > 0) {
+        sp->encrypted_buffer_offset += ret;
+    }
+    return ret;
 }
 
 /* Special recv function for the server connection code */
@@ -204,131 +224,131 @@ sasl_io_read_packet(Connection *c, PRInt32 *err)
 int
 sasl_recv_connection(Connection *c, char *buffer, size_t count,PRInt32 *err)
 {
-	int ret = 0;
-	size_t bytes_in_buffer = 0;
-	sasl_io_private *sp = c->c_sasl_io_private;
+    int ret = 0;
+    size_t bytes_in_buffer = 0;
+    sasl_io_private *sp = c->c_sasl_io_private;
 
-	*err = 0;
-	LDAPDebug( LDAP_DEBUG_CONNS,
-				"sasl_recv_connection for connection %d\n", c->c_connid, 0, 0 );
-	/* Do we have decrypted data buffered from 'before' ? */
-	bytes_in_buffer = sp->decrypted_buffer_count - sp->decrypted_buffer_offset;
-	if (0 == bytes_in_buffer) {
-		/* If there wasn't buffered decrypted data, we need to get some... */
-		if (!sasl_io_reading_packet(sp)) {
-			/* First read the packet length and so on */
-			ret = sasl_io_start_packet(c, err);
-			if (0 != ret) {
-				/* Most likely the i/o timed out */
-				return ret;
-			}
-		}
-				/* We now have the packet length
-		 * we now must read more data off the wire until we have the complete packet
-		*/
-		ret = sasl_io_read_packet(c,err);
-		if (0 == ret || -1 == ret) {
-			return ret;
-		}
-		/* Are we there yet ? */
-		if (sasl_io_finished_packet(sp)) {
-			const char *output_buffer = NULL;
-			unsigned int output_length = 0;
-			LDAPDebug( LDAP_DEBUG_CONNS,
-			"sasl_recv_connection finished reading packet for connection %d\n", c->c_connid, 0, 0 );
-			/* Now decode it */
-			ret = sasl_decode(c->c_sasl_conn,sp->encrypted_buffer,sp->encrypted_buffer_count,&output_buffer,&output_length);
-			if (SASL_OK == ret) {
-				LDAPDebug( LDAP_DEBUG_CONNS,
-				"sasl_recv_connection decoded packet length %d for connection %d\n", output_length, c->c_connid, 0 );
-				if (output_length) {
-					sasl_io_resize_decrypted_buffer(sp,output_length);
-					memcpy(sp->decrypted_buffer,output_buffer,output_length);
-					sp->decrypted_buffer_count = output_length;
-					sp->decrypted_buffer_offset = 0;
-					sp->encrypted_buffer_offset = 0;
-					sp->encrypted_buffer_count = 0;
-				}
-			} else {
-				LDAPDebug( LDAP_DEBUG_ANY,
-				"sasl_recv_connection failed to decode packet for connection %d\n", c->c_connid, 0, 0 );
-			}
-		}
-	}		
-	/* Finally, return data from the buffer to the caller */
-	{
-		size_t bytes_to_return = sp->decrypted_buffer_count - sp->decrypted_buffer_offset;
-		if (bytes_to_return > count) {
-			bytes_to_return = count;
-		}
-		memcpy(buffer, sp->decrypted_buffer, bytes_to_return);
-		if (bytes_in_buffer == bytes_to_return) {
-			sp->decrypted_buffer_offset = 0;
-			sp->decrypted_buffer_count = 0;
-			} else {
-				sp->decrypted_buffer_offset += bytes_to_return;
-		}
-		ret = bytes_to_return;
-	}
-	return ret;
+    *err = 0;
+    LDAPDebug( LDAP_DEBUG_CONNS,
+                "sasl_recv_connection for connection %d\n", c->c_connid, 0, 0 );
+    /* Do we have decrypted data buffered from 'before' ? */
+    bytes_in_buffer = sp->decrypted_buffer_count - sp->decrypted_buffer_offset;
+    if (0 == bytes_in_buffer) {
+        /* If there wasn't buffered decrypted data, we need to get some... */
+        if (!sasl_io_reading_packet(sp)) {
+            /* First read the packet length and so on */
+            ret = sasl_io_start_packet(c, err);
+            if (0 != ret) {
+                /* Most likely the i/o timed out */
+                return ret;
+            }
+        }
+        /* We now have the packet length
+         * we now must read more data off the wire until we have the complete packet
+        */
+        ret = sasl_io_read_packet(c,err);
+        if (0 == ret || -1 == ret) {
+            return ret;
+        }
+        /* Are we there yet ? */
+        if (sasl_io_finished_packet(sp)) {
+            const char *output_buffer = NULL;
+            unsigned int output_length = 0;
+            LDAPDebug( LDAP_DEBUG_CONNS,
+            "sasl_recv_connection finished reading packet for connection %d\n", c->c_connid, 0, 0 );
+            /* Now decode it */
+            ret = sasl_decode(c->c_sasl_conn,sp->encrypted_buffer,sp->encrypted_buffer_count,&output_buffer,&output_length);
+            if (SASL_OK == ret) {
+                LDAPDebug( LDAP_DEBUG_CONNS,
+                "sasl_recv_connection decoded packet length %d for connection %d\n", output_length, c->c_connid, 0 );
+                if (output_length) {
+                    sasl_io_resize_decrypted_buffer(sp,output_length);
+                    memcpy(sp->decrypted_buffer,output_buffer,output_length);
+                    sp->decrypted_buffer_count = output_length;
+                    sp->decrypted_buffer_offset = 0;
+                    sp->encrypted_buffer_offset = 0;
+                    sp->encrypted_buffer_count = 0;
+                }
+            } else {
+                LDAPDebug( LDAP_DEBUG_ANY,
+                "sasl_recv_connection failed to decode packet for connection %d\n", c->c_connid, 0, 0 );
+            }
+        }
+    }        
+    /* Finally, return data from the buffer to the caller */
+    {
+        size_t bytes_to_return = sp->decrypted_buffer_count - sp->decrypted_buffer_offset;
+        if (bytes_to_return > count) {
+            bytes_to_return = count;
+        }
+        memcpy(buffer, sp->decrypted_buffer, bytes_to_return);
+        if (bytes_in_buffer == bytes_to_return) {
+            sp->decrypted_buffer_offset = 0;
+            sp->decrypted_buffer_count = 0;
+            } else {
+                sp->decrypted_buffer_offset += bytes_to_return;
+        }
+        ret = bytes_to_return;
+    }
+    return ret;
 }
          
 int
 sasl_read_function(int ignore, void *buffer, int count, struct lextiof_socket_private *handle )
 {
-	int ret = 0;
-	sasl_io_private *sp = (sasl_io_private*) handle;
+    int ret = 0;
+    sasl_io_private *sp = (sasl_io_private*) handle;
 
-	/* First we look to see if we have buffered data that we can return to the caller */
-	if ( (NULL == sp->decrypted_buffer) || ((sp->decrypted_buffer_count - sp->decrypted_buffer_offset) <= 0) )  {
-		/* If we didn't have buffered data, we need to perform I/O and decrypt */
-		PRUint32 buffer_length = 0;
-		/* Read the packet length */
-		ret = read_function(0, &buffer_length, sizeof(buffer_length), sp->real_handle);
-		if (ret) {
-		}
-		/* Read the payload */
-		ret = read_function(0, sp->encrypted_buffer, buffer_length, sp->real_handle);
-		if (ret) {
-		}
-		/* Now we can call sasl to decrypt */
-		/* ret = sasl_decode(sp->conn->c_sasl_conn,sp->encrypted_buffer, buffer_length, sp->decrypted_buffer, &sp->decrypted_buffer_count ); */
-	}
-	/* If things went well, copy the payload for the caller */
-	if ( 0 == ret ) {
-/*		size_t real_count = 0;
+    /* First we look to see if we have buffered data that we can return to the caller */
+    if ( (NULL == sp->decrypted_buffer) || ((sp->decrypted_buffer_count - sp->decrypted_buffer_offset) <= 0) )  {
+        /* If we didn't have buffered data, we need to perform I/O and decrypt */
+        PRUint32 buffer_length = 0;
+        /* Read the packet length */
+        ret = read_function(0, &buffer_length, sizeof(buffer_length), sp->real_handle);
+        if (ret) {
+        }
+        /* Read the payload */
+        ret = read_function(0, sp->encrypted_buffer, buffer_length, sp->real_handle);
+        if (ret) {
+        }
+        /* Now we can call sasl to decrypt */
+        /* ret = sasl_decode(sp->conn->c_sasl_conn,sp->encrypted_buffer, buffer_length, sp->decrypted_buffer, &sp->decrypted_buffer_count ); */
+    }
+    /* If things went well, copy the payload for the caller */
+    if ( 0 == ret ) {
+/*        size_t real_count = 0;
 
-		if (count >= (sp->buffer_count - sp->buffer_offset) ) {
-			real_count = count;
-		} else {
-			real_count = (sp->buffer_count - sp->buffer_offset);
-		}
-		memcpy(buffer, sp->buffer, real_count);
-		sp->buffer_offset += real_count;  */
-	}
-	
-	return ret;
+        if (count >= (sp->buffer_count - sp->buffer_offset) ) {
+            real_count = count;
+        } else {
+            real_count = (sp->buffer_count - sp->buffer_offset);
+        }
+        memcpy(buffer, sp->buffer, real_count);
+        sp->buffer_offset += real_count;  */
+    }
+    
+    return ret;
 }
 
 int
 sasl_write_function(int ignore, const void *buffer, int count, struct lextiof_socket_private *handle)
 {
-	int ret = 0;
-	sasl_io_private *sp = (sasl_io_private*) handle;
-	const char *crypt_buffer = NULL;
-	unsigned crypt_buffer_size = 0;
+    int ret = 0;
+    sasl_io_private *sp = (sasl_io_private*) handle;
+    const char *crypt_buffer = NULL;
+    unsigned crypt_buffer_size = 0;
 
-	LDAPDebug( LDAP_DEBUG_CONNS,
-				"sasl_write_function writing %d bytes\n", count, 0, 0 );
-	/* Get SASL to encrypt the buffer */
-	ret = sasl_encode(sp->conn->c_sasl_conn, buffer, count, &crypt_buffer, &crypt_buffer_size);
-	LDAPDebug( LDAP_DEBUG_CONNS,
-				"sasl_write_function encoded as %d bytes\n", crypt_buffer_size, 0, 0 );
+    LDAPDebug( LDAP_DEBUG_CONNS,
+                "sasl_write_function writing %d bytes\n", count, 0, 0 );
+    /* Get SASL to encrypt the buffer */
+    ret = sasl_encode(sp->conn->c_sasl_conn, buffer, count, &crypt_buffer, &crypt_buffer_size);
+    LDAPDebug( LDAP_DEBUG_CONNS,
+                "sasl_write_function encoded as %d bytes\n", crypt_buffer_size, 0, 0 );
 
     ret = write_function(0, crypt_buffer, crypt_buffer_size, sp->real_handle);
     if (ret) {
-	}
-	
-	return ret;
+    }
+    
+    return ret;
 }
-	
+    

+ 196 - 151
ldap/servers/slapd/saslbind.c

@@ -4,11 +4,15 @@
  * All rights reserved.
  * END COPYRIGHT BLOCK **/
 
+#undef CYRUS_SASL
+
 #include <slap.h>
 #include <fe.h>
 #include <sasl.h>
 #include <saslplug.h>
+#ifndef CYRUS_SASL
 #include <saslmod.h>
+#endif
 #ifndef _WIN32
 #include <unistd.h>
 #endif
@@ -82,9 +86,9 @@ static int ids_sasl_getopt(
     } else if (strcasecmp(option, "has_plain_passwords") == 0) {
         *result = "yes";
     } else if (strcasecmp(option, "LOG_LEVEL") == 0) {
-		if (LDAPDebugLevelIsSet(LDAP_DEBUG_TRACE)) {
-			*result = "6"; /* SASL_LOG_TRACE */
-		}
+        if (LDAPDebugLevelIsSet(LDAP_DEBUG_TRACE)) {
+            *result = "6"; /* SASL_LOG_TRACE */
+        }
     }
 
     if (*result) *len = strlen(*result);
@@ -100,8 +104,8 @@ static int ids_sasl_log(
 {
     switch (level) {
     case SASL_LOG_ERR:          /* log unusual errors (default) */
-	slapi_log_error(SLAPI_LOG_FATAL, "sasl", "%s", message);
-	break;
+    slapi_log_error(SLAPI_LOG_FATAL, "sasl", "%s", message);
+    break;
 
     case SASL_LOG_FAIL:         /* log all authentication failures */
     case SASL_LOG_WARN:         /* log non-fatal warnings */
@@ -109,7 +113,7 @@ static int ids_sasl_log(
     case SASL_LOG_DEBUG:        /* more verbose than LOG_NOTE */
     case SASL_LOG_TRACE:        /* traces of internal protocols */
     case SASL_LOG_PASS:         /* traces of internal protocols, including
-				 * passwords */
+                                 * passwords */
         LDAPDebug(LDAP_DEBUG_ANY, "sasl(%d): %s", level, message, 0);
         break;
 
@@ -129,22 +133,22 @@ static int ids_sasl_proxy_policy(
     struct propctx *propctx
 )
 {
-	int retVal = SASL_OK;
+    int retVal = SASL_OK;
     /* do not permit sasl proxy authorization */
-	/* if the auth_identity is null or empty string, allow the sasl request to go thru */	
-	if ( (auth_identity != NULL ) && ( strlen(auth_identity) > 0 ) ) {
-		Slapi_DN authId , reqUser;
-		slapi_sdn_init_dn_byref(&authId,auth_identity);
-		slapi_sdn_init_dn_byref(&reqUser,requested_user);
-		if (slapi_sdn_compare((const Slapi_DN *)&reqUser,(const Slapi_DN *) &authId) != 0) {
-        	LDAPDebug(LDAP_DEBUG_TRACE, 
+    /* if the auth_identity is null or empty string, allow the sasl request to go thru */    
+    if ( (auth_identity != NULL ) && ( strlen(auth_identity) > 0 ) ) {
+        Slapi_DN authId , reqUser;
+        slapi_sdn_init_dn_byref(&authId,auth_identity);
+        slapi_sdn_init_dn_byref(&reqUser,requested_user);
+        if (slapi_sdn_compare((const Slapi_DN *)&reqUser,(const Slapi_DN *) &authId) != 0) {
+            LDAPDebug(LDAP_DEBUG_TRACE, 
                   "sasl proxy auth not permitted authid=%s user=%s\n",
                   auth_identity, requested_user, 0);
-        	retVal =  SASL_NOAUTHZ;
-    	}
-		slapi_sdn_done(&authId);
-		slapi_sdn_done(&reqUser); 
-	}
+            retVal =  SASL_NOAUTHZ;
+        }
+        slapi_sdn_done(&authId);
+        slapi_sdn_done(&reqUser); 
+    }
     return retVal;
 }
 
@@ -221,9 +225,9 @@ static Slapi_Entry *ids_sasl_user_to_entry(
     char **attrs = NULL;
     char *userattr = "uid", *realmattr = NULL, *ufilter = NULL;
     void *node;
-	int regexmatch = 0;
-	char *regex_ldap_search_base = NULL;
-	char *regex_ldap_search_filter = NULL;
+    int regexmatch = 0;
+    char *regex_ldap_search_base = NULL;
+    char *regex_ldap_search_filter = NULL;
 
     /* TODO: userattr & realmattr should be configurable */
 
@@ -237,79 +241,79 @@ static Slapi_Entry *ids_sasl_user_to_entry(
                              ctrls, attrs, attrsonly,
                              &entry, &found);
     } else {
-		int offset = 0; 
-		if (strncasecmp(user,"u:",2) == 0 )
-			offset = 2;
+        int offset = 0; 
+        if (strncasecmp(user,"u:",2) == 0 )
+            offset = 2;
         /* TODO: quote the filter values */
 
-		/* New regex-based identity mapping : we call it here before the old code.
-		 * If there's a match, we skip the old way, otherwise we plow ahead for backwards compatibility reasons
-		 */
+        /* New regex-based identity mapping : we call it here before the old code.
+         * If there's a match, we skip the old way, otherwise we plow ahead for backwards compatibility reasons
+         */
 
-		regexmatch = sasl_map_domap((char*)user, (char*)user_realm, &regex_ldap_search_base, &regex_ldap_search_filter);
-		if (regexmatch) {
+        regexmatch = sasl_map_domap((char*)user, (char*)user_realm, &regex_ldap_search_base, &regex_ldap_search_filter);
+        if (regexmatch) {
 
-            		ids_sasl_user_search(regex_ldap_search_base, scope, regex_ldap_search_filter, 
+            ids_sasl_user_search(regex_ldap_search_base, scope, regex_ldap_search_filter, 
                                  ctrls, attrs, attrsonly,
                                  &entry, &found);
 
-			/* Free the filter etc */
-			slapi_ch_free((void**)&regex_ldap_search_base);
-			slapi_ch_free((void**)&regex_ldap_search_filter);
-		} else {
-
-        /* Ensure no buffer overflow. */
-        /* We don't know what the upper limits on username and
-         * realm lengths are. There don't seem to be any defined
-         * in the relevant standards. We may find in the future
-         * that a 1K buffer is insufficient for some mechanism,
-         * but it seems unlikely given that the values are exposed 
-         * to the end user.
-         */
-        ulen = strlen(user+offset);
-        fsize += strlen(userattr) + ulen;
-        if (realmattr && user_realm) {
-            rlen = strlen(user_realm);
-            fsize += strlen(realmattr) + rlen;
-        }
-        if (ufilter) fsize += strlen(ufilter);
-        fsize += 100;            /* includes a good safety margin */
-        if (fsize > 1024) {
-            LDAPDebug(LDAP_DEBUG_ANY, "sasl user name and/or realm too long"
-                      " (ulen=%u, rlen=%u)\n", ulen, rlen, 0);
-            return NULL;
-        }
-
-        /* now we can safely write the filter */
-        sprintf(fptr, "(&(%s=%s)", userattr, user+offset);
-        fptr += strlen(fptr);
-        if (realmattr && user_realm) {
-            sprintf(fptr, "(%s=%s)", realmattr, user_realm);
-            fptr += strlen(fptr);
-        }
-        if (ufilter) {
-            if (*ufilter == '(') {
-                sprintf(fptr, "%s", ufilter);
+            /* Free the filter etc */
+            slapi_ch_free((void**)&regex_ldap_search_base);
+            slapi_ch_free((void**)&regex_ldap_search_filter);
             } else {
-                sprintf(fptr, "(%s)", ufilter);
+    
+            /* Ensure no buffer overflow. */
+            /* We don't know what the upper limits on username and
+             * realm lengths are. There don't seem to be any defined
+             * in the relevant standards. We may find in the future
+             * that a 1K buffer is insufficient for some mechanism,
+             * but it seems unlikely given that the values are exposed 
+             * to the end user.
+             */
+            ulen = strlen(user+offset);
+            fsize += strlen(userattr) + ulen;
+            if (realmattr && user_realm) {
+                rlen = strlen(user_realm);
+                fsize += strlen(realmattr) + rlen;
             }
+            if (ufilter) fsize += strlen(ufilter);
+            fsize += 100;            /* includes a good safety margin */
+            if (fsize > 1024) {
+                LDAPDebug(LDAP_DEBUG_ANY, "sasl user name and/or realm too long"
+                          " (ulen=%u, rlen=%u)\n", ulen, rlen, 0);
+                return NULL;
+            }
+    
+            /* now we can safely write the filter */
+            sprintf(fptr, "(&(%s=%s)", userattr, user+offset);
             fptr += strlen(fptr);
+            if (realmattr && user_realm) {
+                sprintf(fptr, "(%s=%s)", realmattr, user_realm);
+                fptr += strlen(fptr);
+            }
+            if (ufilter) {
+                if (*ufilter == '(') {
+                    sprintf(fptr, "%s", ufilter);
+                } else {
+                    sprintf(fptr, "(%s)", ufilter);
+                }
+                fptr += strlen(fptr);
+            }
+            sprintf(fptr, ")");
+    
+            /* iterate through the naming contexts */
+            for (sdn = slapi_get_first_suffix(&node, 0); sdn != NULL;
+                 sdn = slapi_get_next_suffix(&node, 0)) {
+    
+                ids_sasl_user_search((char*)slapi_sdn_get_dn(sdn), scope, filter, 
+                                     ctrls, attrs, attrsonly,
+                                     &entry, &found);
+            }
         }
-        sprintf(fptr, ")");
-
-        /* iterate through the naming contexts */
-        for (sdn = slapi_get_first_suffix(&node, 0); sdn != NULL;
-             sdn = slapi_get_next_suffix(&node, 0)) {
-
-            ids_sasl_user_search((char*)slapi_sdn_get_dn(sdn), scope, filter, 
-                                 ctrls, attrs, attrsonly,
-                                 &entry, &found);
-        }
-		}
     }
 
     if (found == 1) {
-		LDAPDebug(LDAP_DEBUG_TRACE, "sasl user search found this entry: dn:%s, matching filter=%s\n", entry->e_sdn.dn, filter, 0);
+        LDAPDebug(LDAP_DEBUG_TRACE, "sasl user search found this entry: dn:%s, matching filter=%s\n", entry->e_sdn.dn, filter, 0);
         return entry;
     }
 
@@ -339,10 +343,14 @@ static int ids_sasl_canon_user(
     sasl_conn_t *conn,
     void *context,
     const char *userbuf, unsigned ulen,
+#ifndef CYRUS_SASL
     const char *authidbuf, unsigned alen,
+#endif
     unsigned flags, const char *user_realm,
-    char *out_user, unsigned out_umax, unsigned *out_ulen,
-    char *out_authid, unsigned out_amax, unsigned *out_alen
+    char *out_user, unsigned out_umax, unsigned *out_ulen
+#ifndef CYRUS_SASL
+    ,char *out_authid, unsigned out_amax, unsigned *out_alen
+#endif
 )
 {
     struct propctx *propctx = sasl_auxprop_getctx(conn);
@@ -350,20 +358,29 @@ static int ids_sasl_canon_user(
     Slapi_DN *sdn = NULL;
     char *pw = NULL;
     char *user = NULL;
+#ifndef CYRUS_SASL
     char *authid = NULL;
+#endif
     const char *dn;
     int isroot = 0;
-	char *clear = NULL;
+    char *clear = NULL;
+    int returnvalue = SASL_FAIL;
 
     user = buf2str(userbuf, ulen);
     if (user == NULL) {
         goto fail;
     } 
+#ifdef CYRUS_SASL
+    LDAPDebug(LDAP_DEBUG_TRACE, 
+              "ids_sasl_canon_user(user=%s, realm=%s)\n", 
+              user, user_realm ? user_realm : "", 0);
+#else
     authid = buf2str(authidbuf, alen);
 
     LDAPDebug(LDAP_DEBUG_TRACE, 
               "ids_sasl_canon_user(user=%s, authzid=%s, realm=%s)\n", 
               user, authid, user_realm ? user_realm : "");
+#endif
 
     if (strncasecmp(user, "dn:", 3) == 0) {
         sdn = slapi_sdn_new();
@@ -379,6 +396,11 @@ static int ids_sasl_canon_user(
         /* map the sasl username into an entry */
         entry = ids_sasl_user_to_entry(conn, context, user, user_realm);
         if (entry == NULL) {
+#ifdef CYRUS_SASL
+            /* Specific return value is supposed to be set instead of 
+               an generic error (SASL_FAIL) for Cyrus SASL */
+            returnvalue = SASL_NOAUTHZ;
+#endif
             goto fail;
         }
         dn = slapi_entry_get_ndn(entry);
@@ -392,29 +414,34 @@ static int ids_sasl_canon_user(
 
     clear = pw;
     if (clear) {
-    	if (prop_set(propctx, "userpassword", clear, -1) != 0) {
-    		/* Failure is benign here because some mechanisms don't support this property */
-        	/*LDAPDebug(LDAP_DEBUG_TRACE, "prop_set(userpassword) failed\n", 0, 0, 0);
-        	goto fail */ ;
-    	}
+        if (prop_set(propctx, "userpassword", clear, -1) != 0) {
+            /* Failure is benign here because some mechanisms don't support this property */
+            /*LDAPDebug(LDAP_DEBUG_TRACE, "prop_set(userpassword) failed\n", 0, 0, 0);
+            goto fail */ ;
+        }
     }
 
     /* TODO: canonicalize */
     strcpy(out_user, dn);
-	if (authid )
-	{
-		int offset = 0;
-		/* The authid can start with dn:. In such case remove it */	
-		if (strncasecmp(authid,"dn:",3) == 0 )
-			offset = 3;
-    	strcpy(out_authid, authid+offset);
-	}
+#ifdef CYRUS_SASL
+    /* the length of out_user needs to be set for Cyrus SASL */
+    *out_ulen = strlen(out_user);
+#else
+    if (authid )
+    {
+        int offset = 0;
+        /* The authid can start with dn:. In such case remove it */    
+        if (strncasecmp(authid,"dn:",3) == 0 )
+            offset = 3;
+        strcpy(out_authid, authid+offset);
+    }
     *out_ulen = -1;
     *out_alen = -1;
+    slapi_ch_free((void**)&authid);
+#endif
 
     slapi_entry_free(entry);
     slapi_ch_free((void**)&user);
-    slapi_ch_free((void**)&authid);
     slapi_ch_free((void**)&pw);
     slapi_sdn_free(&sdn);
 
@@ -423,30 +450,46 @@ static int ids_sasl_canon_user(
  fail:
     slapi_entry_free(entry);
     slapi_ch_free((void**)&user);
+#ifndef CYRUS_SASL
     slapi_ch_free((void**)&authid);
+#endif
     slapi_ch_free((void**)&pw);
     slapi_sdn_free(&sdn);
 
-    return SASL_FAIL;
+    return returnvalue;
 }
 
 static sasl_callback_t ids_sasl_callbacks[5] =
 {
-    SASL_CB_GETOPT,
-    (IFP) ids_sasl_getopt,
-    NULL,
-    SASL_CB_LOG,
-    (IFP) ids_sasl_log,
-    NULL,
-    SASL_CB_PROXY_POLICY,
-    (IFP) ids_sasl_proxy_policy,
-    NULL,
-    SASL_CB_SERVER_CANON_USER,
-    (IFP) ids_sasl_canon_user,
-    NULL,
-    SASL_CB_LIST_END,
-    (IFP) NULL,
-    NULL
+    {
+      SASL_CB_GETOPT,
+      (IFP) ids_sasl_getopt,
+      NULL
+    },
+    {
+      SASL_CB_LOG,
+      (IFP) ids_sasl_log,
+      NULL
+    },
+    {
+      SASL_CB_PROXY_POLICY,
+      (IFP) ids_sasl_proxy_policy,
+      NULL
+    },
+    {
+#ifdef CYRUS_SASL
+      SASL_CB_CANON_USER,
+#else
+      SASL_CB_SERVER_CANON_USER,
+#endif
+      (IFP) ids_sasl_canon_user,
+      NULL
+    },
+    {
+      SASL_CB_LIST_END,
+      (IFP) NULL,
+      NULL
+    }
 };
 
 static const char *dn_propnames[] = { "dn", 0 };
@@ -466,7 +509,7 @@ int ids_sasl_init(void)
 
     serverfqdn = get_localhost_DNS();
 
-	LDAPDebug(LDAP_DEBUG_TRACE, "sasl service fqdn is: %s\n", 
+    LDAPDebug(LDAP_DEBUG_TRACE, "sasl service fqdn is: %s\n", 
                   serverfqdn, 0, 0);
 
     result = sasl_server_init(ids_sasl_callbacks, "iDS");
@@ -477,12 +520,13 @@ int ids_sasl_init(void)
         return result;
     }
 
+#ifndef CYRUS_SASL
     result = sasl_server_add_plugin("USERDB", sasl_userdb_init);
 
     if (result != SASL_OK) {
         LDAPDebug(LDAP_DEBUG_TRACE, "failed to add LDAP sasl plugin\n",
                   0, 0, 0);
-	return result;
+        return result;
     }
 
 #if defined(BUILD_GSSAPI)
@@ -492,6 +536,7 @@ int ids_sasl_init(void)
         LDAPDebug(LDAP_DEBUG_TRACE, "failed to add LDAP gssapi plugin\n",
                   0, 0, 0);
     }
+#endif
 #endif
 
     LDAPDebug( LDAP_DEBUG_TRACE, "<= ids_sasl_init\n", 0, 0, 0 );
@@ -611,9 +656,9 @@ ids_sasl_mech_supported(Slapi_PBlock *pb, sasl_conn_t *sasl_conn, const char *me
   /* sasl_listmech is not thread-safe, so we lock here */
   PR_Lock(pb->pb_conn->c_mutex);
   sasl_result = sasl_listmech(sasl_conn, 
-		    NULL,     /* username */
-		    "", ",", "",
-		    &str, NULL, NULL);
+                    NULL,     /* username */
+                    "", ",", "",
+                    &str, NULL, NULL);
   PR_Unlock(pb->pb_conn->c_mutex);
   if (sasl_result != SASL_OK) {
     return 0;
@@ -758,17 +803,17 @@ void ids_sasl_check_bind(Slapi_PBlock *pb)
         isroot = slapi_dn_isroot(dn);
 
         if (!isroot )
-		{
-			/* check if the account is locked */
-			bind_target_entry = get_entry(pb,  dn);
-			if ( bind_target_entry == NULL )
-			{
-				break;
-			} 
-			if ( check_account_lock(pb, bind_target_entry, pwresponse_requested) == 1) {
-				slapi_entry_free(bind_target_entry);
-				break;
-			}
+        {
+            /* check if the account is locked */
+            bind_target_entry = get_entry(pb,  dn);
+            if ( bind_target_entry == NULL )
+            {
+                break;
+            } 
+            if ( check_account_lock(pb, bind_target_entry, pwresponse_requested) == 1) {
+                slapi_entry_free(bind_target_entry);
+                break;
+            }
         }
 
         /* see if we negotiated a security layer */
@@ -781,16 +826,16 @@ void ids_sasl_check_bind(Slapi_PBlock *pb)
                                  "sasl encryption not supported over ssl", 
                                  0, NULL);
                 if ( bind_target_entry != NULL )
-				    slapi_entry_free(bind_target_entry);
+                    slapi_entry_free(bind_target_entry);
                 break;
             } else {
-				/* Enable SASL I/O on the connection now */
-				/* Note that this doesn't go into effect until the next _read_ operation is done */
-				if (0 != sasl_io_enable(pb->pb_conn) ) {
-					send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL,
+                /* Enable SASL I/O on the connection now */
+                /* Note that this doesn't go into effect until the next _read_ operation is done */
+                if (0 != sasl_io_enable(pb->pb_conn) ) {
+                    send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL,
                                  "failed to enable sasl i/o",
-                                 0, NULL);	
-				}
+                                 0, NULL);
+                }
             }
         }
 
@@ -825,14 +870,14 @@ void ids_sasl_check_bind(Slapi_PBlock *pb)
 
         /* check password expiry */
         if (!isroot) {
-			int		pwrc;
-
-			pwrc = need_new_pw (pb, &t, bind_target_entry, pwresponse_requested);
-			if ( bind_target_entry != NULL ) {
-				slapi_entry_free(bind_target_entry);
-				bind_target_entry = NULL;
-			}
-			
+            int pwrc;
+
+            pwrc = need_new_pw(pb, &t, bind_target_entry, pwresponse_requested);
+            if ( bind_target_entry != NULL ) {
+                slapi_entry_free(bind_target_entry);
+                bind_target_entry = NULL;
+            }
+            
             switch (pwrc) {
             case 1:
                 slapi_add_pwd_control(pb, LDAP_CONTROL_PWEXPIRED, 0);
@@ -895,13 +940,13 @@ void ids_sasl_check_bind(Slapi_PBlock *pb)
         break;
     }
 
-	out:
-		if (referral)
-			slapi_entry_free(referral);
-		if (be)
-			slapi_be_Unlock(be);
+    out:
+        if (referral)
+            slapi_entry_free(referral);
+        if (be)
+            slapi_be_Unlock(be);
 
-	LDAPDebug( LDAP_DEBUG_TRACE, "=> ids_sasl_check_bind\n", 0, 0, 0 );
+    LDAPDebug( LDAP_DEBUG_TRACE, "=> ids_sasl_check_bind\n", 0, 0, 0 );
 
     return;
 }