diff options
author | Petr Spacek <pspacek@redhat.com> | 2013-03-08 18:54:58 +0100 |
---|---|---|
committer | Martin Kosek <mkosek@redhat.com> | 2013-03-22 14:31:22 +0100 |
commit | 952a7ac9f55e09eeaa7a24400957aac684a616fb (patch) | |
tree | 3641375ac8daf2b7fd06cee459e031a1d8d911e0 | |
parent | 797baef1a433d14694fcb234c24828c1ad4019dc (diff) | |
download | freeipa-952a7ac9f55e09eeaa7a24400957aac684a616fb.tar.gz freeipa-952a7ac9f55e09eeaa7a24400957aac684a616fb.tar.xz freeipa-952a7ac9f55e09eeaa7a24400957aac684a616fb.zip |
Add 389 DS plugin for special idnsSOASerial attribute handling
Default value "1" is added to replicated idnsZone objects
if idnsSOASerial attribute is missing.
https://fedorahosted.org/freeipa/ticket/3347
Signed-off-by: Petr Spacek <pspacek@redhat.com>
-rw-r--r-- | daemons/configure.ac | 1 | ||||
-rw-r--r-- | daemons/ipa-slapi-plugins/Makefile.am | 1 | ||||
-rw-r--r-- | daemons/ipa-slapi-plugins/ipa-dns/Makefile.am | 40 | ||||
-rw-r--r-- | daemons/ipa-slapi-plugins/ipa-dns/ipa_dns.c | 211 | ||||
-rw-r--r-- | freeipa.spec.in | 2 |
5 files changed, 255 insertions, 0 deletions
diff --git a/daemons/configure.ac b/daemons/configure.ac index ae57d64ee..d3b6b19d1 100644 --- a/daemons/configure.ac +++ b/daemons/configure.ac @@ -334,6 +334,7 @@ AC_CONFIG_FILES([ ipa-sam/Makefile ipa-slapi-plugins/Makefile ipa-slapi-plugins/ipa-cldap/Makefile + ipa-slapi-plugins/ipa-dns/Makefile ipa-slapi-plugins/ipa-enrollment/Makefile ipa-slapi-plugins/ipa-lockout/Makefile ipa-slapi-plugins/ipa-pwd-extop/Makefile diff --git a/daemons/ipa-slapi-plugins/Makefile.am b/daemons/ipa-slapi-plugins/Makefile.am index c79e68db1..08c7558c8 100644 --- a/daemons/ipa-slapi-plugins/Makefile.am +++ b/daemons/ipa-slapi-plugins/Makefile.am @@ -2,6 +2,7 @@ NULL = SUBDIRS = \ ipa-cldap \ + ipa-dns \ ipa-enrollment \ ipa-lockout \ ipa-modrdn \ diff --git a/daemons/ipa-slapi-plugins/ipa-dns/Makefile.am b/daemons/ipa-slapi-plugins/ipa-dns/Makefile.am new file mode 100644 index 000000000..319c6676e --- /dev/null +++ b/daemons/ipa-slapi-plugins/ipa-dns/Makefile.am @@ -0,0 +1,40 @@ +NULL = + +PLUGIN_COMMON_DIR=../common + +INCLUDES = \ + -I. \ + -I$(srcdir) \ + -I$(PLUGIN_COMMON_DIR) \ + -I/usr/include/dirsrv \ + -DPREFIX=\""$(prefix)"\" \ + -DBINDIR=\""$(bindir)"\" \ + -DLIBDIR=\""$(libdir)"\" \ + -DLIBEXECDIR=\""$(libexecdir)"\" \ + -DDATADIR=\""$(datadir)"\" \ + $(AM_CFLAGS) \ + $(LDAP_CFLAGS) \ + $(WARN_CFLAGS) \ + $(NULL) + +plugindir = $(libdir)/dirsrv/plugins +plugin_LTLIBRARIES = \ + libipa_dns.la \ + $(NULL) + +libipa_dns_la_SOURCES = \ + ipa_dns.c \ + $(NULL) + +libipa_dns_la_LDFLAGS = -avoid-version + +libipa_dns_la_LIBADD = \ + $(LDAP_LIBS) \ + $(NULL) + +EXTRA_DIST = \ + $(NULL) + +MAINTAINERCLEANFILES = \ + *~ \ + Makefile.in diff --git a/daemons/ipa-slapi-plugins/ipa-dns/ipa_dns.c b/daemons/ipa-slapi-plugins/ipa-dns/ipa_dns.c new file mode 100644 index 000000000..0769a54aa --- /dev/null +++ b/daemons/ipa-slapi-plugins/ipa-dns/ipa_dns.c @@ -0,0 +1,211 @@ +/** BEGIN COPYRIGHT BLOCK + * This Program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; version 2 of the License. + * + * This Program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. + * Copyright (C) 2013 Red Hat, Inc. + * + * Authors: + * original authors of 389 example ldap/servers/slapd/test-plugins/testpreop.c + * Petr Spacek <pspacek@redhat.com> + * + * All rights reserved. + * + * END COPYRIGHT BLOCK **/ + +/* + * This is 389 DS plug-in with supporting functions for IPA-integrated DNS. + * + * To test this plug-in, stop the server, edit the dse.ldif file + * (in the <server_root>/slapd-<server_id>/config directory) + * and add the following lines before restarting the server: + * + * dn: cn=IPA DNS,cn=plugins,cn=config + * objectClass: top + * objectClass: nsslapdPlugin + * objectClass: extensibleObject + * cn: IPA DNS + * nsslapd-pluginDescription: IPA DNS support plugin + * nsslapd-pluginEnabled: on + * nsslapd-pluginId: ipa_dns + * nsslapd-pluginInitfunc: ipadns_init + * nsslapd-pluginPath: libipa_dns.so + * nsslapd-pluginType: preoperation + * nsslapd-pluginVendor: Red Hat, Inc. + * nsslapd-pluginVersion: 1.0 + * nsslapd-plugin-depends-on-type: database + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> +#include <string.h> +#include "slapi-plugin.h" +#include "util.h" + +#define IPA_PLUGIN_NAME "ipa_dns" +#define IPADNS_CLASS_ZONE "idnsZone" +#define IPADNS_ATTR_SERIAL "idnsSOASerial" +#define IPADNS_DEFAULT_SERIAL "1" + +#define EFALSE 0 +#define ETRUE 1 + +Slapi_PluginDesc ipadns_desc = { IPA_PLUGIN_NAME, "Red Hat, Inc.", "1.0", + "IPA DNS support plugin" }; + +/* Global variable with "constant" = IPADNS_ZONE_SERIAL. */ +Slapi_Value *value_zone = NULL; + +/** + * Determine if given entry represents IPA DNS zone. + * + * \return \c 0 when objectClass idnsZone is not present in the entry. + * \return \c 1 when objectClass idnsZone is present in the entry. + * \return \c -1 when some error occurred. + */ +int +ipadns_entry_iszone( Slapi_Entry *entry ) { + Slapi_Attr *obj_class = NULL; + Slapi_Value *value = NULL; + char *dn = NULL; + int hint = 0; + + dn = slapi_entry_get_dn( entry ); + + if ( slapi_entry_attr_find( entry, SLAPI_ATTR_OBJECTCLASS, &obj_class ) + != 0) { + LOG( "Object without objectClass encountered: entry '%s'\n", + dn ); + return EFAIL; + } + + if ( slapi_attr_first_value( obj_class, &value ) != 0 ) { + LOG( "Cannot iterate over objectClass values in entry '%s'\n", + dn ); + return EOK; + } + + do { + if ( slapi_value_compare( obj_class, value, value_zone ) == 0 ) + return ETRUE; /* Entry is a DNS zone */ + + hint = slapi_attr_next_value( obj_class, hint, &value ); + } while ( hint != -1 ); + + return EFALSE; /* Entry is not a DNS zone */ +} + +/** + * The server calls this plug-in function before executing LDAP ADD operation. + * + * ipadns_add function adds default value to idnsSOAserial attribute + * in idnsZone objects if the the attribute is not present. + * + * Default value is added only to objects coming from other servers + * via replication. + */ +int +ipadns_add( Slapi_PBlock *pb ) +{ + Slapi_Entry *e = NULL; + Slapi_Attr *a = NULL; + char *dn = NULL; + int cnt; + int ret; + int is_repl_op; + + if ( slapi_pblock_get( pb, SLAPI_IS_REPLICATED_OPERATION, + &is_repl_op ) != 0 ) { + LOG_FATAL( "slapi_pblock_get SLAPI_IS_REPLICATED_OPERATION " + "failed!?\n" ); + return EFAIL; + } + + /* Mangle only ADDs coming from replication. */ + if ( !is_repl_op ) + return EOK; + + /* Get the entry that is about to be added. */ + if ( slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &e ) != 0 ) { + LOG( "Could not get entry\n" ); + return EFAIL; + } + dn = slapi_entry_get_dn( e ); + + /* Do nothing if entry doesn't represent IPA DNS zone. */ + ret = ipadns_entry_iszone( e ); + if ( ret == EFALSE ) + return EOK; + else if ( ret == EFAIL ) { + LOG( "Could not check objectClasses in entry '%s'\n", dn ); + return EFAIL; /* TODO: Should I return OK to not block DS? */ + } + + /* Do nothing if the entry already has idnsSOASerial attribute set + * and a value is present. */ + if ( slapi_entry_attr_find( e, IPADNS_ATTR_SERIAL, &a ) == 0 ) { + if ( slapi_attr_get_numvalues( a, &cnt ) != 0 ) { + LOG( "Could not get value count for attribute '%s' " + "in entry '%s'\n", IPADNS_ATTR_SERIAL, dn ); + return EFAIL; + } else if ( cnt != 0 ) { + return EOK; + } + } + + if ( slapi_entry_add_string( e, IPADNS_ATTR_SERIAL, + IPADNS_DEFAULT_SERIAL ) != 0 ) { + LOG( "Could not add default SOA serial to entry '%s'\n", dn ); + return EFAIL; + } + + return EOK; /* allow the operation to continue */ +} + +static int +ipadns_close( Slapi_PBlock *pb ) +{ + ( void ) pb; + if ( value_zone ) + slapi_value_free( &value_zone ); + + return EOK; +} + +/* Initialization function. */ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int +ipadns_init( Slapi_PBlock *pb ) +{ + /* Register the two pre-operation plug-in functions, + and specify the server plug-in version. */ + if ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, + SLAPI_PLUGIN_VERSION_03 ) != 0 || + slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, + (void *)&ipadns_desc ) != 0 || + slapi_pblock_set( pb, SLAPI_PLUGIN_CLOSE_FN, + (void *) ipadns_close ) != 0 || + slapi_pblock_set( pb, SLAPI_PLUGIN_PRE_ADD_FN, + (void *) ipadns_add ) != 0 ) { + LOG_FATAL( "Failed to set version and function\n" ); + return EFAIL; + } + + value_zone = slapi_value_new_string( IPADNS_CLASS_ZONE ); + + return EOK; +} diff --git a/freeipa.spec.in b/freeipa.spec.in index 1a390648c..f864cb2ad 100644 --- a/freeipa.spec.in +++ b/freeipa.spec.in @@ -341,6 +341,7 @@ rm %{buildroot}/%{plugin_dir}/libipa_uuid.la rm %{buildroot}/%{plugin_dir}/libipa_modrdn.la rm %{buildroot}/%{plugin_dir}/libipa_lockout.la rm %{buildroot}/%{plugin_dir}/libipa_cldap.la +rm %{buildroot}/%{plugin_dir}/libipa_dns.la rm %{buildroot}/%{plugin_dir}/libipa_sidgen.la rm %{buildroot}/%{plugin_dir}/libipa_sidgen_task.la rm %{buildroot}/%{plugin_dir}/libipa_extdom_extop.la @@ -667,6 +668,7 @@ fi %attr(755,root,root) %{plugin_dir}/libipa_modrdn.so %attr(755,root,root) %{plugin_dir}/libipa_lockout.so %attr(755,root,root) %{plugin_dir}/libipa_cldap.so +%attr(755,root,root) %{plugin_dir}/libipa_dns.so %attr(755,root,root) %{plugin_dir}/libipa_range_check.so %dir %{_localstatedir}/lib/ipa %attr(700,root,root) %dir %{_localstatedir}/lib/ipa/sysrestore |