+ /* Delete information to invite list */
+ if (action == 0x01 && list) {
+ /* Now delete the arguments from invite list */
+ tmp = silc_argument_get_first_arg(args, &type, &len);
+ while (tmp) {
+ if (type == 1) {
+ /* Check validity of the string. Actually we should parse the
+ whole string and verify all components individually. */
+ if (!silc_utf8_valid(tmp, len)) {
+ tmp = silc_argument_get_next_arg(args, &type, &len);
+ continue;
+ }
+ if (strchr(tmp, ',')) {
+ tmp = silc_argument_get_next_arg(args, &type, &len);
+ continue;
+ }
+
+ /* Delete from the list */
+ silc_hash_table_list(list, &htl);
+ while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
+ if (SILC_PTR_TO_32(ptype) == 1 &&
+ silc_string_match(tmp2->data, tmp)) {
+ silc_hash_table_del_by_context(list, (void *)1, tmp2);
+ break;
+ }
+ }
+ silc_hash_table_list_reset(&htl);
+
+ } else if (type == 2) {
+ /* Public key. */
+ SilcPublicKey pk;
+
+ /* Verify validity of the public key */
+ if (!silc_public_key_payload_decode(tmp, len, &pk)) {
+ tmp = silc_argument_get_next_arg(args, &type, &len);
+ continue;
+ }
+ silc_pkcs_public_key_free(pk);
+
+ /* Delete from the invite list */
+ silc_hash_table_list(list, &htl);
+ while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
+ if (SILC_PTR_TO_32(ptype) == 2 && !memcmp(tmp2->data, tmp, len)) {
+ silc_hash_table_del_by_context(list, (void *)2, tmp2);
+ break;
+ }
+ }
+ silc_hash_table_list_reset(&htl);
+
+ } else if (type == 3) {
+ /* Client ID */
+
+ /* Delete from the invite list */
+ silc_hash_table_list(list, &htl);
+ while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) {
+ if (SILC_PTR_TO_32(ptype) == 3 && !memcmp(tmp2->data, tmp, len)) {
+ silc_hash_table_del_by_context(list, (void *)3, tmp2);
+ break;
+ }
+ }
+ silc_hash_table_list_reset(&htl);
+ }
+
+ tmp = silc_argument_get_next_arg(args, &type, &len);
+ }
+ }
+
+ return TRUE;
+}
+
+/* Destructor for invite and ban list entrys */
+
+void silc_server_inviteban_destruct(void *key, void *context,
+ void *user_context)
+{
+ silc_buffer_free(context);
+}
+
+/* Creates connections accoring to configuration. */
+
+void silc_server_create_connections(SilcServer server)
+{
+ silc_schedule_task_del_by_callback(server->schedule,
+ silc_server_connect_to_router);
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_connect_to_router, server, 1, 0);
+}
+
+static void
+silc_server_process_channel_pk_destruct(void *key, void *context,
+ void *user_context)
+{
+ silc_free(key);
+ silc_pkcs_public_key_free(context);
+}
+
+/* Processes a channel public key, either adds or removes it. */
+
+SilcStatus
+silc_server_process_channel_pk(SilcServer server,
+ SilcChannelEntry channel,
+ SilcUInt32 type, const unsigned char *pk,
+ SilcUInt32 pk_len)
+{
+ unsigned char pkhash[20];
+ SilcPublicKey chpk;
+
+ SILC_LOG_DEBUG(("Processing channel public key"));
+
+ if (!pk || !pk_len)
+ return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
+
+ /* Decode the public key */
+ if (!silc_public_key_payload_decode((unsigned char *)pk, pk_len, &chpk))
+ return SILC_STATUS_ERR_UNSUPPORTED_PUBLIC_KEY;
+
+ /* Create channel public key list (hash table) if needed */
+ if (!channel->channel_pubkeys) {
+ channel->channel_pubkeys =
+ silc_hash_table_alloc(0, silc_hash_data, (void *)20,
+ silc_hash_data_compare, (void *)20,
+ silc_server_process_channel_pk_destruct, channel,
+ TRUE);
+ }
+
+ /* Create SHA-1 digest of the public key data */
+ silc_hash_make(server->sha1hash, pk + 4, pk_len - 4, pkhash);
+
+ if (type == 0x00) {
+ /* Add new public key to channel public key list */
+ SILC_LOG_DEBUG(("Add new channel public key to channel %s",
+ channel->channel_name));
+
+ /* Check for resource limit */
+ if (silc_hash_table_count(channel->channel_pubkeys) > 64) {
+ silc_pkcs_public_key_free(chpk);
+ return SILC_STATUS_ERR_RESOURCE_LIMIT;
+ }
+
+ /* Add if doesn't exist already */
+ if (!silc_hash_table_find(channel->channel_pubkeys, pkhash,
+ NULL, NULL))
+ silc_hash_table_add(channel->channel_pubkeys, silc_memdup(pkhash, 20),
+ chpk);
+ } else if (type == 0x01) {
+ /* Delete public key from channel public key list */
+ SILC_LOG_DEBUG(("Delete a channel public key from channel %s",
+ channel->channel_name));
+ if (!silc_hash_table_del(channel->channel_pubkeys, pkhash))
+ silc_pkcs_public_key_free(chpk);
+ } else {
+ silc_pkcs_public_key_free(chpk);
+ return SILC_STATUS_ERR_NOT_ENOUGH_PARAMS;
+ }
+
+ return SILC_STATUS_OK;
+}
+
+/* Returns the channel public keys as Argument List payload. */
+
+SilcBuffer silc_server_get_channel_pk_list(SilcServer server,
+ SilcChannelEntry channel,
+ SilcBool announce,
+ SilcBool delete)
+{
+ SilcHashTableList htl;
+ SilcBuffer list, pkp;
+ SilcPublicKey pk;
+
+ SILC_LOG_DEBUG(("Encoding channel public keys list"));
+
+ if (!channel->channel_pubkeys ||
+ !silc_hash_table_count(channel->channel_pubkeys))
+ return NULL;
+
+ /* Encode the list */
+ list = silc_buffer_alloc_size(2);
+ silc_buffer_format(list,
+ SILC_STR_UI_SHORT(silc_hash_table_count(
+ channel->channel_pubkeys)),
+ SILC_STR_END);
+
+ silc_hash_table_list(channel->channel_pubkeys, &htl);
+ while (silc_hash_table_get(&htl, NULL, (void *)&pk)) {
+ pkp = silc_public_key_payload_encode(pk);
+ if (!pkp)