+ return SILC_OK;
+}
+
+
+/***************************** SSH2 Public Key ******************************/
+
+/* Add SSH2 style public key to repository */
+
+static SilcResult silc_skr_add_ssh(SilcSKR skr,
+ SilcPublicKey public_key,
+ SilcSKRKeyUsage usage,
+ void *key_context,
+ SilcSKRKey *return_key)
+{
+ SilcSKRKeyInternal key;
+ SilcResult status = SILC_ERR;
+ SilcSshPublicKey ssh_pubkey;
+ const char *subject;
+#if defined(SILC_DEBUG)
+ char tmp[256];
+#endif /* SILC_DEBUG */
+
+ /* Get the SSH public key */
+ ssh_pubkey = silc_pkcs_public_key_get_pkcs(SILC_PKCS_SSH2, public_key);
+
+ /* Get subject */
+ subject = silc_ssh_public_key_get_field(ssh_pubkey, "Subject");
+
+ SILC_LOG_DEBUG(("Adding SSH public key %p [%s], context %p", public_key,
+ subject ? subject : "none", key_context));
+
+ silc_mutex_lock(skr->lock);
+
+ /* Check that this key hasn't been added already */
+ if (silc_skr_find_entry(skr, &status, SILC_SKR_FIND_PUBLIC_KEY,
+ public_key, NULL, key_context, 0)) {
+ silc_mutex_unlock(skr->lock);
+ SILC_LOG_DEBUG(("Key already added"));
+ return SILC_ERR_ALREADY_EXISTS;
+ }
+
+ /* Allocate key entry */
+ key = silc_calloc(1, sizeof(*key));
+ if (!key) {
+ silc_mutex_unlock(skr->lock);
+ return silc_errno;
+ }
+
+ key->key.usage = usage;
+ key->key.key = public_key;
+ key->key.key_context = key_context;
+
+#if defined(SILC_DEBUG)
+ silc_skr_type_string(SILC_SKR_FIND_USAGE, SILC_32_TO_PTR(usage),
+ tmp, sizeof(tmp) - 1);
+ SILC_LOG_DEBUG((" Search constraint %s", tmp));
+#endif /* SILC_DEBUG */
+
+ /* Add key specifics */
+
+ if (!silc_skr_add_entry(skr, SILC_SKR_FIND_PUBLIC_KEY,
+ public_key, key))
+ goto err;
+ key->refcnt++;
+
+ if (!silc_skr_add_entry(skr, SILC_SKR_FIND_PKCS_TYPE,
+ SILC_32_TO_PTR(SILC_PKCS_SSH2), key))
+ goto err;
+ key->refcnt++;
+
+ if (subject) {
+ if (!silc_skr_add_entry(skr, SILC_SKR_FIND_USERNAME,
+ (void *)subject, key))
+ goto err;
+ key->refcnt++;
+ }
+
+ if (key_context) {
+ if (!silc_skr_add_entry(skr, SILC_SKR_FIND_CONTEXT,
+ key_context, key))
+ goto err;
+ key->refcnt++;
+ }
+
+ silc_mutex_unlock(skr->lock);
+
+ if (return_key)
+ *return_key = (SilcSKRKey)key;
+
+ return SILC_OK;
+
+ err:
+ silc_mutex_unlock(skr->lock);
+ return status;
+}
+
+/* Add SSH2 style public key to repository. Only the public key is added,
+ not other information from the key. */
+
+static SilcResult silc_skr_add_ssh_simple(SilcSKR skr,
+ SilcPublicKey public_key,
+ SilcSKRKeyUsage usage,
+ void *key_context,
+ SilcSKRKey *return_key)
+{
+ SilcSKRKeyInternal key;
+ SilcResult status = SILC_ERR;
+ SilcSshPublicKey ssh_pubkey;
+#if defined(SILC_DEBUG)
+ char tmp[256];
+#endif /* SILC_DEBUG */
+
+ /* Get the SSH public key */
+ ssh_pubkey = silc_pkcs_public_key_get_pkcs(SILC_PKCS_SSH2, public_key);
+
+ SILC_LOG_DEBUG(("Adding SSH public key %p, context %p", public_key,
+ key_context));
+
+ silc_mutex_lock(skr->lock);
+
+ /* Check that this key hasn't been added already */
+ if (silc_skr_find_entry(skr, &status, SILC_SKR_FIND_PUBLIC_KEY,
+ public_key, NULL, key_context, 0)) {
+ silc_mutex_unlock(skr->lock);
+ SILC_LOG_DEBUG(("Key already added"));
+ return SILC_ERR_ALREADY_EXISTS;
+ }
+
+ /* Allocate key entry */
+ key = silc_calloc(1, sizeof(*key));
+ if (!key) {
+ silc_mutex_unlock(skr->lock);
+ return silc_errno;
+ }
+
+ key->key.usage = usage;
+ key->key.key = public_key;
+ key->key.key_context = key_context;
+
+#if defined(SILC_DEBUG)
+ silc_skr_type_string(SILC_SKR_FIND_USAGE, SILC_32_TO_PTR(usage),
+ tmp, sizeof(tmp) - 1);
+ SILC_LOG_DEBUG((" Search constraint %s", tmp));
+#endif /* SILC_DEBUG */
+
+ /* Add key specifics */
+
+ if (!silc_skr_add_entry(skr, SILC_SKR_FIND_PUBLIC_KEY,
+ public_key, key))
+ goto err;
+ key->refcnt++;
+
+ if (key_context) {
+ if (!silc_skr_add_entry(skr, SILC_SKR_FIND_CONTEXT,
+ key_context, key))
+ goto err;
+ key->refcnt++;
+ }
+
+ silc_mutex_unlock(skr->lock);
+
+ if (return_key)
+ *return_key = (SilcSKRKey)key;
+
+ return SILC_OK;
+
+ err:
+ silc_mutex_unlock(skr->lock);
+ return status;
+}
+
+/* Deletes SSH public key from repository */
+
+static SilcResult silc_skr_del_ssh_public_key(SilcSKR skr,
+ SilcPublicKey public_key,
+ void *key_context)
+{
+ SilcResult status = SILC_ERR;
+ SilcSshPublicKey ssh_pubkey;
+ SilcSKRKeyInternal key;
+ SilcDList entry;
+ const char *subject;
+
+ /* Get the SSH public key */
+ ssh_pubkey = silc_pkcs_public_key_get_pkcs(SILC_PKCS_SSH2, public_key);
+
+ /* Get subject */
+ subject = silc_ssh_public_key_get_field(ssh_pubkey, "Subject");
+
+ SILC_LOG_DEBUG(("Deleting SSH public key %p [%s]", public_key,
+ subject ? subject : "none"));
+
+ silc_mutex_lock(skr->lock);
+
+ /* Check that this key exists */
+ if (!silc_skr_find_entry(skr, &status, SILC_SKR_FIND_PUBLIC_KEY,
+ public_key, &entry, key_context, 0)) {
+ silc_mutex_unlock(skr->lock);
+ SILC_LOG_DEBUG(("Key does not exist"));
+ return SILC_ERR_NOT_FOUND;
+ }
+
+ silc_dlist_start(entry);
+ key = silc_dlist_get(entry);
+ silc_dlist_uninit(entry);
+
+ silc_skr_del_entry(skr, SILC_SKR_FIND_PUBLIC_KEY, public_key, key);
+ silc_skr_del_entry(skr, SILC_SKR_FIND_PKCS_TYPE,
+ SILC_32_TO_PTR(SILC_PKCS_SSH2), key);
+ silc_skr_del_entry(skr, SILC_SKR_FIND_USERNAME, (void *)subject, key);
+ silc_skr_del_entry(skr, SILC_SKR_FIND_CONTEXT, key_context, key);
+
+ silc_mutex_unlock(skr->lock);
+
+ return SILC_OK;