Esempio n. 1
0
        internal byte[] GetNSec3Hash(NSec3HashAlgorithm algorithm, int iterations, byte[] salt)
        {
            IDigest digest;

            switch (algorithm)
            {
            case NSec3HashAlgorithm.Sha1:
                digest = new Sha1Digest();
                break;

            default:
                throw new NotSupportedException();
            }

            byte[] buffer = new byte[Math.Max(MaximumRecordDataLength + 1, digest.GetDigestSize()) + salt.Length];

            int length = 0;

            DnsMessageBase.EncodeDomainName(buffer, 0, ref length, this, null, true);

            for (int i = 0; i <= iterations; i++)
            {
                DnsMessageBase.EncodeByteArray(buffer, ref length, salt);

                digest.BlockUpdate(buffer, 0, length);

                digest.DoFinal(buffer, 0);
                length = digest.GetDigestSize();
            }

            byte[] res = new byte[length];
            Buffer.BlockCopy(buffer, 0, res, 0, length);

            return(res);
        }
 /// <summary>
 ///   Creates a new instance of the NSec3ParamRecord class
 /// </summary>
 /// <param name="name"> Name of the record </param>
 /// <param name="recordClass"> Class of the record </param>
 /// <param name="timeToLive"> Seconds the record should be cached at most </param>
 /// <param name="hashAlgorithm"> Algorithm of hash </param>
 /// <param name="flags"> Flags of the record </param>
 /// <param name="iterations"> Number of iterations </param>
 /// <param name="salt"> Binary data of salt </param>
 public NSec3ParamRecord(DomainName name, RecordClass recordClass, int timeToLive, NSec3HashAlgorithm hashAlgorithm, byte flags, ushort iterations, byte[] salt)
     : base(name, RecordType.NSec3Param, recordClass, timeToLive)
 {
     HashAlgorithm = hashAlgorithm;
     Flags         = flags;
     Iterations    = iterations;
     Salt          = salt ?? new byte[] { };
 }
		/// <summary>
		///   Creates a new instance of the NSec3ParamRecord class
		/// </summary>
		/// <param name="name"> Name of the record </param>
		/// <param name="recordClass"> Class of the record </param>
		/// <param name="timeToLive"> Seconds the record should be cached at most </param>
		/// <param name="hashAlgorithm"> Algorithm of hash </param>
		/// <param name="flags"> Flags of the record </param>
		/// <param name="iterations"> Number of iterations </param>
		/// <param name="salt"> Binary data of salt </param>
		public NSec3ParamRecord(DomainName name, RecordClass recordClass, int timeToLive, NSec3HashAlgorithm hashAlgorithm, byte flags, ushort iterations, byte[] salt)
			: base(name, RecordType.NSec3Param, recordClass, timeToLive)
		{
			HashAlgorithm = hashAlgorithm;
			Flags = flags;
			Iterations = iterations;
			Salt = salt ?? new byte[] { };
		}
Esempio n. 4
0
        public static int GetPriority(this NSec3HashAlgorithm algorithm)
        {
            switch (algorithm)
            {
            case NSec3HashAlgorithm.Sha1:
                return(1);

            default:
                throw new NotSupportedException();
            }
        }
Esempio n. 5
0
        public static bool IsSupported(this NSec3HashAlgorithm algorithm)
        {
            switch (algorithm)
            {
            case NSec3HashAlgorithm.Sha1:
                return(true);

            default:
                return(false);
            }
        }
Esempio n. 6
0
        /// <summary>
        ///   Creates of new instance of the NSec3Record class
        /// </summary>
        /// <param name="name"> Name of the record </param>
        /// <param name="recordClass"> Class of the record </param>
        /// <param name="timeToLive"> Seconds the record should be cached at most </param>
        /// <param name="hashAlgorithm"> Algorithm of hash </param>
        /// <param name="flags"> Flags of the record </param>
        /// <param name="iterations"> Number of iterations </param>
        /// <param name="salt"> Binary data of salt </param>
        /// <param name="nextHashedOwnerName"> Binary data of hash of next owner </param>
        /// <param name="types"> Types of next owner </param>
        public NSec3Record(DomainName name, RecordClass recordClass, int timeToLive, NSec3HashAlgorithm hashAlgorithm, byte flags, ushort iterations, byte[] salt, byte[] nextHashedOwnerName, List <RecordType> types)
            : base(name, RecordType.NSec3, recordClass, timeToLive)
        {
            HashAlgorithm       = hashAlgorithm;
            Flags               = flags;
            Iterations          = iterations;
            Salt                = salt ?? new byte[] { };
            NextHashedOwnerName = nextHashedOwnerName ?? new byte[] { };

            if ((types == null) || (types.Count == 0))
            {
                Types = new List <RecordType>();
            }
            else
            {
                Types = types.Distinct().OrderBy(x => x).ToList();
            }
        }
		/// <summary>
		///   Creates of new instance of the NSec3Record class
		/// </summary>
		/// <param name="name"> Name of the record </param>
		/// <param name="recordClass"> Class of the record </param>
		/// <param name="timeToLive"> Seconds the record should be cached at most </param>
		/// <param name="hashAlgorithm"> Algorithm of hash </param>
		/// <param name="flags"> Flags of the record </param>
		/// <param name="iterations"> Number of iterations </param>
		/// <param name="salt"> Binary data of salt </param>
		/// <param name="nextHashedOwnerName"> Binary data of hash of next owner </param>
		/// <param name="types"> Types of next owner </param>
		public NSec3Record(DomainName name, RecordClass recordClass, int timeToLive, NSec3HashAlgorithm hashAlgorithm, byte flags, ushort iterations, byte[] salt, byte[] nextHashedOwnerName, List<RecordType> types)
			: base(name, RecordType.NSec3, recordClass, timeToLive)
		{
			HashAlgorithm = hashAlgorithm;
			Flags = flags;
			Iterations = iterations;
			Salt = salt ?? new byte[] { };
			NextHashedOwnerName = nextHashedOwnerName ?? new byte[] { };

			if ((types == null) || (types.Count == 0))
			{
				Types = new List<RecordType>();
			}
			else
			{
				Types = types.Distinct().OrderBy(x => x).ToList();
			}
		}
Esempio n. 8
0
        private Zone SignWithNSec3(DateTime inception, DateTime expiration, List <DnsKeyRecord> zoneSigningKeys, List <DnsKeyRecord> keySigningKeys, NSec3HashAlgorithm nsec3Algorithm, int nsec3Iterations, byte[] nsec3Salt, bool nsec3OptOut)
        {
            var soaRecord         = _records.OfType <SoaRecord>().First();
            var subZoneNameserver = _records.Where(x => (x.RecordType == RecordType.Ns) && (x.Name != Name)).ToList();
            var subZones          = subZoneNameserver.Select(x => x.Name).Distinct().ToList();
            var unsignedRecords   = _records.Where(x => subZones.Any(y => x.Name.IsSubDomainOf(y))).ToList();           // glue records

            if (nsec3OptOut)
            {
                unsignedRecords = unsignedRecords.Union(subZoneNameserver.Where(x => !_records.Any(y => (y.RecordType == RecordType.Ds) && (y.Name == x.Name)))).ToList();                 // delegations without DS record
            }
            var recordsByName = _records.Except(unsignedRecords).Union(zoneSigningKeys).Union(keySigningKeys).GroupBy(x => x.Name).Select(x => new Tuple <DomainName, List <DnsRecordBase> >(x.Key, x.OrderBy(y => y.RecordType == RecordType.Soa ? -1 : (int)y.RecordType).ToList())).OrderBy(x => x.Item1).ToList();

            byte nsec3RecordFlags = (byte)(nsec3OptOut ? 1 : 0);

            Zone res = new Zone(Name, Count * 3);
            List <NSec3Record> nSec3Records = new List <NSec3Record>(Count);

            if (nsec3Salt == null)
            {
                nsec3Salt = SecureRandom.GetSeed(8);
            }

            recordsByName[0].Item2.Add(new NSec3ParamRecord(soaRecord.Name, soaRecord.RecordClass, 0, nsec3Algorithm, 0, (ushort)nsec3Iterations, nsec3Salt));

            HashSet <DomainName> allNames = new HashSet <DomainName>();

            for (int i = 0; i < recordsByName.Count; i++)
            {
                List <RecordType> recordTypes = new List <RecordType>();

                DomainName currentName = recordsByName[i].Item1;

                foreach (var recordsByType in recordsByName[i].Item2.GroupBy(x => x.RecordType))
                {
                    List <DnsRecordBase> records = recordsByType.ToList();

                    recordTypes.Add(recordsByType.Key);
                    res.AddRange(records);

                    // do not sign nameserver delegations for sub zones
                    if ((records[0].RecordType == RecordType.Ns) && (currentName != Name))
                    {
                        continue;
                    }

                    recordTypes.Add(RecordType.RrSig);

                    foreach (var key in zoneSigningKeys)
                    {
                        res.Add(new RrSigRecord(records, key, inception, expiration));
                    }
                    if (records[0].RecordType == RecordType.DnsKey)
                    {
                        foreach (var key in keySigningKeys)
                        {
                            res.Add(new RrSigRecord(records, key, inception, expiration));
                        }
                    }
                }

                byte[] hash = recordsByName[i].Item1.GetNSec3Hash(nsec3Algorithm, nsec3Iterations, nsec3Salt);
                nSec3Records.Add(new NSec3Record(DomainName.ParseFromMasterfile(hash.ToBase32HexString()) + Name, soaRecord.RecordClass, soaRecord.NegativeCachingTTL, nsec3Algorithm, nsec3RecordFlags, (ushort)nsec3Iterations, nsec3Salt, hash, recordTypes));

                allNames.Add(currentName);
                for (int j = currentName.LabelCount - Name.LabelCount; j > 0; j--)
                {
                    DomainName possibleNonTerminal = currentName.GetParentName(j);

                    if (!allNames.Contains(possibleNonTerminal))
                    {
                        hash = possibleNonTerminal.GetNSec3Hash(nsec3Algorithm, nsec3Iterations, nsec3Salt);
                        nSec3Records.Add(new NSec3Record(DomainName.ParseFromMasterfile(hash.ToBase32HexString()) + Name, soaRecord.RecordClass, soaRecord.NegativeCachingTTL, nsec3Algorithm, nsec3RecordFlags, (ushort)nsec3Iterations, nsec3Salt, hash, new List <RecordType>()));

                        allNames.Add(possibleNonTerminal);
                    }
                }
            }

            nSec3Records = nSec3Records.OrderBy(x => x.Name).ToList();

            byte[] firstNextHashedOwnerName = nSec3Records[0].NextHashedOwnerName;

            for (int i = 1; i < nSec3Records.Count; i++)
            {
                nSec3Records[i - 1].NextHashedOwnerName = nSec3Records[i].NextHashedOwnerName;
            }

            nSec3Records[nSec3Records.Count - 1].NextHashedOwnerName = firstNextHashedOwnerName;

            foreach (var nSec3Record in nSec3Records)
            {
                res.Add(nSec3Record);

                foreach (var key in zoneSigningKeys)
                {
                    res.Add(new RrSigRecord(new List <DnsRecordBase>()
                    {
                        nSec3Record
                    }, key, inception, expiration));
                }
            }

            res.AddRange(unsignedRecords);

            return(res);
        }
Esempio n. 9
0
        /// <summary>
        ///   Signs a zone
        /// </summary>
        /// <param name="keys">A list of keys to sign the zone</param>
        /// <param name="inception">The inception date of the signatures</param>
        /// <param name="expiration">The expiration date of the signatures</param>
        /// <param name="nsec3Algorithm">The NSEC3 algorithm (or 0 when NSEC should be used)</param>
        /// <param name="nsec3Iterations">The number of iterations when NSEC3 is used</param>
        /// <param name="nsec3Salt">The salt when NSEC3 is used</param>
        /// <param name="nsec3OptOut">true, of NSEC3 OptOut should be used for delegations without DS record</param>
        /// <returns>A signed zone</returns>
        public Zone Sign(List <DnsKeyRecord> keys, DateTime inception, DateTime expiration, NSec3HashAlgorithm nsec3Algorithm = 0, int nsec3Iterations = 10, byte[] nsec3Salt = null, bool nsec3OptOut = false)
        {
            if ((keys == null) || (keys.Count == 0))
            {
                throw new Exception("No DNS Keys were provided");
            }

            if (!keys.All(x => x.IsZoneKey))
            {
                throw new Exception("No DNS key with Zone Key Flag were provided");
            }

            if (keys.Any(x => (x.PrivateKey == null) || (x.PrivateKey.Length == 0)))
            {
                throw new Exception("For at least one DNS key no Private Key was provided");
            }

            if (keys.Any(x => (x.Protocol != 3) || ((nsec3Algorithm != 0) ? !x.Algorithm.IsCompatibleWithNSec3() : !x.Algorithm.IsCompatibleWithNSec())))
            {
                throw new Exception("At least one invalid DNS key was provided");
            }

            List <DnsKeyRecord> keySigningKeys  = keys.Where(x => x.IsSecureEntryPoint).ToList();
            List <DnsKeyRecord> zoneSigningKeys = keys.Where(x => !x.IsSecureEntryPoint).ToList();

            if (nsec3Algorithm == 0)
            {
                return(SignWithNSec(inception, expiration, zoneSigningKeys, keySigningKeys));
            }
            else
            {
                return(SignWithNSec3(inception, expiration, zoneSigningKeys, keySigningKeys, nsec3Algorithm, nsec3Iterations, nsec3Salt, nsec3OptOut));
            }
        }
Esempio n. 10
0
 internal DomainName GetNsec3HashName(NSec3HashAlgorithm algorithm, int iterations, byte[] salt, DomainName zoneApex)
 {
     return(new DomainName(GetNSec3Hash(algorithm, iterations, salt).ToBase32HexString(), zoneApex));
 }