private static unsafe ICredential CreateCredentialFromItem(SecretItem *item) { GHashTable *secretAttrs = null; IntPtr serviceKeyPtr = IntPtr.Zero; IntPtr accountKeyPtr = IntPtr.Zero; IntPtr passwordPtr = IntPtr.Zero; GError * error = null; try { secretAttrs = secret_item_get_attributes(item); // Extract the service attribute serviceKeyPtr = Marshal.StringToHGlobalAnsi(ServiceAttributeName); IntPtr serviceValuePtr = g_hash_table_lookup(secretAttrs, serviceKeyPtr); string service = Marshal.PtrToStringAuto(serviceValuePtr); // Extract the account attribute accountKeyPtr = Marshal.StringToHGlobalAnsi(AccountAttributeName); IntPtr accountValuePtr = g_hash_table_lookup(secretAttrs, accountKeyPtr); string account = Marshal.PtrToStringAuto(accountValuePtr); // Load the secret value secret_item_load_secret_sync(item, IntPtr.Zero, out error); SecretValue *value = secret_item_get_secret(item); if (value == null) { throw new InteropException("Failed to load secret", -1); } // Extract the secret/password passwordPtr = secret_value_unref_to_password(value, out int passwordLength); string password = Marshal.PtrToStringAuto(passwordPtr, passwordLength); return(new SecretServiceCredential(service, account, password)); } finally { if (secretAttrs != null) { g_hash_table_unref(secretAttrs); } if (accountKeyPtr != IntPtr.Zero) { Marshal.FreeHGlobal(accountKeyPtr); } if (serviceKeyPtr != IntPtr.Zero) { Marshal.FreeHGlobal(serviceKeyPtr); } if (passwordPtr != IntPtr.Zero) { secret_password_free(passwordPtr); } if (error != null) { g_error_free(error); } } }
public static extern unsafe bool secret_service_store_sync( SecretService *service, ref SecretSchema schema, Glib.GHashTable *attributes, string collection, string label, SecretValue *value, IntPtr cancellable, out Glib.GError *error);
public static extern unsafe IntPtr secret_value_unref_to_password(SecretValue *value, out int length);
public static extern unsafe void secret_value_unref(SecretValue *value);
public static extern unsafe IntPtr secret_value_get(SecretValue *value, out int length);
public unsafe void AddOrUpdate(string service, string account, string secret) { GHashTable * attributes = null; SecretValue *secretValue = null; GError * error = null; try { SecretService *secService = GetSecretService(); // Create attributes for the key and user attributes = g_hash_table_new_full(g_str_hash, g_str_equal, Marshal.FreeHGlobal, Marshal.FreeHGlobal); string fullServiceName = CreateServiceName(service); IntPtr serviceKeyPtr = Marshal.StringToHGlobalAnsi(ServiceAttributeName); IntPtr serviceValuePtr = Marshal.StringToHGlobalAnsi(fullServiceName); g_hash_table_insert(attributes, serviceKeyPtr, serviceValuePtr); if (!string.IsNullOrWhiteSpace(account)) { IntPtr accountKeyPtr = Marshal.StringToHGlobalAnsi(AccountAttributeName); IntPtr accountValuePtr = Marshal.StringToHGlobalAnsi(account); g_hash_table_insert(attributes, accountKeyPtr, accountValuePtr); } // Create the secret value object from the secret string byte[] secretBytes = Encoding.UTF8.GetBytes(secret); secretValue = secret_value_new(secretBytes, secretBytes.Length, PlainTextContentType); SecretSchema schema = GetSchema(); // Store the secret with the associated attributes bool result = secret_service_store_sync( secService, ref schema, attributes, null, fullServiceName, // Use full service name as label secretValue, IntPtr.Zero, out error); if (error != null) { int code = error->code; string message = Marshal.PtrToStringAuto(error->message) !; throw new InteropException("Failed to store credentials", code, new Exception(message)); } if (!result) { throw new InteropException("Failed to store credentials", -1); } } finally { if (attributes != null) { g_hash_table_destroy(attributes); } if (secretValue != null) { secret_value_unref(secretValue); } if (error != null) { g_error_free(error); } } }
public unsafe ICredential Get(string key) { GHashTable *queryAttrs = null; GHashTable *secretAttrs = null; IntPtr userKeyPtr = IntPtr.Zero; IntPtr passwordPtr = IntPtr.Zero; GList * results = null; GError * error = null; try { SecretService *service = GetSecretService(); // Build search query queryAttrs = g_hash_table_new_full( g_str_hash, g_str_equal, Marshal.FreeHGlobal, Marshal.FreeHGlobal); IntPtr keyKeyPtr = Marshal.StringToHGlobalAnsi(KeyAttributeName); IntPtr keyValuePtr = Marshal.StringToHGlobalAnsi(key); g_hash_table_insert(queryAttrs, keyKeyPtr, keyValuePtr); SecretSchema schema = GetSchema(); // Execute search query and return one result results = secret_service_search_sync( service, ref schema, queryAttrs, SecretSearchFlags.SECRET_SEARCH_UNLOCK, IntPtr.Zero, out error); if (error != null) { int code = error->code; string message = Marshal.PtrToStringAuto(error->message) !; throw new InteropException("Failed to search for credentials", code, new Exception(message)); } if (results != null && results->data != null) { SecretItem *item = (SecretItem *)results->data; // Although we've unlocked the collection during the search call, // an item can also be individually locked within a collection. // If the item is locked we should try and unlock it. if (secret_item_get_locked(item)) { var toUnlockList = new GList { data = (IntPtr)item, next = IntPtr.Zero, prev = IntPtr.Zero }; int numUnlocked = secret_service_unlock_sync( service, &toUnlockList, IntPtr.Zero, out _, out error ); if (numUnlocked != 1) { throw new InteropException("Failed to unlock item", numUnlocked); } } // Extract the user attribute secretAttrs = secret_item_get_attributes(item); userKeyPtr = Marshal.StringToHGlobalAnsi(UserAttributeName); IntPtr userValuePtr = g_hash_table_lookup(secretAttrs, userKeyPtr); string userName = Marshal.PtrToStringAuto(userValuePtr); // Load the secret value secret_item_load_secret_sync(item, IntPtr.Zero, out error); SecretValue *value = secret_item_get_secret(item); if (value == null) { throw new InteropException("Failed to load secret", -1); } // Extract the secret/password passwordPtr = secret_value_unref_to_password(value, out int passwordLength); string password = Marshal.PtrToStringAuto(passwordPtr, passwordLength); return(new GitCredential(userName, password)); } return(null); } finally { if (queryAttrs != null) { g_hash_table_destroy(queryAttrs); } if (secretAttrs != null) { g_hash_table_unref(secretAttrs); } if (userKeyPtr != IntPtr.Zero) { Marshal.FreeHGlobal(userKeyPtr); } if (passwordPtr != IntPtr.Zero) { secret_password_free(passwordPtr); } if (error != null) { g_error_free(error); } if (results != null) { g_list_free_full(results, g_object_unref); } } }
public unsafe void AddOrUpdate(string key, ICredential credential) { GHashTable * attributes = null; SecretValue *secretValue = null; GError * error = null; try { SecretService *service = GetSecretService(); // Create attributes for the key and user attributes = g_hash_table_new_full(g_str_hash, g_str_equal, Marshal.FreeHGlobal, Marshal.FreeHGlobal); IntPtr keyKeyPtr = Marshal.StringToHGlobalAnsi(KeyAttributeName); IntPtr keyValuePtr = Marshal.StringToHGlobalAnsi(key); g_hash_table_insert(attributes, keyKeyPtr, keyValuePtr); IntPtr userKeyPtr = Marshal.StringToHGlobalAnsi(UserAttributeName); IntPtr userValuePtr = Marshal.StringToHGlobalAnsi(credential.UserName); g_hash_table_insert(attributes, userKeyPtr, userValuePtr); // Create the secret value from the password byte[] passwordBytes = Encoding.UTF8.GetBytes(credential.Password); secretValue = secret_value_new(passwordBytes, passwordBytes.Length, PlainTextContentType); SecretSchema schema = GetSchema(); // Store the secret with the associated attributes bool result = secret_service_store_sync( service, ref schema, attributes, null, key, // Use the key also as the label secretValue, IntPtr.Zero, out error); if (error != null) { int code = error->code; string message = Marshal.PtrToStringAuto(error->message) !; throw new InteropException("Failed to store credentials", code, new Exception(message)); } if (!result) { throw new InteropException("Failed to store credentials", -1); } } finally { if (attributes != null) { g_hash_table_destroy(attributes); } if (secretValue != null) { secret_value_unref(secretValue); } if (error != null) { g_error_free(error); } } }