On Tue, 2014-07-01 at 14:24 +0200, Martin Basti wrote:
> Ticket: https://fedorahosted.org/freeipa/ticket/4413
> Patches attached
> _______________________________________________
> Freeipa-devel mailing list
> Freeipa-devel@redhat.com
> https://www.redhat.com/mailman/listinfo/freeipa-devel

Rebased patches attached

-- 
Martin^2 Basti
>From e9156fea72f0f6fcea64ac26696a7c6256f73ab6 Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
Date: Mon, 30 Jun 2014 17:17:02 +0200
Subject: [PATCH 1/3] Remove NSEC3PARAM record

Ticket: https://fedorahosted.org/freeipa/ticket/4413
---
 ACI.txt                                 |  4 +--
 API.txt                                 | 12 ++-----
 VERSION                                 |  4 +--
 install/share/60ipadns.ldif             |  2 +-
 install/ui/src/freeipa/dns.js           | 16 +--------
 install/updates/40-dns.update           |  2 +-
 ipalib/plugins/dns.py                   | 48 ++-----------------------
 ipatests/test_xmlrpc/test_dns_plugin.py | 62 ---------------------------------
 8 files changed, 12 insertions(+), 138 deletions(-)

diff --git a/ACI.txt b/ACI.txt
index 8e73c5c8541154e73c201994de828aa43c3777b1..b8dfb56a2abea937823cdaed08322dea3dc0c0ef 100644
--- a/ACI.txt
+++ b/ACI.txt
@@ -39,11 +39,11 @@ aci: (targetattr = "idnsallowsyncptr || idnsforwarders || idnsforwardpolicy || i
 dn: cn=System: Add DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example
 aci: (target = "ldap:///idnsname=*,cn=dns,dc=ipa,dc=example";)(version 3.0;acl "permission:System: Add DNS Entries";allow (add) groupdn = "ldap:///cn=System: Add DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example";)
 dn: cn=System: Read DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example
-aci: (targetattr = "a6record || aaaarecord || afsdbrecord || arecord || certrecord || cn || cnamerecord || dlvrecord || dnamerecord || dnsclass || dnsttl || dsrecord || hinforecord || idnsallowdynupdate || idnsallowquery || idnsallowsyncptr || idnsallowtransfer || idnsforwarders || idnsforwardpolicy || idnsname || idnssecinlinesigning || idnssoaexpire || idnssoaminimum || idnssoamname || idnssoarefresh || idnssoaretry || idnssoarname || idnssoaserial || idnsupdatepolicy || idnszoneactive || keyrecord || kxrecord || locrecord || managedby || mdrecord || minforecord || mxrecord || naptrrecord || nsec3paramrecord || nsecrecord || nsrecord || nxtrecord || objectclass || ptrrecord || rrsigrecord || sigrecord || srvrecord || sshfprecord || tlsarecord || txtrecord")(target = "ldap:///idnsname=*,cn=dns,dc=ipa,dc=example";)(version 3.0;acl "permission:System: Read DNS Entries";allow (compare,read,search) groupdn = "ldap:///cn=System: Read DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example";)
+aci: (targetattr = "a6record || aaaarecord || afsdbrecord || arecord || certrecord || cn || cnamerecord || dlvrecord || dnamerecord || dnsclass || dnsttl || dsrecord || hinforecord || idnsallowdynupdate || idnsallowquery || idnsallowsyncptr || idnsallowtransfer || idnsforwarders || idnsforwardpolicy || idnsname || idnssecinlinesigning || idnssoaexpire || idnssoaminimum || idnssoamname || idnssoarefresh || idnssoaretry || idnssoarname || idnssoaserial || idnsupdatepolicy || idnszoneactive || keyrecord || kxrecord || locrecord || managedby || mdrecord || minforecord || mxrecord || naptrrecord || nsecrecord || nsrecord || nxtrecord || objectclass || ptrrecord || rrsigrecord || sigrecord || srvrecord || sshfprecord || tlsarecord || txtrecord")(target = "ldap:///idnsname=*,cn=dns,dc=ipa,dc=example";)(version 3.0;acl "permission:System: Read DNS Entries";allow (compare,read,search) groupdn = "ldap:///cn=System: Read DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example";)
 dn: cn=System: Remove DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example
 aci: (target = "ldap:///idnsname=*,cn=dns,dc=ipa,dc=example";)(version 3.0;acl "permission:System: Remove DNS Entries";allow (delete) groupdn = "ldap:///cn=System: Remove DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example";)
 dn: cn=System: Update DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example
-aci: (targetattr = "a6record || aaaarecord || afsdbrecord || arecord || certrecord || cn || cnamerecord || dlvrecord || dnamerecord || dnsclass || dnsttl || dsrecord || hinforecord || idnsallowdynupdate || idnsallowquery || idnsallowsyncptr || idnsallowtransfer || idnsforwarders || idnsforwardpolicy || idnsname || idnssecinlinesigning || idnssoaexpire || idnssoaminimum || idnssoamname || idnssoarefresh || idnssoaretry || idnssoarname || idnssoaserial || idnsupdatepolicy || idnszoneactive || keyrecord || kxrecord || locrecord || managedby || mdrecord || minforecord || mxrecord || naptrrecord || nsec3paramrecord || nsecrecord || nsrecord || nxtrecord || ptrrecord || rrsigrecord || sigrecord || srvrecord || sshfprecord || tlsarecord || txtrecord")(target = "ldap:///idnsname=*,cn=dns,dc=ipa,dc=example";)(version 3.0;acl "permission:System: Update DNS Entries";allow (write) groupdn = "ldap:///cn=System: Update DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example";)
+aci: (targetattr = "a6record || aaaarecord || afsdbrecord || arecord || certrecord || cn || cnamerecord || dlvrecord || dnamerecord || dnsclass || dnsttl || dsrecord || hinforecord || idnsallowdynupdate || idnsallowquery || idnsallowsyncptr || idnsallowtransfer || idnsforwarders || idnsforwardpolicy || idnsname || idnssecinlinesigning || idnssoaexpire || idnssoaminimum || idnssoamname || idnssoarefresh || idnssoaretry || idnssoarname || idnssoaserial || idnsupdatepolicy || idnszoneactive || keyrecord || kxrecord || locrecord || managedby || mdrecord || minforecord || mxrecord || naptrrecord || nsecrecord || nsrecord || nxtrecord || ptrrecord || rrsigrecord || sigrecord || srvrecord || sshfprecord || tlsarecord || txtrecord")(target = "ldap:///idnsname=*,cn=dns,dc=ipa,dc=example";)(version 3.0;acl "permission:System: Update DNS Entries";allow (write) groupdn = "ldap:///cn=System: Update DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example";)
 dn: cn=System: Add Groups,cn=permissions,cn=pbac,dc=ipa,dc=example
 aci: (targetfilter = "(|(objectclass=ipausergroup)(objectclass=posixgroup))")(version 3.0;acl "permission:System: Add Groups";allow (add) groupdn = "ldap:///cn=System: Add Groups,cn=permissions,cn=pbac,dc=ipa,dc=example";)
 dn: cn=System: Modify Group Membership,cn=permissions,cn=pbac,dc=ipa,dc=example
diff --git a/API.txt b/API.txt
index dedc80edb5afdfea343e1d912c947e501dffd098..24eff072285612476e5088b42d6d5967da4b103d 100644
--- a/API.txt
+++ b/API.txt
@@ -799,7 +799,7 @@ output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDA
 output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: PrimaryKey('value', None, None)
 command: dnsrecord_add
-args: 2,105,3
+args: 2,101,3
 arg: DNSNameParam('dnszoneidnsname', cli_name='dnszone', multivalue=False, only_absolute=True, primary_key=True, query=True, required=True)
 arg: DNSNameParam('idnsname', attribute=True, cli_name='name', multivalue=False, primary_key=True, required=True)
 option: Str('a6_part_data', attribute=False, cli_name='a6_data', multivalue=False, option_group=u'A6 Record', required=False)
@@ -870,10 +870,6 @@ option: Str('naptr_part_replacement', attribute=False, cli_name='naptr_replaceme
 option: Str('naptr_part_service', attribute=False, cli_name='naptr_service', multivalue=False, option_group=u'NAPTR Record', required=False)
 option: NAPTRRecord('naptrrecord', attribute=True, cli_name='naptr_rec', csv=True, multivalue=True, option_group=u'NAPTR Record', required=False)
 option: DNSNameParam('ns_part_hostname', attribute=False, cli_name='ns_hostname', multivalue=False, option_group=u'NS Record', required=False)
-option: Int('nsec3param_part_algorithm', attribute=False, cli_name='nsec3param_algorithm', maxvalue=255, minvalue=0, multivalue=False, option_group=u'NSEC3PARAM Record', required=False)
-option: Int('nsec3param_part_flags', attribute=False, cli_name='nsec3param_flags', default=0, maxvalue=255, minvalue=0, multivalue=False, option_group=u'NSEC3PARAM Record', required=False)
-option: Int('nsec3param_part_iterations', attribute=False, cli_name='nsec3param_iterations', maxvalue=65535, minvalue=0, multivalue=False, option_group=u'NSEC3PARAM Record', required=False)
-option: Str('nsec3param_part_salt', attribute=False, cli_name='nsec3param_salt', default=u'-', minlength=1, multivalue=False, option_group=u'NSEC3PARAM Record', pattern='^([0-9a-fA-F]+|-)$', required=False)
 option: NSEC3PARAMRecord('nsec3paramrecord', attribute=True, cli_name='nsec3param_rec', csv=True, multivalue=True, option_group=u'NSEC3PARAM Record', required=False)
 option: NSEC3Record('nsec3record', attribute=True, cli_name='nsec3_rec', csv=True, multivalue=True, option_group=u'NSEC3 Record', required=False)
 option: NSECRecord('nsecrecord', attribute=True, cli_name='nsec_rec', csv=True, multivalue=True, option_group=u'NSEC Record', required=False)
@@ -1020,7 +1016,7 @@ output: ListOfEntries('result', (<type 'list'>, <type 'tuple'>), Gettext('A list
 output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: Output('truncated', <type 'bool'>, None)
 command: dnsrecord_mod
-args: 2,105,3
+args: 2,101,3
 arg: DNSNameParam('dnszoneidnsname', cli_name='dnszone', multivalue=False, only_absolute=True, primary_key=True, query=True, required=True)
 arg: DNSNameParam('idnsname', attribute=True, cli_name='name', multivalue=False, primary_key=True, query=True, required=True)
 option: Str('a6_part_data', attribute=False, autofill=False, cli_name='a6_data', multivalue=False, option_group=u'A6 Record', required=False)
@@ -1089,10 +1085,6 @@ option: Str('naptr_part_replacement', attribute=False, autofill=False, cli_name=
 option: Str('naptr_part_service', attribute=False, autofill=False, cli_name='naptr_service', multivalue=False, option_group=u'NAPTR Record', required=False)
 option: NAPTRRecord('naptrrecord', attribute=True, autofill=False, cli_name='naptr_rec', csv=True, multivalue=True, option_group=u'NAPTR Record', required=False)
 option: DNSNameParam('ns_part_hostname', attribute=False, autofill=False, cli_name='ns_hostname', multivalue=False, option_group=u'NS Record', required=False)
-option: Int('nsec3param_part_algorithm', attribute=False, autofill=False, cli_name='nsec3param_algorithm', maxvalue=255, minvalue=0, multivalue=False, option_group=u'NSEC3PARAM Record', required=False)
-option: Int('nsec3param_part_flags', attribute=False, autofill=False, cli_name='nsec3param_flags', default=0, maxvalue=255, minvalue=0, multivalue=False, option_group=u'NSEC3PARAM Record', required=False)
-option: Int('nsec3param_part_iterations', attribute=False, autofill=False, cli_name='nsec3param_iterations', maxvalue=65535, minvalue=0, multivalue=False, option_group=u'NSEC3PARAM Record', required=False)
-option: Str('nsec3param_part_salt', attribute=False, autofill=False, cli_name='nsec3param_salt', default=u'-', minlength=1, multivalue=False, option_group=u'NSEC3PARAM Record', pattern='^([0-9a-fA-F]+|-)$', required=False)
 option: NSEC3PARAMRecord('nsec3paramrecord', attribute=True, autofill=False, cli_name='nsec3param_rec', csv=True, multivalue=True, option_group=u'NSEC3PARAM Record', required=False)
 option: NSEC3Record('nsec3record', attribute=True, autofill=False, cli_name='nsec3_rec', csv=True, multivalue=True, option_group=u'NSEC3 Record', required=False)
 option: NSECRecord('nsecrecord', attribute=True, autofill=False, cli_name='nsec_rec', csv=True, multivalue=True, option_group=u'NSEC Record', required=False)
diff --git a/VERSION b/VERSION
index 4a3cfa63ebb6c7f758374f224a111703c2b159c1..99df8a86e055bd197f06747779f3ba8203b8610a 100644
--- a/VERSION
+++ b/VERSION
@@ -89,5 +89,5 @@ IPA_DATA_VERSION=20100614120000
 #                                                      #
 ########################################################
 IPA_API_VERSION_MAJOR=2
-IPA_API_VERSION_MINOR=97
-# Last change: mbasti - New record type added: TLSA
+IPA_API_VERSION_MINOR=98
+# Last change: mbasti - Remove NSEC3PARAM record
diff --git a/install/share/60ipadns.ldif b/install/share/60ipadns.ldif
index 6cc08725c4b2e3ea683f8bf8860d85c41f675d98..6044a7a863659b372e552f62610c26830cb4bc8a 100644
--- a/install/share/60ipadns.ldif
+++ b/install/share/60ipadns.ldif
@@ -53,7 +53,7 @@ attributeTypes: ( 2.16.840.1.113730.3.8.5.15 NAME 'idnsForwarders' DESC 'list of
 attributeTypes: ( 2.16.840.1.113730.3.8.5.16 NAME 'idnsZoneRefresh' DESC 'zone refresh interval' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'IPA v2' )
 attributeTypes: ( 2.16.840.1.113730.3.8.5.17 NAME 'idnsPersistentSearch' DESC 'allow persistent searches' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE X-ORIGIN 'IPA v2' )
 attributeTypes: ( 2.16.840.1.113730.3.8.5.18 NAME 'idnsSecInlineSigning' DESC 'allow inline DNSSEC signing' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE X-ORIGIN 'IPA v4.0' )
-objectClasses: ( 2.16.840.1.113730.3.8.6.0 NAME 'idnsRecord' DESC 'dns Record, usually a host' SUP top STRUCTURAL MUST idnsName MAY ( idnsAllowDynUpdate $ dNSTTL $ dNSClass $ aRecord $ aAAARecord $ a6Record $ nSRecord $ cNAMERecord $ pTRRecord $ sRVRecord $ tXTRecord $ mXRecord $ mDRecord $ hInfoRecord $ mInfoRecord $ aFSDBRecord $ SigRecord $ KeyRecord $ LocRecord $ nXTRecord $ nAPTRRecord $ kXRecord $ certRecord $ dNameRecord $ dSRecord $ sSHFPRecord $ rRSIGRecord $ nSECRecord $ nSEC3PARAMRecord $ DLVRecord $ TLSARecord ) )
+objectClasses: ( 2.16.840.1.113730.3.8.6.0 NAME 'idnsRecord' DESC 'dns Record, usually a host' SUP top STRUCTURAL MUST idnsName MAY ( idnsAllowDynUpdate $ dNSTTL $ dNSClass $ aRecord $ aAAARecord $ a6Record $ nSRecord $ cNAMERecord $ pTRRecord $ sRVRecord $ tXTRecord $ mXRecord $ mDRecord $ hInfoRecord $ mInfoRecord $ aFSDBRecord $ SigRecord $ KeyRecord $ LocRecord $ nXTRecord $ nAPTRRecord $ kXRecord $ certRecord $ dNameRecord $ dSRecord $ sSHFPRecord $ rRSIGRecord $ nSECRecord $ DLVRecord $ TLSARecord ) )
 objectClasses: ( 2.16.840.1.113730.3.8.6.1 NAME 'idnsZone' DESC 'Zone class' SUP idnsRecord STRUCTURAL MUST ( idnsZoneActive $ idnsSOAmName $ idnsSOArName $ idnsSOAserial $ idnsSOArefresh $ idnsSOAretry $ idnsSOAexpire $ idnsSOAminimum ) MAY ( idnsUpdatePolicy $ idnsAllowQuery $ idnsAllowTransfer $ idnsAllowSyncPTR $ idnsForwardPolicy $ idnsForwarders $ idnsSecInlineSigning ) )
 objectClasses: ( 2.16.840.1.113730.3.8.6.2 NAME 'idnsConfigObject' DESC 'DNS global config options' STRUCTURAL MAY ( idnsForwardPolicy $ idnsForwarders $ idnsAllowSyncPTR $ idnsZoneRefresh $ idnsPersistentSearch ) )
 objectClasses: ( 2.16.840.1.113730.3.8.12.18 NAME 'ipaDNSZone' SUP top AUXILIARY MUST idnsName MAY managedBy X-ORIGIN 'IPA v3' )
diff --git a/install/ui/src/freeipa/dns.js b/install/ui/src/freeipa/dns.js
index c7143ca91fef9bbc372654080fe899be1ae8367f..c3b79a50fba43ac61e0a86e47accf99dbcbd720f 100644
--- a/install/ui/src/freeipa/dns.js
+++ b/install/ui/src/freeipa/dns.js
@@ -1076,20 +1076,6 @@ IPA.dns.get_record_metadata = function() {
             columns: ['ns_part_hostname']
         },
         {
-            name: 'nsec3paramrecord',
-            attributes: [
-                'nsec3param_part_algorithm',
-                'nsec3param_part_flags',
-                'nsec3param_part_iterations',
-                'nsec3param_part_salt'
-            ],
-            adder_attributes: [],
-            columns: [
-                'nsec3param_part_algorithm', 'nsec3param_part_flags',
-                'nsec3param_part_iterations', 'nsec3param_part_salt'
-            ]
-        },
-        {
             name: 'ptrrecord',
             attributes: [
                 'ptr_part_hostname'
@@ -1524,7 +1510,7 @@ IPA.dns_record_types = function() {
     //only supported
     var attrs = ['A', 'AAAA', 'A6', 'AFSDB', 'CERT', 'CNAME', 'DNAME',
                    'DS', 'DLV', 'KX', 'LOC', 'MX', 'NAPTR', 'NS',
-                   'NSEC3PARAM', 'PTR', 'SRV', 'SSHFP', 'TLSA', 'TXT'];
+                   'PTR', 'SRV', 'SSHFP', 'TLSA', 'TXT'];
     var record_types = [];
     for (var i=0; i<attrs.length; i++) {
         var attr = attrs[i];
diff --git a/install/updates/40-dns.update b/install/updates/40-dns.update
index 68f654d5c8ecc80c8c2ba982dbce1f3c32fe7762..70172ef3321d061c3b182ccecff37f83fb4cff7d 100644
--- a/install/updates/40-dns.update
+++ b/install/updates/40-dns.update
@@ -10,7 +10,7 @@ addifexist: aci:'(targetattr = "idnsname || cn || idnsallowdynupdate || dnsttl |
 dn: cn=dns, $SUFFIX
 replace:aci:'(targetattr = "*")(version 3.0; acl "No access to DNS tree without a permission"; deny (read,search,compare) (groupdn != "ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX";) and (groupdn != "ldap:///cn=Read DNS Entries,cn=permissions,cn=pbac,$SUFFIX");)::(targetattr = "*")(version 3.0; acl "Read DNS entries from a zone"; allow (read,search,compare) userattr = "parent[0,1].managedby#GROUPDN";)'
 replace:aci:'(targetattr = "*")(version 3.0; acl "Allow read access"; allow (read,search,compare) groupdn = "ldap:///cn=Read DNS Entries,cn=permissions,cn=pbac,$SUFFIX" or userattr = "parent[0,1].managedby#GROUPDN";)::(targetattr = "*")(version 3.0; acl "Read DNS entries from a zone"; allow (read,search,compare) userattr = "parent[0,1].managedby#GROUPDN";)'
-replace:aci:'(targetattr = "idnsname || cn || idnsallowdynupdate || dnsttl || dnsclass || arecord || aaaarecord || a6record || nsrecord || cnamerecord || ptrrecord || srvrecord || txtrecord || mxrecord || mdrecord || hinforecord || minforecord || afsdbrecord || sigrecord || keyrecord || locrecord || nxtrecord || naptrrecord || kxrecord || certrecord || dnamerecord || dsrecord || sshfprecord || rrsigrecord || nsecrecord || idnsname || idnszoneactive || idnssoamname || idnssoarname || idnssoaserial || idnssoarefresh || idnssoaretry || idnssoaexpire || idnssoaminimum || idnsupdatepolicy || idnsallowquery || idnsallowtransfer || idnsallowsyncptr || idnsforwardpolicy || idnsforwarders")(target = "ldap:///idnsname=*,cn=dns,$SUFFIX";)(version 3.0;acl "Update DNS entries in a zone";allow (write) userattr = "parent[0,1].managedby#GROUPDN";)::(targetattr = "idnsname || cn || idnsallowdynupdate || dnsttl || dnsclass || arecord || aaaarecord || a6record || nsrecord || cnamerecord || ptrrecord || srvrecord || txtrecord || mxrecord || mdrecord || hinforecord || minforecord || afsdbrecord || sigrecord || keyrecord || locrecord || nxtrecord || naptrrecord || kxrecord || certrecord || dnamerecord || dsrecord || sshfprecord || rrsigrecord || nsecrecord || idnsname || idnszoneactive || idnssoamname || idnssoarname || idnssoaserial || idnssoarefresh || idnssoaretry || idnssoaexpire || idnssoaminimum || idnsupdatepolicy || idnsallowquery || idnsallowtransfer || idnsallowsyncptr || idnsforwardpolicy || idnsforwarders || nsec3paramrecord || dlvrecord || idnssecinlinesigning ")(target = "ldap:///idnsname=*,cn=dns,$SUFFIX";)(version 3.0;acl "Update DNS entries in a zone";allow (write) userattr = "parent[0,1].managedby#GROUPDN";)'
+replace:aci:'(targetattr = "idnsname || cn || idnsallowdynupdate || dnsttl || dnsclass || arecord || aaaarecord || a6record || nsrecord || cnamerecord || ptrrecord || srvrecord || txtrecord || mxrecord || mdrecord || hinforecord || minforecord || afsdbrecord || sigrecord || keyrecord || locrecord || nxtrecord || naptrrecord || kxrecord || certrecord || dnamerecord || dsrecord || sshfprecord || rrsigrecord || nsecrecord || idnsname || idnszoneactive || idnssoamname || idnssoarname || idnssoaserial || idnssoarefresh || idnssoaretry || idnssoaexpire || idnssoaminimum || idnsupdatepolicy || idnsallowquery || idnsallowtransfer || idnsallowsyncptr || idnsforwardpolicy || idnsforwarders")(target = "ldap:///idnsname=*,cn=dns,$SUFFIX";)(version 3.0;acl "Update DNS entries in a zone";allow (write) userattr = "parent[0,1].managedby#GROUPDN";)::(targetattr = "idnsname || cn || idnsallowdynupdate || dnsttl || dnsclass || arecord || aaaarecord || a6record || nsrecord || cnamerecord || ptrrecord || srvrecord || txtrecord || mxrecord || mdrecord || hinforecord || minforecord || afsdbrecord || sigrecord || keyrecord || locrecord || nxtrecord || naptrrecord || kxrecord || certrecord || dnamerecord || dsrecord || sshfprecord || rrsigrecord || nsecrecord || idnsname || idnszoneactive || idnssoamname || idnssoarname || idnssoaserial || idnssoarefresh || idnssoaretry || idnssoaexpire || idnssoaminimum || idnsupdatepolicy || idnsallowquery || idnsallowtransfer || idnsallowsyncptr || idnsforwardpolicy || idnsforwarders || dlvrecord || idnssecinlinesigning ")(target = "ldap:///idnsname=*,cn=dns,$SUFFIX";)(version 3.0;acl "Update DNS entries in a zone";allow (write) userattr = "parent[0,1].managedby#GROUPDN";)'
 
 # add DNS plugin
 dn: cn=IPA DNS,cn=plugins,cn=config
diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py
index c892813a5ca4dec5729cfc129d47d61bcb4a1bd2..bcf415ba1750b11f1c19d0beaa2c24f7f9c70b0e 100644
--- a/ipalib/plugins/dns.py
+++ b/ipalib/plugins/dns.py
@@ -1257,34 +1257,7 @@ class NSEC3Record(DNSRecord):
 class NSEC3PARAMRecord(DNSRecord):
     rrtype = 'NSEC3PARAM'
     rfc = 5155
-    parts = (
-        Int('algorithm',
-            label=_('Algorithm'),
-            minvalue=0,
-            maxvalue=255,
-            ),
-        Int('flags',
-            label=_('Flags'),
-            minvalue=0,
-            maxvalue=255,
-            default=0,
-            ),
-        Int('iterations',
-            label=_('Iterations'),
-            minvalue=0,
-            maxvalue=65535,
-            ),
-        Str('salt',
-            label=_('Salt'),
-            doc=_('A hexadecimal salt value. Requires hexadecimal digits '
-                  'or hyphen ("-") if no salt is required'),
-            minlength=1,
-            default=u'-',  # no salt
-            pattern=r'^([0-9a-fA-F]+|-)$',
-            pattern_errmsg=u'only hexadecimal digits or single hyphen ("-") '
-                           u'are allowed'
-            ),
-    )
+    supported = False
 
 def _validate_naptr_flags(ugettext, flags):
     allowed_flags = u'SAUP'
@@ -2178,7 +2151,7 @@ class dnszone(DNSZoneBase):
                 'idnssoaretry', 'idnssoarname', 'idnssoaserial',
                 'idnsupdatepolicy', 'idnszoneactive', 'keyrecord', 'kxrecord',
                 'locrecord', 'managedby', 'mdrecord', 'minforecord',
-                'mxrecord', 'naptrrecord', 'nsecrecord', 'nsec3paramrecord',
+                'mxrecord', 'naptrrecord', 'nsecrecord',
                 'nsrecord', 'nxtrecord', 'ptrrecord', 'rrsigrecord',
                 'sigrecord', 'srvrecord', 'sshfprecord', 'tlsarecord',
                 'txtrecord',
@@ -2212,7 +2185,7 @@ class dnszone(DNSZoneBase):
                 'idnssoaretry', 'idnssoarname', 'idnssoaserial',
                 'idnsupdatepolicy', 'idnszoneactive', 'keyrecord', 'kxrecord',
                 'locrecord', 'managedby', 'mdrecord', 'minforecord',
-                'mxrecord', 'naptrrecord', 'nsecrecord', 'nsec3paramrecord',
+                'mxrecord', 'naptrrecord', 'nsecrecord',
                 'nsrecord', 'nxtrecord', 'ptrrecord', 'rrsigrecord',
                 'sigrecord', 'srvrecord', 'sshfprecord', 'tlsarecord',
                 'txtrecord',
@@ -2558,13 +2531,6 @@ class dnsrecord(LDAPObject):
         for nsrecord in nsrecords:
             check_ns_rec_resolvable(keys[0], DNSName(nsrecord))
 
-    def _nsec3paramrecord_pre_callback(self, ldap, dn, entry_attrs, *keys, **options):
-        assert isinstance(dn, DN)
-        nsec3paramrecord = entry_attrs.get('nsec3paramrecord')
-        if nsec3paramrecord and not self.is_pkey_zone_record(*keys):
-            raise errors.ValidationError(name='nsec3paramrecord',
-                        error=unicode(_('must be in zone record')))
-
     def _idnsname_pre_callback(self, ldap, dn, entry_attrs, *keys, **options):
         assert isinstance(dn, DN)
         if keys[-1].is_absolute():
@@ -2851,14 +2817,6 @@ class dnsrecord(LDAPObject):
                                   'NS record except when located in a zone root '
                                   'record (RFC 6672, section 2.3)'))
 
-        # NSEC3PARAM record validation
-        nsec3params = rrattrs.get('nsec3paramrecord')
-        if nsec3params is not None:
-            if len(nsec3params) > 1:
-                raise errors.ValidationError(name='nsec3paramrecord',
-                    error=_('Only one NSEC3PARAM record is '
-                            'allowed per zone'))
-
     def _entry2rrsets(self, entry_attrs, dns_name, dns_domain):
         '''Convert entry_attrs to a dictionary {rdtype: rrset}.
 
diff --git a/ipatests/test_xmlrpc/test_dns_plugin.py b/ipatests/test_xmlrpc/test_dns_plugin.py
index 2c8c85f93c73605dda93ddf50b80132ce0e50897..995dd93a4d5aa405d4443a1a726b50e2e1d4e363 100644
--- a/ipatests/test_xmlrpc/test_dns_plugin.py
+++ b/ipatests/test_xmlrpc/test_dns_plugin.py
@@ -1594,68 +1594,6 @@ class test_dns(Declarative):
 
 
         dict(
-            desc='Try to add NSEC3PARAM record out of zone record %r' % (zone1),
-            command=('dnsrecord_add', [zone1, u'test'],
-                     {'nsec3paramrecord': u'1 0 2 ad50f1'}),
-            expected=errors.ValidationError(name='nsec3paramrecord',
-                        error=u'must be in zone record'),
-        ),
-
-
-        dict(
-            desc='Try to add invalid NSEC3PARAM record to zone %r' % (zone1),
-            command=('dnsrecord_add', [zone1, u'@'],
-                     {'nsec3paramrecord': u'1 0 2 -ad50f1'}),
-            expected=errors.ValidationError(name='salt',
-                        error=u'only hexadecimal digits or single hyphen ("-") are allowed'),
-        ),
-
-
-        dict(
-            desc='Add NSEC3PARAM record to zone %r' % (zone1),
-            command=('dnsrecord_add', [zone1, u'@'],
-                     {'nsec3paramrecord': u'1 0 2 ad50f1'}),
-            expected={
-                'value': _dns_zone_record,
-                'summary': None,
-                'result': {
-                    'dn': zone1_dn,
-                    'arecord': [u'172.16.29.111'],
-                    'idnsname': [_dns_zone_record],
-                    'nsrecord': [zone1_absolute],
-                    'nsec3paramrecord': [u'1 0 2 ad50f1'],
-                    'objectclass': objectclasses.dnszone,
-                },
-            },
-        ),
-
-
-        dict(
-            desc='Try to add another NSEC3PARAM record to zone %r' % (zone1),
-            command=('dnsrecord_add', [zone1, u'@'],
-                     {'nsec3paramrecord': u'1 0 2 -'}),
-            expected=errors.ValidationError(name='nsec3paramrecord',
-                        error=u'Only one NSEC3PARAM record is allowed per zone'),
-        ),
-
-
-        dict(
-            desc='Remove NSEC3PARAM record from zone %r' % (zone1),
-            command=('dnsrecord_del', [zone1, u'@'],
-                     {'nsec3paramrecord': u'1 0 2 ad50f1'}),
-            expected={
-                'value': [_dns_zone_record],
-                'summary': None,
-                'result': {
-                    'arecord': [u'172.16.29.111'],
-                    'idnsname': [_dns_zone_record],
-                    'nsrecord': [zone1_absolute],
-                },
-            },
-        ),
-
-
-        dict(
             desc='Create zone %r' % zone3,
             command=(
                 'dnszone_add', [zone3], {
-- 
1.8.3.1

>From 87da9b263817dd20a606f788d92d62cacdb7f3d8 Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
Date: Mon, 30 Jun 2014 18:29:40 +0200
Subject: [PATCH 2/3] Add NSEC3PARAM to zone settings

Ticket: https://fedorahosted.org/freeipa/ticket/4413
---
 ACI.txt                       |  4 ++--
 API.txt                       |  9 +++++---
 VERSION                       |  4 ++--
 install/share/60ipadns.ldif   |  2 +-
 install/ui/src/freeipa/dns.js |  3 ++-
 install/updates/40-dns.update |  2 +-
 ipalib/plugins/dns.py         | 53 ++++++++++++++++++++++++++++++++++++++++---
 7 files changed, 64 insertions(+), 13 deletions(-)

diff --git a/ACI.txt b/ACI.txt
index b8dfb56a2abea937823cdaed08322dea3dc0c0ef..8e73c5c8541154e73c201994de828aa43c3777b1 100644
--- a/ACI.txt
+++ b/ACI.txt
@@ -39,11 +39,11 @@ aci: (targetattr = "idnsallowsyncptr || idnsforwarders || idnsforwardpolicy || i
 dn: cn=System: Add DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example
 aci: (target = "ldap:///idnsname=*,cn=dns,dc=ipa,dc=example";)(version 3.0;acl "permission:System: Add DNS Entries";allow (add) groupdn = "ldap:///cn=System: Add DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example";)
 dn: cn=System: Read DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example
-aci: (targetattr = "a6record || aaaarecord || afsdbrecord || arecord || certrecord || cn || cnamerecord || dlvrecord || dnamerecord || dnsclass || dnsttl || dsrecord || hinforecord || idnsallowdynupdate || idnsallowquery || idnsallowsyncptr || idnsallowtransfer || idnsforwarders || idnsforwardpolicy || idnsname || idnssecinlinesigning || idnssoaexpire || idnssoaminimum || idnssoamname || idnssoarefresh || idnssoaretry || idnssoarname || idnssoaserial || idnsupdatepolicy || idnszoneactive || keyrecord || kxrecord || locrecord || managedby || mdrecord || minforecord || mxrecord || naptrrecord || nsecrecord || nsrecord || nxtrecord || objectclass || ptrrecord || rrsigrecord || sigrecord || srvrecord || sshfprecord || tlsarecord || txtrecord")(target = "ldap:///idnsname=*,cn=dns,dc=ipa,dc=example";)(version 3.0;acl "permission:System: Read DNS Entries";allow (compare,read,search) groupdn = "ldap:///cn=System: Read DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example";)
+aci: (targetattr = "a6record || aaaarecord || afsdbrecord || arecord || certrecord || cn || cnamerecord || dlvrecord || dnamerecord || dnsclass || dnsttl || dsrecord || hinforecord || idnsallowdynupdate || idnsallowquery || idnsallowsyncptr || idnsallowtransfer || idnsforwarders || idnsforwardpolicy || idnsname || idnssecinlinesigning || idnssoaexpire || idnssoaminimum || idnssoamname || idnssoarefresh || idnssoaretry || idnssoarname || idnssoaserial || idnsupdatepolicy || idnszoneactive || keyrecord || kxrecord || locrecord || managedby || mdrecord || minforecord || mxrecord || naptrrecord || nsec3paramrecord || nsecrecord || nsrecord || nxtrecord || objectclass || ptrrecord || rrsigrecord || sigrecord || srvrecord || sshfprecord || tlsarecord || txtrecord")(target = "ldap:///idnsname=*,cn=dns,dc=ipa,dc=example";)(version 3.0;acl "permission:System: Read DNS Entries";allow (compare,read,search) groupdn = "ldap:///cn=System: Read DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example";)
 dn: cn=System: Remove DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example
 aci: (target = "ldap:///idnsname=*,cn=dns,dc=ipa,dc=example";)(version 3.0;acl "permission:System: Remove DNS Entries";allow (delete) groupdn = "ldap:///cn=System: Remove DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example";)
 dn: cn=System: Update DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example
-aci: (targetattr = "a6record || aaaarecord || afsdbrecord || arecord || certrecord || cn || cnamerecord || dlvrecord || dnamerecord || dnsclass || dnsttl || dsrecord || hinforecord || idnsallowdynupdate || idnsallowquery || idnsallowsyncptr || idnsallowtransfer || idnsforwarders || idnsforwardpolicy || idnsname || idnssecinlinesigning || idnssoaexpire || idnssoaminimum || idnssoamname || idnssoarefresh || idnssoaretry || idnssoarname || idnssoaserial || idnsupdatepolicy || idnszoneactive || keyrecord || kxrecord || locrecord || managedby || mdrecord || minforecord || mxrecord || naptrrecord || nsecrecord || nsrecord || nxtrecord || ptrrecord || rrsigrecord || sigrecord || srvrecord || sshfprecord || tlsarecord || txtrecord")(target = "ldap:///idnsname=*,cn=dns,dc=ipa,dc=example";)(version 3.0;acl "permission:System: Update DNS Entries";allow (write) groupdn = "ldap:///cn=System: Update DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example";)
+aci: (targetattr = "a6record || aaaarecord || afsdbrecord || arecord || certrecord || cn || cnamerecord || dlvrecord || dnamerecord || dnsclass || dnsttl || dsrecord || hinforecord || idnsallowdynupdate || idnsallowquery || idnsallowsyncptr || idnsallowtransfer || idnsforwarders || idnsforwardpolicy || idnsname || idnssecinlinesigning || idnssoaexpire || idnssoaminimum || idnssoamname || idnssoarefresh || idnssoaretry || idnssoarname || idnssoaserial || idnsupdatepolicy || idnszoneactive || keyrecord || kxrecord || locrecord || managedby || mdrecord || minforecord || mxrecord || naptrrecord || nsec3paramrecord || nsecrecord || nsrecord || nxtrecord || ptrrecord || rrsigrecord || sigrecord || srvrecord || sshfprecord || tlsarecord || txtrecord")(target = "ldap:///idnsname=*,cn=dns,dc=ipa,dc=example";)(version 3.0;acl "permission:System: Update DNS Entries";allow (write) groupdn = "ldap:///cn=System: Update DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example";)
 dn: cn=System: Add Groups,cn=permissions,cn=pbac,dc=ipa,dc=example
 aci: (targetfilter = "(|(objectclass=ipausergroup)(objectclass=posixgroup))")(version 3.0;acl "permission:System: Add Groups";allow (add) groupdn = "ldap:///cn=System: Add Groups,cn=permissions,cn=pbac,dc=ipa,dc=example";)
 dn: cn=System: Modify Group Membership,cn=permissions,cn=pbac,dc=ipa,dc=example
diff --git a/API.txt b/API.txt
index 24eff072285612476e5088b42d6d5967da4b103d..3b56313a29e37731e3273e439909d986a243b232 100644
--- a/API.txt
+++ b/API.txt
@@ -1136,7 +1136,7 @@ output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDA
 output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: PrimaryKey('value', None, None)
 command: dnszone_add
-args: 1,25,3
+args: 1,26,3
 arg: DNSNameParam('idnsname', attribute=True, cli_name='name', multivalue=False, only_absolute=True, primary_key=True, required=True)
 option: Str('addattr*', cli_name='addattr', exclude='webui')
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
@@ -1160,6 +1160,7 @@ option: Int('idnssoaserial', attribute=True, autofill=True, cli_name='serial', m
 option: Str('idnsupdatepolicy', attribute=True, autofill=True, cli_name='update_policy', multivalue=False, required=False)
 option: Str('ip_address?')
 option: Str('name_from_ip', attribute=False, cli_name='name_from_ip', multivalue=False, required=False)
+option: Str('nsec3paramrecord', attribute=True, cli_name='nsec3param_rec', multivalue=False, pattern='^\\d+ \\d+ \\d+ ([0-9a-fA-F]+|-)$', required=False)
 option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
 option: Str('setattr*', cli_name='setattr', exclude='webui')
 option: Str('version?', exclude='webui')
@@ -1196,7 +1197,7 @@ output: Output('result', <type 'bool'>, None)
 output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: PrimaryKey('value', None, None)
 command: dnszone_find
-args: 1,27,4
+args: 1,28,4
 arg: Str('criteria?', noextrawhitespace=False)
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
 option: StrEnum('dnsclass', attribute=True, autofill=False, cli_name='class', multivalue=False, query=True, required=False, values=(u'IN', u'CS', u'CH', u'HS'))
@@ -1220,6 +1221,7 @@ option: Int('idnssoaserial', attribute=True, autofill=False, cli_name='serial',
 option: Str('idnsupdatepolicy', attribute=True, autofill=False, cli_name='update_policy', multivalue=False, query=True, required=False)
 option: Bool('idnszoneactive', attribute=True, autofill=False, cli_name='zone_active', multivalue=False, query=True, required=False)
 option: Str('name_from_ip', attribute=False, autofill=False, cli_name='name_from_ip', multivalue=False, query=True, required=False)
+option: Str('nsec3paramrecord', attribute=True, autofill=False, cli_name='nsec3param_rec', multivalue=False, pattern='^\\d+ \\d+ \\d+ ([0-9a-fA-F]+|-)$', query=True, required=False)
 option: Flag('pkey_only?', autofill=True, default=False)
 option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
 option: Int('sizelimit?', autofill=False, minvalue=0)
@@ -1230,7 +1232,7 @@ output: ListOfEntries('result', (<type 'list'>, <type 'tuple'>), Gettext('A list
 output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: Output('truncated', <type 'bool'>, None)
 command: dnszone_mod
-args: 1,26,3
+args: 1,27,3
 arg: DNSNameParam('idnsname', attribute=True, cli_name='name', multivalue=False, only_absolute=True, primary_key=True, query=True, required=True)
 option: Str('addattr*', cli_name='addattr', exclude='webui')
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
@@ -1254,6 +1256,7 @@ option: DNSNameParam('idnssoarname', attribute=True, autofill=False, cli_name='a
 option: Int('idnssoaserial', attribute=True, autofill=False, cli_name='serial', maxvalue=4294967295L, minvalue=1, multivalue=False, required=False)
 option: Str('idnsupdatepolicy', attribute=True, autofill=False, cli_name='update_policy', multivalue=False, required=False)
 option: Str('name_from_ip', attribute=False, autofill=False, cli_name='name_from_ip', multivalue=False, required=False)
+option: Str('nsec3paramrecord', attribute=True, autofill=False, cli_name='nsec3param_rec', multivalue=False, pattern='^\\d+ \\d+ \\d+ ([0-9a-fA-F]+|-)$', required=False)
 option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
 option: Flag('rights', autofill=True, default=False)
 option: Str('setattr*', cli_name='setattr', exclude='webui')
diff --git a/VERSION b/VERSION
index 99df8a86e055bd197f06747779f3ba8203b8610a..f943a3c2604cc1c16e72be6488e728ba3ea31984 100644
--- a/VERSION
+++ b/VERSION
@@ -89,5 +89,5 @@ IPA_DATA_VERSION=20100614120000
 #                                                      #
 ########################################################
 IPA_API_VERSION_MAJOR=2
-IPA_API_VERSION_MINOR=98
-# Last change: mbasti - Remove NSEC3PARAM record
+IPA_API_VERSION_MINOR=99
+# Last change: mbasti - add NSEC3PARAM zone attribute
diff --git a/install/share/60ipadns.ldif b/install/share/60ipadns.ldif
index 6044a7a863659b372e552f62610c26830cb4bc8a..eccc4fe1dc8eb9f67f0449de738044b903120aa8 100644
--- a/install/share/60ipadns.ldif
+++ b/install/share/60ipadns.ldif
@@ -54,7 +54,7 @@ attributeTypes: ( 2.16.840.1.113730.3.8.5.16 NAME 'idnsZoneRefresh' DESC 'zone r
 attributeTypes: ( 2.16.840.1.113730.3.8.5.17 NAME 'idnsPersistentSearch' DESC 'allow persistent searches' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE X-ORIGIN 'IPA v2' )
 attributeTypes: ( 2.16.840.1.113730.3.8.5.18 NAME 'idnsSecInlineSigning' DESC 'allow inline DNSSEC signing' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE X-ORIGIN 'IPA v4.0' )
 objectClasses: ( 2.16.840.1.113730.3.8.6.0 NAME 'idnsRecord' DESC 'dns Record, usually a host' SUP top STRUCTURAL MUST idnsName MAY ( idnsAllowDynUpdate $ dNSTTL $ dNSClass $ aRecord $ aAAARecord $ a6Record $ nSRecord $ cNAMERecord $ pTRRecord $ sRVRecord $ tXTRecord $ mXRecord $ mDRecord $ hInfoRecord $ mInfoRecord $ aFSDBRecord $ SigRecord $ KeyRecord $ LocRecord $ nXTRecord $ nAPTRRecord $ kXRecord $ certRecord $ dNameRecord $ dSRecord $ sSHFPRecord $ rRSIGRecord $ nSECRecord $ DLVRecord $ TLSARecord ) )
-objectClasses: ( 2.16.840.1.113730.3.8.6.1 NAME 'idnsZone' DESC 'Zone class' SUP idnsRecord STRUCTURAL MUST ( idnsZoneActive $ idnsSOAmName $ idnsSOArName $ idnsSOAserial $ idnsSOArefresh $ idnsSOAretry $ idnsSOAexpire $ idnsSOAminimum ) MAY ( idnsUpdatePolicy $ idnsAllowQuery $ idnsAllowTransfer $ idnsAllowSyncPTR $ idnsForwardPolicy $ idnsForwarders $ idnsSecInlineSigning ) )
+objectClasses: ( 2.16.840.1.113730.3.8.6.1 NAME 'idnsZone' DESC 'Zone class' SUP idnsRecord STRUCTURAL MUST ( idnsZoneActive $ idnsSOAmName $ idnsSOArName $ idnsSOAserial $ idnsSOArefresh $ idnsSOAretry $ idnsSOAexpire $ idnsSOAminimum ) MAY ( idnsUpdatePolicy $ idnsAllowQuery $ idnsAllowTransfer $ idnsAllowSyncPTR $ idnsForwardPolicy $ idnsForwarders $ idnsSecInlineSigning $ nSEC3PARAMRecord ) )
 objectClasses: ( 2.16.840.1.113730.3.8.6.2 NAME 'idnsConfigObject' DESC 'DNS global config options' STRUCTURAL MAY ( idnsForwardPolicy $ idnsForwarders $ idnsAllowSyncPTR $ idnsZoneRefresh $ idnsPersistentSearch ) )
 objectClasses: ( 2.16.840.1.113730.3.8.12.18 NAME 'ipaDNSZone' SUP top AUXILIARY MUST idnsName MAY managedBy X-ORIGIN 'IPA v3' )
 objectClasses: ( 2.16.840.1.113730.3.8.6.3 NAME 'idnsForwardZone' DESC 'Forward Zone class' SUP top STRUCTURAL MUST ( idnsName $ idnsZoneActive ) MAY ( idnsForwarders $ idnsForwardPolicy ) )
diff --git a/install/ui/src/freeipa/dns.js b/install/ui/src/freeipa/dns.js
index c3b79a50fba43ac61e0a86e47accf99dbcbd720f..11285a9f095bba35e16c1340fc272e824d699a15 100644
--- a/install/ui/src/freeipa/dns.js
+++ b/install/ui/src/freeipa/dns.js
@@ -222,7 +222,8 @@ return {
                     {
                         $type: 'checkbox',
                         name: 'idnssecinlinesigning'
-                    }
+                    },
+                    'nsec3paramrecord'
                 ]
             }],
             actions: [
diff --git a/install/updates/40-dns.update b/install/updates/40-dns.update
index 70172ef3321d061c3b182ccecff37f83fb4cff7d..796a293692f790666bafaca865d010b7f6899e6f 100644
--- a/install/updates/40-dns.update
+++ b/install/updates/40-dns.update
@@ -10,7 +10,7 @@ addifexist: aci:'(targetattr = "idnsname || cn || idnsallowdynupdate || dnsttl |
 dn: cn=dns, $SUFFIX
 replace:aci:'(targetattr = "*")(version 3.0; acl "No access to DNS tree without a permission"; deny (read,search,compare) (groupdn != "ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX";) and (groupdn != "ldap:///cn=Read DNS Entries,cn=permissions,cn=pbac,$SUFFIX");)::(targetattr = "*")(version 3.0; acl "Read DNS entries from a zone"; allow (read,search,compare) userattr = "parent[0,1].managedby#GROUPDN";)'
 replace:aci:'(targetattr = "*")(version 3.0; acl "Allow read access"; allow (read,search,compare) groupdn = "ldap:///cn=Read DNS Entries,cn=permissions,cn=pbac,$SUFFIX" or userattr = "parent[0,1].managedby#GROUPDN";)::(targetattr = "*")(version 3.0; acl "Read DNS entries from a zone"; allow (read,search,compare) userattr = "parent[0,1].managedby#GROUPDN";)'
-replace:aci:'(targetattr = "idnsname || cn || idnsallowdynupdate || dnsttl || dnsclass || arecord || aaaarecord || a6record || nsrecord || cnamerecord || ptrrecord || srvrecord || txtrecord || mxrecord || mdrecord || hinforecord || minforecord || afsdbrecord || sigrecord || keyrecord || locrecord || nxtrecord || naptrrecord || kxrecord || certrecord || dnamerecord || dsrecord || sshfprecord || rrsigrecord || nsecrecord || idnsname || idnszoneactive || idnssoamname || idnssoarname || idnssoaserial || idnssoarefresh || idnssoaretry || idnssoaexpire || idnssoaminimum || idnsupdatepolicy || idnsallowquery || idnsallowtransfer || idnsallowsyncptr || idnsforwardpolicy || idnsforwarders")(target = "ldap:///idnsname=*,cn=dns,$SUFFIX";)(version 3.0;acl "Update DNS entries in a zone";allow (write) userattr = "parent[0,1].managedby#GROUPDN";)::(targetattr = "idnsname || cn || idnsallowdynupdate || dnsttl || dnsclass || arecord || aaaarecord || a6record || nsrecord || cnamerecord || ptrrecord || srvrecord || txtrecord || mxrecord || mdrecord || hinforecord || minforecord || afsdbrecord || sigrecord || keyrecord || locrecord || nxtrecord || naptrrecord || kxrecord || certrecord || dnamerecord || dsrecord || sshfprecord || rrsigrecord || nsecrecord || idnsname || idnszoneactive || idnssoamname || idnssoarname || idnssoaserial || idnssoarefresh || idnssoaretry || idnssoaexpire || idnssoaminimum || idnsupdatepolicy || idnsallowquery || idnsallowtransfer || idnsallowsyncptr || idnsforwardpolicy || idnsforwarders || dlvrecord || idnssecinlinesigning ")(target = "ldap:///idnsname=*,cn=dns,$SUFFIX";)(version 3.0;acl "Update DNS entries in a zone";allow (write) userattr = "parent[0,1].managedby#GROUPDN";)'
+replace:aci:'(targetattr = "idnsname || cn || idnsallowdynupdate || dnsttl || dnsclass || arecord || aaaarecord || a6record || nsrecord || cnamerecord || ptrrecord || srvrecord || txtrecord || mxrecord || mdrecord || hinforecord || minforecord || afsdbrecord || sigrecord || keyrecord || locrecord || nxtrecord || naptrrecord || kxrecord || certrecord || dnamerecord || dsrecord || sshfprecord || rrsigrecord || nsecrecord || idnsname || idnszoneactive || idnssoamname || idnssoarname || idnssoaserial || idnssoarefresh || idnssoaretry || idnssoaexpire || idnssoaminimum || idnsupdatepolicy || idnsallowquery || idnsallowtransfer || idnsallowsyncptr || idnsforwardpolicy || idnsforwarders")(target = "ldap:///idnsname=*,cn=dns,$SUFFIX";)(version 3.0;acl "Update DNS entries in a zone";allow (write) userattr = "parent[0,1].managedby#GROUPDN";)::(targetattr = "idnsname || cn || idnsallowdynupdate || dnsttl || dnsclass || arecord || aaaarecord || a6record || nsrecord || cnamerecord || ptrrecord || srvrecord || txtrecord || mxrecord || mdrecord || hinforecord || minforecord || afsdbrecord || sigrecord || keyrecord || locrecord || nxtrecord || naptrrecord || kxrecord || certrecord || dnamerecord || dsrecord || sshfprecord || rrsigrecord || nsecrecord || idnsname || idnszoneactive || idnssoamname || idnssoarname || idnssoaserial || idnssoarefresh || idnssoaretry || idnssoaexpire || idnssoaminimum || idnsupdatepolicy || idnsallowquery || idnsallowtransfer || idnsallowsyncptr || idnsforwardpolicy || idnsforwarders || dlvrecord || idnssecinlinesigning || nsec3paramrecord ")(target = "ldap:///idnsname=*,cn=dns,$SUFFIX";)(version 3.0;acl "Update DNS entries in a zone";allow (write) userattr = "parent[0,1].managedby#GROUPDN";)'
 
 # add DNS plugin
 dn: cn=IPA DNS,cn=plugins,cn=config
diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py
index bcf415ba1750b11f1c19d0beaa2c24f7f9c70b0e..9c31d6f3211423fc4896f129ad093c0faaad092a 100644
--- a/ipalib/plugins/dns.py
+++ b/ipalib/plugins/dns.py
@@ -23,6 +23,7 @@ from __future__ import absolute_import
 import netaddr
 import time
 import re
+import binascii
 import dns.name
 import dns.exception
 import dns.resolver
@@ -433,6 +434,43 @@ def _validate_bind_forwarder(ugettext, forwarder):
 
     return None
 
+# webui requires basestring errmsg
+_nsec3param_errmsg = u'expected format: <0-255> <0-255> <0-65535> hexadecimal_digits_or_hyphen'
+
+
+def _validate_nsec3param_record(ugettext, value):
+    _nsec3param_pattern = (r'^(?P<alg>\d+) (?P<flags>\d+) (?P<iter>\d+) '
+        r'(?P<salt>[0-9a-fA-F]+|-)$')
+    rec = re.compile(_nsec3param_pattern, flags=re.U)
+    result = rec.match(value)
+
+    if result is None:
+        return _(_nsec3param_errmsg)
+
+    alg = int(result.group('alg'))
+    flags = int(result.group('flags'))
+    iterations = int(result.group('iter'))
+    salt = result.group('salt')
+
+    if alg > 255:
+        return _('algorithm value: allowed interval 0-255')
+
+    if flags > 255:
+        return _('flags value: allowed interval 0-255')
+
+    if iterations > 65535:
+        return _('iterations value: allowed interval 0-65535')
+
+    if salt == u'-':
+        return None
+
+    try:
+        binascii.a2b_hex(salt)
+    except Exception, e:
+        return _('salt value: %(err)s') % {'err': e}
+    return None
+
+
 def _hostname_validator(ugettext, value):
     assert isinstance(value, DNSName)
     if len(value.make_absolute().labels) < 3:
@@ -1257,7 +1295,7 @@ class NSEC3Record(DNSRecord):
 class NSEC3PARAMRecord(DNSRecord):
     rrtype = 'NSEC3PARAM'
     rfc = 5155
-    supported = False
+    supported = False  # this is part of zone in IPA
 
 def _validate_naptr_flags(ugettext, flags):
     allowed_flags = u'SAUP'
@@ -2121,6 +2159,15 @@ class dnszone(DNSZoneBase):
             label=_('Allow in-line DNSSEC signing'),
             doc=_('Allow inline DNSSEC signing of records in the zone'),
         ),
+        Str('nsec3paramrecord?',
+            _validate_nsec3param_record,
+            cli_name='nsec3param_rec',
+            label=_('NSEC3PARAM record'),
+            doc=_('NSEC3PARAM record for zone in format: hash_alg flags iterations salt'),
+            pattern=r'^\d+ \d+ \d+ ([0-9a-fA-F]+|-)$',
+            pattern_errmsg=_nsec3param_errmsg,
+
+        ),
     )
     # Permissions will be apllied for forwardzones too
     managed_permissions = {
@@ -2151,7 +2198,7 @@ class dnszone(DNSZoneBase):
                 'idnssoaretry', 'idnssoarname', 'idnssoaserial',
                 'idnsupdatepolicy', 'idnszoneactive', 'keyrecord', 'kxrecord',
                 'locrecord', 'managedby', 'mdrecord', 'minforecord',
-                'mxrecord', 'naptrrecord', 'nsecrecord',
+                'mxrecord', 'naptrrecord', 'nsecrecord', 'nsec3paramrecord',
                 'nsrecord', 'nxtrecord', 'ptrrecord', 'rrsigrecord',
                 'sigrecord', 'srvrecord', 'sshfprecord', 'tlsarecord',
                 'txtrecord',
@@ -2185,7 +2232,7 @@ class dnszone(DNSZoneBase):
                 'idnssoaretry', 'idnssoarname', 'idnssoaserial',
                 'idnsupdatepolicy', 'idnszoneactive', 'keyrecord', 'kxrecord',
                 'locrecord', 'managedby', 'mdrecord', 'minforecord',
-                'mxrecord', 'naptrrecord', 'nsecrecord',
+                'mxrecord', 'naptrrecord', 'nsecrecord', 'nsec3paramrecord',
                 'nsrecord', 'nxtrecord', 'ptrrecord', 'rrsigrecord',
                 'sigrecord', 'srvrecord', 'sshfprecord', 'tlsarecord',
                 'txtrecord',
-- 
1.8.3.1

>From 6fc8126b3ea54efc0bf443b7118a5f9ab0334ff6 Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
Date: Tue, 1 Jul 2014 13:39:57 +0200
Subject: [PATCH 3/3] NSEC3PARAM tests

Ticket: https://fedorahosted.org/freeipa/ticket/4413
---
 ipatests/test_xmlrpc/test_dns_plugin.py | 104 ++++++++++++++++++++++++++++++++
 1 file changed, 104 insertions(+)

diff --git a/ipatests/test_xmlrpc/test_dns_plugin.py b/ipatests/test_xmlrpc/test_dns_plugin.py
index 995dd93a4d5aa405d4443a1a726b50e2e1d4e363..9546aabc2e75550d73e38b200312006bdcc0f304 100644
--- a/ipatests/test_xmlrpc/test_dns_plugin.py
+++ b/ipatests/test_xmlrpc/test_dns_plugin.py
@@ -448,6 +448,110 @@ class test_dns(Declarative):
             },
         ),
 
+        dict(
+            desc='Try to add invalid NSEC3PARAM record to zone %s' % (zone1),
+            command=('dnszone_mod', [zone1], {'nsec3paramrecord': u'0 0 0 0 X'}),
+            expected=errors.ValidationError(name="nsec3param_rec",
+                        error=(u'expected format: <0-255> <0-255> <0-65535> '
+                               u'hexadecimal_digits_or_hyphen')
+            )
+        ),
+
+
+        dict(
+            desc='Try to add invalid NSEC3PARAM record to zone %s' % (zone1),
+            command=('dnszone_mod', [zone1], {'nsec3paramrecord': u'0 0 0 X'}),
+            expected=errors.ValidationError(name="nsec3param_rec",
+                        error=(u'expected format: <0-255> <0-255> <0-65535> '
+                               u'hexadecimal_digits_or_hyphen')
+            )
+        ),
+
+
+        dict(
+            desc='Try to add invalid NSEC3PARAM record to zone %s' % (zone1),
+            command=('dnszone_mod', [zone1], {'nsec3paramrecord': u'333 0 0 -'}),
+            expected=errors.ValidationError(name="nsec3param_rec",
+                        error=u'algorithm value: allowed interval 0-255'
+            )
+        ),
+
+
+        dict(
+            desc='Try to add invalid NSEC3PARAM record to zone %s' % (zone1),
+            command=('dnszone_mod', [zone1], {'nsec3paramrecord': u'0 333 0 -'}),
+            expected=errors.ValidationError(name="nsec3param_rec",
+                        error=u'flags value: allowed interval 0-255'
+            )
+        ),
+
+
+        dict(
+            desc='Try to add invalid NSEC3PARAM record to zone %s' % (zone1),
+            command=('dnszone_mod', [zone1], {'nsec3paramrecord': u'0 0 65536 -'}),
+            expected=errors.ValidationError(name="nsec3param_rec",
+                        error=u'iterations value: allowed interval 0-65535'
+            )
+        ),
+
+
+        dict(
+            desc='Try to add invalid NSEC3PARAM record to zone %s' % (zone1),
+            command=('dnszone_mod', [zone1], {'nsec3paramrecord': u'0 0 0 A'}),
+            expected=errors.ValidationError(name="nsec3param_rec",
+                        error=u'salt value: Odd-length string'
+            )
+        ),
+
+
+        dict(
+            desc='Add NSEC3PARAM record to zone %s' % (zone1),
+            command=('dnszone_mod', [zone1], {'nsec3paramrecord': u'0 0 0 -'}),
+            expected={
+                'value': zone1_absolute_dnsname,
+                'summary': None,
+                'result': {
+                    'idnsname': [zone1_absolute_dnsname],
+                    'idnszoneactive': [u'TRUE'],
+                    'nsrecord': [zone1_ns],
+                    'idnssoamname': [zone1_ns_dnsname],
+                    'idnssoarname': [zone1_rname_dnsname],
+                    'idnssoaserial': [fuzzy_digits],
+                    'idnssoarefresh': [u'5478'],
+                    'idnssoaretry': [fuzzy_digits],
+                    'idnssoaexpire': [fuzzy_digits],
+                    'idnssoaminimum': [fuzzy_digits],
+                    'idnsallowtransfer': [u'none;'],
+                    'idnsallowquery': [u'any;'],
+                    'nsec3paramrecord': [u'0 0 0 -'],
+                },
+            },
+        ),
+
+
+        dict(
+            desc='Delete NSEC3PARAM record from zone %s' % (zone1),
+            command=('dnszone_mod', [zone1], {'nsec3paramrecord': u''}),
+            expected={
+                'value': zone1_absolute_dnsname,
+                'summary': None,
+                'result': {
+                    'idnsname': [zone1_absolute_dnsname],
+                    'idnszoneactive': [u'TRUE'],
+                    'nsrecord': [zone1_ns],
+                    'idnssoamname': [zone1_ns_dnsname],
+                    'idnssoarname': [zone1_rname_dnsname],
+                    'idnssoaserial': [fuzzy_digits],
+                    'idnssoarefresh': [u'5478'],
+                    'idnssoaretry': [fuzzy_digits],
+                    'idnssoaexpire': [fuzzy_digits],
+                    'idnssoaminimum': [fuzzy_digits],
+                    'idnsallowtransfer': [u'none;'],
+                    'idnsallowquery': [u'any;'],
+                },
+            },
+        ),
+
 
         dict(
             desc='Try to create reverse zone %r with NS record in it' % revzone1,
-- 
1.8.3.1

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to