Example #1
0
        public void Clear()
        {
            _logger.LogInformation("Clearing cache");
            FileIOWithRetries.DeleteCacheFile(_cacheFilePath, _logger);

            _logger.LogInformation($"Before deleting secret from Linux keyring");

            IntPtr error = IntPtr.Zero;

            Libsecret.secret_password_clear_sync(
                schema: GetLibsecretSchema(),
                cancellable: IntPtr.Zero,
                error: out error,
                attribute1Type: _attributeKey1,
                attribute1Value: _attributeValue1,
                attribute2Type: _attributeKey2,
                attribute2Value: _attributeValue2,
                end: IntPtr.Zero);

            if (error != IntPtr.Zero)
            {
                try
                {
                    GError err = (GError)Marshal.PtrToStructure(error, typeof(GError));
                    _logger.LogError($"An error was encountered while clearing secret from keyring in the {nameof(MsalCacheStorage)} domain:'{err.Domain}' code:'{err.Code}' message:'{err.Message}'");
                }
                catch (Exception e)
                {
                    _logger.LogError($"An exception was encountered while processing libsecret error information during clearing secret in the {nameof(MsalCacheStorage)} ex:'{e}'");
                }
            }

            _logger.LogInformation("After deleting secret from linux keyring");
        }
Example #2
0
        private IntPtr GetLibsecretSchema()
        {
            if (_libsecretSchema == IntPtr.Zero)
            {
                _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, "Before creating libsecret schema");

                _libsecretSchema = Libsecret.secret_schema_new(
                    name: _creationProperties.KeyringSchemaName,
                    flags: (int)Libsecret.SecretSchemaFlags.SECRET_SCHEMA_DONT_MATCH_NAME,
                    attribute1: _creationProperties.KeyringAttribute1.Key,
                    attribute1Type: (int)Libsecret.SecretSchemaAttributeType.SECRET_SCHEMA_ATTRIBUTE_STRING,
                    attribute2: _creationProperties.KeyringAttribute2.Key,
                    attribute2Type: (int)Libsecret.SecretSchemaAttributeType.SECRET_SCHEMA_ATTRIBUTE_STRING,
                    end: IntPtr.Zero);

                if (_libsecretSchema == IntPtr.Zero)
                {
                    _logger.TraceEvent(TraceEventType.Error, /*id*/ 0, $"Failed to create libsecret schema from the {nameof(MsalCacheStorage)}");
                }

                _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, "After creating libsecret schema");
            }

            return(_libsecretSchema);
        }
Example #3
0
        private IntPtr GetLibsecretSchema()
        {
            if (_libsecretSchema == IntPtr.Zero)
            {
                _logger.LogInformation("Before creating libsecret schema");

                _libsecretSchema = Libsecret.secret_schema_new(
                    name: _keyringSchemaName,
                    flags: (int)Libsecret.SecretSchemaFlags.SECRET_SCHEMA_DONT_MATCH_NAME,
                    attribute1: _attributeKey1,
                    attribute1Type: (int)Libsecret.SecretSchemaAttributeType.SECRET_SCHEMA_ATTRIBUTE_STRING,
                    attribute2: _attributeKey2,
                    attribute2Type: (int)Libsecret.SecretSchemaAttributeType.SECRET_SCHEMA_ATTRIBUTE_STRING,
                    end: IntPtr.Zero);

                if (_libsecretSchema == IntPtr.Zero)
                {
                    _logger.LogError($"Failed to create libsecret schema from the {nameof(MsalCacheStorage)}");
                }

                _logger.LogInformation("After creating libsecret schema");
            }

            return(_libsecretSchema);
        }
Example #4
0
        public byte[] Read()
        {
            _logger.LogInformation("ReadDataCore");

            _logger.LogInformation($"ReadDataCore, Before reading from linux keyring");

            byte[] fileData = null;

            IntPtr error = IntPtr.Zero;

            string secret = Libsecret.secret_password_lookup_sync(
                schema: GetLibsecretSchema(),
                cancellable: IntPtr.Zero,
                error: out error,
                attribute1Type: _attributeKey1,
                attribute1Value: _attributeValue1,
                attribute2Type: _attributeKey2,
                attribute2Value: _attributeValue2,
                end: IntPtr.Zero);

            if (error != IntPtr.Zero)
            {
                try
                {
                    GError err = (GError)Marshal.PtrToStructure(error, typeof(GError));
                    _logger.LogError($"An error was encountered while reading secret from keyring in the {nameof(MsalCacheStorage)} domain:'{err.Domain}' code:'{err.Code}' message:'{err.Message}'");
                }
                catch (Exception e)
                {
                    _logger.LogError($"An exception was encountered while processing libsecret error information during reading in the {nameof(MsalCacheStorage)} ex:'{e}'");
                }
            }
            else if (string.IsNullOrEmpty(secret))
            {
                _logger.LogError("No matching secret found in the keyring");
            }
            else
            {
                _logger.LogInformation("Base64 decoding the secret string");
                fileData = Convert.FromBase64String(secret);
                _logger.LogInformation($"ReadDataCore, read '{fileData?.Length}' bytes from the keyring");
            }

            return(fileData);
        }
Example #5
0
        public void Write(byte[] data)
        {
            _logger.LogInformation("Before saving to linux keyring");

            IntPtr error = IntPtr.Zero;

            Libsecret.secret_password_store_sync(
                schema: GetLibsecretSchema(),
                collection: _keyringCollection,
                label: _keyringSecretLabel,
                password: Convert.ToBase64String(data),
                cancellable: IntPtr.Zero,
                error: out error,
                attribute1Type: _attributeKey1,
                attribute1Value: _attributeValue1,
                attribute2Type: _attributeKey2,
                attribute2Value: _attributeValue2,
                end: IntPtr.Zero);

            if (error != IntPtr.Zero)
            {
                try
                {
                    GError err = (GError)Marshal.PtrToStructure(error, typeof(GError));
                    _logger.LogError($"An error was encountered while saving secret to keyring in the {nameof(MsalCacheStorage)} domain:'{err.Domain}' code:'{err.Code}' message:'{err.Message}'");
                }
                catch (Exception e)
                {
                    _logger.LogError($"An exception was encountered while processing libsecret error information during saving in the {nameof(MsalCacheStorage)} ex:'{e}'");
                }
            }

            _logger.LogInformation("After saving to linux keyring");

            // Change data to 1 byte so we can write it to the cache file to update the last write time using the same write code used for windows.
            FileIOWithRetries.WriteDataToFile(_cacheFilePath, new byte[] { 1 }, _logger);
        }
        public void Write(byte[] data)
        {
            _logger.LogInformation("Before saving to linux keyring");

            IntPtr error = IntPtr.Zero;

            Libsecret.secret_password_store_sync(
                schema: GetLibsecretSchema(),
                collection: _keyringCollection,
                label: _keyringSecretLabel,
                password: Convert.ToBase64String(data),
                cancellable: IntPtr.Zero,
                error: out error,
                attribute1Type: _attributeKey1,
                attribute1Value: _attributeValue1,
                attribute2Type: _attributeKey2,
                attribute2Value: _attributeValue2,
                end: IntPtr.Zero);

            if (error != IntPtr.Zero)
            {
                try
                {
                    GError err = (GError)Marshal.PtrToStructure(error, typeof(GError));
                    _logger.LogError($"An error was encountered while saving secret to keyring in the {nameof(Storage)} domain:'{err.Domain}' code:'{err.Code}' message:'{err.Message}'");
                }
                catch (Exception e)
                {
                    _logger.LogError($"An exception was encountered while processing libsecret error information during saving in the {nameof(Storage)} ex:'{e}'");
                }
            }

            _logger.LogInformation("After saving to linux keyring");

            // Change the "last modified" attribute and trigger file changed events
            FileIOWithRetries.TouchFile(_cacheFilePath, _logger);
        }
Example #7
0
        private void ClearCore()
        {
            _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, "Clearing cache");
            bool cacheFileExists = File.Exists(CacheFilePath);

            _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, $"ReadDataCore Cache file exists '{cacheFileExists}'");

            TryProcessFile(() =>
            {
                _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, "Before deleting the cache file");
                try
                {
                    File.Delete(CacheFilePath);
                }
                catch (Exception e)
                {
                    _logger.TraceEvent(TraceEventType.Error, /*id*/ 0, $"Problem deleting the cache file '{e}'");
                }

                _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, $"After deleting the cache file.");
            });

            if (SharedUtilities.IsMacPlatform())
            {
                _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, "Before delete mac keychain");
                MacKeyChain.DeleteKey(
                    _creationProperties.MacKeyChainServiceName,
                    _creationProperties.MacKeyChainAccountName);
                _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, "After delete mac keychain");
            }
            else if (SharedUtilities.IsLinuxPlatform())
            {
                _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, $"Before deletring secret from linux keyring");

                IntPtr error = IntPtr.Zero;

                Libsecret.secret_password_clear_sync(
                    schema: GetLibsecretSchema(),
                    cancellable: IntPtr.Zero,
                    error: out error,
                    attribute1Type: _creationProperties.KeyringAttribute1.Key,
                    attribute1Value: _creationProperties.KeyringAttribute1.Value,
                    attribute2Type: _creationProperties.KeyringAttribute2.Key,
                    attribute2Value: _creationProperties.KeyringAttribute2.Value,
                    end: IntPtr.Zero);

                if (error != IntPtr.Zero)
                {
                    try
                    {
                        GError err = (GError)Marshal.PtrToStructure(error, typeof(GError));
                        _logger.TraceEvent(TraceEventType.Error, /*id*/ 0, $"An error was encountered while clearing secret from keyring in the {nameof(MsalCacheStorage)} domain:'{err.Domain}' code:'{err.Code}' message:'{err.Message}'");
                    }
                    catch (Exception e)
                    {
                        _logger.TraceEvent(TraceEventType.Error, /*id*/ 0, $"An exception was encountered while processing libsecret error information during clearing secret in the {nameof(MsalCacheStorage)} ex:'{e}'");
                    }
                }

                _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, "After deleting secret from linux keyring");
            }
            else if (!SharedUtilities.IsWindowsPlatform())
            {
                _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, "Not supported platform");
                throw new PlatformNotSupportedException();
            }
        }
Example #8
0
        private void WriteDataCore(byte[] data)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, $"Write Data core, going to write '{data.Length}' to the storage");

            if (SharedUtilities.IsMacPlatform() || SharedUtilities.IsLinuxPlatform())
            {
                if (SharedUtilities.IsMacPlatform())
                {
                    _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, "Before write to mac keychain");
                    MacKeyChain.WriteKey(
                        _creationProperties.MacKeyChainServiceName,
                        _creationProperties.MacKeyChainAccountName,
                        data);

                    _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, "After write to mac keychain");
                }
                else if (SharedUtilities.IsLinuxPlatform())
                {
                    _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, "Before saving to linux keyring");

                    IntPtr error = IntPtr.Zero;

                    Libsecret.secret_password_store_sync(
                        schema: GetLibsecretSchema(),
                        collection: _creationProperties.KeyringCollection,
                        label: _creationProperties.KeyringSecretLabel,
                        password: Convert.ToBase64String(data),
                        cancellable: IntPtr.Zero,
                        error: out error,
                        attribute1Type: _creationProperties.KeyringAttribute1.Key,
                        attribute1Value: _creationProperties.KeyringAttribute1.Value,
                        attribute2Type: _creationProperties.KeyringAttribute2.Key,
                        attribute2Value: _creationProperties.KeyringAttribute2.Value,
                        end: IntPtr.Zero);

                    if (error != IntPtr.Zero)
                    {
                        try
                        {
                            GError err = (GError)Marshal.PtrToStructure(error, typeof(GError));
                            _logger.TraceEvent(TraceEventType.Error, /*id*/ 0, $"An error was encountered while saving secret to keyring in the {nameof(MsalCacheStorage)} domain:'{err.Domain}' code:'{err.Code}' message:'{err.Message}'");
                        }
                        catch (Exception e)
                        {
                            _logger.TraceEvent(TraceEventType.Error, /*id*/ 0, $"An exception was encountered while processing libsecret error information during saving in the {nameof(MsalCacheStorage)} ex:'{e}'");
                        }
                    }

                    _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, "After saving to linux keyring");
                }

                // Change data to 1 byte so we can write it to the cache file to update the last write time using the same write code used for windows.
                data = new byte[] { 1 };
            }

            string directoryForCacheFile = Path.GetDirectoryName(CacheFilePath);

            if (!Directory.Exists(directoryForCacheFile))
            {
                string directory = Path.GetDirectoryName(CacheFilePath);
                _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, $"Creating directory '{directory}'");
                Directory.CreateDirectory(directory);
            }

            _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, $"Cache file directory exists. '{Directory.Exists(directoryForCacheFile)}' now writing cache file");

            TryProcessFile(() =>
            {
                File.WriteAllBytes(CacheFilePath, data);
            });
        }
Example #9
0
        private byte[] ReadDataCore()
        {
            _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, "ReadDataCore");

            byte[] fileData = null;

            bool cacheFileExists = File.Exists(CacheFilePath);

            _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, $"ReadDataCore Cache file exists '{cacheFileExists}'");

            if (SharedUtilities.IsWindowsPlatform())
            {
                if (cacheFileExists)
                {
                    TryProcessFile(() =>
                    {
                        fileData = File.ReadAllBytes(CacheFilePath);
                        _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, $"ReadDataCore, read '{fileData.Length}' bytes from the file");
                    });
                }
            }
            else if (SharedUtilities.IsMacPlatform())
            {
                _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, $"ReadDataCore, Before reading from mac keychain");
                fileData = MacKeyChain.RetrieveKey(_creationProperties.MacKeyChainServiceName, _creationProperties.MacKeyChainAccountName, _logger);

                _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, $"ReadDataCore, read '{fileData?.Length}' bytes from the keychain");
            }
            else if (SharedUtilities.IsLinuxPlatform())
            {
                _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, $"ReadDataCore, Before reading from linux keyring");

                IntPtr error = IntPtr.Zero;

                string secret = Libsecret.secret_password_lookup_sync(
                    schema: GetLibsecretSchema(),
                    cancellable: IntPtr.Zero,
                    error: out error,
                    attribute1Type: _creationProperties.KeyringAttribute1.Key,
                    attribute1Value: _creationProperties.KeyringAttribute1.Value,
                    attribute2Type: _creationProperties.KeyringAttribute2.Key,
                    attribute2Value: _creationProperties.KeyringAttribute2.Value,
                    end: IntPtr.Zero);

                if (error != IntPtr.Zero)
                {
                    try
                    {
                        GError err = (GError)Marshal.PtrToStructure(error, typeof(GError));
                        _logger.TraceEvent(TraceEventType.Error, /*id*/ 0, $"An error was encountered while reading secret from keyring in the {nameof(MsalCacheStorage)} domain:'{err.Domain}' code:'{err.Code}' message:'{err.Message}'");
                    }
                    catch (Exception e)
                    {
                        _logger.TraceEvent(TraceEventType.Error, /*id*/ 0, $"An exception was encountered while processing libsecret error information during reading in the {nameof(MsalCacheStorage)} ex:'{e}'");
                    }
                }
                else if (string.IsNullOrEmpty(secret))
                {
                    _logger.TraceEvent(TraceEventType.Error, /*id*/ 0, "No matching secret found in the keyring");
                }
                else
                {
                    _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, "Base64 decoding the secret string");
                    fileData = Convert.FromBase64String(secret);
                    _logger.TraceEvent(TraceEventType.Information, /*id*/ 0, $"ReadDataCore, read '{fileData?.Length}' bytes from the keyring");
                }
            }
            else
            {
                _logger.TraceEvent(TraceEventType.Error, /*id*/ 0, "Platform not supported");
                throw new PlatformNotSupportedException();
            }

            return(fileData);
        }