gboolean gkd_secret_lock (GckObject *collection, DBusError *derr) { GckBuilder builder = GCK_BUILDER_INIT; GError *error = NULL; GList *objects, *l; GckSession *session; gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_CREDENTIAL); gck_builder_add_ulong (&builder, CKA_G_OBJECT, gck_object_get_handle (collection)); session = gck_object_get_session (collection); g_return_val_if_fail (session, FALSE); objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error); g_object_unref (session); if (error != NULL) { g_warning ("couldn't search for credential objects: %s", egg_error_message (error)); dbus_set_error (derr, DBUS_ERROR_FAILED, "Couldn't lock collection"); g_clear_error (&error); return FALSE; } for (l = objects; l; l = g_list_next (l)) { if (!gck_object_destroy (l->data, NULL, &error)) { g_warning ("couldn't destroy credential object: %s", egg_error_message (error)); g_clear_error (&error); } } gck_list_unref_free (objects); return TRUE; }
static GckSlot* calculate_secrets_slot (void) { GckSlot *slot = NULL; GckModule *module; GList *modules; GError *err = NULL; CK_FUNCTION_LIST_PTR funcs; /* TODO: Should we be handling just one module here? */ funcs = gkd_pkcs11_get_functions (); g_return_val_if_fail (funcs != NULL, NULL); module = gck_module_new (funcs); g_return_val_if_fail (module, NULL); modules = g_list_prepend (NULL, module); slot = gck_modules_token_for_uri (modules, "pkcs11:token=Secret%20Store", &err); if (!slot && err) { g_warning ("couldn't find secret store: %s", egg_error_message (err)); g_clear_error (&err); } gck_list_unref_free (modules); return slot; }
static gboolean init_pin_for_uninitialized_slots (GList *modules, const gchar *master) { GError *error = NULL; GList *slots, *l; gboolean initialize; GckTokenInfo *info; GckSession *session; g_return_val_if_fail (master, FALSE); slots = gck_modules_get_slots (modules, TRUE); for (l = slots; l; l = g_list_next (l)) { info = gck_slot_get_token_info (l->data); initialize = (info && !(info->flags & CKF_USER_PIN_INITIALIZED)); if (initialize) { session = open_and_login_session (l->data, CKU_SO, NULL); if (session != NULL) { if (!gck_session_init_pin (session, (const guchar*)master, strlen (master), NULL, &error)) { if (!g_error_matches (error, GCK_ERROR, CKR_FUNCTION_NOT_SUPPORTED)) g_warning ("couldn't initialize slot with master password: %s", egg_error_message (error)); g_clear_error (&error); } g_object_unref (session); } } gck_token_info_free (info); } gck_list_unref_free (slots); return TRUE; }
static void imported_display (GcrImporter *importer) { GParamSpec *spec; gchar *label = NULL; spec = g_object_class_find_property (G_OBJECT_GET_CLASS (importer), "imported"); if (spec == NULL) return; g_object_get (importer, "label", &label, NULL); if (spec->value_type == GCK_TYPE_LIST) { GList *list, *l; g_object_get (importer, "imported", &list, NULL); for (l = list; l != NULL; l = g_list_next (l)) imported_object (l->data, label); gck_list_unref_free (list); } else if (spec->value_type == G_TYPE_STRV) { gchar **fingerprints; guint i; g_object_get (importer, "imported", &fingerprints, NULL); for (i = 0; fingerprints && fingerprints[i] != NULL; i++) imported_fingerprint (fingerprints[i], label); g_strfreev (fingerprints); } }
static GckObject* lookup_login_keyring (GckSession *session) { GckAttributes *atts; GError *error = NULL; GckObject *login = NULL; GList *objects; guint length; g_return_val_if_fail (GCK_IS_SESSION (session), NULL); atts = gck_attributes_new (); gck_attributes_add_ulong (atts, CKA_CLASS, CKO_G_COLLECTION); gck_attributes_add_boolean (atts, CKA_TOKEN, TRUE); gck_attributes_add_string (atts, CKA_ID, "login"); objects = gck_session_find_objects (session, atts, NULL, &error); gck_attributes_unref (atts); if (error) { g_warning ("couldn't search for login keyring: %s", egg_error_message (error)); g_clear_error (&error); return NULL; } length = g_list_length (objects); if (length == 1) login = g_object_ref (objects->data); else if (length > 1) g_warning ("more than one login keyring exists"); gck_list_unref_free (objects); return login; }
static GckObject * secret_objects_lookup_gck_object_for_path (GkdSecretObjects *self, const gchar *sender, const gchar *path, GError **error_out) { GckBuilder builder = GCK_BUILDER_INIT; GList *objects; GckSession *session; gchar *c_ident; gchar *i_ident; GckObject *object = NULL; GError *error = NULL; g_return_val_if_fail (path, FALSE); if (!gkd_secret_util_parse_path (path, &c_ident, &i_ident) || !c_ident) goto out; /* The session we're using to access the object */ session = gkd_secret_service_get_pkcs11_session (self->service, sender); g_return_val_if_fail (session, FALSE); if (i_ident) { gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY); gck_builder_add_string (&builder, CKA_G_COLLECTION, c_ident); gck_builder_add_string (&builder, CKA_ID, i_ident); } else { gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_COLLECTION); gck_builder_add_string (&builder, CKA_ID, c_ident); } objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error); g_free (c_ident); g_free (i_ident); if (error != NULL) { g_warning ("couldn't lookup object: %s: %s", path, egg_error_message (error)); g_clear_error (&error); } if (!objects) goto out; object = g_object_ref (objects->data); gck_list_unref_free (objects); out: if (!object) g_set_error (error_out, GKD_SECRET_ERROR, GKD_SECRET_ERROR_NO_SUCH_OBJECT, "The '%s' object does not exist", path); return object; }
static gpointer run_client_thread (gpointer data) { gint *socket = data; GkdSshAgentCall call; EggBuffer req; EggBuffer resp; guchar op; memset (&call, 0, sizeof (call)); call.sock = g_atomic_int_get (socket); g_assert (call.sock != -1); egg_buffer_init_full (&req, 128, egg_secure_realloc); egg_buffer_init_full (&resp, 128, (EggBufferAllocator)g_realloc); call.req = &req; call.resp = &resp; call.modules = gck_list_ref_copy (pkcs11_modules); for (;;) { egg_buffer_reset (call.req); /* 1. Read in the request */ if (!read_packet_with_size (&call)) break; /* 2. Now decode the operation */ if (!egg_buffer_get_byte (call.req, 4, NULL, &op)) break; if (op >= GKD_SSH_OP_MAX) break; g_assert (gkd_ssh_agent_operations[op]); /* 3. Execute the right operation */ egg_buffer_reset (call.resp); egg_buffer_add_uint32 (call.resp, 0); if (!(gkd_ssh_agent_operations[op]) (&call)) break; if (!egg_buffer_set_uint32 (call.resp, 0, call.resp->len - 4)) break; /* 4. Write the reply back out */ if (!write_all (call.sock, call.resp->buf, call.resp->len)) break; } egg_buffer_uninit (&req); egg_buffer_uninit (&resp); gck_list_unref_free (call.modules); call.modules = NULL; close (call.sock); g_atomic_int_set (socket, -1); return NULL; }
static GckObject * lookup_public_key (GckObject *object, GCancellable *cancellable, GError **lerror) { GckBuilder builder = GCK_BUILDER_INIT; gulong attr_types[] = { CKA_ID }; GckAttributes *attrs; GError *error = NULL; GckSession *session; GckObject *result; const GckAttribute *id; GList *objects; attrs = gck_object_cache_lookup (object, attr_types, G_N_ELEMENTS (attr_types), cancellable, &error); if (error != NULL) { _gcr_debug ("couldn't load private key id: %s", error->message); g_propagate_error (lerror, error); return NULL; } id = gck_attributes_find (attrs, CKA_ID); if (id == NULL || gck_attribute_is_invalid (id)) { gck_attributes_unref (attrs); _gcr_debug ("couldn't load private key id"); g_set_error_literal (lerror, GCK_ERROR, CKR_ATTRIBUTE_TYPE_INVALID, gck_message_from_rv (CKR_ATTRIBUTE_TYPE_INVALID)); return NULL; } gck_builder_add_ulong (&builder, CKA_CLASS, CKO_PUBLIC_KEY); gck_builder_add_attribute (&builder, id); gck_attributes_unref (attrs); session = gck_object_get_session (object); objects = gck_session_find_objects (session, gck_builder_end (&builder), cancellable, &error); g_object_unref (session); if (error != NULL) { _gcr_debug ("couldn't lookup public key: %s", error->message); g_propagate_error (lerror, error); return NULL; } if (!objects) return NULL; result = g_object_ref (objects->data); gck_list_unref_free (objects); return result; }
void gkd_secret_objects_foreach_collection (GkdSecretObjects *self, const gchar *caller, GkdSecretObjectsForeach callback, gpointer user_data) { GckBuilder builder = GCK_BUILDER_INIT; GckSession *session; GError *error = NULL; GList *collections, *l; gpointer identifier; gsize n_identifier; gchar *path; g_return_if_fail (GKD_SECRET_IS_OBJECTS (self)); g_return_if_fail (callback); /* The session we're using to access the object */ if (caller == NULL) { session = gkd_secret_service_internal_pkcs11_session (self->service); } else { session = gkd_secret_service_get_pkcs11_session (self->service, caller); } gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_COLLECTION); collections = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error); if (error != NULL) { g_warning ("couldn't lookup collections: %s", egg_error_message (error)); g_clear_error (&error); return; } for (l = collections; l; l = g_list_next (l)) { identifier = gck_object_get_data (l->data, CKA_ID, NULL, &n_identifier, &error); if (identifier == NULL) { g_warning ("couldn't get collection identifier: %s", egg_error_message (error)); g_clear_error (&error); continue; } path = gkd_secret_util_build_path (SECRET_COLLECTION_PREFIX, identifier, n_identifier); g_free (identifier); (callback) (self, path, l->data, user_data); g_free (path); } gck_list_unref_free (collections); }
gboolean gkd_secret_lock_all (GckSession *session, DBusError *derr) { GckBuilder builder = GCK_BUILDER_INIT; GError *error = NULL; GList *objects, *l; /* Lock all the main collections */ gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_CREDENTIAL); gck_builder_add_boolean (&builder, CKA_GNOME_TRANSIENT, TRUE); objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error); if (error != NULL) { g_warning ("couldn't search for credential objects: %s", egg_error_message (error)); dbus_set_error (derr, DBUS_ERROR_FAILED, "Couldn't lock service"); g_clear_error (&error); return FALSE; } for (l = objects; l; l = g_list_next (l)) { if (!gck_object_destroy (l->data, NULL, &error)) { g_warning ("couldn't destroy credential object: %s", egg_error_message (error)); g_clear_error (&error); } } /* Now delete all session objects */ gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY); gck_builder_add_string (&builder, CKA_G_COLLECTION, "session"); objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error); if (error != NULL) { g_warning ("couldn't search for session items: %s", egg_error_message (error)); dbus_set_error (derr, DBUS_ERROR_FAILED, "Couldn't lock service"); g_clear_error (&error); return FALSE; } for (l = objects; l; l = g_list_next (l)) { if (!gck_object_destroy (l->data, NULL, &error)) { g_warning ("couldn't destroy session item: %s", egg_error_message (error)); g_clear_error (&error); } } gck_list_unref_free (objects); return TRUE; }
gboolean gkd_ssh_agent_initialize_with_module (GckModule *module) { GckSession *session = NULL; GList *slots, *l; GArray *mechs; GError *error = NULL; g_assert (GCK_IS_MODULE (module)); /* Find a good slot for our session keys */ slots = gck_module_get_slots (module, TRUE); for (l = slots; session == NULL && l; l = g_list_next (l)) { /* Check that it has the mechanisms we need */ mechs = gck_slot_get_mechanisms (l->data); if (gck_mechanisms_check (mechs, CKM_RSA_PKCS, CKM_DSA, GCK_INVALID)) { /* Try and open a session */ session = gck_slot_open_session (l->data, GCK_SESSION_AUTHENTICATE, NULL, &error); if (!session) { g_warning ("couldn't create pkcs#11 session: %s", egg_error_message (error)); g_clear_error (&error); } } g_array_unref (mechs); } gck_list_unref_free (slots); if (!session) { g_warning ("couldn't select a usable pkcs#11 slot for the ssh agent to use"); return FALSE; } g_assert (!pkcs11_modules); pkcs11_modules = g_list_append (NULL, g_object_ref (module)); pkcs11_main_mutex = g_new0 (GMutex, 1); g_mutex_init (pkcs11_main_mutex); pkcs11_main_cond = g_new0 (GCond, 1); g_cond_init (pkcs11_main_cond); pkcs11_main_checked = FALSE; pkcs11_main_session = session; return TRUE; }
GckObject* gkd_secret_objects_lookup_item (GkdSecretObjects *self, const gchar *caller, const gchar *path) { GckBuilder builder = GCK_BUILDER_INIT; GckObject *object = NULL; GError *error = NULL; GList *objects; GckSession *session; gchar *collection; gchar *identifier; g_return_val_if_fail (GKD_SECRET_IS_OBJECTS (self), NULL); g_return_val_if_fail (caller, NULL); g_return_val_if_fail (path, NULL); if (!gkd_secret_util_parse_path (path, &collection, &identifier)) return NULL; /* The session we're using to access the object */ session = gkd_secret_service_get_pkcs11_session (self->service, caller); g_return_val_if_fail (session, NULL); gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY); gck_builder_add_string (&builder, CKA_ID, identifier); gck_builder_add_string (&builder, CKA_G_COLLECTION, collection); objects = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error); g_free (identifier); g_free (collection); if (error != NULL) { g_warning ("couldn't lookup item: %s: %s", path, egg_error_message (error)); g_clear_error (&error); } if (objects) object = g_object_ref (objects->data); gck_list_unref_free (objects); return object; }
void gkd_secret_objects_foreach_item (GkdSecretObjects *self, const gchar *caller, const gchar *base, GkdSecretObjectsForeach callback, gpointer user_data) { GckBuilder builder = GCK_BUILDER_INIT; GckSession *session; GError *error = NULL; gchar *identifier; GList *items; g_return_if_fail (GKD_SECRET_IS_OBJECTS (self)); g_return_if_fail (base != NULL); g_return_if_fail (callback != NULL); /* The session we're using to access the object */ if (caller == NULL) { session = gkd_secret_service_internal_pkcs11_session (self->service); } else { session = gkd_secret_service_get_pkcs11_session (self->service, caller); } if (!gkd_secret_util_parse_path (base, &identifier, NULL)) g_return_if_reached (); gck_builder_add_ulong (&builder, CKA_CLASS, CKO_SECRET_KEY); gck_builder_add_string (&builder, CKA_G_COLLECTION, identifier); items = gck_session_find_objects (session, gck_builder_end (&builder), NULL, &error); if (error == NULL) { objects_foreach_item (self, items, base, callback, user_data); } else { g_warning ("couldn't lookup items in '%s' collection: %s", identifier, egg_error_message (error)); g_clear_error (&error); } gck_list_unref_free (items); g_free (identifier); }
gboolean gkd_login_unlock (const gchar *master) { GList *modules; gboolean result; /* We don't support null or empty master passwords */ if (!master || !master[0]) return FALSE; modules = module_instances (); result = unlock_or_create_login (modules, master); if (result == TRUE) init_pin_for_uninitialized_slots (modules, master); gck_list_unref_free (modules); return result; }
static void on_parser_parsed (GcrParser *parser, gpointer user_data) { ImportClosure *closure = user_data; GcrParsed *parsed; GList *filtered; parsed = gcr_parser_get_parsed (parser); if (closure->num_parsed == 0) { closure->importers = gcr_importer_create_for_parsed (parsed); } else { filtered = gcr_importer_queue_and_filter_for_parsed (closure->importers, parsed); gck_list_unref_free (closure->importers); closure->importers = filtered; } closure->num_parsed++; }
gboolean gkd_login_change_lock (const gchar *original, const gchar *master) { GList *modules; gboolean result; /* We don't support null or empty master passwords */ if (!master || !master[0]) return FALSE; if (original == NULL) original = ""; modules = module_instances (); result = change_or_create_login (modules, original, master); if (result == TRUE) set_pin_for_any_slots (modules, original, master); gck_list_unref_free (modules); return result; }
void gkd_ssh_agent_uninitialize (void) { gboolean ret; g_assert (pkcs11_main_mutex); ret = g_mutex_trylock (pkcs11_main_mutex); g_assert (ret); g_assert (GCK_IS_SESSION (pkcs11_main_session)); g_assert (!pkcs11_main_checked); g_object_unref (pkcs11_main_session); pkcs11_main_session = NULL; g_mutex_unlock (pkcs11_main_mutex); g_mutex_clear (pkcs11_main_mutex); g_free (pkcs11_main_mutex); g_cond_clear (pkcs11_main_cond); g_free (pkcs11_main_cond); gck_list_unref_free (pkcs11_modules); pkcs11_modules = NULL; }
int gkr_tool_import (int argc, char *argv[]) { GcrParser *parser; GError *error = NULL; GInputStream *input; ImportClosure *closure; GFile *file; gchar **imp; int ret = 0; GList *l; ret = gkr_tool_parse_options (&argc, &argv, import_entries); if (ret != 0) return ret; if(!import_files || !*import_files) { gkr_tool_handle_error (NULL, "specify files to import"); return 2; } if (!gcr_pkcs11_initialize (NULL, &error)) { gkr_tool_handle_error (&error, "couldn't initialize pkcs11 modules"); return 1; } parser = gcr_parser_new (); closure = g_new0 (ImportClosure, 1); g_signal_connect (parser, "parsed", G_CALLBACK (on_parser_parsed), closure); for (imp = import_files; *imp; ++imp) { file = g_file_new_for_commandline_arg (*imp); input = G_INPUT_STREAM (g_file_read (file, NULL, &error)); g_object_unref (file); if (input == NULL) { gkr_tool_handle_error (&error, "couldn't read file: %s", *imp); ret = 1; } else { if (!gcr_parser_parse_stream (parser, input, NULL, &error)) { if (error->code != GCR_ERROR_CANCELLED) gkr_tool_handle_error (&error, "couldn't parse: %s", *imp); ret = 1; } g_object_unref (input); } } if (closure->importers == NULL) { gkr_tool_handle_error (NULL, "couldn't find any place to import files"); ret = 1; } for (l = closure->importers; l != NULL; l = g_list_next (l)) { if (gcr_importer_import (l->data, NULL, &error)) { if (!gkr_tool_mode_quiet) imported_display (l->data); } else { if (error->code != GCR_ERROR_CANCELLED) gkr_tool_handle_error (&error, "couldn't import"); ret = 1; } } gck_list_unref_free (closure->importers); g_free (closure); g_object_unref (parser); return ret; }
gboolean gkd_secret_objects_handle_search_items (GkdSecretObjects *self, GDBusMethodInvocation *invocation, GVariant *attributes, const gchar *base, gboolean separate_locked) { GckBuilder builder = GCK_BUILDER_INIT; GckObject *search; GckSession *session; GError *error = NULL; gchar *identifier; gpointer data; gsize n_data; GList *locked, *unlocked; GList *items; GVariantBuilder result; if (!gkd_secret_property_parse_fields (attributes, &builder)) { gck_builder_clear (&builder); g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Invalid data in attributes argument"); return TRUE; } if (base != NULL) { if (!gkd_secret_util_parse_path (base, &identifier, NULL)) g_return_val_if_reached (FALSE); gck_builder_add_string (&builder, CKA_G_COLLECTION, identifier); g_free (identifier); } gck_builder_add_ulong (&builder, CKA_CLASS, CKO_G_SEARCH); gck_builder_add_boolean (&builder, CKA_TOKEN, FALSE); /* The session we're using to access the object */ session = gkd_secret_service_get_pkcs11_session (self->service, g_dbus_method_invocation_get_sender (invocation)); g_return_val_if_fail (session, FALSE); /* Create the search object */ search = gck_session_create_object (session, gck_builder_end (&builder), NULL, &error); if (error != NULL) { g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Couldn't search for items: %s", egg_error_message (error)); g_clear_error (&error); return TRUE; } /* Get the matched item handles, and delete the search object */ data = gck_object_get_data (search, CKA_G_MATCHED, NULL, &n_data, &error); gck_object_destroy (search, NULL, NULL); g_object_unref (search); if (error != NULL) { g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Couldn't retrieve matched items: %s", egg_error_message (error)); g_clear_error (&error); return TRUE; } /* Build a list of object handles */ items = gck_objects_from_handle_array (session, data, n_data / sizeof (CK_OBJECT_HANDLE)); g_free (data); /* Filter out the locked items */ if (separate_locked) { GVariant *unlocked_variant, *locked_variant; item_cleanup_search_results (session, items, &locked, &unlocked); g_variant_builder_init (&result, G_VARIANT_TYPE ("ao")); objects_foreach_item (self, unlocked, NULL, on_object_path_append_to_builder, &result); unlocked_variant = g_variant_builder_end (&result); g_variant_builder_init (&result, G_VARIANT_TYPE ("ao")); objects_foreach_item (self, locked, NULL, on_object_path_append_to_builder, &result); locked_variant = g_variant_builder_end (&result); g_list_free (locked); g_list_free (unlocked); g_dbus_method_invocation_return_value (invocation, g_variant_new ("(@ao@ao)", unlocked_variant, locked_variant)); } else { g_variant_builder_init (&result, G_VARIANT_TYPE ("ao")); objects_foreach_item (self, items, NULL, on_object_path_append_to_builder, &result); g_dbus_method_invocation_return_value (invocation, g_variant_new ("(@ao)", g_variant_builder_end (&result))); } gck_list_unref_free (items); return TRUE; }