/* * Unix interface for libldap * * Copyright 2021 Hans Leidekker for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #if 0 #pragma makedep unix #endif #include "config.h" #ifdef HAVE_LDAP #include #include #include #ifdef HAVE_LDAP_H # include #endif #ifdef HAVE_SASL_SASL_H # include #endif #include "ntstatus.h" #define WIN32_NO_STATUS #include "windef.h" #include "winternl.h" #include "winbase.h" #include "wine/debug.h" #include "libldap.h" WINE_DEFAULT_DEBUG_CHANNEL(wldap32); C_ASSERT( sizeof(BerValueU) == sizeof(BerValue) ); C_ASSERT( sizeof(LDAPModU) == sizeof(LDAPMod) ); C_ASSERT( sizeof(LDAPControlU) == sizeof(LDAPControl) ); C_ASSERT( sizeof(LDAPSortKeyU) == sizeof(LDAPSortKey) ); C_ASSERT( sizeof(LDAPVLVInfoU) == sizeof(LDAPVLVInfo) ); C_ASSERT( sizeof(LDAPAPIInfoU) == sizeof(LDAPAPIInfo) ); C_ASSERT( sizeof(LDAPAPIFeatureInfoU) == sizeof(LDAPAPIFeatureInfo) ); C_ASSERT( sizeof(struct timevalU) == sizeof(struct timeval) ); #define WLDAP32_LBER_ERROR (~0l) static LDAPMod *nullmods[] = { NULL }; static const struct ldap_callbacks *callbacks; void * CDECL wrap_ber_alloc_t( int options ) { return ber_alloc_t( options ); } void CDECL wrap_ber_bvecfree( struct bervalU **berval ) { ber_bvecfree( (struct berval **)berval ); } void CDECL wrap_ber_bvfree( struct bervalU *berval ) { ber_bvfree( (struct berval *)berval ); } unsigned int CDECL wrap_ber_first_element( void *ber, ULONG *ret_len, char **last ) { ber_len_t len; ber_tag_t ret; if ((ret = ber_first_element( ber, &len, last )) == LBER_ERROR) return WLDAP32_LBER_ERROR; if (ret > ~0u) { ERR( "ret too large\n" ); return WLDAP32_LBER_ERROR; } if (len > ~0u) { ERR( "len too large\n" ); return WLDAP32_LBER_ERROR; } *ret_len = len; return ret; } int CDECL wrap_ber_flatten( void *ber, struct bervalU **berval ) { return ber_flatten( ber, (struct berval **)berval ); } void CDECL wrap_ber_free( void *ber, int freebuf ) { ber_free( ber, freebuf ); } void * CDECL wrap_ber_init( struct bervalU *berval ) { return ber_init( (struct berval *)berval ); } unsigned int CDECL wrap_ber_next_element( void *ber, unsigned int *ret_len, char *last ) { ber_len_t len; ber_tag_t ret; if ((ret = ber_next_element( ber, &len, last )) == LBER_ERROR) return WLDAP32_LBER_ERROR; if (ret > ~0u) { ERR( "ret too large\n" ); return WLDAP32_LBER_ERROR; } if (len > ~0u) { ERR( "len too large\n" ); return WLDAP32_LBER_ERROR; } *ret_len = len; return ret; } unsigned int CDECL wrap_ber_peek_tag( void *ber, unsigned int *ret_len ) { ber_len_t len; ber_tag_t ret; if ((ret = ber_peek_tag( ber, &len )) == LBER_ERROR) return WLDAP32_LBER_ERROR; if (len > ~0u) { ERR( "len too large\n" ); return WLDAP32_LBER_ERROR; } *ret_len = len; return ret; } unsigned int CDECL wrap_ber_skip_tag( void *ber, unsigned int *ret_len ) { ber_len_t len; ber_tag_t ret; if ((ret = ber_skip_tag( ber, &len )) == LBER_ERROR) return WLDAP32_LBER_ERROR; if (len > ~0u) { ERR( "len too large\n" ); return WLDAP32_LBER_ERROR; } *ret_len = len; return ret; } int WINAPIV wrap_ber_printf( void *ber, char *fmt, ... ) { int ret; __ms_va_list args; assert( strlen(fmt) == 1 ); __ms_va_start( args, fmt ); switch (fmt[0]) { case 'b': case 'e': case 'i': { int i = va_arg( args, int ); ret = ber_printf( ber, fmt, i ); break; } case 'o': case 's': { char *str = va_arg( args, char * ); ret = ber_printf( ber, fmt, str ); break; } case 't': { unsigned int tag = va_arg( args, unsigned int ); ret = ber_printf( ber, fmt, tag ); break; } case 'v': { char **array = va_arg( args, char ** ); ret = ber_printf( ber, fmt, array ); break; } case 'V': { struct berval **array = va_arg( args, struct berval ** ); ret = ber_printf( ber, fmt, array ); break; } case 'B': { char *str = va_arg( args, char * ); int len = va_arg( args, int ); ret = ber_printf( ber, fmt, str, len ); break; } case 'n': case '{': case '}': case '[': case ']': ret = ber_printf( ber, fmt ); break; default: assert( 0 ); } __ms_va_end( args ); return ret; } int WINAPIV wrap_ber_scanf( void *ber, char *fmt, ... ) { int ret; __ms_va_list args; assert( strlen(fmt) == 1 ); __ms_va_start( args, fmt ); switch (fmt[0]) { case 'a': { char **str = va_arg( args, char ** ); ret = ber_scanf( ber, fmt, str ); break; } case 'b': case 'e': case 'i': { int *i = va_arg( args, int * ); ret = ber_scanf( ber, fmt, i ); break; } case 't': { unsigned int *tag = va_arg( args, unsigned int * ); ret = ber_scanf( ber, fmt, tag ); break; } case 'v': { char ***array = va_arg( args, char *** ); ret = ber_scanf( ber, fmt, array ); break; } case 'B': { char **str = va_arg( args, char ** ); int *len = va_arg( args, int * ); ret = ber_scanf( ber, fmt, str, len ); break; } case 'O': { struct berval **berval = va_arg( args, struct berval ** ); ret = ber_scanf( ber, fmt, berval ); break; } case 'V': { struct berval ***array = va_arg( args, struct berval *** ); ret = ber_scanf( ber, fmt, array ); break; } case 'n': case 'x': case '{': case '}': case '[': case ']': ret = ber_scanf( ber, fmt ); break; default: assert( 0 ); } __ms_va_end( args ); return ret; } int CDECL wrap_ldap_abandon_ext( void *ld, int msgid, LDAPControlU **serverctrls, LDAPControlU **clientctrls ) { return ldap_abandon_ext( ld, msgid, (LDAPControl **)serverctrls, (LDAPControl **)clientctrls ); } int CDECL wrap_ldap_add_ext( void *ld, const char *dn, LDAPModU **attrs, LDAPControlU **serverctrls, LDAPControlU **clientctrls, ULONG *msg ) { int dummy; return ldap_add_ext( ld, dn ? dn : "", attrs ? (LDAPMod **)attrs : nullmods, (LDAPControl **)serverctrls, (LDAPControl **)clientctrls, msg ? (int *)msg : &dummy ); } int CDECL wrap_ldap_add_ext_s( void *ld, const char *dn, LDAPModU **attrs, LDAPControlU **serverctrls, LDAPControlU **clientctrls ) { return ldap_add_ext_s( ld, dn ? dn : "", attrs ? (LDAPMod **)attrs : nullmods, (LDAPControl **)serverctrls, (LDAPControl **)clientctrls ); } int CDECL wrap_ldap_compare_ext( void *ld, const char *dn, const char *attrs, struct bervalU *value, LDAPControlU **serverctrls, LDAPControlU **clientctrls, ULONG *msg ) { int dummy; return ldap_compare_ext( ld, dn ? dn : "", attrs ? attrs : "", (struct berval *)value, (LDAPControl **)serverctrls, (LDAPControl **)clientctrls, msg ? (int *)msg : &dummy ); } int CDECL wrap_ldap_compare_ext_s( void *ld, const char *dn, const char *attrs, struct bervalU *value, LDAPControlU **serverctrls, LDAPControlU **clientctrls ) { return ldap_compare_ext_s( ld, dn ? dn : "", attrs ? attrs : "", (struct berval *)value, (LDAPControl **)serverctrls, (LDAPControl **)clientctrls ); } void CDECL wrap_ldap_control_free( LDAPControlU *control ) { ldap_control_free( (LDAPControl *)control ); } void CDECL wrap_ldap_controls_free( LDAPControlU **control ) { ldap_controls_free( (LDAPControl **)control ); } int CDECL wrap_ldap_count_entries( void *ld, void *chain ) { return ldap_count_entries( ld, chain ); } int CDECL wrap_ldap_count_references( void *ld, void *chain ) { return ldap_count_references( ld, chain ); } int CDECL wrap_ldap_count_values_len( struct bervalU **values ) { return ldap_count_values_len( (struct berval **)values ); } int CDECL wrap_ldap_create_sort_control( void *ld, LDAPSortKeyU **keylist, int critical, LDAPControlU **control ) { return ldap_create_sort_control( ld, (LDAPSortKey **)keylist, critical, (LDAPControl **)control ); } int CDECL wrap_ldap_create_vlv_control( void *ld, LDAPVLVInfoU *info, LDAPControlU **control ) { return ldap_create_vlv_control( ld, (LDAPVLVInfo *)info, (LDAPControl **)control ); } int CDECL wrap_ldap_delete_ext( void *ld, const char *dn, LDAPControlU **serverctrls, LDAPControlU **clientctrls, ULONG *msg ) { int dummy; return ldap_delete_ext( ld, dn ? dn : "", (LDAPControl **)serverctrls, (LDAPControl **)clientctrls, msg ? (int *)msg : &dummy ); } int CDECL wrap_ldap_delete_ext_s( void *ld, const char *dn, LDAPControlU **serverctrls, LDAPControlU **clientctrls ) { return ldap_delete_ext_s( ld, dn ? dn : "", (LDAPControl **)serverctrls, (LDAPControl **)clientctrls ); } char * CDECL wrap_ldap_dn2ufn( const char *dn ) { return ldap_dn2ufn( dn ); } char ** CDECL wrap_ldap_explode_dn( const char *dn, int notypes ) { return ldap_explode_dn( dn, notypes ); } int CDECL wrap_ldap_extended_operation( void *ld, const char *oid, struct bervalU *data, LDAPControlU **serverctrls, LDAPControlU **clientctrls, ULONG *msg ) { int dummy; return ldap_extended_operation( ld, oid ? oid : "", (struct berval *)data, (LDAPControl **)serverctrls, (LDAPControl **)clientctrls, msg ? (int *)msg : &dummy ); } int CDECL wrap_ldap_extended_operation_s( void *ld, const char *oid, struct bervalU *data, LDAPControlU **serverctrls, LDAPControlU **clientctrls, char **retoid, struct bervalU **retdata ) { return ldap_extended_operation_s( ld, oid ? oid : "", (struct berval *)data, (LDAPControl **)serverctrls, (LDAPControl **)clientctrls, retoid, (struct berval **)retdata ); } char * CDECL wrap_ldap_get_dn( void *ld, void *entry ) { return ldap_get_dn( ld, entry ); } char * CDECL wrap_ldap_first_attribute( void *ld, void *entry, void **ber ) { return ldap_first_attribute( ld, entry, (BerElement **)ber ); } void * CDECL wrap_ldap_first_entry( void *ld, void *chain ) { return ldap_first_entry( ld, chain ); } void * CDECL wrap_ldap_first_reference( void *ld, void *chain ) { return ldap_first_reference( ld, chain ); } int CDECL wrap_ldap_get_option( void *ld, int option, void *value ) { return ldap_get_option( ld, option, value ); } struct bervalU ** CDECL wrap_ldap_get_values_len( void *ld, void *entry, const char *attr ) { return (struct bervalU **)ldap_get_values_len( ld, entry, attr ); } int CDECL wrap_ldap_initialize( void **ld, const char *url ) { return ldap_initialize( (LDAP **)ld, url ); } void CDECL wrap_ldap_memfree( void *ptr ) { return ldap_memfree( ptr ); } void CDECL wrap_ldap_memvfree( void **ptr ) { ldap_memvfree( ptr ); } int CDECL wrap_ldap_modify_ext( void *ld, const char *dn, LDAPModU **mods, LDAPControlU **serverctrls, LDAPControlU **clientctrls, ULONG *msg ) { int dummy; return ldap_modify_ext( ld, dn ? dn : "", mods ? (LDAPMod **)mods : nullmods, (LDAPControl **)serverctrls, (LDAPControl **)clientctrls, msg ? (int *)msg : &dummy ); } int CDECL wrap_ldap_modify_ext_s( void *ld, const char *dn, LDAPModU **mods, LDAPControlU **serverctrls, LDAPControlU **clientctrls ) { return ldap_modify_ext_s( ld, dn ? dn : "", mods ? (LDAPMod **)mods : nullmods, (LDAPControl **)serverctrls, (LDAPControl **)clientctrls ); } int CDECL wrap_ldap_msgfree( void *msg ) { return ldap_msgfree( msg ); } char * CDECL wrap_ldap_next_attribute( void *ld, void *entry, void *ber ) { return ldap_next_attribute( ld, entry, ber ); } void * CDECL wrap_ldap_next_entry( void *ld, void *entry ) { return ldap_next_entry( ld, entry ); } void * CDECL wrap_ldap_next_reference( void *ld, void *entry ) { return ldap_next_reference( ld, entry ); } int CDECL wrap_ldap_parse_extended_result( void *ld, void *result, char **retoid, struct bervalU **retdata, int free ) { return ldap_parse_extended_result( ld, result, retoid, (struct berval **)retdata, free ); } int CDECL wrap_ldap_parse_reference( void *ld, void *ref, char ***referrals, LDAPControlU ***serverctrls, int free ) { return ldap_parse_reference( ld, ref, referrals, (LDAPControl ***)serverctrls, free ); } int CDECL wrap_ldap_parse_result( void *ld, void *res, int *errcode, char **matcheddn, char **errmsg, char ***referrals, LDAPControlU ***serverctrls, int free ) { return ldap_parse_result( ld, res, errcode, matcheddn, errmsg, referrals, (LDAPControl ***)serverctrls, free ); } int CDECL wrap_ldap_parse_sortresponse_control( void *ld, LDAPControlU *ctrl, int *result, char **attr ) { return ldap_parse_sortresponse_control( ld, (LDAPControl *)ctrl, result, attr ); } int CDECL wrap_ldap_parse_vlvresponse_control( void *ld, LDAPControlU *ctrls, int *target_pos, int *list_count, struct bervalU **ctx, int *errcode ) { return ldap_parse_vlvresponse_control( ld, (LDAPControl *)ctrls, target_pos, list_count, (struct berval **)ctx, errcode ); } int CDECL wrap_ldap_rename( void *ld, const char *dn, const char *newrdn, const char *newparent, int delete, LDAPControlU **clientctrls, LDAPControlU **serverctrls, ULONG *msg ) { return ldap_rename( ld, dn ? dn : "", newrdn, newparent, delete, (LDAPControl **)clientctrls, (LDAPControl **)serverctrls, (int *)msg ); } int CDECL wrap_ldap_rename_s( void *ld, const char *dn, const char *newrdn, const char *newparent, int delete, LDAPControlU **clientctrls, LDAPControlU **serverctrls ) { return ldap_rename_s( ld, dn ? dn : "", newrdn, newparent, delete, (LDAPControl **)clientctrls, (LDAPControl **)serverctrls ); } int CDECL wrap_ldap_result( void *ld, int msgid, int all, struct timevalU *timeout, void **result ) { return ldap_result( ld, msgid, all, (struct timeval *)timeout, (LDAPMessage **)result ); } int CDECL wrap_ldap_sasl_bind( void *ld, const char *dn, const char *mech, struct bervalU *cred, LDAPControlU **serverctrls, LDAPControlU **clientctrls, int *msgid ) { return ldap_sasl_bind( ld, dn, mech, (struct berval *)cred, (LDAPControl **)serverctrls, (LDAPControl **)clientctrls, msgid ); } int CDECL wrap_ldap_sasl_bind_s( void *ld, const char *dn, const char *mech, struct bervalU *cred, LDAPControlU **serverctrls, LDAPControlU **clientctrls, struct bervalU **servercred ) { return ldap_sasl_bind_s( ld, dn, mech, (struct berval *)cred, (LDAPControl **)serverctrls, (LDAPControl **)clientctrls, (struct berval **)servercred ); } static int wrap_sasl_interact( LDAP *ld, unsigned int flags, void *defaults, void *interact ) { #ifdef HAVE_SASL_SASL_H C_ASSERT( sizeof(struct sasl_interactU) == sizeof(struct sasl_interact) ); return callbacks->sasl_interact( ld, flags, defaults, interact ); #endif return -1; } int CDECL wrap_ldap_sasl_interactive_bind_s( void *ld, const char *dn, const char *mech, LDAPControlU **serverctrls, LDAPControlU **clientctrls, unsigned int flags, void *defaults ) { return ldap_sasl_interactive_bind_s( ld, dn, mech, (LDAPControl **)serverctrls, (LDAPControl **)clientctrls, flags, wrap_sasl_interact, defaults ); } int CDECL wrap_ldap_search_ext( void *ld, const char *base, int scope, const char *filter, char **attrs, int attrsonly, LDAPControlU **serverctrls, LDAPControlU **clientctrls, struct timevalU *timeout, int sizelimit, ULONG *msg ) { return ldap_search_ext( ld, base, scope, filter, attrs, attrsonly, (LDAPControl **)serverctrls, (LDAPControl **)clientctrls, (struct timeval *)timeout, sizelimit, (int *)msg ); } int CDECL wrap_ldap_search_ext_s( void *ld, const char *base, int scope, const char *filter, char **attrs, int attrsonly, LDAPControlU **serverctrls, LDAPControlU **clientctrls, struct timevalU *timeout, int sizelimit, void **result ) { return ldap_search_ext_s( ld, base, scope, filter, attrs, attrsonly, (LDAPControl **)serverctrls, (LDAPControl **)clientctrls, (struct timeval *)timeout, sizelimit, (LDAPMessage **)result ); } int CDECL wrap_ldap_set_option( void *ld, int option, const void *value ) { return ldap_set_option( ld, option, value ); } int CDECL wrap_ldap_start_tls_s( void *ld, LDAPControlU **serverctrls, LDAPControlU **clientctrls ) { return ldap_start_tls_s( ld, (LDAPControl **)serverctrls, (LDAPControl **)clientctrls ); } int CDECL wrap_ldap_unbind_ext( void *ld, LDAPControlU **serverctrls, LDAPControlU **clientctrls ) { return ldap_unbind_ext( ld, (LDAPControl **)serverctrls, (LDAPControl **)clientctrls ); } int CDECL wrap_ldap_unbind_ext_s( void *ld, LDAPControlU **serverctrls, LDAPControlU **clientctrls ) { return ldap_unbind_ext_s( ld, (LDAPControl **)serverctrls, (LDAPControl **)clientctrls ); } void CDECL wrap_ldap_value_free_len( struct bervalU **values ) { ldap_value_free_len( (struct berval **)values ); } static const struct ldap_funcs funcs = { wrap_ber_alloc_t, wrap_ber_bvecfree, wrap_ber_bvfree, wrap_ber_first_element, wrap_ber_flatten, wrap_ber_free, wrap_ber_init, wrap_ber_next_element, wrap_ber_peek_tag, wrap_ber_skip_tag, wrap_ber_printf, wrap_ber_scanf, wrap_ldap_abandon_ext, wrap_ldap_add_ext, wrap_ldap_add_ext_s, wrap_ldap_compare_ext, wrap_ldap_compare_ext_s, wrap_ldap_control_free, wrap_ldap_controls_free, wrap_ldap_count_entries, wrap_ldap_count_references, wrap_ldap_count_values_len, wrap_ldap_create_sort_control, wrap_ldap_create_vlv_control, wrap_ldap_delete_ext, wrap_ldap_delete_ext_s, wrap_ldap_dn2ufn, wrap_ldap_explode_dn, wrap_ldap_extended_operation, wrap_ldap_extended_operation_s, wrap_ldap_get_dn, wrap_ldap_get_option, wrap_ldap_get_values_len, wrap_ldap_initialize, wrap_ldap_first_attribute, wrap_ldap_first_entry, wrap_ldap_first_reference, wrap_ldap_memfree, wrap_ldap_memvfree, wrap_ldap_modify_ext, wrap_ldap_modify_ext_s, wrap_ldap_msgfree, wrap_ldap_next_attribute, wrap_ldap_next_entry, wrap_ldap_next_reference, wrap_ldap_parse_extended_result, wrap_ldap_parse_reference, wrap_ldap_parse_result, wrap_ldap_parse_sortresponse_control, wrap_ldap_parse_vlvresponse_control, wrap_ldap_rename, wrap_ldap_rename_s, wrap_ldap_result, wrap_ldap_sasl_bind, wrap_ldap_sasl_bind_s, wrap_ldap_sasl_interactive_bind_s, wrap_ldap_search_ext, wrap_ldap_search_ext_s, wrap_ldap_set_option, wrap_ldap_start_tls_s, wrap_ldap_unbind_ext, wrap_ldap_unbind_ext_s, wrap_ldap_value_free_len, }; NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out ) { if (reason != DLL_PROCESS_ATTACH) return STATUS_SUCCESS; callbacks = ptr_in; *(const struct ldap_funcs **)ptr_out = &funcs; return STATUS_SUCCESS; } #endif /* HAVE_LDAP */