Пример #1
0
        /// <summary>
        /// Closes the package, optionally leaving the output stream open.
        /// </summary>
        /// <param name="leaveOutputOpen"><c>true</c> to leave the output stream open.</param>
        public void Close(bool leaveOutputOpen)
        {
            if (packageOut != null)
            {
                // Append the terminating entry.

                new PackageEntry(this).Serialize(packageOut);

                // Before we close the package, we need to compute the MD5
                // hash of everything after the header in the output stream
                // and update the hash in the header.

                var header = new PackageHeader();

                packageOut.Position = cbHeader;
                header.Hash         = MD5Hasher.Compute(packageOut, packageOut.Length - cbHeader);

                packageOut.Position = 0;
                header.Seralize(packageOut);

                if (!leaveOutputOpen)
                {
                    packageOut.Close();
                }

                packageOut = null;
            }

            if (packageIn != null)
            {
                packageIn.Close();
                packageIn = null;
            }
        }
Пример #2
0
        private void CompareFiles(string path1, string path2)
        {
            EnhancedFileStream es1 = null;
            EnhancedFileStream es2 = null;

            try
            {
                es1 = new EnhancedFileStream(path1, FileMode.Open, FileAccess.Read);
                es2 = new EnhancedFileStream(path2, FileMode.Open, FileAccess.Read);

                Assert.AreEqual(es1.Length, es2.Length);
                CollectionAssert.AreEqual(MD5Hasher.Compute(es1, es1.Length), MD5Hasher.Compute(es2, es2.Length));
            }
            finally
            {
                if (es1 != null)
                {
                    es1.Close();
                }

                if (es2 != null)
                {
                    es2.Close();
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Computes an MD5 hash code for the log entry
        /// </summary>
        /// <param name="extension">The extended entry information (or <c>null</c>).</param>
        /// <param name="entryType">The log entry type.</param>
        /// <param name="message">The log message (or <c>null</c>).</param>
        /// <param name="e">The logged exception (or <c>null</c>).</param>
        /// <returns>The computed hash.</returns>
        private static MD5Key ComputeMD5Hash(ISysLogEntryExtension extension, SysLogEntryType entryType, string message, Exception e)
        {
            StringBuilder sb = new StringBuilder(1024);

            if (extension != null)
            {
                sb.Append(extension.Format());
            }

            sb.Append('\t');

            sb.Append(entryType.ToString());
            sb.Append('\t');

            if (message != null)
            {
                sb.Append(message);
            }

            sb.Append('\t');

            if (e != null)
            {
                sb.Append(e.GetType().FullName);
                sb.Append('\t');
                sb.Append(e.Message);
                sb.Append('\t');
                sb.Append(e.StackTrace.ToString());
            }

            return(new MD5Key(MD5Hasher.Compute(sb.ToString())));
        }
Пример #4
0
        private static int Hash(string fileName)
        {
            try
            {
                byte[] hash;

                using (EnhancedStream es = new EnhancedFileStream(fileName, FileMode.Open, FileAccess.Read))
                {
                    hash = MD5Hasher.Compute(es, es.Length);
                }

                using (StreamWriter writer = new StreamWriter(fileName + ".md5", false, Helper.AnsiEncoding))
                {
                    writer.WriteLine("MD5={0}", Helper.ToHex(hash));
                }

                File.Copy(fileName, fileName + ".setup");

                return(0);
            }
            catch (Exception e)
            {
                Program.Error("Error ({0}): {1}", e.GetType().Name, e.Message);
                return(1);
            }
        }
Пример #5
0
        public void WebTransferFile_UploadMD5()
        {
            // Test the file upload with MD5 validation scenario and
            // also test appending with position.

            WebTransferFile transferFile;
            Guid            id;

            byte[] block1 = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            byte[] block2 = new byte[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
            byte[] block;
            long   pos;

            ClearFolder();

            // Create a file

            id           = Guid.NewGuid();
            transferFile = new WebTransferFile(id, folder, new Uri("http://test.com"), ".pdf", true, true);
            Assert.AreEqual(id, transferFile.ID);
            Assert.IsTrue(transferFile.IsUploading);
            Assert.IsTrue(File.Exists(transferFile.Path + WebTransferCache.UploadExtension));
            Assert.AreEqual(new Uri(new Uri("http://test.com"), transferFile.ID.ToString("D") + ".pdf"), transferFile.Uri);

            // Append the first block

            pos = 0;
            transferFile.Append(pos, block1);

            // Append it again to simulate a duplicate

            transferFile.Append(pos, block1);
            pos += block1.Length;

            // Open an existing file

            transferFile = new WebTransferFile(id, folder, new Uri("http://test.com"), ".pdf", false, true);
            Assert.AreEqual(id, transferFile.ID);
            Assert.IsTrue(transferFile.IsUploading);
            Assert.IsTrue(File.Exists(transferFile.Path + WebTransferCache.UploadExtension));
            Assert.AreEqual(new Uri(new Uri("http://test.com"), transferFile.ID.ToString("D") + ".pdf"), transferFile.Uri);

            // Append the second block

            transferFile.Append(pos, block2);

            // Complete the upload and verify the file contents.

            transferFile.Commit(MD5Hasher.Compute(Helper.Concat(block1, block2)));
            Assert.AreEqual(id, transferFile.ID);
            Assert.IsFalse(transferFile.IsUploading);
            Assert.IsTrue(File.Exists(transferFile.Path));
            Assert.AreEqual(new Uri(new Uri("http://test.com"), transferFile.ID.ToString("D") + ".pdf"), transferFile.Uri);

            using (var stream = transferFile.GetStream())
            {
                block = stream.ReadBytes((int)stream.Length);
                CollectionAssert.AreEqual(Helper.Concat(block1, block2), block);
            }
        }
Пример #6
0
        /// <summary>
        /// Updates a message file's metadata.
        /// </summary>
        /// <param name="path">The file path.</param>
        /// <param name="msgInfo">The message metadata.</param>
        internal void WriteMessageMetadata(string path, QueuedMsgInfo msgInfo)
        {
            using (var fsMsg = new EnhancedFileStream(path, FileMode.Open, FileAccess.ReadWrite))
            {
                // Seek past the message's header and body.

                int    cbBody;
                byte[] md5Hash;

                fsMsg.Position = MsgHeaderSize;
                cbBody         = fsMsg.ReadInt32();
                fsMsg.Position = fsMsg.Position + cbBody;

                // Write the metadata and truncate the file.

                fsMsg.WriteString16(msgInfo.ToString());
                fsMsg.SetLength(fsMsg.Position);

                // Regenerate the MD5 Hash

                fsMsg.Position = MsgMD5Offset + MD5Hasher.DigestSize;
                md5Hash        = MD5Hasher.Compute(fsMsg, fsMsg.Length - fsMsg.Position);
                fsMsg.Position = MsgMD5Offset;
                fsMsg.WriteBytesNoLen(md5Hash);
            }
        }
Пример #7
0
        /// <summary>
        /// Writes a message file.
        /// </summary>
        /// <param name="path">The file path.</param>
        /// <param name="msg">The message.</param>
        /// <param name="msgInfo">The message metadata.</param>
        internal void WriteMessage(string path, QueuedMsg msg, QueuedMsgInfo msgInfo)
        {
            byte[] md5Hash;

            using (var fsMsg = new EnhancedFileStream(path, FileMode.Create, FileAccess.ReadWrite))
            {
                // Write the file header

                fsMsg.WriteInt32(MsgMagic);         // Magic Number
                fsMsg.WriteInt32(0);                // Format Version
                fsMsg.WriteInt32(0);                // Reserved
                fsMsg.WriteBytesNoLen(md5Zeros);    // MD5 hash placeholder

                // Write the message body.

                fsMsg.WriteBytes32(msg.BodyRaw);

                // Write the metadata.

                fsMsg.WriteString16(msgInfo.ToString());

                // Compute and save the MD5 hash

                fsMsg.Position = MsgHeaderSize;
                md5Hash        = MD5Hasher.Compute(fsMsg, fsMsg.Length - fsMsg.Position);
                fsMsg.Position = MsgMD5Offset;
                fsMsg.WriteBytesNoLen(md5Hash);
            }
        }
Пример #8
0
        public void Hashers_MD5()
        {
            EnhancedMemoryStream ms;

            byte[] data;
            byte[] digest1, digest2;

            digest1 = MD5Hasher.Compute(new byte[] { 0, 1, 2, 3 }, 0, 4);
            Assert.AreEqual(16, digest1.Length);
            Assert.AreEqual(16, MD5Hasher.DigestSize);

            digest2 = MD5Hasher.Compute(new byte[] { 1, 1, 2, 3 }, 0, 4);
            Assert.AreNotEqual(digest1, digest2);

            digest1 = MD5Hasher.Compute(new byte[0]);
            Assert.AreEqual(16, digest1.Length);
            Assert.AreEqual(16, MD5Hasher.DigestSize);

            digest1 = MD5Hasher.Compute(new byte[] { 0, 1, 2, 3 });
            ms      = new EnhancedMemoryStream();

            ms.Seek(0, SeekOrigin.Begin);
            ms.Write(new byte[] { 0, 1, 2, 3 }, 0, 4);
            ms.Seek(0, SeekOrigin.Begin);
            digest2 = MD5Hasher.Compute(ms, 4);
            CollectionAssert.AreEqual(digest1, digest2);
            Assert.AreEqual(16, digest2.Length);
            Assert.AreEqual(0, ms.Position);

            data = new byte[2048];
            for (int i = 0; i < data.Length; i++)
            {
                data[i] = (byte)i;
            }

            digest1 = MD5Hasher.Compute(data);

            ms.Seek(0, SeekOrigin.Begin);
            ms.Write(data, 0, data.Length);
            ms.Seek(0, SeekOrigin.Begin);

            digest2 = MD5Hasher.Compute(ms, data.Length);
            CollectionAssert.AreEqual(digest1, digest2);
            Assert.AreEqual(16, digest2.Length);
            Assert.AreEqual(0, ms.Position);

            digest1 = MD5Hasher.Compute("hello");
            digest2 = MD5Hasher.Compute("world");
            CollectionAssert.AreNotEqual(digest1, digest2);
            CollectionAssert.AreEqual(digest1, MD5Hasher.Compute("hello"));

            // These really aren't very good tests for folding but
            // at least they'll verify that it doesn't crash

            Assert.AreEqual(MD5Hasher.FoldOnce(new byte[] { 0, 1, 2, 3 }), MD5Hasher.FoldOnce(new byte[] { 0, 1, 2, 3 }));
            Assert.AreNotEqual((object)MD5Hasher.FoldOnce(new byte[] { 1, 1, 2, 3 }), (object)MD5Hasher.FoldOnce(new byte[] { 0, 1, 2, 3 }));
            Assert.AreEqual(MD5Hasher.FoldTwice(new byte[] { 0, 1, 2, 3 }), MD5Hasher.FoldTwice(new byte[] { 0, 1, 2, 3 }));
            Assert.AreNotEqual(MD5Hasher.FoldTwice(new byte[] { 1, 1, 2, 3 }), MD5Hasher.FoldTwice(new byte[] { 0, 1, 2, 3 }));
        }
Пример #9
0
        /// <summary>
        /// Reads the metadata from a message file.
        /// </summary>
        /// <param name="msgID">The message ID.</param>
        /// <param name="path">Fully qualified path to the message file.</param>
        /// <returns>The <see cref="QueuedMsgInfo" />.</returns>
        internal QueuedMsgInfo ReadMessageMetadata(Guid msgID, string path)
        {
            QueuedMsgInfo msgInfo;
            int           cbBody;

            byte[] md5Hash;
            long   savePos;

            using (var fsMsg = new EnhancedFileStream(path, FileMode.Open, FileAccess.ReadWrite))
            {
                try
                {
                    // Read the message file header

                    if (fsMsg.ReadInt32() != MsgMagic)      // Magic Number
                    {
                        throw new Exception();
                    }

                    if (fsMsg.ReadInt32() != 0)             // Format Version
                    {
                        throw new Exception();
                    }

                    fsMsg.ReadInt32();                      // Reserved

                    // Verify that the MD5 hash saved in then file matches the
                    // hash computed for the remainder of the file as it exists
                    // right now.

                    md5Hash = fsMsg.ReadBytes(MD5Hasher.DigestSize);
                    savePos = fsMsg.Position;

                    if (!Helper.ArrayEquals(md5Hash, MD5Hasher.Compute(fsMsg, fsMsg.Length - fsMsg.Position)))
                    {
                        throw new FormatException(string.Format("Message file [{0}] is corrupt. MD5 digests do not match.", path));
                    }

                    fsMsg.Position = savePos;

                    // Skip over the message body data

                    cbBody         = fsMsg.ReadInt32();
                    fsMsg.Position = fsMsg.Position + cbBody;

                    // Read the metadata and add the provider specific information

                    msgInfo              = new QueuedMsgInfo(fsMsg.ReadString16());
                    msgInfo.PersistID    = msgInfo.ID;
                    msgInfo.ProviderData = path;

                    return(msgInfo);
                }
                catch
                {
                    throw new FormatException(string.Format("Bad message file [{0}].", path));
                }
            }
        }
Пример #10
0
 private void GetFileInfo(string fileName, out int size, out byte[] md5)
 {
     using (var es = new EnhancedFileStream(tempFolder + "\\" + fileName, FileMode.Open, FileAccess.Read))
     {
         size = (int)es.Length;
         md5  = MD5Hasher.Compute(es, size);
     }
 }
Пример #11
0
        public void AppPackage_MD5()
        {
            string       tempPath = GetTempFileName();
            string       tempDir  = Helper.AddTrailingSlash(Path.GetTempPath());
            AppPackage   package  = null;
            MemoryStream ms;

            byte[] md5;

            try
            {
                package = AppPackage.Create(tempPath, AppRef.Parse("appref://myapps/mypackage.zip?version=1.2.3.4"), @"
LaunchType   = Test.MyType:MyAssembly.dll;
LaunchMethod = Foo;
LaunchArgs   = Bar;
");
                using (ms = new MemoryStream(4096))
                {
                    for (int i = 0; i < 4096; i++)
                    {
                        ms.WriteByte((byte)i);
                    }

                    ms.Position = 0;
                    package.AddFile("Test.dat", ms);
                }

                package.Close();
                package = null;

                // Verify that a MD5 hash computed manually on the package file jibes
                // with what AppPackage computes.

                using (var fs = new EnhancedFileStream(tempPath, FileMode.Open, FileAccess.Read))
                {
                    md5 = MD5Hasher.Compute(fs, fs.Length);
                }

                package = AppPackage.Open(tempPath);
                CollectionAssert.AreEqual(md5, package.MD5);

                package.Close();
                package = null;
            }
            finally
            {
                if (package != null)
                {
                    package.Close();
                }

                Delete(tempPath);
            }
        }
Пример #12
0
        /// <summary>
        /// Computes, sets, and returns the response authenticator for the packet.
        /// </summary>
        /// <param name="request">The corresponding request packet.</param>
        /// <param name="secret">The shared secret for the NAS.</param>
        /// <returns>The computed response authenticator.</returns>
        /// <remarks>
        /// This is computed via a MD5 hash over the serialized request
        /// packet plus the serialized response attributes, plus the
        /// shared secret.
        /// </remarks>
        public byte[] ComputeResponseAuthenticator(RadiusPacket request, string secret)
        {
            byte[] serialized = this.ToArray();
            byte[] bytes;

            bytes = Helper.Concat(Helper.Extract(serialized, 0, 4), request.Authenticator);
            bytes = Helper.Concat(bytes, Helper.Extract(serialized, HeaderSize));
            bytes = Helper.Concat(bytes, Helper.ToAnsi(secret));

            return(this.Authenticator = MD5Hasher.Compute(bytes));
        }
Пример #13
0
        /// <summary>
        /// Constructs an <b>Authorization</b> header value by computing the
        /// digest as defined by <a href="http://www.ietf.org/rfc/rfc2069.txt?number=2069">RFC 2069</a>
        /// and modified by <a href="http://www.ietf.org/rfc/rfc3261.txt?number=3261">RFC 3261</a>
        /// from the user credentials and <b>WWW-Authenticate</b> header values
        /// passed.
        /// </summary>
        /// <param name="authenticate">The <see cref="SipAuthenticateValue" /> specifying the authentication challenge.</param>
        /// <param name="userName">The user name.</param>
        /// <param name="password">The user's password.</param>
        /// <param name="method">The SIP method exactly as it </param>
        /// <param name="digestUri">The URI of the SIP server entity where the authorization value will be presented.</param>
        public SipAuthorizationValue(SipAuthenticateValue authenticate,
                                     string userName,
                                     string password,
                                     string method,
                                     string digestUri)
        {
            if (String.Compare(authenticate.Algorithm, "MD5") != 0)
            {
                throw new SipException("Unsupported digest algorithm [{0}].", authenticate.Algorithm, true);
            }

            base["algorithm"] = "MD5";      // Algorithm defaults to MD5
            base["username"]  = userName;
            base["realm"]     = authenticate.Realm;
            base["uri"]       = digestUri;
            base["nonce"]     = authenticate.Nonce;

            // Compute the authorization digest.

            string key;

            byte[] hash;
            string ha1;
            string ha2;
            string response;

            // Compute: HA1 = H(username + ":" + realm + ":" + password)

            key  = userName + ":" + authenticate.Realm + ":" + password;
            hash = MD5Hasher.Compute(Helper.ToUTF8(key));     // $todo(jeff.lill): Not complety sure of the encoding
            ha1  = Helper.ToHex(hash);

            // Compute: HA2 = H(method + ":" + digesturi)

            key  = method.ToUpper() + ":" + digestUri;
            hash = MD5Hasher.Compute(Helper.ToUTF8(key));     // $todo(jeff.lill): Not complety sure of the encoding
            ha2  = Helper.ToHex(hash);

            // Compute: response = H(HA1 + ":" + nonce + ":" + HA2)

            key      = ha1 + ":" + authenticate.Nonce + ":" + ha2;
            hash     = MD5Hasher.Compute(Helper.ToUTF8(key));     // $todo(jeff.lill): Not complety sure of the encoding
            response = Helper.ToHex(hash);

            base["response"] = response;
        }
Пример #14
0
        /// <summary>
        /// Completes the uploading of the file by verifying that its contents
        /// match the MD5 signature passed and then stripping the temporary
        /// upload extension from its file name.
        /// </summary>
        /// <param name="md5Signature">A 16-byte array with the file's MD-5 signature.</param>
        /// <exception cref="IOException">Thrown if the file does not exist or the signature doesn't match.</exception>
        /// <exception cref="ArgumentException">Thrown if is is not a upload file.</exception>
        /// <remarks>
        /// <note>
        /// This method <b>does not</b> throw an exception if this method has already
        /// been called to complete the upload and the method will delete the file if
        /// the signature doesn't match.
        /// </note>
        /// </remarks>
        public void Commit(byte[] md5Signature)
        {
            string uploadPath = this.Path + WebTransferCache.UploadExtension;

            byte[] actualSignature;

            if (!IsUploading)
            {
                throw new ArgumentException("File is not being uploaded.");
            }

            if (md5Signature.Length != MD5Hasher.DigestSize)
            {
                throw new ArgumentException("Invalid MD5 signature.", "md5Signature");
            }

            if (File.Exists(uploadPath))
            {
                using (var stream = GetStream())
                {
                    actualSignature = MD5Hasher.Compute(stream, stream.Length);
                }

                if (!Helper.ArrayEquals(md5Signature, actualSignature))
                {
                    Helper.DeleteFile(uploadPath);
                    throw new IOException("Upload failure: MD5 signature mismatch.");
                }

                IsUploading = false;

                File.Move(uploadPath, this.Path);
            }
            else if (!File.Exists(this.Path))
            {
                throw new IOException(string.Format("Upload file [{0}] does not exist.", this.Path));
            }
        }
Пример #15
0
        public void Hashers_HMAC_MD5()
        {
            byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            byte[] key;
            byte[] digest;

            key    = new byte[] { 0, 1, 2, 3, 4, 5 };
            digest = MD5Hasher.Compute(key, data);
            Assert.AreEqual(MD5Hasher.DigestSize, digest.Length);

            key = new byte[128];
            for (int i = 0; i < key.Length; i++)
            {
                key[i] = (byte)i;
            }

            digest = MD5Hasher.Compute(key, data);
            Assert.AreEqual(MD5Hasher.DigestSize, digest.Length);

            // The data for this test came from RFC2104

            key = new byte[16];
            for (int i = 0; i < key.Length; i++)
            {
                key[i] = 0xAA;
            }

            data = new byte[50];
            for (int i = 0; i < data.Length; i++)
            {
                data[i] = 0xDD;
            }

            digest = MD5Hasher.Compute(key, data);
            CollectionAssert.AreEqual(Helper.FromHex("56be34521d144c88dbb8c733f0e8b3f6"), digest);
        }
Пример #16
0
        /// <summary>
        /// Handles the installation of an application's configuration file.
        /// </summary>
        /// <param name="iniFile">The application INI file name (e.g. "MyApp.ini").</param>
        /// <remarks>
        /// <para>
        /// This method provides the mechanism by which setup won't overwrite
        /// user changes to an configuration file when installing an updated
        /// version of the application.  The method compares the MD5 hash of the
        /// base version of the INI file to the hash of the currently installed
        /// INI file.  If the hashes match, the installed version will be overwritten
        /// by the base version.  If the hashes differ, then the user will be
        /// notified and given the opportunity to choose whether to overwrite
        /// the installed INI.  In either case, any installed INI file will be
        /// backed up.
        /// </para>
        /// <para>
        /// This method assumes that the base version of the INI file is named
        /// <b>&lt;file&gt;.ini.base</b> and the file with the base MD5 hash is
        /// named <b>&lt;file&gt;.ini.md5</b>.  The method generates a new MD5
        /// file as necessary.
        /// </para>
        /// </remarks>
        public void InstallIniFile(string iniFile)
        {
            string baseFile = iniFile + ".base";

            byte[] baseMD5;
            byte[] curMD5;

            if (!File.Exists(installIniFolder + baseFile))
            {
                throw new IOException(string.Format("[{0}] file needs to be added to the setup project.", baseFile));
            }

            if (!File.Exists(installIniFolder + iniFile))
            {
                // No INI file exists, so simply copy the base file over and generate
                // the MD5 hash.

                File.Copy(installIniFolder + baseFile, installIniFolder + iniFile);

                using (EnhancedStream es = new EnhancedFileStream(installIniFolder + iniFile, FileMode.Open, FileAccess.Read))
                {
                    curMD5 = MD5Hasher.Compute(es, es.Length);
                }

                using (StreamWriter writer = new StreamWriter(installIniFolder + iniFile + ".md5", false, Helper.AnsiEncoding))
                {
                    writer.WriteLine("MD5={0}", Helper.ToHex(curMD5));
                }

                return;
            }

            // Compute the MD5 hash for the existing file and compare it to the
            // hash for the original base file (if there is one).

            using (EnhancedFileStream es = new EnhancedFileStream(installIniFolder + iniFile, FileMode.Open, FileAccess.Read))
            {
                curMD5 = MD5Hasher.Compute(es, es.Length);
            }

            try
            {
                using (var reader = new StreamReader(installIniFolder + iniFile + ".md5", Helper.AnsiEncoding))
                {
                    string line;

                    line = reader.ReadLine();
                    if (line == null)
                    {
                        throw new Exception();
                    }

                    if (!line.StartsWith("MD5="))
                    {
                        throw new Exception();
                    }

                    baseMD5 = Helper.FromHex(line.Substring(4));
                }
            }
            catch
            {
                baseMD5 = new byte[0];  // The hashes will always differ if the MD5 file doesn't exist or isn't valid.
            }

            // Make a backup copy of the current INI file.

            File.Copy(installIniFolder + iniFile, installIniFolder + Helper.ToIsoDate(DateTime.UtcNow).Replace(':', '-') + "-" + iniFile);

            if (Helper.ArrayEquals(baseMD5, curMD5))
            {
                // If the base and current MD5 hashes are the same, we can be assured that the
                // user has not customized the INI file.  In this case, we'll simply overwrite
                // the existing INI file with the new version.

                File.Delete(installIniFolder + iniFile);
                File.Copy(installIniFolder + baseFile, installIniFolder + iniFile);
            }
            else
            {
                // It looks like the user has modified the INI file.  So prompt the user
                // to see if he wants to overwrite or not.

                if (MessageBox.Show(string.Format("The application configuration file [{0}] has been customized.\r\n\r\nDo you want to overwrite this with the new version?", iniFile),
                                    setupTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
                {
                    File.Delete(installIniFolder + iniFile);
                    File.Copy(installIniFolder + baseFile, installIniFolder + iniFile);
                }
            }

            // Generate the MD5 hash file from the base INI file.

            using (var es = new EnhancedFileStream(installIniFolder + baseFile, FileMode.Open, FileAccess.Read))
            {
                baseMD5 = MD5Hasher.Compute(es, es.Length);
            }

            using (var writer = new StreamWriter(installIniFolder + iniFile + ".md5", false, Helper.AnsiEncoding))
            {
                writer.WriteLine("MD5={0}", Helper.ToHex(baseMD5));
            }

            // Perform any macro replacements.

            if (iniMacroReplacements.Count > 0)
            {
                using (var fs = new EnhancedFileStream(installIniFolder + iniFile, FileMode.Open, FileAccess.ReadWrite))
                {
                    foreach (var replacement in iniMacroReplacements)
                    {
                        fs.Position = 0;
                        Config.EditMacro(fs, Helper.AnsiEncoding, replacement.Key, replacement.Value);
                    }
                }
            }
        }
Пример #17
0
        public void Initialize()
        {
            Helper.InitializeApp(Assembly.GetExecutingAssembly());

            this.ADSettings   = new ADTestSettings();
            this.DB           = SqlTestDatabase.Create();
            this.AuthFilePath = Path.GetTempFileName();

            //-------------------------------------------------------------
            // Initialize file authentication

            Helper.WriteToFile(this.AuthFilePath, @"

file.com;file1;file-password1
file.com;file2;file-password2
");
            this.Accounts.Add(new AuthTestAccount(AuthTestExtensionType.File, "file.com", "file1", "file-password1"));
            this.Accounts.Add(new AuthTestAccount(AuthTestExtensionType.File, "file.com", "file2", "file-password2"));

            //-------------------------------------------------------------
            // Initialize RADIUS authentication

            RadiusServerSettings radiusSettings = new RadiusServerSettings();

            radiusSettings.NetworkBinding = NetworkBinding.Parse("ANY:52111");
            radiusSettings.Devices.Add(new RadiusNasInfo(IPAddress.Loopback, this.RadiusSecret));
            radiusSettings.Devices.Add(new RadiusNasInfo(NetHelper.GetActiveAdapter(), this.RadiusSecret));

            this.RadiusServer = new RadiusServer();
            this.RadiusServer.Start(radiusSettings);
            this.RadiusServer.LoadAccountsFromString(@"

radius.com;radius1;radius-password1
radius.com;radius2;radius-password2
");
            this.Accounts.Add(new AuthTestAccount(AuthTestExtensionType.Radius, "radius.com", "radius1", "radius-password1"));
            this.Accounts.Add(new AuthTestAccount(AuthTestExtensionType.Radius, "radius.com", "radius2", "radius-password2"));

            //-------------------------------------------------------------
            // Initialize config authentication

            Config.SetConfig(@"

Accounts[0] = config.com;config1;config-password1
Accounts[1] = config.com;config2;config-password2
");
            this.Accounts.Add(new AuthTestAccount(AuthTestExtensionType.Config, "config.com", "config1", "config-password1"));
            this.Accounts.Add(new AuthTestAccount(AuthTestExtensionType.Config, "config.com", "config2", "config-password2"));

#if TEST_AD
            //-------------------------------------------------------------
            // Initialize active directory authentication

#if !TEST_AD_LDAP
            if (ADSettings.NasSecret != string.Empty)   // Disable the test if the NAS secret is blank
#endif
            this.Accounts.Add(new AuthTestAccount(AuthTestExtensionType.Ldap, ADSettings.Domain, ADSettings.Account, ADSettings.Password));
#endif

            //-------------------------------------------------------------
            // Initalize ODBC authentication

            SqlConnection   sqlCon = null;
            SqlScriptRunner scriptRunner;
            MacroProcessor  processor;
            string          initScript =
                @"
create table Accounts (

Realm           varchar(64),
Account         varchar(64),
Password        varchar(64),
MD5             varbinary(128),
SHA1            varbinary(128),
SHA256          varbinary(128),
SHA512          varbinary(128)
)
go

insert into Accounts(Realm,Account,Password,MD5,SHA1,SHA256,SHA512)
values ('odbc.com','odbc1','odbc-password1',$(md5-1),$(sha1-1),$(sha256-1),$(sha512-1))

insert into Accounts(Realm,Account,Password,MD5,SHA1,SHA256,SHA512)
values ('odbc.com','odbc2','odbc-password2',$(md5-2),$(sha1-2),$(sha256-2),$(sha512-2))

go
";
            try
            {
                processor = new MacroProcessor();
                processor.Add("md5-1", SqlHelper.Literal(MD5Hasher.Compute("odbc-password1")));
                processor.Add("sha1-1", SqlHelper.Literal(SHA1Hasher.Compute("odbc-password1")));
                processor.Add("sha256-1", SqlHelper.Literal(SHA256Hasher.Compute("odbc-password1")));
                processor.Add("sha512-1", SqlHelper.Literal(SHA512Hasher.Compute("odbc-password1")));

                processor.Add("md5-2", SqlHelper.Literal(MD5Hasher.Compute("odbc-password2")));
                processor.Add("sha1-2", SqlHelper.Literal(SHA1Hasher.Compute("odbc-password2")));
                processor.Add("sha256-2", SqlHelper.Literal(SHA256Hasher.Compute("odbc-password2")));
                processor.Add("sha512-2", SqlHelper.Literal(SHA512Hasher.Compute("odbc-password2")));

                initScript = processor.Expand(initScript);

                sqlCon       = DB.OpenConnection();
                scriptRunner = new SqlScriptRunner(initScript);
                scriptRunner.Run(sqlCon);

                this.Accounts.Add(new AuthTestAccount(AuthTestExtensionType.Odbc, "odbc.com", "odbc1", "odbc-password1"));
                this.Accounts.Add(new AuthTestAccount(AuthTestExtensionType.Odbc, "odbc.com", "odbc2", "odbc-password2"));
            }
            finally
            {
                if (sqlCon != null)
                {
                    sqlCon.Close();
                }
            }
        }
Пример #18
0
        public void WebTransferCache_UploadBadMD5()
        {
            // Verify that we can detect a corrupted upload.

            WebTransferCache cache;
            WebTransferFile  transferFile;
            Guid             id;

            byte[] block1 = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            byte[] block2 = new byte[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
            long   pos;

            byte[] md5;

            ClearFolder();

            cache = new WebTransferCache(new Uri("http://test.com"), folder, "", TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10));
            cache.Start();

            try
            {
                // Create a file

                transferFile = cache.GetUploadFile(Guid.Empty, ".pdf");
                id           = transferFile.ID;
                Assert.AreNotEqual(Guid.Empty, transferFile.ID);
                Assert.IsTrue(transferFile.IsUploading);
                Assert.IsTrue(File.Exists(transferFile.Path + WebTransferCache.UploadExtension));
                Assert.AreEqual(new Uri(new Uri("http://test.com/" + cache.HashIDToSubFolder(transferFile.ID)), transferFile.ID.ToString("D") + ".pdf"), transferFile.Uri);

                // Append the first block

                pos = 0;
                transferFile.Append(pos, block1);

                // Append it again to simulate a duplicate

                transferFile.Append(pos, block1);
                pos += block1.Length;

                // Open an existing file

                transferFile = cache.GetUploadFile(id, ".pdf");
                Assert.AreEqual(id, transferFile.ID);
                Assert.IsTrue(transferFile.IsUploading);
                Assert.IsTrue(File.Exists(transferFile.Path + WebTransferCache.UploadExtension));
                Assert.AreEqual(new Uri(new Uri("http://test.com/" + cache.HashIDToSubFolder(transferFile.ID)), transferFile.ID.ToString("D") + ".pdf"), transferFile.Uri);

                // Append the second block

                transferFile.Append(pos, block2);

                // Complete the upload and verify the file contents.

                md5    = MD5Hasher.Compute(Helper.Concat(block1, block2));
                md5[0] = (byte)~md5[0];    // Mess with the hash

                try
                {
                    transferFile.Commit(md5);
                    Assert.Fail("Expected an IOException detecting the MD5 signature mismatch.");
                }
                catch (IOException)
                {
                    // Expected
                }
            }
            finally
            {
                cache.Stop();
            }
        }
Пример #19
0
        /// <summary>
        /// Encrypts a user password string by combining it with the shared NAS
        /// secret and the message authenticator as described in RFC 2865 page 27.
        /// </summary>
        /// <param name="userPassword">The user password to be encrypted.</param>
        /// <param name="secret">The shared NAS secret.</param>
        /// <returns>The encrypted password.</returns>
        /// <exception cref="RadiusException">Thrown if the password is too large or too small.</exception>
        public byte[] EncryptUserPassword(string userPassword, string secret)
        {
            var bs = new EnhancedBlockStream(128, 128);

            byte[] secretBytes = Helper.ToAnsi(secret);
            byte[] cypherBlock = new byte[16];
            byte[] rawPwd;
            byte[] xorHash;
            byte[] pwd;
            int    pos;

            try
            {
                rawPwd = Helper.ToAnsi(userPassword);
                if (rawPwd.Length == 0)
                {
                    throw new RadiusException("Zero length password is not allowed.");
                }

                // Copy userPassword into pwd, padding the result out with zeros
                // to a multiple of 16 bytes

                if (rawPwd.Length % 16 == 0)
                {
                    pwd = rawPwd;
                }
                else
                {
                    pwd = new byte[(rawPwd.Length / 16 + 1) * 16];
                    Array.Copy(rawPwd, pwd, rawPwd.Length);
                }

                // The first XOR hash is MD5(secret + authenticator)

                xorHash = MD5Hasher.Compute(Helper.Concat(secretBytes, this.Authenticator));

                // Perform the encryption

                pos = 0;
                while (true)
                {
                    // Cyperblock = XOR hash ^ next 16 bytes of password

                    for (int i = 0; i < 16; i++)
                    {
                        cypherBlock[i] = (byte)(xorHash[i] ^ pwd[pos + i]);
                    }

                    bs.WriteBytesNoLen(cypherBlock);

                    pos += 16;
                    if (pos >= pwd.Length)
                    {
                        break;
                    }

                    // Next XOR hash is MD5(secret + cypherblock)

                    xorHash = MD5Hasher.Compute(Helper.Concat(secretBytes, cypherBlock));
                }

                if (bs.Length > 128)
                {
                    throw new RadiusException("Encrypted password exceeds 128 bytes.");
                }

                return(bs.ToArray());
            }
            finally
            {
                bs.Close();
            }
        }
Пример #20
0
        /// <summary>
        /// Decrypts a user password by encrypted using <see cref="EncryptUserPassword" />
        /// using the message authenticator and the shared NAS secret.
        /// </summary>
        /// <param name="encryptedPassword">The encrypted password.</param>
        /// <param name="secret">The shared NAS secret.</param>
        /// <returns>The decrypted password.</returns>
        /// <exception cref="RadiusException">Thrown if the encrypted password is invalid.</exception>
        public string DecryptUserPassword(byte[] encryptedPassword, string secret)
        {
            var bs = new EnhancedBlockStream(128, 128);

            byte[] secretBytes = Helper.ToAnsi(secret);
            byte[] clearBlock  = new byte[16];
            byte[] xorHash;
            byte[] decrypted;
            int    pos;
            int    zeroPos;

            try
            {
                // The encrypted password length must be a non-zero multiple of 16 bytes.

                if (encryptedPassword.Length == 0 || encryptedPassword.Length % 16 != 0)
                {
                    throw new RadiusException("Encrypted user password length must be a positive multiple of 16 bytes.");
                }

                // The first XOR hash is MD5(secret + authenticator)

                xorHash = MD5Hasher.Compute(Helper.Concat(secretBytes, this.Authenticator));

                // Perform the decryption.  The trick here is to unmunge the 16 byte
                // blocks by XORing them with the current XOR hash.

                pos = 0;
                while (true)
                {
                    // clearBlock = XOR hash ^ next 16 encrypted bytes

                    for (int i = 0; i < 16; i++)
                    {
                        clearBlock[i] = (byte)(xorHash[i] ^ encryptedPassword[pos + i]);
                    }

                    bs.WriteBytesNoLen(clearBlock);

                    pos += 16;
                    if (pos >= encryptedPassword.Length)
                    {
                        break;
                    }

                    // Next XOR hash = MD5(secret + last cypherblock)

                    xorHash = MD5Hasher.Compute(Helper.Concat(secretBytes, Helper.Extract(encryptedPassword, pos - 16, 16)));
                }

                // Scan forward to the first zero byte.  If we find one, we're going
                // to assume that it was a padding byte.

                decrypted = bs.ToArray();
                zeroPos   = -1;

                for (int i = 0; i < decrypted.Length; i++)
                {
                    if (decrypted[i] == 0)
                    {
                        zeroPos = i;
                        break;
                    }
                }

                if (zeroPos == -1)
                {
                    return(Helper.FromAnsi(decrypted));
                }
                else
                {
                    return(Helper.FromAnsi(decrypted, 0, zeroPos));
                }
            }
            finally
            {
                bs.Close();
            }
        }
Пример #21
0
        public void WebTransferCache_Upload()
        {
            // Test the file upload scenario.

            WebTransferCache cache;
            WebTransferFile  transferFile;
            Guid             id;

            byte[] block1 = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            byte[] block2 = new byte[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
            byte[] block;
            long   pos;

            ClearFolder();

            cache = new WebTransferCache(new Uri("http://test.com"), folder, "", TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10));
            cache.Start();

            try
            {
                // Create a file

                transferFile = cache.GetUploadFile(Guid.Empty, ".pdf");
                id           = transferFile.ID;
                Assert.AreNotEqual(Guid.Empty, transferFile.ID);
                Assert.IsTrue(transferFile.IsUploading);
                Assert.IsTrue(File.Exists(transferFile.Path + WebTransferCache.UploadExtension));
                Assert.AreEqual(new Uri(new Uri("http://test.com/" + cache.HashIDToSubFolder(transferFile.ID)), transferFile.ID.ToString("D") + ".pdf"), transferFile.Uri);

                // Append the first block

                pos = 0;
                transferFile.Append(pos, block1);

                // Append it again to simulate a duplicate

                transferFile.Append(pos, block1);
                pos += block1.Length;

                // Open an existing file

                transferFile = cache.GetUploadFile(id, ".pdf");
                Assert.AreEqual(id, transferFile.ID);
                Assert.IsTrue(transferFile.IsUploading);
                Assert.IsTrue(File.Exists(transferFile.Path + WebTransferCache.UploadExtension));
                Assert.AreEqual(new Uri(new Uri("http://test.com/" + cache.HashIDToSubFolder(transferFile.ID)), transferFile.ID.ToString("D") + ".pdf"), transferFile.Uri);

                // Append the second block

                transferFile.Append(pos, block2);

                // Complete the upload and verify the file contents.

                transferFile.Commit(MD5Hasher.Compute(Helper.Concat(block1, block2)));
                Assert.AreEqual(id, transferFile.ID);
                Assert.IsFalse(transferFile.IsUploading);
                Assert.IsTrue(File.Exists(transferFile.Path));
                Assert.AreEqual(new Uri(new Uri("http://test.com/" + cache.HashIDToSubFolder(transferFile.ID)), transferFile.ID.ToString("D") + ".pdf"), transferFile.Uri);

                using (var stream = transferFile.GetStream())
                {
                    block = stream.ReadBytes((int)stream.Length);
                    CollectionAssert.AreEqual(Helper.Concat(block1, block2), block);
                }
            }
            finally
            {
                cache.Stop();
            }
        }
Пример #22
0
        public void WebTransferCache_UploadEncrypt()
        {
            // Test file upload with encryption.

            WebTransferCache cache;
            WebTransferFile  transferFile;
            Guid             id;

            byte[] block1 = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            byte[] block2 = new byte[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
            byte[] block;
            long   pos;

            ClearFolder();

            cache = new WebTransferCache(new Uri("http://test.com"), folder, "", TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10));
            cache.Start();

            try
            {
                // Create a file

                transferFile = cache.GetUploadFile(Guid.Empty, ".pdf");
                id           = transferFile.ID;
                Assert.AreNotEqual(Guid.Empty, transferFile.ID);
                Assert.IsTrue(transferFile.IsUploading);
                Assert.IsTrue(File.Exists(transferFile.Path + WebTransferCache.UploadExtension));
                Assert.AreEqual(new Uri(new Uri("http://test.com/" + cache.HashIDToSubFolder(transferFile.ID)), transferFile.ID.ToString("D") + ".pdf"), transferFile.Uri);

                // Append the first block

                pos = 0;
                transferFile.Append(pos, block1);

                // Append it again to simulate a duplicate

                transferFile.Append(pos, block1);
                pos += block1.Length;

                // Open an existing file

                transferFile = cache.GetUploadFile(id, ".pdf");
                Assert.AreEqual(id, transferFile.ID);
                Assert.IsTrue(transferFile.IsUploading);
                Assert.IsTrue(File.Exists(transferFile.Path + WebTransferCache.UploadExtension));
                Assert.AreEqual(new Uri(new Uri("http://test.com/" + cache.HashIDToSubFolder(transferFile.ID)), transferFile.ID.ToString("D") + ".pdf"), transferFile.Uri);

                // Append the second block

                transferFile.Append(pos, block2);

                // Complete the upload and verify the file contents.

                transferFile.Commit(MD5Hasher.Compute(Helper.Concat(block1, block2)));
                Assert.AreEqual(id, transferFile.ID);
                Assert.IsFalse(transferFile.IsUploading);
                Assert.IsTrue(File.Exists(transferFile.Path));
                Assert.AreEqual(new Uri(new Uri("http://test.com/" + cache.HashIDToSubFolder(transferFile.ID)), transferFile.ID.ToString("D") + ".pdf"), transferFile.Uri);

                using (var stream = transferFile.GetStream())
                {
                    block = stream.ReadBytes((int)stream.Length);
                    CollectionAssert.AreEqual(Helper.Concat(block1, block2), block);
                }

                // Now encrypt the file and verify.

                var key = Crypto.GenerateSymmetricKey(CryptoAlgorithm.AES, 256);

                cache.EncryptFile(key, id, ".pdf");

                using (var stream = transferFile.GetStream())
                {
                    block = stream.ReadBytes((int)stream.Length);
                    CollectionAssert.AreNotEqual(Helper.Concat(block1, block2), block); // Shouldn't be equal any more due to the encryption.
                }

                // Decrypt and verify.

                using (var stream = transferFile.GetStream())
                {
                    using (var decryptor = new StreamDecryptor(key))
                    {
                        var ms = new MemoryStream();

                        decryptor.Decrypt(stream, ms);
                        CollectionAssert.AreEqual(Helper.Concat(block1, block2), ms.ToArray());
                    }
                }
            }
            finally
            {
                cache.Stop();
            }
        }
Пример #23
0
        /// <summary>
        /// Scans the input stream, validating its structure and loading
        /// the package entries.
        /// </summary>
        private void Load()
        {
            PackageHeader header;

            byte[] hash;

            packageIn.Position = 0;
            header             = new PackageHeader(packageIn);
            cbHeader           = (int)packageIn.Position;

            // Compute a MD5 hash on the rest of then file and compare
            // the result to what we read from the header.

            hash = MD5Hasher.Compute(packageIn, packageIn.Length - cbHeader);
            if (hash.Length != header.Hash.Length)
            {
                throw new PackageException(CorruptPackage);
            }

            for (int i = 0; i < hash.Length; i++)
            {
                if (hash[i] != header.Hash[i])
                {
                    throw new PackageException(CorruptPackage);
                }
            }

            // Read the package entry headers.

            packageIn.Position = cbHeader;
            while (true)
            {
                var entry = new PackageEntry(this, packageIn);

                if (entry.IsEol)
                {
                    break;
                }

                entries.Add(entry.FullName.ToUpper(), entry);
            }

            // Walk back through the entries and link each entry to
            // its parent folder.

            foreach (PackageEntry entry in entries.Values)
            {
                PackageEntry parent;
                int          pos;

                if (entry == root)
                {
                    continue;
                }

                pos = entry.FullName.LastIndexOf('/');
                if (pos == -1)
                {
                    throw new PackageException(CorruptPackage);
                }

                if (pos == 0)
                {
                    parent = root;
                }
                else
                {
                    parent = (PackageEntry)entries[entry.FullName.Substring(0, pos).ToUpper()];
                    if (parent == null)
                    {
                        throw new PackageException(CorruptPackage);
                    }
                }

                entry.SetParent(parent);
                parent.AddChild(entry);
            }
        }
Пример #24
0
        /// <summary>
        /// Authenticates the account credentials against the authentication extension.
        /// </summary>
        /// <param name="realm">The authentication realm.</param>
        /// <param name="account">The account ID.</param>
        /// <param name="password">The password.</param>
        /// <returns>A <see cref="AuthenticationResult" /> instance with the result of the operation.</returns>
        /// <remarks>
        /// <para>
        /// The <see cref="AuthenticationResult.Status" /> property indicates the disposition
        /// of the authentication operation.  Extensions will return <see cref="AuthenticationStatus.Authenticated" />
        /// if the operation was successful.  Authentication failures due to the
        /// sumbission of invalid credentials will be indicated by returning one of
        /// the error codes.  Extensions may return specific error codes such as
        /// <see cref="AuthenticationStatus.BadPassword" /> and <see cref="AuthenticationStatus.BadAccount" />
        /// or the generic error code <see cref="AuthenticationStatus.AccessDenied" />.
        /// </para>
        /// <para>
        /// The <see cref="AuthenticationResult.MaxCacheTime" /> returns as the maximum time the
        /// results of the authentication operation should be cached.
        /// </para>
        /// </remarks>
        /// <exception cref="AuthenticationException">Thrown for authentication related exception.</exception>
        public AuthenticationResult Authenticate(string realm, string account, string password)
        {
            OdbcConnection dbCon;
            OdbcCommand    cmd;
            OdbcDataReader reader = null;
            MacroProcessor processor;
            string         _conString;
            string         query;
            int            authCode;

            using (TimedLock.Lock(this))
            {
                if (!IsOpen)
                {
                    throw new AuthenticationException("Authentication extension is closed.");
                }

                cAuthentications++;
                _conString = conString;

                // Substitute the credentials into the query template.

                processor = new MacroProcessor();
                processor.Add("realm", SqlHelper.Literal(realm));
                processor.Add("account", SqlHelper.Literal(account));
                processor.Add("password", SqlHelper.Literal(password));
                processor.Add("md5-password", SqlHelper.Literal(MD5Hasher.Compute(password)));
                processor.Add("sha1-password", SqlHelper.Literal(SHA1Hasher.Compute(password)));
                processor.Add("sha256-password", SqlHelper.Literal(SHA256Hasher.Compute(password)));
                processor.Add("sha512-password", SqlHelper.Literal(SHA512Hasher.Compute(password)));
                query = processor.Expand(queryTemplate);
            }

            // Perform the query.

            dbCon = new OdbcConnection(_conString);
            dbCon.Open();

            try
            {
                cmd             = dbCon.CreateCommand();
                cmd.CommandText = query;
                cmd.CommandType = CommandType.Text;

                perf.Queries.Increment();
                reader = cmd.ExecuteReader();
                if (!reader.Read())
                {
                    authCode = (int)AuthenticationStatus.AccessDenied; // Empty result set
                }
                else
                {
                    object o    = reader[0];
                    Type   type = o.GetType();

                    if (type == typeof(byte))
                    {
                        authCode = (int)(byte)o;
                    }
                    else if (type == typeof(int))
                    {
                        authCode = (int)o;
                    }
                    else if (type == typeof(long))
                    {
                        authCode = (int)(long)o;
                    }
                    else
                    {
                        throw new AuthenticationException("ODBC authenticate query returned a [{0}] instead of the expected [integer].", type.Name);
                    }

                    if (authCode < 0 || authCode > 5)
                    {
                        throw new AuthenticationException("ODBC authenticate query returned the invalid return code [{0}]. Valid codes range from 0..5", authCode);
                    }
                }
            }
            catch (Exception e)
            {
                perf.Exceptions.Increment();
                throw new AuthenticationException(e);
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                }

                dbCon.Close();
            }

            return(new AuthenticationResult((AuthenticationStatus)authCode, maxCacheTime));
        }