From: Howard Chu Date: Fri, 7 Sep 2007 12:02:43 +0000 (+0000) Subject: back-sock by Brian Candler (B.Candler@pobox.com) ITS#4094 (untested) X-Git-Tag: OPENLDAP_REL_ENG_2_4_9~20^2~681 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=b6827c75a802a7003d0d94ba12dce854efeb16fb;p=openldap back-sock by Brian Candler (B.Candler@pobox.com) ITS#4094 (untested) --- diff --git a/configure.in b/configure.in index cad9a70bbb..7fa5d6f849 100644 --- a/configure.in +++ b/configure.in @@ -291,6 +291,7 @@ Backends="bdb \ perl \ relay \ shell \ + sock \ sql" AC_ARG_ENABLE(xxslapbackends,[ @@ -320,6 +321,8 @@ OL_ARG_ENABLE(relay,[ --enable-relay enable relay backend], yes, [no yes mod], ol_enable_backends)dnl OL_ARG_ENABLE(shell,[ --enable-shell enable shell backend], no, [no yes mod], ol_enable_backends)dnl +OL_ARG_ENABLE(sock,[ --enable-sock enable sock backend], + no, [no yes mod], ol_enable_backends)dnl OL_ARG_ENABLE(sql,[ --enable-sql enable sql backend], no, [no yes mod], ol_enable_backends)dnl @@ -462,6 +465,7 @@ elif test $ol_enable_modules != yes && test $ol_enable_perl = no && test $ol_enable_relay = no && test $ol_enable_shell = no && + test $ol_enable_sock = no && test $ol_enable_sql = no ; then dnl no slapd backend @@ -519,6 +523,7 @@ BUILD_PASSWD=no BUILD_PERL=no BUILD_RELAY=no BUILD_SHELL=no +BUILD_SOCK=no BUILD_SQL=no BUILD_ACCESSLOG=no @@ -2634,6 +2639,19 @@ if test "$ol_enable_shell" != no ; then AC_DEFINE_UNQUOTED(SLAPD_SHELL,$MFLAG,[define to support SHELL backend]) fi +if test "$ol_enable_sock" != no ; then + BUILD_SLAPD=yes + BUILD_SOCK=$ol_enable_sock + if test "$ol_enable_sock" = mod ; then + SLAPD_DYNAMIC_BACKENDS="$SLAPD_DYNAMIC_BACKENDS back-sock" + MFLAG=SLAPD_MOD_DYNAMIC + else + SLAPD_STATIC_BACKENDS="$SLAPD_STATIC_BACKENDS back-sock" + MFLAG=SLAPD_MOD_STATIC + fi + AC_DEFINE_UNQUOTED(SLAPD_SOCK,$MFLAG,[define to support SOCK backend]) +fi + if test "$ol_link_sql" != no ; then BUILD_SLAPD=yes BUILD_SQL=$ol_enable_sql @@ -2902,6 +2920,7 @@ dnl backends AC_SUBST(BUILD_RELAY) AC_SUBST(BUILD_PERL) AC_SUBST(BUILD_SHELL) + AC_SUBST(BUILD_SOCK) AC_SUBST(BUILD_SQL) dnl overlays AC_SUBST(BUILD_ACCESSLOG) @@ -3001,6 +3020,7 @@ AC_CONFIG_FILES([Makefile:build/top.mk:Makefile.in:build/dir.mk] [servers/slapd/back-perl/Makefile:build/top.mk:servers/slapd/back-perl/Makefile.in:build/mod.mk] [servers/slapd/back-relay/Makefile:build/top.mk:servers/slapd/back-relay/Makefile.in:build/mod.mk] [servers/slapd/back-shell/Makefile:build/top.mk:servers/slapd/back-shell/Makefile.in:build/mod.mk] +[servers/slapd/back-sock/Makefile:build/top.mk:servers/slapd/back-sock/Makefile.in:build/mod.mk] [servers/slapd/back-sql/Makefile:build/top.mk:servers/slapd/back-sql/Makefile.in:build/mod.mk] [servers/slapd/shell-backends/Makefile:build/top.mk:servers/slapd/shell-backends/Makefile.in:build/srv.mk] [servers/slapd/slapi/Makefile:build/top.mk:servers/slapd/slapi/Makefile.in:build/lib.mk:build/lib-shared.mk] diff --git a/servers/slapd/back-sock/add.c b/servers/slapd/back-sock/add.c new file mode 100644 index 0000000000..69879bc57d --- /dev/null +++ b/servers/slapd/back-sock/add.c @@ -0,0 +1,65 @@ +/* add.c - sock backend add function */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 2007 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "portable.h" + +#include + +#include +#include + +#include "slap.h" +#include "back-sock.h" + +int +sock_back_add( + Operation *op, + SlapReply *rs ) +{ + struct sockinfo *si = (struct sockinfo *) op->o_bd->be_private; + AttributeDescription *entry = slap_schema.si_ad_entry; + FILE *fp; + int len; + + if ( ! access_allowed( op, op->oq_add.rs_e, + entry, NULL, ACL_WADD, NULL ) ) + { + send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, NULL ); + return -1; + } + + if ( (fp = opensock( si->si_sockpath )) == NULL ) { + send_ldap_error( op, rs, LDAP_OTHER, + "could not open socket" ); + return( -1 ); + } + + /* write out the request to the add process */ + fprintf( fp, "ADD\n" ); + fprintf( fp, "msgid: %ld\n", (long) op->o_msgid ); + sock_print_conn( fp, op->o_conn, si ); + sock_print_suffixes( fp, op->o_bd ); + ldap_pvt_thread_mutex_lock( &entry2str_mutex ); + fprintf( fp, "%s", entry2str( op->oq_add.rs_e, &len ) ); + ldap_pvt_thread_mutex_unlock( &entry2str_mutex ); + fprintf (fp, "\n" ); + + /* read in the result and send it along */ + sock_read_and_send_results( op, rs, fp ); + + fclose( fp ); + return( 0 ); +} diff --git a/servers/slapd/back-sock/back-sock.h b/servers/slapd/back-sock/back-sock.h new file mode 100644 index 0000000000..7340d93ba5 --- /dev/null +++ b/servers/slapd/back-sock/back-sock.h @@ -0,0 +1,52 @@ +/* sock.h - socket backend header file */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 2007 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#ifndef SLAPD_SOCK_H +#define SLAPD_SOCK_H + +#include "proto-sock.h" + +LDAP_BEGIN_DECL + +struct sockinfo { + const char *si_sockpath; + int si_extensions; +}; + +#define SOCK_EXT_BINDDN 1 +#define SOCK_EXT_PEERNAME 2 +#define SOCK_EXT_SSF 4 + +extern FILE *opensock LDAP_P(( + const char *sockpath)); + +extern void sock_print_suffixes LDAP_P(( + FILE *fp, + BackendDB *bd)); + +extern void sock_print_conn LDAP_P(( + FILE *fp, + Connection *conn, + struct sockinfo *si)); + +extern int sock_read_and_send_results LDAP_P(( + Operation *op, + SlapReply *rs, + FILE *fp)); + +LDAP_END_DECL + +#endif diff --git a/servers/slapd/back-sock/bind.c b/servers/slapd/back-sock/bind.c new file mode 100644 index 0000000000..2c84bc68ab --- /dev/null +++ b/servers/slapd/back-sock/bind.c @@ -0,0 +1,76 @@ +/* bind.c - sock backend bind function */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 2007 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "portable.h" + +#include + +#include +#include + +#include "slap.h" +#include "back-sock.h" + +int +sock_back_bind( + Operation *op, + SlapReply *rs ) +{ + struct sockinfo *si = (struct sockinfo *) op->o_bd->be_private; + AttributeDescription *entry = slap_schema.si_ad_entry; + Entry e; + FILE *fp; + int rc; + + e.e_id = NOID; + e.e_name = op->o_req_dn; + e.e_nname = op->o_req_ndn; + e.e_attrs = NULL; + e.e_ocflags = 0; + e.e_bv.bv_len = 0; + e.e_bv.bv_val = NULL; + e.e_private = NULL; + + if ( ! access_allowed( op, &e, + entry, NULL, ACL_AUTH, NULL ) ) + { + send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, NULL ); + return -1; + } + + if ( (fp = opensock( si->si_sockpath )) == NULL ) { + send_ldap_error( op, rs, LDAP_OTHER, + "could not open socket" ); + return( -1 ); + } + + /* write out the request to the bind process */ + fprintf( fp, "BIND\n" ); + fprintf( fp, "msgid: %ld\n", (long) op->o_msgid ); + sock_print_conn( fp, op->o_conn, si ); + sock_print_suffixes( fp, op->o_bd ); + fprintf( fp, "dn: %s\n", op->o_req_dn.bv_val ); + fprintf( fp, "method: %d\n", op->oq_bind.rb_method ); + fprintf( fp, "credlen: %lu\n", op->oq_bind.rb_cred.bv_len ); + fprintf( fp, "cred: %s\n", op->oq_bind.rb_cred.bv_val ); /* XXX */ + fprintf( fp, "\n" ); + + /* read in the results and send them along */ + rc = sock_read_and_send_results( op, rs, fp ); + fclose( fp ); + + return( rc ); +} diff --git a/servers/slapd/back-sock/compare.c b/servers/slapd/back-sock/compare.c new file mode 100644 index 0000000000..73d138615e --- /dev/null +++ b/servers/slapd/back-sock/compare.c @@ -0,0 +1,80 @@ +/* compare.c - sock backend compare function */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 1998-2007 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "portable.h" + +#include + +#include +#include + +#include "slap.h" +#include "back-sock.h" + +int +sock_back_compare( + Operation *op, + SlapReply *rs ) +{ + struct sockinfo *si = (struct sockinfo *) op->o_bd->be_private; + AttributeDescription *entry = slap_schema.si_ad_entry; + Entry e; + FILE *fp; + + e.e_id = NOID; + e.e_name = op->o_req_dn; + e.e_nname = op->o_req_ndn; + e.e_attrs = NULL; + e.e_ocflags = 0; + e.e_bv.bv_len = 0; + e.e_bv.bv_val = NULL; + e.e_private = NULL; + + if ( ! access_allowed( op, &e, + entry, NULL, ACL_READ, NULL ) ) + { + send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, NULL ); + return -1; + } + + if ( (fp = opensock( si->si_sockpath )) == NULL ) { + send_ldap_error( op, rs, LDAP_OTHER, + "could not open socket" ); + return( -1 ); + } + + /* + * FIX ME: This should use LDIF routines so that binary + * values are properly dealt with + */ + + /* write out the request to the compare process */ + fprintf( fp, "COMPARE\n" ); + fprintf( fp, "msgid: %ld\n", (long) op->o_msgid ); + sock_print_conn( fp, op->o_conn, si ); + sock_print_suffixes( fp, op->o_bd ); + fprintf( fp, "dn: %s\n", op->o_req_dn.bv_val ); + fprintf( fp, "%s: %s\n", + op->oq_compare.rs_ava->aa_desc->ad_cname.bv_val, + op->oq_compare.rs_ava->aa_value.bv_val /* could be binary! */ ); + fclose( fp ); + + /* read in the result and send it along */ + sock_read_and_send_results( op, rs, fp ); + + fclose( fp ); + return( 0 ); +} diff --git a/servers/slapd/back-sock/config.c b/servers/slapd/back-sock/config.c new file mode 100644 index 0000000000..c9938dde2b --- /dev/null +++ b/servers/slapd/back-sock/config.c @@ -0,0 +1,78 @@ +/* config.c - sock backend configuration file routine */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 2007 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "portable.h" + +#include + +#include +#include + +#include "slap.h" +#include "back-sock.h" + +int +sock_back_db_config( + BackendDB *be, + const char *fname, + int lineno, + int argc, + char **argv +) +{ + struct sockinfo *si = (struct sockinfo *) be->be_private; + + if ( si == NULL ) { + fprintf( stderr, "%s: line %d: sock backend info is null!\n", + fname, lineno ); + return( 1 ); + } + + /* socketpath */ + if ( strcasecmp( argv[0], "socketpath" ) == 0 ) { + if ( argc != 2 ) { + fprintf( stderr, + "%s: line %d: exactly one parameter needed for \"socketpath\"\n", + fname, lineno ); + return( 1 ); + } + si->si_sockpath = ch_strdup( argv[1] ); + + /* extensions */ + } else if ( strcasecmp( argv[0], "extensions" ) == 0 ) { + int i; + for ( i=1; isi_extensions |= SOCK_EXT_BINDDN; + else if ( strcasecmp( argv[i], "peername" ) == 0 ) + si->si_extensions |= SOCK_EXT_PEERNAME; + else if ( strcasecmp( argv[i], "ssf" ) == 0 ) + si->si_extensions |= SOCK_EXT_SSF; + else { + fprintf( stderr, + "%s: line %d: unknown extension \"%s\"\n", + fname, lineno, argv[i] ); + return( 1 ); + } + } + + /* anything else */ + } else { + return SLAP_CONF_UNKNOWN; + } + + return 0; +} diff --git a/servers/slapd/back-sock/delete.c b/servers/slapd/back-sock/delete.c new file mode 100644 index 0000000000..940b37bf14 --- /dev/null +++ b/servers/slapd/back-sock/delete.c @@ -0,0 +1,71 @@ +/* delete.c - sock backend delete function */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 2007 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "portable.h" + +#include + +#include +#include + +#include "slap.h" +#include "back-sock.h" + +int +sock_back_delete( + Operation *op, + SlapReply *rs ) +{ + struct sockinfo *si = (struct sockinfo *) op->o_bd->be_private; + AttributeDescription *entry = slap_schema.si_ad_entry; + Entry e; + FILE *fp; + + e.e_id = NOID; + e.e_name = op->o_req_dn; + e.e_nname = op->o_req_ndn; + e.e_attrs = NULL; + e.e_ocflags = 0; + e.e_bv.bv_len = 0; + e.e_bv.bv_val = NULL; + e.e_private = NULL; + + if ( ! access_allowed( op, &e, + entry, NULL, ACL_WDEL, NULL ) ) + { + send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, NULL ); + return -1; + } + + if ( (fp = opensock( si->si_sockpath )) == NULL ) { + send_ldap_error( op, rs, LDAP_OTHER, + "could not open socket" ); + return( -1 ); + } + + /* write out the request to the delete process */ + fprintf( fp, "DELETE\n" ); + fprintf( fp, "msgid: %ld\n", (long) op->o_msgid ); + sock_print_conn( fp, op->o_conn, si ); + sock_print_suffixes( fp, op->o_bd ); + fprintf( fp, "dn: %s\n", op->o_req_dn.bv_val ); + fprintf( fp, "\n" ); + + /* read in the results and send them along */ + sock_read_and_send_results( op, rs, fp ); + fclose( fp ); + return( 0 ); +} diff --git a/servers/slapd/back-sock/init.c b/servers/slapd/back-sock/init.c new file mode 100644 index 0000000000..30f834513f --- /dev/null +++ b/servers/slapd/back-sock/init.c @@ -0,0 +1,92 @@ +/* init.c - initialize sock backend */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 2007 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "portable.h" + +#include + +#include + +#include "slap.h" +#include "back-sock.h" + +int +sock_back_initialize( + BackendInfo *bi +) +{ + bi->bi_open = 0; + bi->bi_config = 0; + bi->bi_close = 0; + bi->bi_destroy = 0; + + bi->bi_db_init = sock_back_db_init; + bi->bi_db_config = sock_back_db_config; + bi->bi_db_open = 0; + bi->bi_db_close = 0; + bi->bi_db_destroy = sock_back_db_destroy; + + bi->bi_op_bind = sock_back_bind; + bi->bi_op_unbind = sock_back_unbind; + bi->bi_op_search = sock_back_search; + bi->bi_op_compare = sock_back_compare; + bi->bi_op_modify = sock_back_modify; + bi->bi_op_modrdn = sock_back_modrdn; + bi->bi_op_add = sock_back_add; + bi->bi_op_delete = sock_back_delete; + bi->bi_op_abandon = 0; + + bi->bi_extended = 0; + + bi->bi_chk_referrals = 0; + + bi->bi_connection_init = 0; + bi->bi_connection_destroy = 0; + + return 0; +} + +int +sock_back_db_init( + Backend *be, + struct config_reply_s *cr +) +{ + struct sockinfo *si; + + si = (struct sockinfo *) ch_calloc( 1, sizeof(struct sockinfo) ); + + be->be_private = si; + + return si == NULL; +} + +int +sock_back_db_destroy( + Backend *be, + struct config_reply_s *cr +) +{ + free( be->be_private ); + return 0; +} + +#if SLAPD_SOCK == SLAPD_MOD_DYNAMIC + +/* conditionally define the init_module() function */ +SLAP_BACKEND_INIT_MODULE( sock ) + +#endif /* SLAPD_SOCK == SLAPD_MOD_DYNAMIC */ diff --git a/servers/slapd/back-sock/modify.c b/servers/slapd/back-sock/modify.c new file mode 100644 index 0000000000..d3db9c408c --- /dev/null +++ b/servers/slapd/back-sock/modify.c @@ -0,0 +1,102 @@ +/* modify.c - sock backend modify function */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 2007 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "portable.h" + +#include + +#include +#include + +#include "slap.h" +#include "back-sock.h" + +int +sock_back_modify( + Operation *op, + SlapReply *rs ) +{ + Modification *mod; + struct sockinfo *si = (struct sockinfo *) op->o_bd->be_private; + AttributeDescription *entry = slap_schema.si_ad_entry; + Modifications *ml = op->orm_modlist; + Entry e; + FILE *fp; + int i; + + e.e_id = NOID; + e.e_name = op->o_req_dn; + e.e_nname = op->o_req_ndn; + e.e_attrs = NULL; + e.e_ocflags = 0; + e.e_bv.bv_len = 0; + e.e_bv.bv_val = NULL; + e.e_private = NULL; + + if ( ! access_allowed( op, &e, + entry, NULL, ACL_WRITE, NULL ) ) + { + send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, NULL ); + return -1; + } + + if ( (fp = opensock( si->si_sockpath )) == NULL ) { + send_ldap_error( op, rs, LDAP_OTHER, + "could not open socket" ); + return( -1 ); + } + + /* write out the request to the modify process */ + fprintf( fp, "MODIFY\n" ); + fprintf( fp, "msgid: %ld\n", (long) op->o_msgid ); + sock_print_conn( fp, op->o_conn, si ); + sock_print_suffixes( fp, op->o_bd ); + fprintf( fp, "dn: %s\n", op->o_req_dn.bv_val ); + for ( ; ml != NULL; ml = ml->sml_next ) { + mod = &ml->sml_mod; + + /* FIXME: should use LDIF routines to deal with binary data */ + + switch ( mod->sm_op ) { + case LDAP_MOD_ADD: + fprintf( fp, "add: %s\n", mod->sm_desc->ad_cname.bv_val ); + break; + + case LDAP_MOD_DELETE: + fprintf( fp, "delete: %s\n", mod->sm_desc->ad_cname.bv_val ); + break; + + case LDAP_MOD_REPLACE: + fprintf( fp, "replace: %s\n", mod->sm_desc->ad_cname.bv_val ); + break; + } + + if( mod->sm_values != NULL ) { + for ( i = 0; mod->sm_values[i].bv_val != NULL; i++ ) { + fprintf( fp, "%s: %s\n", mod->sm_desc->ad_cname.bv_val, + mod->sm_values[i].bv_val /* binary! */ ); + } + } + + fprintf( fp, "-\n" ); + } + fprintf( fp, "\n" ); + + /* read in the results and send them along */ + sock_read_and_send_results( op, rs, fp ); + fclose( fp ); + return( 0 ); +} diff --git a/servers/slapd/back-sock/modrdn.c b/servers/slapd/back-sock/modrdn.c new file mode 100644 index 0000000000..7c68f75053 --- /dev/null +++ b/servers/slapd/back-sock/modrdn.c @@ -0,0 +1,77 @@ +/* modrdn.c - sock backend modrdn function */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 2007 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "portable.h" + +#include + +#include +#include + +#include "slap.h" +#include "back-sock.h" + +int +sock_back_modrdn( + Operation *op, + SlapReply *rs ) +{ + struct sockinfo *si = (struct sockinfo *) op->o_bd->be_private; + AttributeDescription *entry = slap_schema.si_ad_entry; + Entry e; + FILE *fp; + + e.e_id = NOID; + e.e_name = op->o_req_dn; + e.e_nname = op->o_req_ndn; + e.e_attrs = NULL; + e.e_ocflags = 0; + e.e_bv.bv_len = 0; + e.e_bv.bv_val = NULL; + e.e_private = NULL; + + if ( ! access_allowed( op, &e, entry, NULL, + op->oq_modrdn.rs_newSup ? ACL_WDEL : ACL_WRITE, + NULL ) ) + { + send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, NULL ); + return -1; + } + + if ( (fp = opensock( si->si_sockpath )) == NULL ) { + send_ldap_error( op, rs, LDAP_OTHER, + "could not open socket" ); + return( -1 ); + } + + /* write out the request to the modrdn process */ + fprintf( fp, "MODRDN\n" ); + fprintf( fp, "msgid: %ld\n", (long) op->o_msgid ); + sock_print_conn( fp, op->o_conn, si ); + sock_print_suffixes( fp, op->o_bd ); + fprintf( fp, "dn: %s\n", op->o_req_dn.bv_val ); + fprintf( fp, "newrdn: %s\n", op->oq_modrdn.rs_newrdn.bv_val ); + fprintf( fp, "deleteoldrdn: %d\n", op->oq_modrdn.rs_deleteoldrdn ? 1 : 0 ); + if ( op->oq_modrdn.rs_newSup != NULL ) { + fprintf( fp, "newSuperior: %s\n", op->oq_modrdn.rs_newSup->bv_val ); + } + fprintf( fp, "\n" ); + + /* read in the results and send them along */ + sock_read_and_send_results( op, rs, fp ); + fclose( fp ); + return( 0 ); +} diff --git a/servers/slapd/back-sock/opensock.c b/servers/slapd/back-sock/opensock.c new file mode 100644 index 0000000000..64d3231b82 --- /dev/null +++ b/servers/slapd/back-sock/opensock.c @@ -0,0 +1,66 @@ +/* opensock.c - open a unix domain socket */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 2007 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "portable.h" + +#include + +#include +#include +#include +#include + +#include "slap.h" +#include "back-sock.h" + +/* + * FIXME: count the number of concurrent open sockets (since each thread + * may open one). Perhaps block here if a soft limit is reached, and fail + * if a hard limit reached + */ + +FILE * +opensock( + const char *sockpath +) +{ + int fd; + FILE *fp; + struct sockaddr_un sockun; + + fd = socket(PF_UNIX, SOCK_STREAM, 0); + if ( fd < 0 ) { + Debug( LDAP_DEBUG_ANY, "socket create failed\n", 0, 0, 0 ); + return( NULL ); + } + + sockun.sun_family = AF_UNIX; + sprintf(sockun.sun_path, "%.*s", (int)(sizeof(sockun.sun_path)-1), + sockpath); + if ( connect( fd, (struct sockaddr *)&sockun, sizeof(sockun) ) < 0 ) { + Debug( LDAP_DEBUG_ANY, "socket connect(%s) failed\n", + sockpath ? sockpath : "", 0, 0 ); + return( NULL ); + } + + if ( ( fp = fdopen( fd, "r+" ) ) == NULL ) { + Debug( LDAP_DEBUG_ANY, "fdopen failed\n", 0, 0, 0 ); + close( fd ); + return( NULL ); + } + + return( fp ); +} diff --git a/servers/slapd/back-sock/proto-sock.h b/servers/slapd/back-sock/proto-sock.h new file mode 100644 index 0000000000..bc6c6f205e --- /dev/null +++ b/servers/slapd/back-sock/proto-sock.h @@ -0,0 +1,42 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 2007 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#ifndef _PROTO_SOCK_H +#define _PROTO_SOCK_H + +LDAP_BEGIN_DECL + +extern BI_init sock_back_initialize; + +extern BI_open sock_back_open; +extern BI_close sock_back_close; +extern BI_destroy sock_back_destroy; + +extern BI_db_init sock_back_db_init; +extern BI_db_destroy sock_back_db_destroy; +extern BI_db_config sock_back_db_config; + +extern BI_op_bind sock_back_bind; +extern BI_op_unbind sock_back_unbind; +extern BI_op_search sock_back_search; +extern BI_op_compare sock_back_compare; +extern BI_op_modify sock_back_modify; +extern BI_op_modrdn sock_back_modrdn; +extern BI_op_add sock_back_add; +extern BI_op_delete sock_back_delete; + +LDAP_END_DECL + +#endif /* _PROTO_SOCK_H */ diff --git a/servers/slapd/back-sock/result.c b/servers/slapd/back-sock/result.c new file mode 100644 index 0000000000..df380f20a7 --- /dev/null +++ b/servers/slapd/back-sock/result.c @@ -0,0 +1,149 @@ +/* result.c - sock backend result reading function */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 2007 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "portable.h" + +#include + +#include +#include +#include +#include + +#include "slap.h" +#include "back-sock.h" + +/* + * FIXME: make a RESULT section compulsory from the socket response. + * Otherwise, a partial/aborted response is treated as 'success'. + * This is a divergence from the back-shell protocol, but makes things + * more robust. + */ + +int +sock_read_and_send_results( + Operation *op, + SlapReply *rs, + FILE *fp ) +{ + int bsize, len; + char *buf, *bp; + char line[BUFSIZ]; + char ebuf[128]; + + /* read in the result and send it along */ + buf = (char *) ch_malloc( BUFSIZ ); + buf[0] = '\0'; + bsize = BUFSIZ; + bp = buf; + while ( !feof(fp) ) { + errno = 0; + if ( fgets( line, sizeof(line), fp ) == NULL ) { + if ( errno == EINTR ) continue; + + Debug( LDAP_DEBUG_ANY, "sock: fgets failed: %s (%d)\n", + AC_STRERROR_R(errno, ebuf, sizeof ebuf), errno, 0 ); + break; + } + + Debug( LDAP_DEBUG_SHELL, "sock search reading line (%s)\n", + line, 0, 0 ); + + /* ignore lines beginning with # (LDIFv1 comments) */ + if ( *line == '#' ) { + continue; + } + + /* ignore lines beginning with DEBUG: */ + if ( strncasecmp( line, "DEBUG:", 6 ) == 0 ) { + continue; + } + + len = strlen( line ); + while ( bp + len - buf > bsize ) { + size_t offset = bp - buf; + bsize += BUFSIZ; + buf = (char *) ch_realloc( buf, bsize ); + bp = &buf[offset]; + } + strcpy( bp, line ); + bp += len; + + /* line marked the end of an entry or result */ + if ( *line == '\n' ) { + if ( strncasecmp( buf, "RESULT", 6 ) == 0 ) { + break; + } + + if ( (rs->sr_entry = str2entry( buf )) == NULL ) { + Debug( LDAP_DEBUG_ANY, "str2entry(%s) failed\n", + buf, 0, 0 ); + } else { + rs->sr_attrs = op->oq_search.rs_attrs; + rs->sr_flags = REP_ENTRY_MODIFIABLE; + send_search_entry( op, rs ); + entry_free( rs->sr_entry ); + } + + bp = buf; + } + } + (void) str2result( buf, &rs->sr_err, (char **)&rs->sr_matched, (char **)&rs->sr_text ); + + /* otherwise, front end will send this result */ + if ( rs->sr_err != 0 || op->o_tag != LDAP_REQ_BIND ) { + send_ldap_result( op, rs ); + } + + free( buf ); + + return( rs->sr_err ); +} + +void +sock_print_suffixes( + FILE *fp, + Backend *be +) +{ + int i; + + for ( i = 0; be->be_suffix[i].bv_val != NULL; i++ ) { + fprintf( fp, "suffix: %s\n", be->be_suffix[i].bv_val ); + } +} + +void +sock_print_conn( + FILE *fp, + Connection *conn, + struct sockinfo *si +) +{ + if ( conn == NULL ) return; + + if( si->si_extensions & SOCK_EXT_BINDDN ) { + fprintf( fp, "binddn: %s\n", + conn->c_dn.bv_len ? conn->c_dn.bv_val : "" ); + } + if( si->si_extensions & SOCK_EXT_PEERNAME ) { + fprintf( fp, "peername: %s\n", + conn->c_peer_name.bv_len ? conn->c_peer_name.bv_val : "" ); + } + if( si->si_extensions & SOCK_EXT_SSF ) { + fprintf( fp, "ssf: %d\n", conn->c_ssf ); + } +} diff --git a/servers/slapd/back-sock/search.c b/servers/slapd/back-sock/search.c new file mode 100644 index 0000000000..995e4b8388 --- /dev/null +++ b/servers/slapd/back-sock/search.c @@ -0,0 +1,70 @@ +/* search.c - sock backend search function */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 2007 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "portable.h" + +#include + +#include +#include + +#include "slap.h" +#include "back-sock.h" + +/* + * FIXME: add a filterSearchResults option like back-perl has + */ + +int +sock_back_search( + Operation *op, + SlapReply *rs ) +{ + struct sockinfo *si = (struct sockinfo *) op->o_bd->be_private; + FILE *fp; + AttributeName *an; + + if ( (fp = opensock( si->si_sockpath )) == NULL ) { + send_ldap_error( op, rs, LDAP_OTHER, + "could not open socket" ); + return( -1 ); + } + + /* write out the request to the search process */ + fprintf( fp, "SEARCH\n" ); + fprintf( fp, "msgid: %ld\n", (long) op->o_msgid ); + sock_print_conn( fp, op->o_conn, si ); + sock_print_suffixes( fp, op->o_bd ); + fprintf( fp, "base: %s\n", op->o_req_dn.bv_val ); + fprintf( fp, "scope: %d\n", op->oq_search.rs_scope ); + fprintf( fp, "deref: %d\n", op->oq_search.rs_deref ); + fprintf( fp, "sizelimit: %d\n", op->oq_search.rs_slimit ); + fprintf( fp, "timelimit: %d\n", op->oq_search.rs_tlimit ); + fprintf( fp, "filter: %s\n", op->oq_search.rs_filterstr.bv_val ); + fprintf( fp, "attrsonly: %d\n", op->oq_search.rs_attrsonly ? 1 : 0 ); + fprintf( fp, "attrs:%s", op->oq_search.rs_attrs == NULL ? " all" : "" ); + for ( an = op->oq_search.rs_attrs; an && an->an_name.bv_val; an++ ) { + fprintf( fp, " %s", an->an_name.bv_val ); + } + fprintf( fp, "\n\n" ); /* end of attr line plus blank line */ + + /* read in the results and send them along */ + rs->sr_attrs = op->oq_search.rs_attrs; + sock_read_and_send_results( op, rs, fp ); + + fclose( fp ); + return( 0 ); +} diff --git a/servers/slapd/back-sock/searchexample.conf b/servers/slapd/back-sock/searchexample.conf new file mode 100644 index 0000000000..63d6ecd21f --- /dev/null +++ b/servers/slapd/back-sock/searchexample.conf @@ -0,0 +1,19 @@ +# $OpenLDAP$ +## This work is part of OpenLDAP Software . +## +## Copyright 2007 The OpenLDAP Foundation. +## All rights reserved. +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted only as authorized by the OpenLDAP +## Public License. +## +## A copy of this license is available in the file LICENSE in the +## top-level directory of the distribution or, alternatively, at +## . + +include /usr/local/etc/openldap/schema/core.schema + +database sock +suffix "dc=example,dc=com" +socketpath /tmp/example.sock diff --git a/servers/slapd/back-sock/searchexample.pl b/servers/slapd/back-sock/searchexample.pl new file mode 100644 index 0000000000..d15b03a5cf --- /dev/null +++ b/servers/slapd/back-sock/searchexample.pl @@ -0,0 +1,73 @@ +#!/usr/bin/perl -w -T + +# See: http://seamons.com/net_server/net_server.html + +package ExampleDB; + +use strict; +use vars qw(@ISA); +use Net::Server::PreFork; # any personality will do + +@ISA = qw(Net::Server::PreFork); + +ExampleDB->run( + port=>"/tmp/example.sock|unix" + #conf_file=>"/etc/example.conf" +); +exit; + +### over-ridden subs below +# The protocol is the same as back-shell + +sub process_request { + my $self = shift; + + eval { + + local $SIG{ALRM} = sub { die "Timed Out!\n" }; + my $timeout = 30; # give the user 30 seconds to type a line + alarm($timeout); + + my $request = ; + + if ($request eq "SEARCH\n") { + my %req = (); + while (my $line = ) { + chomp($line); + last if $line eq ""; + if ($line =~ /^([^:]+):\s*(.*)$/) { # FIXME: handle base64 encoded + $req{$1} = $2; + } + } + #sleep(2); # to test concurrency + print "dn: cn=test, dc=example, dc=com\n"; + print "cn: test\n"; + print "objectclass: cnobject\n"; + print "\n"; + print "RESULT\n"; + print "code: 0\n"; + print "info: answered by process $$\n"; + } + else { + print "RESULT\n"; + print "code: 53\n"; # unwillingToPerform + print "info: I don't implement $request"; + } + + }; + + return unless $@; + if( $@=~/timed out/i ){ + print "RESULT\n"; + print "code: 3\n"; # timeLimitExceeded + print "info: Timed out\n"; + } + else { + print "RESULT\n"; + print "code: 1\n"; # operationsError + print "info: $@\n"; # FIXME: remove CR/LF + } + +} + +1; diff --git a/servers/slapd/back-sock/unbind.c b/servers/slapd/back-sock/unbind.c new file mode 100644 index 0000000000..737cce6291 --- /dev/null +++ b/servers/slapd/back-sock/unbind.c @@ -0,0 +1,53 @@ +/* unbind.c - sock backend unbind function */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 2007 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "portable.h" + +#include + +#include +#include + +#include "slap.h" +#include "back-sock.h" + +int +sock_back_unbind( + Operation *op, + SlapReply *rs +) +{ + struct sockinfo *si = (struct sockinfo *) op->o_bd->be_private; + FILE *fp; + + if ( (fp = opensock( si->si_sockpath )) == NULL ) { + send_ldap_error( op, rs, LDAP_OTHER, + "could not open socket" ); + return( -1 ); + } + + /* write out the request to the unbind process */ + fprintf( fp, "UNBIND\n" ); + fprintf( fp, "msgid: %ld\n", (long) op->o_msgid ); + sock_print_conn( fp, op->o_conn, si ); + sock_print_suffixes( fp, op->o_bd ); + fprintf( fp, "\n" ); + + /* no response to unbind */ + fclose( fp ); + + return 0; +}