diff options
author | Noriko Hosoi <nhosoi@redhat.com> | 2005-02-24 21:45:44 +0000 |
---|---|---|
committer | Noriko Hosoi <nhosoi@redhat.com> | 2005-02-24 21:45:44 +0000 |
commit | 370d483a51167d5b9e7cf936a03f3bb42cae5cd4 (patch) | |
tree | d7a8ac1a13f94f82b349da141ba3b2f8fd606b15 | |
parent | 537c8cb011005a99df7b26a9490dedb33c7b42db (diff) | |
download | ds-370d483a51167d5b9e7cf936a03f3bb42cae5cd4.tar.gz ds-370d483a51167d5b9e7cf936a03f3bb42cae5cd4.tar.xz ds-370d483a51167d5b9e7cf936a03f3bb42cae5cd4.zip |
[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.
-rw-r--r-- | ldap/servers/slapd/sasl_io.c | 462 | ||||
-rw-r--r-- | ldap/servers/slapd/saslbind.c | 347 |
2 files changed, 437 insertions, 372 deletions
diff --git a/ldap/servers/slapd/sasl_io.c b/ldap/servers/slapd/sasl_io.c index 7345be35..bf250658 100644 --- a/ldap/servers/slapd/sasl_io.c +++ b/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; } - + diff --git a/ldap/servers/slapd/saslbind.c b/ldap/servers/slapd/saslbind.c index b7a2464e..3e86fece 100644 --- a/ldap/servers/slapd/saslbind.c +++ b/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, ®ex_ldap_search_base, ®ex_ldap_search_filter); - if (regexmatch) { + regexmatch = sasl_map_domap((char*)user, (char*)user_realm, ®ex_ldap_search_base, ®ex_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**)®ex_ldap_search_base); - slapi_ch_free((void**)®ex_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**)®ex_ldap_search_base); + slapi_ch_free((void**)®ex_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) @@ -493,6 +537,7 @@ int ids_sasl_init(void) 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; } |