static GP11Object* create_credential (GP11Session *session, GP11Object *object, const gchar *secret, GError **error) { GP11Attributes *attrs; GP11Object *cred; g_return_val_if_fail (GP11_IS_SESSION (session), NULL); g_return_val_if_fail (!object || GP11_IS_OBJECT (object), NULL); if (!secret) secret = ""; attrs = gp11_attributes_newv (CKA_CLASS, GP11_ULONG, CKO_G_CREDENTIAL, CKA_VALUE, strlen (secret), secret, CKA_MATE_TRANSIENT, GP11_BOOLEAN, TRUE, CKA_TOKEN, GP11_BOOLEAN, TRUE, GP11_INVALID); if (object) gp11_attributes_add_ulong (attrs, CKA_G_OBJECT, gp11_object_get_handle (object)); cred = gp11_session_create_object_full (session, attrs, NULL, error); gp11_attributes_unref (attrs); if (cred != NULL) gp11_object_set_session (cred, session); return cred; }
static void state_create_object (GcrImporter *self, gboolean async) { GP11Attributes *attrs; GP11Object *object; GError *error = NULL; /* No more objects */ if (g_queue_is_empty (&self->pv->queue)) { next_state (self, state_complete); } else { /* Pop first one off the list */ attrs = g_queue_pop_head (&self->pv->queue); g_assert (attrs); gp11_attributes_add_boolean (attrs, CKA_TOKEN, CK_TRUE); if (async) { gp11_session_create_object_async (self->pv->session, attrs, self->pv->cancel, on_create_object, self); } else { object = gp11_session_create_object_full (self->pv->session, attrs, self->pv->cancel, &error); complete_create_object (self, object, error); } gp11_attributes_unref (attrs); } }
static void cleanup_state_data (GcrImporter *self) { GP11Attributes *attrs; if (self->pv->buffer) g_byte_array_free (self->pv->buffer, TRUE); self->pv->buffer = NULL; if (self->pv->session) g_object_unref (self->pv->session); self->pv->session = NULL; while ((attrs = g_queue_pop_head (&self->pv->queue)) != NULL) gp11_attributes_unref (attrs); g_assert (g_queue_is_empty (&self->pv->queue)); if (self->pv->input) g_object_unref (self->pv->input); self->pv->input = NULL; if (self->pv->cancel) g_object_unref (self->pv->cancel); self->pv->cancel = NULL; }
/** * gp11_object_get: * @self: The object to get attributes from. * @err: A location to store an error. * @...: The attribute types to get. * * Get the specified attributes from the object. This call may * block for an indefinite period. * * Return value: The resulting PKCS#11 attributes, or NULL if an error occurred. * The result must be unreffed when you're finished with it. **/ GP11Attributes* gp11_object_get (GP11Object *self, GError **err, ...) { GP11Attributes *attrs; va_list va; gulong type; g_return_val_if_fail (GP11_IS_OBJECT (self), NULL); g_return_val_if_fail (!err || !*err, NULL); attrs = gp11_attributes_new (); va_start (va, err); for (;;) { type = va_arg (va, gulong); if (type == GP11_INVALID) break; gp11_attributes_add_invalid (attrs, type); } va_end (va); if (!gp11_object_get_full (self, attrs, NULL, err)) { gp11_attributes_unref (attrs); return NULL; } return attrs; }
static void free_set_attributes (SetAttributes *args) { g_assert (args); gp11_attributes_unref (args->attrs); g_free (args); }
/** * gp11_object_get_template_full: * @self: The object to get an attribute template from. * @attr_type: The template attribute type. * @cancellable: Optional cancellation object, or NULL. * @err: A location to store an error. * * Get an attribute template from the object. The attr_type must be for * an attribute which returns a template. * * This call may block for an indefinite period. * * Return value: The resulting PKCS#11 attribute template, or NULL if an error occurred. **/ GP11Attributes* gp11_object_get_template_full (GP11Object *self, gulong attr_type, GCancellable *cancellable, GError **err) { GP11ObjectData *data = GP11_OBJECT_GET_DATA (self); get_template_args args; GP11Session *session; gboolean ret; g_return_val_if_fail (GP11_IS_OBJECT (self), NULL); g_return_val_if_fail (!err || !*err, NULL); session = require_session_sync (self, 0, err); if (!session) return NULL; memset (&args, 0, sizeof (args)); args.object = data->handle; args.type = attr_type; ret = _gp11_call_sync (session, perform_get_template, NULL, &args, cancellable, err); g_object_unref (session); _gp11_attributes_unlock (args.attrs); /* Free any value if failed */ if (!ret) { gp11_attributes_unref (args.attrs); args.attrs = NULL; } return args.attrs; }
static void free_get_template (get_template_args *args) { g_assert (args); gp11_attributes_unref (args->attrs); g_free (args); }
static DBusMessage* service_method_create_collection (GkdSecretService *self, DBusMessage *message) { DBusMessageIter iter, array; GP11Attributes *attrs; GkdSecretCreate *create; ServiceClient *client; DBusMessage *reply; const gchar *path; const char *caller; const gchar *coll; /* Parse the incoming message */ if (!dbus_message_has_signature (message, "a{sv}")) return NULL; if (!dbus_message_iter_init (message, &iter)) g_return_val_if_reached (NULL); attrs = gp11_attributes_new (); dbus_message_iter_recurse (&iter, &array); if (!gkd_secret_property_parse_all (&array, attrs)) { gp11_attributes_unref (attrs); return dbus_message_new_error_printf (message, DBUS_ERROR_INVALID_ARGS, "Invalid properties"); } gp11_attributes_add_boolean (attrs, CKA_TOKEN, TRUE); /* Create the prompt object, for the password */ caller = dbus_message_get_sender (message); create = gkd_secret_create_new (self, caller, attrs); gp11_attributes_unref (attrs); path = gkd_secret_dispatch_get_object_path (GKD_SECRET_DISPATCH (create)); client = g_hash_table_lookup (self->clients, caller); g_return_val_if_fail (client, NULL); g_hash_table_replace (client->prompts, (gpointer)path, create); coll = "/"; reply = dbus_message_new_method_return (message); dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &coll, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID); return reply; }
static DBusMessage* service_method_create_with_master_password (GkdSecretService *self, DBusMessage *message) { DBusError derr = DBUS_ERROR_INIT; DBusMessageIter iter, array; DBusMessage *reply = NULL; GkdSecretSecret *secret = NULL; GP11Attributes *attrs = NULL; gchar *path; /* Parse the incoming message */ if (!dbus_message_has_signature (message, "a{sv}(oayay)")) return NULL; if (!dbus_message_iter_init (message, &iter)) g_return_val_if_reached (NULL); attrs = gp11_attributes_new (); dbus_message_iter_recurse (&iter, &array); if (!gkd_secret_property_parse_all (&array, attrs)) { gp11_attributes_unref (attrs); return dbus_message_new_error (message, DBUS_ERROR_INVALID_ARGS, "Invalid properties argument"); } dbus_message_iter_next (&iter); secret = gkd_secret_secret_parse (self, message, &iter, &derr); if (secret == NULL) { gp11_attributes_unref (attrs); return gkd_secret_error_to_reply (message, &derr); } gp11_attributes_add_boolean (attrs, CKA_TOKEN, TRUE); path = gkd_secret_create_with_secret (attrs, secret, &derr); gp11_attributes_unref (attrs); gkd_secret_secret_free (secret); if (path == NULL) return gkd_secret_error_to_reply (message, &derr); reply = dbus_message_new_method_return (message); dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID); g_free (path); return reply; }
/** * gp11_object_set: * @self: The object to set attributes on. * @err: A location to return an error. * @...: The attributes to set. * * Set PKCS#11 attributes on an object. * This call may block for an indefinite period. * * The arguments must be triples of: attribute type, data type, value * * <para>The variable argument list should contain: * <variablelist> * <varlistentry> * <term>a)</term> * <listitem><para>The gulong attribute type (ie: CKA_LABEL). </para></listitem> * </varlistentry> * <varlistentry> * <term>b)</term> * <listitem><para>The attribute data type (one of GP11_BOOLEAN, GP11_ULONG, * GP11_STRING, GP11_DATE) orthe raw attribute value length.</para></listitem> * </varlistentry> * <varlistentry> * <term>c)</term> * <listitem><para>The attribute value, either a gboolean, gulong, gchar*, GDate* or * a pointer to a raw attribute value.</para></listitem> * </varlistentry> * </variablelist> * The variable argument list should be terminated with GP11_INVALID.</para> * * Return value: Whether the call was successful or not. **/ gboolean gp11_object_set (GP11Object *self, GError **err, ...) { GP11Attributes *attrs; va_list va; CK_RV rv; g_return_val_if_fail (GP11_IS_OBJECT (self), FALSE); g_return_val_if_fail (!err || !*err, FALSE); va_start (va, err); attrs = gp11_attributes_new_valist (g_realloc, va); va_end (va); rv = gp11_object_set_full (self, attrs, NULL, err); gp11_attributes_unref (attrs); return rv; }
static void on_open_session(GP11Slot *slot, GAsyncResult *result, SeahorsePkcs11Refresher *self) { GError *err = NULL; GP11Attributes *attrs; g_return_if_fail (SEAHORSE_IS_PKCS11_REFRESHER (self)); self->session = gp11_slot_open_session_finish (slot, result, &err); if (!self->session) { seahorse_pkcs11_mark_complete (SEAHORSE_OPERATION (self), err); return; } /* Step 2. Load all the objects that we want */ attrs = gp11_attributes_new (); gp11_attributes_add_boolean (attrs, CKA_TOKEN, TRUE); gp11_attributes_add_ulong (attrs, CKA_CLASS, CKO_CERTIFICATE); gp11_session_find_objects_async (self->session, attrs, self->cancellable, (GAsyncReadyCallback)on_find_objects, self); gp11_attributes_unref (attrs); }
/** * gp11_module_enumerate_objects: * @self: The module to enumerate objects. * @func: Function to call for each object. * @user_data: Data to pass to the function. * @...: The arguments must be triples of: attribute type, data type, value. * * Call a function for every matching object on the module. This call may * block for an indefinite period. * * * <para>The variable argument list should contain: * <variablelist> * <varlistentry> * <term>a)</term> * <listitem><para>The gulong attribute type (ie: CKA_LABEL). </para></listitem> * </varlistentry> * <varlistentry> * <term>b)</term> * <listitem><para>The attribute data type (one of GP11_BOOLEAN, GP11_ULONG, * GP11_STRING, GP11_DATE) orthe raw attribute value length.</para></listitem> * </varlistentry> * <varlistentry> * <term>c)</term> * <listitem><para>The attribute value, either a gboolean, gulong, gchar*, GDate* or * a pointer to a raw attribute value.</para></listitem> * </varlistentry> * </variablelist> * The variable argument list should be terminated with GP11_INVALID.</para> * * This function will open a session per slot. It's recommended that you * set the 'reuse-sessions' property on each slot if you'll be calling * it a lot. * * You can access the session in which the object was found, by using the * gp11_object_get_session() function on the resulting objects. * * This function skips tokens that are not initialize, and makes a best effort to * find objects on valid tokens. * * The function can return FALSE to stop the enumeration. * * Return value: If FALSE then an error prevented all matching objects from being enumerated. **/ gboolean gp11_module_enumerate_objects (GP11Module *self, GP11ObjectForeachFunc func, gpointer user_data, ...) { GP11Attributes *attrs; GError *error = NULL; va_list va; va_start (va, user_data); attrs = gp11_attributes_new_valist (g_realloc, va); va_end (va); gp11_module_enumerate_objects_full (self, attrs, NULL, func, user_data, &error); gp11_attributes_unref (attrs); if (error != NULL) { g_warning ("enumerating objects failed: %s", error->message); g_clear_error (&error); return FALSE; } return TRUE; }
/** * gp11_module_enumerate_objects_full: * @self: The module to enumerate objects. * @attrs: Attributes that the objects must have, or empty for all objects. * @cancellable: Optional cancellation object, or NULL. * @func: Function to call for each object. * @user_data: Data to pass to the function. * @error: Location to return error information. * * Call a function for every matching object on the module. This call may * block for an indefinite period. * * This function will open a session per slot. It's recommended that you * set the 'reuse-sessions' property on each slot if you'll be calling * it a lot. * * You can access the session in which the object was found, by using the * gp11_object_get_session() function on the resulting objects. * * The function can return FALSE to stop the enumeration. * * Return value: If FALSE then an error prevented all matching objects from being enumerated. **/ gboolean gp11_module_enumerate_objects_full (GP11Module *self, GP11Attributes *attrs, GCancellable *cancellable, GP11ObjectForeachFunc func, gpointer user_data, GError **err) { gboolean stop = FALSE; gboolean ret = TRUE; GList *objects, *o; GList *slots, *l; GError *error = NULL; GP11Session *session; g_return_val_if_fail (GP11_IS_MODULE (self), FALSE); g_return_val_if_fail (attrs, FALSE); g_return_val_if_fail (func, FALSE); gp11_attributes_ref (attrs); slots = gp11_module_get_slots (self, TRUE); for (l = slots; ret && !stop && l; l = g_list_next (l)) { /* TODO: We really should allow the caller to specify the flags, at least read-write */ session = gp11_slot_open_session (l->data, CKF_RW_SESSION | CKF_SERIAL_SESSION, &error); if (!session) { g_return_val_if_fail (error != NULL, FALSE); /* Ignore these errors when enumerating */ if (g_error_matches (error, GP11_ERROR, CKR_USER_PIN_NOT_INITIALIZED)) { g_clear_error (&error); } else { ret = FALSE; g_propagate_error (err, error); error = NULL; } continue; } objects = gp11_session_find_objects_full (session, attrs, cancellable, &error); if (error) { ret = FALSE; g_object_unref (session); g_propagate_error (err, error); error = NULL; continue; } for (o = objects; !stop && o; o = g_list_next (o)) { gp11_object_set_session (o->data, session); if (!(func)(o->data, user_data)) { stop = TRUE; break; } } g_object_unref (session); gp11_list_unref_free (objects); } gp11_list_unref_free (slots); gp11_attributes_unref (attrs); return ret; }