Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2005 - 2007 Pekka Riikonen
+ Copyright (C) 2005 - 2008 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
*/
-#include "silc.h"
+#include "silccrypto.h"
#include "silcskr.h"
/************************** Types and definitions ***************************/
#if defined(SILC_DEBUG)
static const char *find_name[] = {
- "PKCS TYPE",
- "USERNAME",
- "HOST",
- "REALNAME",
- "EMAIL",
- "ORG",
- "COUNTRY",
+ "PKCS TYPE ",
+ "USERNAME ",
+ "HOST ",
+ "REALNAME ",
+ "EMAIL ",
+ "ORG ",
+ "COUNTRY ",
"PUBLIC KEY",
- "CONTEXT",
- "USAGE",
+ "CONTEXT ",
+ "USAGE ",
NULL
};
#endif /* SILC_DEBUG */
case SILC_SKR_FIND_PKCS_TYPE:
case SILC_SKR_FIND_USAGE:
silc_snprintf(retbuf, retbuf_size, "[%s] [%d]", find_name[type],
- (int)SILC_PTR_TO_32(data));
+ (int)SILC_PTR_TO_32(data));
break;
case SILC_SKR_FIND_PUBLIC_KEY:
default:
silc_snprintf(retbuf, retbuf_size, "[%s] [%s]", find_name[type],
- (char *)data);
+ (char *)data);
}
}
#endif /* SILC_DEBUG */
break;
default:
- /* In SILC Public key all entries are referenced from the public key
+ /* In SILC and SSH2 keys all entries are referenced from the public key
so don't free them. This test is valid only when removing key
from the repository. */
- if (pkcs_type == SILC_PKCS_SILC)
+ if (pkcs_type == SILC_PKCS_SILC || pkcs_type == SILC_PKCS_SSH2)
break;
silc_free(context);
break;
}
- return type->type + silc_hash_string(type->data, user_context);
+ return type->type + silc_hash_string_case(type->data, user_context);
}
/* Hash table comparison function for key entries */
/* Finds entry from repository by search constraint type and data */
static SilcBool silc_skr_find_entry(SilcSKR skr,
- SilcSKRStatus *status,
+ SilcResult *status,
SilcSKRFindType type,
void *type_data,
SilcDList *results,
{
SilcSKREntry entry;
+#if defined(SILC_DEBUG)
+ char tmp[256];
+ memset(tmp, 0, sizeof(tmp));
+ silc_skr_type_string(type, type_data, tmp, sizeof(tmp) - 1);
+ SILC_LOG_DEBUG(("Search constraint %s", tmp));
+#endif /* SILC_DEBUG */
+
entry = silc_calloc(1, sizeof(*entry));
if (!entry)
return FALSE;
/* This performs AND operation. Any entry already in `results' that is not
in `list' will be removed from `results'. */
-static SilcBool silc_skr_results_and(SilcDList list, SilcSKRStatus *status,
+static SilcBool silc_skr_results_and(SilcDList list, SilcResult *status,
SilcDList *results)
{
SilcSKRKeyInternal entry, r;
/* Add SILC style public key to repository */
-static SilcSKRStatus silc_skr_add_silc(SilcSKR skr,
- SilcPublicKey public_key,
- SilcSKRKeyUsage usage,
- void *key_context,
- SilcSKRKey *return_key)
+static SilcResult silc_skr_add_silc(SilcSKR skr,
+ SilcPublicKey public_key,
+ SilcSKRKeyUsage usage,
+ void *key_context,
+ SilcSKRKey *return_key)
{
SilcSKRKeyInternal key;
- SilcSKRStatus status = SILC_SKR_ERROR;
+ SilcResult status = SILC_ERR;
SilcPublicKeyIdentifier ident;
SilcSILCPublicKey silc_pubkey;
+#if defined(SILC_DEBUG)
+ char tmp[256];
+#endif /* SILC_DEBUG */
/* Get the SILC public key */
- silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key);
+ silc_pubkey = silc_pkcs_public_key_get_pkcs(SILC_PKCS_SILC, public_key);
ident = &silc_pubkey->identifier;
- SILC_LOG_DEBUG(("Adding SILC public key [%s]", ident->username));
+ SILC_LOG_DEBUG(("Adding SILC public key %p [%s], context %p",
+ public_key, ident->username, key_context));
silc_mutex_lock(skr->lock);
public_key, NULL, key_context, 0)) {
silc_mutex_unlock(skr->lock);
SILC_LOG_DEBUG(("Key already added"));
- return status | SILC_SKR_ALREADY_EXIST;
+ return SILC_ERR_ALREADY_EXISTS;
}
/* Allocate key entry */
key = silc_calloc(1, sizeof(*key));
if (!key) {
silc_mutex_unlock(skr->lock);
- return status | SILC_SKR_NO_MEMORY;
+ 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,
if (return_key)
*return_key = (SilcSKRKey)key;
- return SILC_SKR_OK;
+ return SILC_OK;
err:
silc_mutex_unlock(skr->lock);
/* Add SILC style public key to repository, and only the public key, not
other details from the key. */
-static SilcSKRStatus silc_skr_add_silc_simple(SilcSKR skr,
- SilcPublicKey public_key,
- SilcSKRKeyUsage usage,
- void *key_context,
- SilcSKRKey *return_key)
+static SilcResult silc_skr_add_silc_simple(SilcSKR skr,
+ SilcPublicKey public_key,
+ SilcSKRKeyUsage usage,
+ void *key_context,
+ SilcSKRKey *return_key)
{
SilcSKRKeyInternal key;
- SilcSKRStatus status = SILC_SKR_ERROR;
+ SilcResult status = SILC_ERR;
+#if defined(SILC_DEBUG)
+ char tmp[256];
+#endif /* SILC_DEBUG */
SILC_LOG_DEBUG(("Adding SILC public key"));
public_key, NULL, key_context, 0)) {
silc_mutex_unlock(skr->lock);
SILC_LOG_DEBUG(("Key already added"));
- return status | SILC_SKR_ALREADY_EXIST;
+ return SILC_ERR_ALREADY_EXISTS;
}
/* Allocate key entry */
key = silc_calloc(1, sizeof(*key));
if (!key) {
silc_mutex_unlock(skr->lock);
- return status | SILC_SKR_NO_MEMORY;
+ 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 cons %s", tmp));
+#endif /* SILC_DEBUG */
+
/* Add key specifics */
if (!silc_skr_add_entry(skr, SILC_SKR_FIND_PUBLIC_KEY,
if (return_key)
*return_key = (SilcSKRKey)key;
- return SILC_SKR_OK;
+ return SILC_OK;
err:
silc_mutex_unlock(skr->lock);
/* Deletes SILC public key from repository */
-static SilcSKRStatus silc_skr_del_silc_public_key(SilcSKR skr,
- SilcPublicKey public_key,
- void *key_context)
+static SilcResult silc_skr_del_silc_public_key(SilcSKR skr,
+ SilcPublicKey public_key,
+ void *key_context)
{
- SilcSKRStatus status = SILC_SKR_ERROR;
+ SilcResult status = SILC_ERR;
SilcPublicKeyIdentifier ident;
SilcSILCPublicKey silc_pubkey;
SilcSKRKeyInternal key;
SilcDList entry;
/* Get the SILC public key */
- silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key);
+ silc_pubkey = silc_pkcs_public_key_get_pkcs(SILC_PKCS_SILC, public_key);
ident = &silc_pubkey->identifier;
SILC_LOG_DEBUG(("Deleting SILC public key [%s]", ident->username));
public_key, &entry, key_context, 0)) {
silc_mutex_unlock(skr->lock);
SILC_LOG_DEBUG(("Key does not exist"));
- return status | SILC_SKR_NOT_FOUND;
+ return SILC_ERR_NOT_FOUND;
}
silc_dlist_start(entry);
silc_mutex_unlock(skr->lock);
- return SILC_SKR_OK;
+ 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;
}
if (!silc_mutex_alloc(&skr->lock))
return FALSE;
- skr->keys = silc_hash_table_alloc(0, silc_skr_hash, NULL,
+ skr->keys = silc_hash_table_alloc(NULL, 0, silc_skr_hash, NULL,
silc_skr_compare, NULL,
silc_skr_destructor, NULL, TRUE);
if (!skr->keys)
/* Adds public key to key repository */
-SilcSKRStatus silc_skr_add_public_key(SilcSKR skr,
- SilcPublicKey public_key,
- SilcSKRKeyUsage usage,
- void *key_context,
- SilcSKRKey *return_key)
+SilcResult silc_skr_add_public_key(SilcSKR skr,
+ SilcPublicKey public_key,
+ SilcSKRKeyUsage usage,
+ void *key_context,
+ SilcSKRKey *return_key)
{
SilcPKCSType type;
if (!public_key)
- return SILC_SKR_ERROR;
+ return SILC_ERR_INVALID_ARGUMENT;
type = silc_pkcs_get_type(public_key);
return silc_skr_add_silc(skr, public_key, usage, key_context, return_key);
break;
+ case SILC_PKCS_SSH2:
+ return silc_skr_add_ssh(skr, public_key, usage, key_context, return_key);
+ break;
+
default:
break;
}
- return SILC_SKR_ERROR;
+ return SILC_ERR_NOT_SUPPORTED;
}
/* Adds public key to repository. */
-SilcSKRStatus silc_skr_add_public_key_simple(SilcSKR skr,
- SilcPublicKey public_key,
- SilcSKRKeyUsage usage,
- void *key_context,
- SilcSKRKey *return_key)
+SilcResult silc_skr_add_public_key_simple(SilcSKR skr,
+ SilcPublicKey public_key,
+ SilcSKRKeyUsage usage,
+ void *key_context,
+ SilcSKRKey *return_key)
{
SilcPKCSType type;
if (!public_key)
- return SILC_SKR_ERROR;
+ return SILC_ERR_INVALID_ARGUMENT;
type = silc_pkcs_get_type(public_key);
return_key);
break;
+ case SILC_PKCS_SSH2:
+ return silc_skr_add_ssh_simple(skr, public_key, usage, key_context,
+ return_key);
+ break;
+
default:
break;
}
- return SILC_SKR_ERROR;
+ return SILC_ERR_NOT_SUPPORTED;
}
/* Remove key from repository */
-SilcSKRStatus silc_skr_del_public_key(SilcSKR skr,
+SilcResult silc_skr_del_public_key(SilcSKR skr,
SilcPublicKey public_key,
void *key_context)
{
SilcPKCSType type;
if (!public_key)
- return SILC_SKR_ERROR;
+ return SILC_ERR_INVALID_ARGUMENT;
type = silc_pkcs_get_type(public_key);
return silc_skr_del_silc_public_key(skr, public_key, key_context);
break;
+ case SILC_PKCS_SSH2:
+ return silc_skr_del_ssh_public_key(skr, public_key, key_context);
+ break;
+
default:
break;
}
- return SILC_SKR_ERROR;
+ return SILC_ERR_NOT_SUPPORTED;
}
/* Reference key */
if (!find)
return NULL;
- find->constr = silc_hash_table_alloc(0, silc_hash_uint, NULL, NULL, NULL,
+ find->constr = silc_hash_table_alloc(NULL, 0, silc_hash_uint,
+ NULL, NULL, NULL,
silc_skr_find_destructor, NULL, TRUE);
if (!find->constr) {
silc_skr_find_free(find);
SilcBool silc_skr_find_set_context(SilcSKRFind find, void *context)
{
+ if (!context)
+ return TRUE;
return silc_hash_table_add(find->constr,
SILC_32_TO_PTR(SILC_SKR_FIND_CONTEXT), context);
}
SilcSKRFindCallback callback,
void *callback_context)
{
- SilcSKRStatus status = SILC_SKR_ERROR;
+ SilcResult status = SILC_ERR;
SilcHashTableList htl;
SilcDList list, results = NULL;
void *type, *ctx, *usage = NULL;
+#if defined(SILC_DEBUG)
+ char tmp[256];
+#endif /* SILC_DEBUG */
SILC_LOG_DEBUG(("Finding key from repository"));
silc_hash_table_find(find->constr, SILC_32_TO_PTR(SILC_SKR_FIND_USAGE),
NULL, &usage);
+#if defined(SILC_DEBUG)
+ if (usage) {
+ memset(tmp, 0, sizeof(tmp));
+ silc_skr_type_string(SILC_SKR_FIND_USAGE, usage, tmp, sizeof(tmp) - 1);
+ SILC_LOG_DEBUG(("Finding key by %s", tmp));
+ }
+#endif /* SILC_DEBUG */
+
silc_hash_table_list(find->constr, &htl);
while (silc_hash_table_get(&htl, &type, &ctx)) {
+ /* SILC_SKR_FIND_USAGE is handled separately while searching the keys. */
+ if ((SilcSKRFindType)SILC_32_TO_PTR(type) == SILC_SKR_FIND_USAGE)
+ continue;
+
#if defined(SILC_DEBUG)
- char tmp[256];
memset(tmp, 0, sizeof(tmp));
silc_skr_type_string((SilcSKRFindType)SILC_32_TO_PTR(type),
ctx, tmp, sizeof(tmp) - 1);
SILC_LOG_DEBUG(("Finding key by %s", tmp));
#endif /* SILC_DEBUG */
- /* SILC_SKR_FIND_USAGE is handled separately while searching the keys. */
- if ((SilcSKRFindType)SILC_32_TO_PTR(type) == SILC_SKR_FIND_USAGE)
- continue;
-
/* Find entries by this search constraint */
if (!silc_skr_find_entry(skr, &status,
(SilcSKRFindType)SILC_32_TO_PTR(type),
callback(skr, find, status, NULL, callback_context);
} else {
silc_dlist_start(results);
- callback(skr, find, SILC_SKR_OK, results, callback_context);
+ callback(skr, find, SILC_OK, results, callback_context);
}
return NULL;