Beispiel #1
0
        /// ----------------------------------------------------------------------------------------
        /// <summary>
        /// Helper method: Get preferences dictionary from decrypted data.
        /// In editing mode, users have to enter the right SEB administrator password 
        /// before they can access the settings contents
        /// and returns the decrypted bytes 
        /// </summary>
        /// ----------------------------------------------------------------------------------------
        private static IDictionary<string, object> GetPreferencesDictFromConfigData(byte[] sebData, GetPasswordMethod getPassword, bool forEditing)
        {
            IDictionary<string, object> sebPreferencesDict = null;
            try
            {
                // Get preferences dictionary from decrypted data
                sebPreferencesDict = (IDictionary<string, object>)PropertyList.readPlist(sebData);
            }
            catch(Exception readPlistException)
            {
                SebMessageBox.Show(SEBUIStrings.loadingSettingsFailed, SEBUIStrings.loadingSettingsFailedReason, MessageBoxImage.Error, MessageBoxButton.OK);
                Console.WriteLine(readPlistException.Message);
                return null;
            }
            // In editing mode, the user has to enter the right SEB administrator password used in those settings before he can access their contents
            if(forEditing)
            {
                // Get the admin password set in these settings
                string sebFileHashedAdminPassword = SebInstance.Settings.Get<string>(SebSettings.KeyHashedAdminPassword);
                // If there was no or empty admin password set in these settings, the user can access them anyways
                if(!String.IsNullOrEmpty(sebFileHashedAdminPassword))
                {
                    // Get the current hashed admin password
                    string hashedAdminPassword = SebInstance.Settings.Get<string>(SebSettings.KeyHashedAdminPassword);
                    if(hashedAdminPassword == null)
                    {
                        hashedAdminPassword = "";
                    }
                    // If the current hashed admin password is same as the hashed admin password from the settings file
                    // then the user is allowed to access the settings
                    if(String.Compare(hashedAdminPassword, sebFileHashedAdminPassword, StringComparison.OrdinalIgnoreCase) != 0)
                    {
                        // otherwise we have to ask for the SEB administrator password used in those settings and
                        // allow opening settings only if the user enters the right one

                        if(!askForPasswordAndCompareToHashedPassword(sebFileHashedAdminPassword, getPassword, forEditing))
                        {
                            return null;
                        }
                    }
                }
            }
            // Reading preferences was successful!
            return sebPreferencesDict;
        }
Beispiel #2
0
        /// ----------------------------------------------------------------------------------------
        /// <summary>
        /// Helper method which decrypts the byte array using an empty password, 
        /// or the administrator password currently set in SEB 
        /// or asks for the password used for encrypting this SEB file
        /// for configuring the client 
        /// </summary>
        /// ----------------------------------------------------------------------------------------
        private static IDictionary<string, object> DecryptDataWithPasswordForConfiguringClient(byte[] sebData, GetPasswordMethod getPassword, bool forEditing, ref string sebFilePassword, ref bool passwordIsHash)
        {
            passwordIsHash = false;
            string password;
            // First try to decrypt with the current admin password
            // get admin password hash
            var hashedAdminPassword = SebInstance.Settings.Get<string>(SebSettings.KeyHashedAdminPassword);
            if(hashedAdminPassword == null)
            {
                hashedAdminPassword = "";
            }
            // We use always uppercase letters in the base16 hashed admin password used for encrypting
            hashedAdminPassword = hashedAdminPassword.ToUpper();
            IDictionary<string, object> sebPreferencesDict;
            var decryptedSebData = SebProtectionController.DecryptDataWithPassword(sebData, hashedAdminPassword);
            if(decryptedSebData == null)
            {
                // If decryption with admin password didn't work, try it with an empty password
                decryptedSebData = SebProtectionController.DecryptDataWithPassword(sebData, "");
                if(decryptedSebData == null)
                {
                    // If decryption with empty and admin password didn't work, ask for the password the .seb file was encrypted with
                    // Allow up to 5 attempts for entering decoding password
                    var gotPassword = getPassword(GetPasswordPurpose.ConfigureClient, p =>
                    {
                        var hashedPassword = SebProtectionController.ComputePasswordHash(p);
                        // we try to decrypt with the hashed password
                        decryptedSebData = SebProtectionController.DecryptDataWithPassword(sebData, hashedPassword);
                        return decryptedSebData != null;
                    }, out password);
                    // If cancel was pressed, abort
                    if(!gotPassword.HasValue)
                    {
                        return null;
                    }
                    if(!gotPassword.Value)
                    {
                        //wrong password entered in 5th try: stop reading .seb file
                        SebMessageBox.Show(SEBUIStrings.reconfiguringLocalSettingsFailed, SEBUIStrings.reconfiguringLocalSettingsFailedWrongPassword, MessageBoxImage.Error, MessageBoxButton.OK);
                        return null;
                    }
                    else
                    {
                        // Decrypting with entered password worked: We save it for returning it later
                        if(forEditing) sebFilePassword = password;
                    }
                }
            }
            else
            {
                //decrypting with hashedAdminPassword worked: we save it for returning as decryption password
                sebFilePassword = hashedAdminPassword;
                // identify that password as hash
                passwordIsHash = true;
            }
            // Decryption worked

            // Ungzip the .seb (according to specification >= v14) decrypted serialized XML plist data
            decryptedSebData = GZipByte.Decompress(decryptedSebData);

            // Check if the openend reconfiguring seb file has the same admin password inside like the current one

            try
            {
                sebPreferencesDict = (IDictionary<string, object>)PropertyList.readPlist(decryptedSebData);
            }
            catch(Exception readPlistException)
            {
                // Error when deserializing the decrypted configuration data
                // We abort reading the new settings here
                SebMessageBox.Show(SEBUIStrings.loadingSettingsFailed, SEBUIStrings.loadingSettingsFailedReason, MessageBoxImage.Error, MessageBoxButton.OK);
                Console.WriteLine(readPlistException.Message);
                return null;
            }
            // Get the admin password set in these settings
            var sebFileHashedAdminPassword = (string)SebInstance.Settings.valueForDictionaryKey(sebPreferencesDict, SebSettings.KeyHashedAdminPassword);
            if(sebFileHashedAdminPassword == null)
            {
                sebFileHashedAdminPassword = "";
            }
            // Has the SEB config file the same admin password inside as the current settings have?
            if(String.Compare(hashedAdminPassword, sebFileHashedAdminPassword, StringComparison.OrdinalIgnoreCase) != 0)
            {
                //No: The admin password inside the .seb file wasn't the same as the current one
                if(forEditing)
                {
                    // If the file is openend for editing (and not to reconfigure SEB)
                    // we have to ask the user for the admin password inside the file
                    if(!askForPasswordAndCompareToHashedPassword(sebFileHashedAdminPassword, getPassword, forEditing))
                    {
                        // If the user didn't enter the right password we abort
                        return null;
                    }
                }
                else
                {
                    // The file was actually opened for reconfiguring the SEB client:
                    // we have to ask for the current admin password and
                    // allow reconfiguring only if the user enters the right one
                    // We don't check this for the case the current admin password was used to encrypt the new settings
                    // In this case there can be a new admin pw defined in the new settings and users don't need to enter the old one
                    if(passwordIsHash == false && hashedAdminPassword.Length > 0)
                    {
                        // Allow up to 5 attempts for entering current admin password
                        var gotPassword = getPassword(GetPasswordPurpose.ConfigureLocalAdmin, p =>
                        {
                            var hashedPassword = string.IsNullOrEmpty(p) ? string.Empty : SebProtectionController.ComputePasswordHash(p);
                            return String.Compare(hashedPassword, hashedAdminPassword, StringComparison.OrdinalIgnoreCase) == 0;
                        }, out password);
                        if(!gotPassword.GetValueOrDefault())
                        {
                            //wrong password entered in 5th try: stop reading .seb file
                            SebMessageBox.Show(SEBUIStrings.reconfiguringLocalSettingsFailed, SEBUIStrings.reconfiguringLocalSettingsFailedWrongCurrentAdminPwd, MessageBoxImage.Error, MessageBoxButton.OK);
                            return null;
                        }
                    }
                }
            }

            // We need to set the right value for the key sebConfigPurpose to know later where to store the new settings
            sebPreferencesDict[SebSettings.KeySebConfigPurpose] = (int)SebSettings.sebConfigPurposes.sebConfigPurposeConfiguringClient;

            // Reading preferences was successful!
            return sebPreferencesDict;
        }
Beispiel #3
0
        /// ----------------------------------------------------------------------------------------
        /// <summary>
        /// Decrypt, parse and use new SEB settings
        /// </summary>
        /// ----------------------------------------------------------------------------------------
        public static bool StoreDecryptedSEBSettings(byte[] sebData, GetPasswordMethod getPassword, SebSettings settings)
        {
            Logger.AddInformation("Reconfiguring");
            string sebFilePassword = null;
            bool passwordIsHash = false;
            X509Certificate2 sebFileCertificateRef = null;

            var sebPreferencesDict = DecryptSEBSettings(sebData, getPassword, false, ref sebFilePassword, ref passwordIsHash, ref sebFileCertificateRef);
            if(sebPreferencesDict == null)
            {
                return false; //Decryption didn't work, we abort
            }

            // Store decrypted settings
            Logger.AddInformation("Attempting to StoreSebClientSettings");
            settings.StoreSebClientSettings(sebPreferencesDict);
            Logger.AddInformation("Successfully StoreSebClientSettings");

            return true;
        }
Beispiel #4
0
 /// ----------------------------------------------------------------------------------------
 /// <summary>
 /// Ask user to enter password and compare it to the passed (hashed) password string 
 /// Returns true if correct password was entered 
 /// </summary>
 /// ----------------------------------------------------------------------------------------
 private static bool askForPasswordAndCompareToHashedPassword(string sebFileHashedAdminPassword, GetPasswordMethod getPassword, bool forEditing)
 {
     // Check if there wasn't a hashed password (= empty password)
     if(sebFileHashedAdminPassword.Length == 0)
     {
         return true;
     }
     // We have to ask for the SEB administrator password used in the settings
     // and allow opening settings only if the user enters the right one
     // Allow up to 5 attempts for entering  admin password
     string password;
     var gotPassword = getPassword(GetPasswordPurpose.LoadingSettings, p =>
     {
         var hashedPassword = string.IsNullOrEmpty(p) ? string.Empty : SebProtectionController.ComputePasswordHash(p);
         return String.Compare(hashedPassword, sebFileHashedAdminPassword, StringComparison.OrdinalIgnoreCase) == 0;
     }, out password);
     if(!gotPassword.GetValueOrDefault())
     {
         //wrong password entered in 5th try: stop reading .seb file
         SebMessageBox.Show(SEBUIStrings.loadingSettingsFailed, SEBUIStrings.loadingSettingsFailedWrongAdminPwd, MessageBoxImage.Error, MessageBoxButton.OK);
         return false;
     }
     // Right password entered
     return true;
 }
Beispiel #5
0
        /// ----------------------------------------------------------------------------------------
        /// <summary>
        /// Decrypt and deserialize SEB settings
        /// When forEditing = true, then the decrypting password the user entered and/or 
        /// certificate reference found in the .seb file is returned 
        /// </summary>
        /// ----------------------------------------------------------------------------------------
        public static IDictionary<string, object> DecryptSEBSettings(byte[] sebData, GetPasswordMethod getPassword, bool forEditing, ref string sebFilePassword, ref bool passwordIsHash, ref X509Certificate2 sebFileCertificateRef)
        {
            // Ungzip the .seb (according to specification >= v14) source data
            byte[] unzippedSebData = GZipByte.Decompress(sebData);

            // if unzipped data is not null, then unzipping worked, we use unzipped data
            // if unzipped data is null, then the source data may be an uncompressed .seb file, we proceed with it
            if(unzippedSebData != null) sebData = unzippedSebData;

            string prefixString;

            // save the data including the first 4 bytes for the case that it's acutally an unencrypted XML plist
            byte[] sebDataUnencrypted = sebData.Clone() as byte[];

            // Get 4-char prefix
            prefixString = GetPrefixStringFromData(ref sebData);

            //// Check prefix identifying encryption modes

            // Prefix = pkhs ("Public Key Hash") ?

            if(String.CompareOrdinal(prefixString, PUBLIC_KEY_HASH_MODE) == 0)
            {

                // Decrypt with cryptographic identity/private key
                sebData = DecryptDataWithPublicKeyHashPrefix(sebData, forEditing, ref sebFileCertificateRef);
                //SEBMessageBox.Show(SEBUIStrings.errorDecryptingSettings, SEBUIStrings.certificateNotFoundInStore, MessageBoxIcon.Error, MessageBoxButtons.OK, neverShowTouchOptimized : forEditing);
                //SEBMessageBox.Show(SEBUIStrings.errorDecryptingSettings, SEBUIStrings.certificateDecryptingError + ex.Message, MessageBoxImage.Error, MessageBoxButton.OK);
                if(sebData == null)
                {
                    return null;
                }

                // Get 4-char prefix again
                // and remaining data without prefix, which is either plain or still encoded with password
                prefixString = GetPrefixStringFromData(ref sebData);
            }

            // Prefix = pswd ("Password") ?
            if(String.CompareOrdinal(prefixString, PASSWORD_MODE) == 0)
            {
                // Decrypt with password
                // if the user enters the right one
                byte[] sebDataDecrypted = null;
                string password;
                var gotPassword = getPassword(GetPasswordPurpose.PasswordMode, p =>
                {
                    sebDataDecrypted = SebProtectionController.DecryptDataWithPassword(sebData, p);
                    return sebDataDecrypted != null;
                }, out password);

                if(!gotPassword.HasValue)
                {
                    return null;
                }
                if(!gotPassword.Value)
                {
                    //wrong password entered in 5th try: stop reading .seb file
                    SebMessageBox.Show(SEBUIStrings.decryptingSettingsFailed, SEBUIStrings.decryptingSettingsFailedReason, MessageBoxImage.Error, MessageBoxButton.OK);
                    return null;
                }
                sebData = sebDataDecrypted;
                // If these settings are being decrypted for editing, we return the decryption password
                if(forEditing) sebFilePassword = password;
            }
            else
            {
                // Prefix = pwcc ("Password Configuring Client") ?
                if(String.CompareOrdinal(prefixString, PASSWORD_CONFIGURING_CLIENT_MODE) == 0)
                {

                    // Decrypt with password and configure local client settings
                    // and quit afterwards, returning if reading the .seb file was successfull
                    var sebSettings = DecryptDataWithPasswordForConfiguringClient(sebData, getPassword, forEditing, ref sebFilePassword, ref passwordIsHash);
                    return sebSettings;
                }
                else
                {
                    // Prefix = plnd ("Plain Data") ?

                    if(String.CompareOrdinal(prefixString, PLAIN_DATA_MODE) != 0)
                    {
                        // No valid 4-char prefix was found in the .seb file
                        // Check if .seb file is unencrypted
                        if(String.CompareOrdinal(prefixString, UNENCRYPTED_MODE) == 0)
                        {
                            // .seb file seems to be an unencrypted XML plist
                            // get the original data including the first 4 bytes
                            sebData = sebDataUnencrypted;
                        }
                        else
                        {
                            // No valid prefix and no unencrypted file with valid header
                            // cancel reading .seb file
                            SebMessageBox.Show(SEBUIStrings.settingsNotUsable, SEBUIStrings.settingsNotUsableReason, MessageBoxImage.Error, MessageBoxButton.OK);
                            return null;
                        }
                    }
                }
            }
            // If we don't deal with an unencrypted seb file
            // ungzip the .seb (according to specification >= v14) decrypted serialized XML plist data
            if(String.CompareOrdinal(prefixString, UNENCRYPTED_MODE) != 0)
            {
                sebData = GZipByte.Decompress(sebData);
            }

            // Get preferences dictionary from decrypted data
            var sebPreferencesDict = GetPreferencesDictFromConfigData(sebData, getPassword, forEditing);
            // If we didn't get a preferences dict back, we abort reading settings
            if(sebPreferencesDict == null) return null;

            // We need to set the right value for the key sebConfigPurpose to know later where to store the new settings
            sebPreferencesDict[SebSettings.KeySebConfigPurpose] = (int)SebSettings.sebConfigPurposes.sebConfigPurposeStartingExam;

            // Reading preferences was successful!
            return sebPreferencesDict;
        }