changes.
+Tue Jul 10 20:02:04 EEST 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * Added queue entry free list to thread pool instead of
+ allocating new entry everytime new entry is needed. Affected
+ file is lib/silcutil/silcthread.c.
+
+ * Added support for new PKCS API and other API changes to
+ client library. Affected files are in lib/silcclient/.
+
Mon Jul 9 20:21:13 EEST 2007 Pekka Riikonen <priikone@silcnet.org>
* Added SILC Accelerator Library. Provides generic way to
lib/silcmath
============
- o Import TFM. Talk to Tom to add the missing functions. Use TFM in
- client and client library, but TMA in server, due to the significantly
- increased memory consumption with TFM, and the rare need for public
- key operations in server.
-
- We want TFM's speed but not TFM's memory requirements. Talk to Tom
- about making the TFM mp dynamic just as it is in LTM.
+ o Import TFM. We want TFM's speed but its memory requirements are
+ just too much. By default it uses large pre-allocated tables which
+ will eat memory when there are thousands of public keys in system.
+ We probably want to change TFM's fp_int dynamic so that a specific
+ size can be allocated for the int. We could have two new functions:
+
+ SilcBool silc_mp_init_size(SilcMPInt *mp, SilcUInt32 bit_size);
+ SilcBool silc_mp_sinit_size(SilcStack stack, SilcMPInt *mp,
+ SilcUInt32 bit_size);
+
+ Which by default allocates `bit_size' bits instead of some default
+ value. silc_mp_init would allocate the default FP_SIZE with TFM
+ and do normal init with TMA and GMP. _init_size with TMA and GMP
+ would be same as _init.
+
+ o Add AND, OR and XOR support to TFM or ask Tom to do it.
o The SILC MP API function must start returning indication of success
and failure of the operation.
--- /dev/null
+Tue Jul 10 20:13:47 EEST 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * Added support for the new PKCS API.
+
+-----------------------------------------------------------------------------
+
+For older changes please see the CHANGES file from the CVS tree.
'LIBS' => '',
'OBJECT' => '$(O_FILES)',
'TYPEMAPS' => ['../common/typemap'],
- 'INC' => '-I../../.. -I@top_srcdir@/src -I@top_srcdir@/src/core -I@top_srcdir@/src/silc/core -I@top_srcdir@/src/silc -I$(silc_top_srcdir) -I$(silc_top_srcdir)/lib/silccore -I$(silc_top_srcdir)/lib/silccrypt -I$(silc_top_srcdir)/lib/silcmath -DHAVE_SILCDEFS_H -I$(silc_top_srcdir)/lib/silcske -I$(silc_top_srcdir)/lib/silcsim -I$(silc_top_srcdir)/lib/silcskr -I$(silc_top_srcdir)/lib/silchttp -I$(silc_top_srcdir)/lib/silcasn1 -I$(silc_top_srcdir)/lib/silcapputil -I$(silc_top_srcdir)/lib/silcvcard -I$(silc_top_srcdir)/lib/silcutil -I$(silc_top_srcdir)/lib/silcsftp -I$(silc_top_srcdir)/lib/silcclient -I$(silc_top_srcdir)/lib/contrib -I$(silc_top_srcdir)/includes -I$(silc_top_srcdir)/doc @GLIB_CFLAGS@',
+ 'INC' => '-I../../.. -I@top_srcdir@/src -I@top_srcdir@/src/core -I@top_srcdir@/src/silc/core -I@top_srcdir@/src/silc -I$(silc_top_srcdir) -I$(silc_top_srcdir)/lib/silccore -I$(silc_top_srcdir)/lib/silccrypt -I$(silc_top_srcdir)/lib/silcmath -DHAVE_SILCDEFS_H -I$(silc_top_srcdir)/lib/silcske -I$(silc_top_srcdir)/lib/silcsim -I$(silc_top_srcdir)/lib/silcskr -I$(silc_top_srcdir)/lib/silchttp -I$(silc_top_srcdir)/lib/silcasn1 -I$(silc_top_srcdir)/lib/silcapputil -I$(silc_top_srcdir)/lib/silcvcard -I$(silc_top_srcdir)/lib/silcutil -I$(silc_top_srcdir)/lib/silcsftp -I$(silc_top_srcdir)/lib/silcclient -I$(silc_top_srcdir)/lib/silcacc -I$(silc_top_srcdir)/lib/contrib -I$(silc_top_srcdir)/includes -I$(silc_top_srcdir)/doc @GLIB_CFLAGS@',
'VERSION_FROM' => '@srcdir@/Silc.pm');
if (silc_pkcs_get_type(pubkey) != SILC_PKCS_SILC)
continue;
- pk = silc_pkcs_public_key_encode(pubkey, &pk_len);
+ pk = silc_pkcs_public_key_encode(NULL, pubkey, &pk_len);
if (!pk)
continue;
va_end(va);
}
+void static verify_message_signature_verified(SilcBool success,
+ void *context)
+{
+ *(SilcBool *)context = success;
+}
+
/* Try to verify a message using locally stored public key data */
int verify_message_signature(SilcClientEntry sender,
SilcUInt32 pk_datalen;
struct stat st;
int ret = SILC_MSG_SIGNED_VERIFIED, i;
+ SilcBool verified = FALSE;
/* get public key from the signature payload and compare it with the
one stored in the client entry */
}
/* the public key is now in pk, our "level of trust" in ret */
- if ((pk) && silc_message_signed_verify(message, pk,
- sha1hash) != SILC_AUTH_OK)
- ret = SILC_MSG_SIGNED_FAILED;
+ if (pk) {
+ silc_message_signed_verify(message, pk, sha1hash,
+ verify_message_signature_verified, &verified);
+ if (!verified)
+ ret = SILC_MSG_SIGNED_FAILED;
+ }
if (pk)
silc_pkcs_public_key_free(pk);
}
/* Encode public key */
- pk = silc_pkcs_public_key_encode(public_key, &pk_len);
+ pk = silc_pkcs_public_key_encode(NULL, public_key, &pk_len);
if (!pk) {
if (completion)
completion(FALSE, context);
}
/* Encode the key data */
- encpk = silc_pkcs_public_key_encode(local_pubkey, &encpk_len);
+ encpk = silc_pkcs_public_key_encode(NULL, local_pubkey, &encpk_len);
if (!encpk) {
printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
SILCTXT_PUBKEY_RECEIVED,verify->entity_name ?
silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key);
ident = &silc_pubkey->identifier;
- pk = silc_pkcs_public_key_encode(public_key, &pk_len);
+ pk = silc_pkcs_public_key_encode(NULL, public_key, &pk_len);
if (!pk)
return;
fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
#endif
}
}
-
- /* Register other defaults */
- silc_cipher_register_default();
}
static void silc_register_hash(SilcClient client, const char *hash)
#endif
}
}
-
- /* Register other defaults */
- silc_hash_register_default();
}
static void silc_register_hmac(SilcClient client, const char *hmac)
#endif
}
}
-
- /* Register other defaults */
- silc_hmac_register_default();
}
/* Finalize init. Init finish signal calls this. */
if ((argc == 2) && (strcasecmp(argv[1], "list-ciphers") == 0)) {
#else
if (strcmp(opt->longName, "list-ciphers") == 0) {
- silc_cipher_register_default();
#endif
silc_client_list_ciphers();
FUNCTION_EXIT;
if ((argc == 2) && (strcasecmp(argv[1], "list-hash-funcs") == 0)) {
#else
if (strcmp(opt->longName, "list-hash-funcs") == 0) {
- silc_hash_register_default();
#endif
silc_client_list_hash_funcs();
FUNCTION_EXIT;
if ((argc == 2) && (strcasecmp(argv[1], "list-hmacs") == 0)) {
#else
if (strcmp(opt->longName, "list-hmacs") == 0) {
- silc_hmac_register_default();
#endif
silc_client_list_hmacs();
FUNCTION_EXIT;
if ((argc == 2) && (strcasecmp(argv[1], "list-pkcs") == 0)) {
#else
if (strcmp(opt->longName, "list-pkcs") == 0) {
- silc_pkcs_register_default();
#endif
silc_client_list_pkcs();
FUNCTION_EXIT;
MSGLEVEL_CRAP, SILCTXT_CONFIG_NEXTTIME);
goto out;
#else
- silc_cipher_register_default();
- silc_pkcs_register_default();
- silc_hash_register_default();
- silc_hmac_register_default();
+ silc_crypto_init(NULL);
silc_create_key_pair(opt_pkcs, opt_bits, NULL, NULL,
NULL, NULL, NULL, NULL, TRUE);
exit(0);
ENTRY_REDIRECT_FLAG_HIDDEN, rec);
goto out;
#else
- silc_cipher_register_default();
- silc_pkcs_register_default();
- silc_hash_register_default();
- silc_hmac_register_default();
+ silc_crypto_init(NULL);
silc_change_private_key_passphrase(arg, NULL, NULL);
exit(0);
#endif
#ifndef SILC_PLUGIN
if (strcmp(opt->longName, "show-key") == 0) {
/* Dump the key */
- silc_cipher_register_default();
- silc_pkcs_register_default();
- silc_hash_register_default();
- silc_hmac_register_default();
+ silc_crypto_init(NULL);
silc_show_public_key_file((char *)arg);
exit(0);
}
if (init_failed)
return;
#endif
- silc_pkcs_register_default();
#ifdef SILC_PLUGIN
command_bind("silc", MODULE_NAME, (SIGNAL_FUNC) silc_opt_callback);
bool nopk;
} *AttrVerify;
+static void silc_query_attributes_verify(SilcBool success, void *context)
+{
+ *(SilcBool *)context = success;
+}
+
void silc_query_attributes_print(SILC_SERVER_REC *server,
SilcClient client,
SilcClientConnection conn,
/* Verify the signature now */
unsigned char *verifyd;
SilcUInt32 verify_len;
+ SilcBool verified = FALSE;
if (verify->public_key) {
verifyd = silc_attribute_get_verify_data(attrs, FALSE, &verify_len);
- if (verifyd && silc_pkcs_verify(verify->public_key,
- usersign.data,
- usersign.data_len,
- verifyd, verify_len,
- sha1hash)) {
+ if (verifyd)
+ silc_pkcs_verify(verify->public_key, usersign.data,
+ usersign.data_len, verifyd, verify_len, sha1hash,
+ silc_query_attributes_verify, &verified);
+
+ if (verified) {
printformat_module("fe-common/silc", server, NULL,
MSGLEVEL_CRAP, SILCTXT_ATTR_USER_SIGN_VERIFIED);
} else {
SilcPKCSType type = 0;
unsigned char *verifyd;
SilcUInt32 verify_len;
+ SilcBool verified = FALSE;
if (!strcmp(serverpk.type, "silc-rsa"))
type = SILC_PKCS_SILC;
serverpk.data_len,
&public_key)) {
verifyd = silc_attribute_get_verify_data(attrs, TRUE, &verify_len);
- if (verifyd && silc_pkcs_verify(public_key,
- serversign.data,
- serversign.data_len,
- verifyd, verify_len,
- sha1hash)) {
+ if (verifyd)
+ silc_pkcs_verify(public_key, serversign.data,
+ serversign.data_len, verifyd, verify_len, sha1hash,
+ silc_query_attributes_verify, &verified);
+ if (verified) {
printformat_module("fe-common/silc", server, NULL,
MSGLEVEL_CRAP, SILCTXT_ATTR_SERVER_SIGN_VERIFIED);
} else {
/* Try to read detached session data and use it if found. */
file = silc_get_session_filename(server);
- params.detach_data = silc_file_readfile(file, ¶ms.detach_data_len);
+ params.detach_data = silc_file_readfile(file, ¶ms.detach_data_len, NULL);
if (params.detach_data)
params.detach_data[params.detach_data_len] = 0;
if (params.detach_data)
if (client->rng)
silc_rng_free(client->rng);
- if (!client->internal->params->dont_register_crypto_library) {
- silc_cipher_unregister_all();
- silc_pkcs_unregister_all();
- silc_hash_unregister_all();
- silc_hmac_unregister_all();
- }
+ if (!client->internal->params->dont_register_crypto_library)
+ silc_crypto_uninit();
silc_packet_engine_stop(client->internal->packet_engine);
silc_dlist_uninit(client->internal->ftp_sessions);
if (!client->internal->ftp_sessions)
return FALSE;
- if (!client->internal->params->dont_register_crypto_library) {
+ if (!client->internal->params->dont_register_crypto_library)
/* Initialize the crypto library. If application has done this already
- this has no effect. Also, we will not be overriding something
- application might have registered earlier. */
- silc_cipher_register_default();
- silc_pkcs_register_default();
- silc_hash_register_default();
- silc_hmac_register_default();
- }
+ this has no effect. */
+ silc_crypto_init(NULL);
/* Initialize random number generator */
client->rng = silc_rng_alloc();
unsigned int prv_resp : 1; /* TRUE if we are responder when using
private message keys. */
SilcUInt16 resolve_cmd_ident; /* Command identifier when resolving */
- SilcAtomic8 refcnt; /* Reference counter */
+ SilcAtomic16 refcnt; /* Reference counter */
} SilcClientEntryInternal;
/* Internal channel entry context */
#include "silcclient.h"
#include "client_internal.h"
+typedef struct {
+ SilcBuffer buffer;
+ SilcPKCSSignCb sign_cb;
+ void *context;
+} *SilcAttrSign;
+
typedef struct {
SilcBuffer buffer;
} SilcAttrForeach;
data, data_len);
}
+/* Attribute signature callback */
+
+static void
+silc_client_attributes_process_signed(SilcBool success,
+ const unsigned char *signature,
+ SilcUInt32 signature_len,
+ void *context)
+{
+ SilcAttrSign s = context;
+ SilcAttributeObjPk pk;
+
+ if (success) {
+ pk.type = NULL;
+ pk.data = (unsigned char *)signature;
+ pk.data_len = signature_len;
+ s->buffer =
+ silc_attribute_payload_encode(s->buffer,
+ SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE,
+ SILC_ATTRIBUTE_FLAG_VALID,
+ &pk, sizeof(pk));
+ }
+
+ s->sign_cb(TRUE, silc_buffer_data(s->buffer), silc_buffer_len(s->buffer),
+ s->context);
+
+ silc_buffer_free(s->buffer);
+ silc_free(s);
+}
+
/* Process list of attributes. Returns reply to the requested attributes. */
-SilcBuffer silc_client_attributes_process(SilcClient client,
- SilcClientConnection conn,
- SilcDList attrs)
+void silc_client_attributes_process(SilcClient client,
+ SilcClientConnection conn,
+ SilcDList attrs,
+ SilcPKCSSignCb sign_cb,
+ void *context)
{
+ SilcAttrSign s;
SilcBuffer buffer = NULL;
SilcAttrForeach f;
SilcAttribute attribute;
SilcAttributePayload attr;
SilcAttributeObjPk pk;
- unsigned char sign[2048 + 1];
- SilcUInt32 sign_len;
SILC_LOG_DEBUG(("Process Requested Attributes"));
attributes, ignore the request. */
if (!conn->internal->attrs) {
SILC_LOG_DEBUG(("User has not set any attributes"));
- return NULL;
+ sign_cb(FALSE, NULL, 0, context);
+ return;
}
/* Always put our public key. */
pk.type = "silc-rsa";
- pk.data = silc_pkcs_public_key_encode(conn->public_key, &pk.data_len);
+ pk.data = silc_pkcs_public_key_encode(NULL, conn->public_key, &pk.data_len);
buffer = silc_attribute_payload_encode(buffer,
SILC_ATTRIBUTE_USER_PUBLIC_KEY,
pk.data ? SILC_ATTRIBUTE_FLAG_VALID :
}
buffer = f.buffer;
- /* Finally compute the digital signature of all the data we provided. */
- if (silc_pkcs_sign(conn->private_key, silc_buffer_data(buffer),
- silc_buffer_len(buffer), sign, sizeof(sign), &sign_len,
- TRUE, conn->internal->sha1hash)) {
- pk.type = NULL;
- pk.data = sign;
- pk.data_len = sign_len;
- buffer =
- silc_attribute_payload_encode(buffer,
- SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE,
- SILC_ATTRIBUTE_FLAG_VALID,
- &pk, sizeof(pk));
+ s = silc_calloc(1, sizeof(*s));
+ if (!s) {
+ sign_cb(FALSE, NULL, 0, context);
+ return;
}
+ s->sign_cb = sign_cb;
+ s->context = context;
+ s->buffer = buffer;
- return buffer;
+ /* Finally compute the digital signature of all the data we provided. */
+ silc_pkcs_sign(conn->private_key, silc_buffer_data(buffer),
+ silc_buffer_len(buffer), TRUE, conn->internal->sha1hash,
+ silc_client_attributes_process_signed, s);
}
static void silc_client_attribute_destruct(void *key, void *context,
/************************** Channel Message Send ****************************/
+typedef struct {
+ SilcClient client;
+ SilcClientConnection conn;
+ SilcChannelEntry channel;
+} *SilcClientChannelMessageContext;
+
+/* Message payload encoding callback */
+
+static void silc_client_send_channel_message_final(SilcBuffer message,
+ void *context)
+{
+ SilcClientChannelMessageContext c = context;
+
+ /* Send the channel message */
+ if (message)
+ silc_packet_send_ext(c->conn->stream, SILC_PACKET_CHANNEL_MESSAGE, 0,
+ 0, NULL, SILC_ID_CHANNEL, &c->channel->id,
+ silc_buffer_datalen(message), NULL, NULL);
+
+ silc_client_unref_channel(c->client, c->conn, c->channel);
+ silc_free(c);
+}
+
/* Sends channel message to `channel'. */
SilcBool silc_client_send_channel_message(SilcClient client,
unsigned char *data,
SilcUInt32 data_len)
{
+ SilcClientChannelMessageContext c;
SilcChannelUser chu;
- SilcBuffer buffer;
SilcCipher cipher;
SilcHmac hmac;
- SilcBool ret;
SilcID sid, rid;
SILC_LOG_DEBUG(("Sending channel message"));
return FALSE;
}
- /* Encode the message payload. This also encrypts the message payload. */
+ c = silc_calloc(1, sizeof(*c));
+ if (!c)
+ return FALSE;
+
+ c->client = client;
+ c->conn = conn;
+ c->channel = silc_client_ref_channel(client, conn, channel);
+
sid.type = SILC_ID_CLIENT;
sid.u.client_id = chu->client->id;
rid.type = SILC_ID_CHANNEL;
rid.u.channel_id = chu->channel->id;
- buffer = silc_message_payload_encode(flags, data, data_len, TRUE, FALSE,
- cipher, hmac, client->rng, NULL,
- conn->private_key, hash, &sid, &rid,
- NULL);
- if (silc_unlikely(!buffer)) {
- SILC_LOG_ERROR(("Error encoding channel message"));
- return FALSE;
- }
- /* Send the channel message */
- ret = silc_packet_send_ext(conn->stream, SILC_PACKET_CHANNEL_MESSAGE, 0,
- 0, NULL, SILC_ID_CHANNEL, &channel->id,
- silc_buffer_datalen(buffer), NULL, NULL);
+ /* Encode the message payload. This also encrypts the message payload. */
+ silc_message_payload_encode(flags, data, data_len, TRUE, FALSE,
+ cipher, hmac, client->rng, NULL,
+ conn->private_key, hash, &sid, &rid, NULL,
+ silc_client_send_channel_message_final, c);
- silc_buffer_free(buffer);
- return ret;
+ return TRUE;
}
/************************* Channel Message Receive **************************/
return NULL;
silc_rwlock_alloc(&client_entry->internal.lock);
- silc_atomic_init8(&client_entry->internal.refcnt, 0);
+ silc_atomic_init16(&client_entry->internal.refcnt, 0);
client_entry->id = *id;
client_entry->mode = mode;
client_entry->realname = userinfo ? strdup(userinfo) : NULL;
silc_client_ftp_session_free_client(client, client_entry);
if (client_entry->internal.ke)
silc_client_abort_key_agreement(client, conn, client_entry);
- silc_atomic_uninit8(&client_entry->internal.refcnt);
+ silc_atomic_uninit16(&client_entry->internal.refcnt);
silc_rwlock_free(client_entry->internal.lock);
silc_free(client_entry);
}
if (!client_entry)
return FALSE;
- if (silc_atomic_sub_int8(&client_entry->internal.refcnt, 1) > 0)
+ if (silc_atomic_sub_int16(&client_entry->internal.refcnt, 1) > 0)
return FALSE;
SILC_LOG_DEBUG(("Deleting client %p", client_entry));
SilcClientConnection conn,
SilcClientEntry client_entry)
{
- silc_atomic_add_int8(&client_entry->internal.refcnt, 1);
+ silc_atomic_add_int16(&client_entry->internal.refcnt, 1);
SILC_LOG_DEBUG(("Client %p refcnt %d->%d", client_entry,
- silc_atomic_get_int8(&client_entry->internal.refcnt) - 1,
- silc_atomic_get_int8(&client_entry->internal.refcnt)));
+ silc_atomic_get_int16(&client_entry->internal.refcnt) - 1,
+ silc_atomic_get_int16(&client_entry->internal.refcnt)));
return client_entry;
}
{
if (client_entry) {
SILC_LOG_DEBUG(("Client %p refcnt %d->%d", client_entry,
- silc_atomic_get_int8(&client_entry->internal.refcnt),
- silc_atomic_get_int8(&client_entry->internal.refcnt) - 1));
+ silc_atomic_get_int16(&client_entry->internal.refcnt),
+ silc_atomic_get_int16(&client_entry->internal.refcnt) - 1));
silc_client_del_client(client, conn, client_entry);
}
}
char *remote_host, int port,
SilcClientConnectCallback callback,
void *context);
-SilcBuffer silc_client_attributes_process(SilcClient client,
- SilcClientConnection conn,
- SilcDList attrs);
+void silc_client_attributes_process(SilcClient client,
+ SilcClientConnection conn,
+ SilcDList attrs,
+ SilcPKCSSignCb sign_cb,
+ void *context);
#endif /* CLIENT_INTERNAL_H */
/************************** Private Message Send ****************************/
+typedef struct {
+ SilcClient client;
+ SilcClientConnection conn;
+ SilcClientEntry client_entry;
+} *SilcClientPrvmsgContext;
+
+/* Message payload encoding callback */
+
+static void silc_client_send_private_message_final(SilcBuffer message,
+ void *context)
+{
+ SilcClientPrvmsgContext p = context;
+
+ /* Send the private message packet */
+ if (message)
+ silc_packet_send_ext(p->conn->stream, SILC_PACKET_PRIVATE_MESSAGE,
+ p->client_entry->internal.send_key ?
+ SILC_PACKET_FLAG_PRIVMSG_KEY : 0,
+ 0, NULL, SILC_ID_CLIENT, &p->client_entry->id,
+ silc_buffer_datalen(message), NULL, NULL);
+
+ silc_client_unref_client(p->client, p->conn, p->client_entry);
+ silc_free(p);
+}
+
/* Sends private message to remote client. */
SilcBool silc_client_send_private_message(SilcClient client,
unsigned char *data,
SilcUInt32 data_len)
{
- SilcBuffer buffer;
- SilcBool ret;
+ SilcClientPrvmsgContext p;
SilcID sid, rid;
if (silc_unlikely(!client || !conn || !client_entry))
rid.type = SILC_ID_CLIENT;
rid.u.client_id = client_entry->id;
- /* Encode private message payload */
- buffer =
- silc_message_payload_encode(flags, data, data_len,
- (!client_entry->internal.send_key ? FALSE :
- !client_entry->internal.generated),
- TRUE, client_entry->internal.send_key,
- client_entry->internal.hmac_send,
- client->rng, NULL, conn->private_key,
- hash, &sid, &rid, NULL);
- if (silc_unlikely(!buffer)) {
- SILC_LOG_ERROR(("Error encoding private message"));
+ p = silc_calloc(1, sizeof(*p));
+ if (!p)
return FALSE;
- }
- /* Send the private message packet */
- ret = silc_packet_send_ext(conn->stream, SILC_PACKET_PRIVATE_MESSAGE,
- client_entry->internal.send_key ?
- SILC_PACKET_FLAG_PRIVMSG_KEY : 0,
- 0, NULL, SILC_ID_CLIENT, &client_entry->id,
- silc_buffer_datalen(buffer), NULL, NULL);
+ p->client = client;
+ p->conn = conn;
+ p->client_entry = silc_client_ref_client(client, conn, client_entry);
- silc_buffer_free(buffer);
- return ret;
+ /* Encode private message payload */
+ silc_message_payload_encode(flags, data, data_len,
+ (!client_entry->internal.send_key ? FALSE :
+ !client_entry->internal.generated),
+ TRUE, client_entry->internal.send_key,
+ client_entry->internal.hmac_send,
+ client->rng, NULL, conn->private_key,
+ hash, &sid, &rid, NULL,
+ silc_client_send_private_message_final, p);
+
+ return TRUE;
}
/************************* Private Message Receive **************************/
SilcClient client;
SilcClientConnection conn;
SilcBufferStruct detach;
+ SilcBuffer auth;
char *nickname;
+ unsigned char *id;
+ SilcUInt32 id_len;
SilcUInt32 channel_count;
} *SilcClientResumeSession;
va_end(ap);
}
+/* Resume authentication data generation callback */
+
+static void silc_client_resume_auth_generated(const SilcBuffer data,
+ void *context)
+{
+ SilcClientConnection conn = context;
+ SilcClientResumeSession resume =
+ silc_fsm_get_state_context(&conn->internal->event_thread);
+
+ if (!data)
+ silc_fsm_next(&conn->internal->event_thread, silc_client_st_resume_error);
+ else
+ resume->auth = silc_buffer_copy(data);
+
+ SILC_FSM_CALL_CONTINUE_SYNC(&conn->internal->event_thread);
+}
+
/****************************** NEW_ID packet *******************************/
SilcClientConnection conn = fsm_context;
SilcClient client = conn->client;
SilcClientResumeSession resume;
- SilcBuffer auth;
unsigned char *id;
SilcUInt16 id_len;
SilcClientID client_id;
silc_fsm_next(fsm, silc_client_st_resume_error);
return SILC_FSM_CONTINUE;
}
+ resume->id = id;
+ resume->id_len = id_len;
/* Generate authentication data that server will verify */
- auth = silc_auth_public_key_auth_generate(conn->public_key,
- conn->private_key,
- client->rng,
- conn->internal->hash,
- &client_id, SILC_ID_CLIENT);
- if (!auth) {
- /** Out of memory */
- silc_fsm_next(fsm, silc_client_st_resume_error);
- return SILC_FSM_CONTINUE;
- }
+ silc_fsm_next(fsm, silc_client_st_resume_send);
+ SILC_FSM_CALL(silc_auth_public_key_auth_generate(
+ conn->public_key, conn->private_key,
+ client->rng, conn->internal->hash,
+ &client_id, SILC_ID_CLIENT,
+ silc_client_resume_auth_generated, conn));
+ /* NOT REACHED */
+}
+
+/* Send RESUME_CLIENT packet */
+
+SILC_FSM_STATE(silc_client_st_resume_send)
+{
+ SilcClientConnection conn = fsm_context;
+ SilcClientResumeSession resume = state_context;
+
+ SILC_LOG_DEBUG(("Send RESUME_CLIENT packet"));
/* Send RESUME_CLIENT packet to resume to network */
if (!silc_packet_send_va(conn->stream, SILC_PACKET_RESUME_CLIENT, 0,
- SILC_STR_UI_SHORT(id_len),
- SILC_STR_DATA(id, id_len),
- SILC_STR_DATA(silc_buffer_data(auth),
- silc_buffer_len(auth)),
+ SILC_STR_UI_SHORT(resume->id_len),
+ SILC_STR_DATA(resume->id, resume->id_len),
+ SILC_STR_DATA(silc_buffer_data(resume->auth),
+ silc_buffer_len(resume->auth)),
SILC_STR_END)) {
/** Error sending packet */
SILC_LOG_DEBUG(("Error sending packet"));
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2006 Pekka Riikonen
+ Copyright (C) 2006 - 2007 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
SILC_FSM_STATE(silc_client_st_register_complete);
SILC_FSM_STATE(silc_client_st_register_error);
SILC_FSM_STATE(silc_client_st_resume);
+SILC_FSM_STATE(silc_client_st_resume_send);
SILC_FSM_STATE(silc_client_st_resume_resolve_channels);
SILC_FSM_STATE(silc_client_st_resume_resolve_cmodes);
SILC_FSM_STATE(silc_client_st_resume_completed);
goto out;
break;
}
- obj.data = silc_pkcs_public_key_encode(pk, &obj.data_len);
+ obj.data = silc_pkcs_public_key_encode(NULL, pk, &obj.data_len);
attrs = silc_attribute_payload_encode(attrs,
SILC_ATTRIBUTE_USER_PUBLIC_KEY,
SILC_STR_UI_SHORT(1),
SILC_STR_END);
if (pubkey) {
- chidp = silc_public_key_payload_encode(pubkey);
+ chidp = silc_public_key_payload_encode(NULL, pubkey);
args = silc_argument_payload_encode_one(args, silc_buffer_data(chidp),
silc_buffer_len(chidp), 2);
silc_buffer_free(chidp);
/********************************** KILL ************************************/
+/* Signature callback */
+
+static void silc_client_command_kill_signed(const SilcBuffer buffer,
+ void *context)
+{
+ SilcClientCommandContext cmd = context;
+
+ if (!buffer) {
+ silc_fsm_finish(&cmd->thread);
+ return;
+ }
+
+ silc_fsm_set_state_context(&cmd->thread, buffer);
+ SILC_FSM_CALL_CONTINUE_SYNC(&cmd->thread);
+}
+
+/* Send KILL command */
+
+SILC_FSM_STATE(silc_client_command_kill_send)
+{
+ SilcClientCommandContext cmd = fsm_context;
+ SilcClientConnection conn = cmd->conn;
+ SilcClient client = conn->client;
+ SilcBuffer idp, auth = state_context;
+ SilcClientEntry target = cmd->context;
+ char *comment = NULL;
+
+ if (cmd->argc >= 3)
+ if (strcasecmp(cmd->argv[2], "-pubkey"))
+ comment = cmd->argv[2];
+
+ /* Send the KILL command to the server */
+ idp = silc_id_payload_encode(&target->id, SILC_ID_CLIENT);
+ silc_client_command_send_va(conn, cmd, cmd->cmd, NULL, NULL, 3,
+ 1, silc_buffer_datalen(idp),
+ 2, comment, comment ? strlen(comment) : 0,
+ 3, silc_buffer_datalen(auth));
+
+ silc_buffer_free(idp);
+ silc_client_unref_client(client, conn, target);
+
+ /* Notify application */
+ COMMAND(SILC_STATUS_OK);
+
+ /** Wait for command reply */
+ silc_fsm_next(fsm, silc_client_command_reply_wait);
+ return SILC_FSM_CONTINUE;
+}
+
/* Command KILL. Router operator can use this command to remove an client
fromthe SILC Network. */
SilcClientCommandContext cmd = fsm_context;
SilcClientConnection conn = cmd->conn;
SilcClient client = conn->client;
- SilcBuffer idp, auth = NULL;
SilcClientEntry target;
SilcDList clients;
- char *nickname = NULL, *comment = NULL;
+ char *nickname = NULL;
if (cmd->argc < 2) {
SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO,
cmd));
target = silc_dlist_get(clients);
+ cmd->context = silc_client_ref_client(client, conn, target);
- if (cmd->argc >= 3) {
- if (strcasecmp(cmd->argv[2], "-pubkey"))
- comment = cmd->argv[2];
+ silc_free(nickname);
+ silc_client_list_free(client, conn, clients);
+ /** Send KILL */
+ silc_fsm_next(fsm, silc_client_command_kill_send);
+
+ if (cmd->argc >= 3) {
if (!strcasecmp(cmd->argv[2], "-pubkey") ||
(cmd->argc >= 4 && !strcasecmp(cmd->argv[3], "-pubkey"))) {
/* Encode the public key authentication payload */
- auth = silc_auth_public_key_auth_generate(conn->public_key,
- conn->private_key,
- conn->client->rng,
- conn->internal->sha1hash,
- &target->id, SILC_ID_CLIENT);
+ SILC_FSM_CALL(silc_auth_public_key_auth_generate(
+ conn->public_key,
+ conn->private_key,
+ conn->client->rng,
+ conn->internal->sha1hash,
+ &target->id, SILC_ID_CLIENT,
+ silc_client_command_kill_signed,
+ cmd));
+ /* NOT REACHED */
}
}
- /* Send the KILL command to the server */
- idp = silc_id_payload_encode(&target->id, SILC_ID_CLIENT);
- silc_client_command_send_va(conn, cmd, cmd->cmd, NULL, NULL, 3,
- 1, silc_buffer_datalen(idp),
- 2, comment, comment ? strlen(comment) : 0,
- 3, silc_buffer_datalen(auth));
- silc_buffer_free(idp);
- silc_buffer_free(auth);
- silc_free(nickname);
- silc_client_list_free(client, conn, clients);
-
- /* Notify application */
- COMMAND(SILC_STATUS_OK);
-
- /** Wait for command reply */
- silc_fsm_next(fsm, silc_client_command_reply_wait);
return SILC_FSM_CONTINUE;
}
/********************************** JOIN ************************************/
+typedef struct {
+ int type;
+ SilcBuffer auth;
+ SilcBuffer cauth;
+} *SilcClientJoinContext;
+
+/* Signature callback */
+
+static void silc_client_command_join_signed(const SilcBuffer buffer,
+ void *context)
+{
+ SilcClientCommandContext cmd = context;
+ SilcClientJoinContext j = cmd->context;
+
+ if (!buffer) {
+ silc_fsm_finish(&cmd->thread);
+ return;
+ }
+
+ if (!j->type)
+ j->auth = silc_buffer_copy(buffer);
+ else
+ j->cauth = silc_buffer_copy(buffer);
+
+ SILC_FSM_CALL_CONTINUE(&cmd->thread);
+}
+
/* Command JOIN. Joins to a channel. */
SILC_FSM_STATE(silc_client_command_join)
SilcClientConnection conn = cmd->conn;
SilcClient client = conn->client;
SilcChannelEntry channel = NULL;
+ SilcClientJoinContext j = cmd->context;
SilcBuffer auth = NULL, cauth = NULL;
char *name, *passphrase = NULL, *pu8, *cipher = NULL, *hmac = NULL;
int i, passphrase_len = 0;
} else if (!strcasecmp(cmd->argv[i], "-hmac") && cmd->argc > i + 1) {
hmac = cmd->argv[++i];
} else if (!strcasecmp(cmd->argv[i], "-founder")) {
- auth = silc_auth_public_key_auth_generate(conn->public_key,
- conn->private_key,
- conn->client->rng,
- conn->internal->sha1hash,
- conn->local_id,
- SILC_ID_CLIENT);
+ if (!j || !j->auth) {
+ if (!j) {
+ j = silc_calloc(1, sizeof(*j));
+ if (!j)
+ goto out;
+ cmd->context = j;
+ }
+ j->type = 0;
+ silc_free(passphrase);
+ silc_client_unref_channel(client, conn, channel);
+ SILC_FSM_CALL(silc_auth_public_key_auth_generate(
+ conn->public_key,
+ conn->private_key,
+ conn->client->rng,
+ conn->internal->sha1hash,
+ conn->local_id,
+ SILC_ID_CLIENT,
+ silc_client_command_join_signed,
+ cmd));
+ /* NOT REACHED */
+ }
} else if (!strcasecmp(cmd->argv[i], "-auth")) {
SilcPublicKey pubkey = conn->public_key;
SilcPrivateKey privkey = conn->private_key;
- unsigned char *pk, pkhash[SILC_HASH_MAXLEN], *pubdata;
+ unsigned char *pk, pkhash[SILC_HASH_MAXLEN], pubdata[128];
SilcUInt32 pk_len;
- if (cmd->argc >= i + 3) {
- char *pass = "";
- if (cmd->argc >= i + 4) {
- pass = cmd->argv[i + 3];
- i++;
+ if (!j || !j->cauth) {
+ if (!j) {
+ j = silc_calloc(1, sizeof(*j));
+ if (!j)
+ goto out;
+ cmd->context = j;
}
- if (!silc_load_key_pair(cmd->argv[i + 1], cmd->argv[i + 2], pass,
- &pubkey, &privkey)) {
- SAY(conn->client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR,
- "Could not load key pair, check your arguments");
- COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
- goto out;
+
+ if (cmd->argc >= i + 3) {
+ char *pass = "";
+ if (cmd->argc >= i + 4) {
+ pass = cmd->argv[i + 3];
+ i++;
+ }
+ if (!silc_load_key_pair(cmd->argv[i + 1], cmd->argv[i + 2], pass,
+ &pubkey, &privkey)) {
+ SAY(conn->client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR,
+ "Could not load key pair, check your arguments");
+ COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+ goto out;
+ }
+ i += 2;
}
- i += 2;
- }
- pk = silc_pkcs_public_key_encode(pubkey, &pk_len);
- silc_hash_make(conn->internal->sha1hash, pk, pk_len, pkhash);
- silc_free(pk);
- pubdata = silc_rng_get_rn_data(conn->client->rng, 128);
- memcpy(pubdata, pkhash, 20);
- cauth = silc_auth_public_key_auth_generate_wpub(pubkey, privkey,
- pubdata, 128,
- conn->internal->sha1hash,
- conn->local_id,
- SILC_ID_CLIENT);
- memset(pubdata, 0, 128);
- silc_free(pubdata);
+ j->type = 1;
+ pk = silc_pkcs_public_key_encode(NULL, pubkey, &pk_len);
+ silc_hash_make(conn->internal->sha1hash, pk, pk_len, pkhash);
+ silc_free(pk);
+ silc_rng_get_rn_data(conn->client->rng, sizeof(pubdata), pubdata,
+ sizeof(pubdata));
+ memcpy(pubdata, pkhash, 20);
+ silc_free(passphrase);
+ silc_client_unref_channel(client, conn, channel);
+ SILC_FSM_CALL(silc_auth_public_key_auth_generate_wpub(
+ pubkey, privkey,
+ pubdata, sizeof(pubdata),
+ conn->internal->sha1hash,
+ conn->local_id,
+ SILC_ID_CLIENT,
+ silc_client_command_join_signed,
+ cmd));
+ /* NOT REACHED */
+ }
} else {
/* Passphrases must be UTF-8 encoded, so encode if it is not */
if (!silc_utf8_valid(cmd->argv[i], cmd->argv_lens[i])) {
6, silc_buffer_datalen(auth),
7, silc_buffer_datalen(cauth));
- silc_buffer_free(auth);
- silc_buffer_free(cauth);
if (passphrase)
memset(passphrase, 0, strlen(passphrase));
silc_free(passphrase);
silc_client_unref_channel(client, conn, channel);
+ if (j) {
+ silc_buffer_free(j->auth);
+ silc_buffer_free(j->cauth);
+ silc_free(j);
+ }
/* Notify application */
COMMAND(SILC_STATUS_OK);
/********************************** CMODE ***********************************/
+/* Signature callback */
+
+static void silc_client_command_cmode_signed(const SilcBuffer buffer,
+ void *context)
+{
+ SilcClientCommandContext cmd = context;
+
+ if (!buffer) {
+ silc_fsm_finish(&cmd->thread);
+ return;
+ }
+
+ silc_fsm_set_state_context(&cmd->thread, buffer);
+ SILC_FSM_CALL_CONTINUE_SYNC(&cmd->thread);
+}
+
/* CMODE command. Sets channel mode. Modes that does not require any arguments
can be set several at once. Those modes that require argument must be set
separately (unless set with modes that does not require arguments). */
SilcClientCommandContext cmd = fsm_context;
SilcClientConnection conn = cmd->conn;
SilcClient client = conn->client;
+ SilcBuffer auth = state_context;
SilcChannelEntry channel = NULL;
- SilcBuffer chidp, auth = NULL, pk = NULL;
+ SilcBuffer chidp, pk = NULL;
unsigned char *name, *cp, modebuf[4], tmp[4], *arg = NULL;
SilcUInt32 mode, add, type, len, arg_len = 0;
int i;
break;
case 'f':
if (add) {
- SilcPublicKey pubkey = conn->public_key;
- SilcPrivateKey privkey = conn->private_key;
-
- mode |= SILC_CHANNEL_MODE_FOUNDER_AUTH;
- type = 7;
-
- if (cmd->argc >= 5) {
- char *pass = "";
- if (cmd->argc >= 6)
- pass = cmd->argv[5];
- if (!silc_load_key_pair(cmd->argv[3], cmd->argv[4], pass,
- &pubkey, &privkey)) {
- SAY(client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR,
- "Could not load key pair, check your arguments");
- COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
- goto out;
+ if (!auth) {
+ SilcPublicKey pubkey = conn->public_key;
+ SilcPrivateKey privkey = conn->private_key;
+
+ mode |= SILC_CHANNEL_MODE_FOUNDER_AUTH;
+ type = 7;
+
+ if (cmd->argc >= 5) {
+ char *pass = "";
+ if (cmd->argc >= 6)
+ pass = cmd->argv[5];
+ if (!silc_load_key_pair(cmd->argv[3], cmd->argv[4], pass,
+ &pubkey, &privkey)) {
+ SAY(client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR,
+ "Could not load key pair, check your arguments");
+ COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+ goto out;
+ }
}
- }
- pk = silc_public_key_payload_encode(pubkey);
- auth = silc_auth_public_key_auth_generate(pubkey, privkey,
- conn->client->rng,
- conn->internal->sha1hash,
- conn->local_id,
- SILC_ID_CLIENT);
+ pk = silc_public_key_payload_encode(NULL, pubkey);
+ silc_client_unref_channel(client, conn, channel);
+ SILC_FSM_CALL(silc_auth_public_key_auth_generate(
+ pubkey, privkey,
+ conn->client->rng,
+ conn->internal->sha1hash,
+ conn->local_id,
+ SILC_ID_CLIENT,
+ silc_client_command_cmode_signed,
+ cmd));
+ /* NOT REACHED */
+ }
arg = silc_buffer_data(auth);
arg_len = silc_buffer_len(auth);
} else {
}
if (chpk) {
- pk = silc_public_key_payload_encode(chpk);
+ pk = silc_public_key_payload_encode(NULL, chpk);
auth = silc_argument_payload_encode_one(auth,
silc_buffer_datalen(pk),
chadd ? 0x00 : 0x01);
/********************************* CUMODE ***********************************/
+/* Signature callback */
+
+static void silc_client_command_cumode_signed(const SilcBuffer buffer,
+ void *context)
+{
+ SilcClientCommandContext cmd = context;
+
+ if (!buffer) {
+ silc_fsm_finish(&cmd->thread);
+ return;
+ }
+
+ silc_fsm_set_state_context(&cmd->thread, buffer);
+ SILC_FSM_CALL_CONTINUE_SYNC(&cmd->thread);
+}
+
/* CUMODE command. Changes client's mode on a channel. */
SILC_FSM_STATE(silc_client_command_cumode)
SilcClientCommandContext cmd = fsm_context;
SilcClientConnection conn = cmd->conn;
SilcClient client = conn->client;
+ SilcBuffer auth = state_context;
SilcChannelEntry channel = NULL;
SilcChannelUser chu;
SilcClientEntry client_entry;
- SilcBuffer clidp, chidp, auth = NULL;
+ SilcBuffer clidp, chidp;
SilcDList clients = NULL;
unsigned char *name, *cp, modebuf[4];
SilcUInt32 mode = 0, add, len;
break;
case 'f':
if (add) {
- SilcPublicKey pubkey = conn->public_key;
- SilcPrivateKey privkey = conn->private_key;
-
- if (cmd->argc >= 6) {
- char *pass = "";
- if (cmd->argc >= 7)
- pass = cmd->argv[6];
- if (!silc_load_key_pair(cmd->argv[4], cmd->argv[5], pass,
- &pubkey, &privkey)) {
- SAY(conn->client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR,
- "Could not load key pair, check your arguments");
- COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
- goto out;
+ if (!auth) {
+ SilcPublicKey pubkey = conn->public_key;
+ SilcPrivateKey privkey = conn->private_key;
+
+ if (cmd->argc >= 6) {
+ char *pass = "";
+ if (cmd->argc >= 7)
+ pass = cmd->argv[6];
+ if (!silc_load_key_pair(cmd->argv[4], cmd->argv[5], pass,
+ &pubkey, &privkey)) {
+ SAY(conn->client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR,
+ "Could not load key pair, check your arguments");
+ COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+ goto out;
+ }
}
+
+ silc_free(nickname);
+ silc_client_list_free(client, conn, clients);
+ silc_client_unref_channel(client, conn, channel);
+
+ SILC_FSM_CALL(silc_auth_public_key_auth_generate(
+ pubkey, privkey,
+ conn->client->rng,
+ conn->internal->sha1hash,
+ conn->local_id,
+ SILC_ID_CLIENT,
+ silc_client_command_cumode_signed,
+ cmd));
+ /* NOT REACHED */
}
- auth = silc_auth_public_key_auth_generate(pubkey, privkey,
- conn->client->rng,
- conn->internal->sha1hash,
- conn->local_id,
- SILC_ID_CLIENT);
mode |= SILC_CHANNEL_UMODE_CHANFO;
} else {
mode &= ~SILC_CHANNEL_UMODE_CHANFO;
typedef struct {
unsigned char *passphrase;
SilcUInt32 passphrase_len;
+ SilcBuffer auth;
} *SilcClientCommandOper;
/* Ask passphrase callback */
SILC_FSM_CALL_CONTINUE(&cmd->thread);
}
+static void silc_client_command_oper_sign_cb(const SilcBuffer data,
+ void *context)
+{
+ SilcClientCommandContext cmd = context;
+ SilcClientCommandOper oper = cmd->context;
+
+ if (data)
+ oper->auth = silc_buffer_copy(data);
+
+ /* Continue */
+ SILC_FSM_CALL_CONTINUE(&cmd->thread);
+}
+
/* Send OPER/SILCOPER command */
SILC_FSM_STATE(silc_client_command_oper_send)
SilcClientCommandContext cmd = fsm_context;
SilcClientConnection conn = cmd->conn;
SilcClientCommandOper oper = cmd->context;
- SilcBuffer auth;
-
- if (!oper || !oper->passphrase) {
- /* Encode the public key authentication payload */
- auth = silc_auth_public_key_auth_generate(conn->public_key,
- conn->private_key,
- conn->client->rng,
- conn->internal->hash,
- conn->local_id,
- SILC_ID_CLIENT);
- } else {
- /* Encode the password authentication payload */
- auth = silc_auth_payload_encode(SILC_AUTH_PASSWORD, NULL, 0,
- oper->passphrase, oper->passphrase_len);
- }
+ SilcBuffer auth = oper ? oper->auth : NULL;
silc_client_command_send_va(conn, cmd, cmd->cmd, NULL, NULL, 2,
1, cmd->argv[1], strlen(cmd->argv[1]),
return SILC_FSM_CONTINUE;
}
+/* Get authentication data */
+
+SILC_FSM_STATE(silc_client_command_oper_get_auth)
+{
+ SilcClientCommandContext cmd = fsm_context;
+ SilcClientConnection conn = cmd->conn;
+ SilcClientCommandOper oper = cmd->context;
+
+ silc_fsm_next(fsm, silc_client_command_oper_send);
+
+ if (!oper || !oper->passphrase) {
+ /* Encode the public key authentication payload */
+ SILC_FSM_CALL(silc_auth_public_key_auth_generate(
+ conn->public_key,
+ conn->private_key,
+ conn->client->rng,
+ conn->internal->hash,
+ conn->local_id, SILC_ID_CLIENT,
+ silc_client_command_oper_sign_cb,
+ oper));
+ /* NOT REACHED */
+ }
+
+ /* Encode the password authentication payload */
+ oper->auth = silc_auth_payload_encode(NULL, SILC_AUTH_PASSWORD, NULL, 0,
+ oper->passphrase, oper->passphrase_len);
+
+ return SILC_FSM_CONTINUE;
+}
+
/* OPER command. Used to obtain server operator privileges. */
SILC_FSM_STATE(silc_client_command_oper)
return SILC_FSM_FINISH;
}
- silc_fsm_next(fsm, silc_client_command_oper_send);
+ silc_fsm_next(fsm, silc_client_command_oper_get_auth);
/* Get passphrase */
if (cmd->argc < 3) {
SILC_STR_UI_SHORT(1),
SILC_STR_END);
if (pubkey) {
- chidp = silc_public_key_payload_encode(pubkey);
+ chidp = silc_public_key_payload_encode(NULL, pubkey);
args = silc_argument_payload_encode_one(args,
silc_buffer_datalen(chidp), 2);
silc_buffer_free(chidp);
silc_buffer_format(args,
SILC_STR_UI_SHORT(1),
SILC_STR_END);
- buffer = silc_public_key_payload_encode(pk);
+ buffer = silc_public_key_payload_encode(NULL, pk);
args = silc_argument_payload_encode_one(args, silc_buffer_datalen(buffer),
pubkey_add ? 0x00 : 0x01);
silc_buffer_free(buffer);
/****************** Client Side Incoming Command Handling *******************/
-/* Reply to WHOIS command from server */
+typedef struct {
+ SilcClientConnection conn;
+ SilcUInt16 cmd_ident;
+} *SilcClientProcessWhois;
+
+/* Send reply to WHOIS from server */
+
+static void
+silc_client_command_process_whois_send(SilcBool success,
+ const unsigned char *data,
+ SilcUInt32 data_len, void *context)
+{
+ SilcClientProcessWhois w = context;
+ SilcBufferStruct buffer;
+ SilcBuffer packet;
+
+ if (!data) {
+ silc_free(w);
+ return;
+ }
+
+ silc_buffer_set(&buffer, (unsigned char *)data, data_len);
+
+ /* Send the attributes back in COMMAND_REPLY packet */
+ packet =
+ silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
+ SILC_STATUS_OK, 0, w->cmd_ident,
+ 1, 11, buffer.data,
+ silc_buffer_len(&buffer));
+ if (!packet) {
+ silc_free(w);
+ return;
+ }
+
+ SILC_LOG_DEBUG(("Sending back requested WHOIS attributes"));
+
+ silc_packet_send(w->conn->stream, SILC_PACKET_COMMAND_REPLY, 0,
+ silc_buffer_datalen(packet));
+
+ silc_buffer_free(packet);
+ silc_free(w);
+}
+
+/* Process WHOIS command from server */
static void silc_client_command_process_whois(SilcClient client,
SilcClientConnection conn,
SilcCommandPayload payload,
SilcArgumentPayload args)
{
+ SilcClientProcessWhois w;
SilcDList attrs;
unsigned char *tmp;
SilcUInt32 tmp_len;
- SilcBuffer buffer, packet;
SILC_LOG_DEBUG(("Received WHOIS command"));
if (!attrs)
return;
- /* Process requested attributes */
- buffer = silc_client_attributes_process(client, conn, attrs);
- if (!buffer) {
+ w = silc_calloc(1, sizeof(*w));
+ if (!w) {
silc_attribute_payload_list_free(attrs);
return;
}
+ w->conn = conn;
+ w->cmd_ident = silc_command_get_ident(payload);
- /* Send the attributes back in COMMAND_REPLY packet */
- packet =
- silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
- SILC_STATUS_OK, 0,
- silc_command_get_ident(payload),
- 1, 11, buffer->data,
- silc_buffer_len(buffer));
- if (!packet) {
- silc_buffer_free(buffer);
- return;
- }
-
- SILC_LOG_DEBUG(("Sending back requested WHOIS attributes"));
-
- silc_packet_send(conn->stream, SILC_PACKET_COMMAND_REPLY, 0,
- silc_buffer_datalen(packet));
-
- silc_buffer_free(packet);
- silc_buffer_free(buffer);
+ /* Process requested attributes */
+ silc_client_attributes_process(client, conn, attrs,
+ silc_client_command_process_whois_send, w);
+ silc_attribute_payload_list_free(attrs);
}
/* Client is able to receive some command packets even though they are
not all SILC server versions return such channel name strings. */
SilcBool full_channel_names;
- /* If this is set to TRUE, the silcclient library will not register and
- deregister the cipher, pkcs, hash and hmac algorithms. The application
- itself will need to handle that. */
+ /* If this is set to TRUE, the silcclient library will not initialize
+ or uninitialize the SILC Crypto Toolkit. The application will have
+ to do that itself by calling silc_crypto_init and silc_crypto_uninit. */
SilcBool dont_register_crypto_library;
} SilcClientParams;