+ /* Get founder public key */
+ tmp = silc_argument_get_arg_type(args, 6, &tmp_len);
+ if (tmp && mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
+ if (channel->founder_key)
+ silc_pkcs_public_key_free(channel->founder_key);
+ channel->founder_key = NULL;
+ SILC_LOG_DEBUG(("Founder public key received"));
+ if (!silc_pkcs_public_key_payload_decode(tmp, tmp_len,
+ &channel->founder_key)) {
+ SILC_LOG_DEBUG(("Enforcing sender to change channel mode"));
+ mode &= ~SILC_CHANNEL_MODE_FOUNDER_AUTH;
+ silc_server_send_notify_cmode(server, sock, FALSE, channel,
+ mode, server->id, SILC_ID_SERVER,
+ channel->cipher,
+ channel->hmac_name,
+ channel->passphrase, NULL, NULL);
+ if (channel->founder_key)
+ silc_pkcs_public_key_free(channel->founder_key);
+ channel->founder_key = NULL;
+ }
+ }
+
+ if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH && !channel->founder_key &&
+ server->server_type == SILC_ROUTER) {
+ SILC_LOG_DEBUG(("Enforcing sender to change channel mode"));
+ mode &= ~SILC_CHANNEL_MODE_FOUNDER_AUTH;
+ silc_server_send_notify_cmode(server, sock, FALSE, channel,
+ mode, server->id, SILC_ID_SERVER,
+ channel->cipher,
+ channel->hmac_name,
+ channel->passphrase, NULL, NULL);
+ }
+
+ /* Process channel public key(s). */
+ tmp = silc_argument_get_arg_type(args, 7, &tmp_len);
+ if (tmp && mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
+ SilcStatus ret =
+ silc_server_set_channel_pk_list(server, sock, channel, tmp, tmp_len);
+
+ /* If list was set already we will enforce the same list to server. */
+ if (ret == SILC_STATUS_ERR_OPERATION_ALLOWED) {
+ SilcBuffer chpklist = silc_server_get_channel_pk_list(server, channel,
+ TRUE, FALSE);
+ silc_server_send_notify_cmode(server, sock, FALSE, channel,
+ mode, server->id, SILC_ID_SERVER,
+ channel->cipher,
+ channel->hmac_name,
+ channel->passphrase, NULL,
+ chpklist);
+ silc_buffer_free(chpklist);
+ }
+ }
+
+ /* Get the user limit */
+ tmp = silc_argument_get_arg_type(args, 8, &tmp_len);
+ if (tmp && tmp_len == 4 && mode & SILC_CHANNEL_MODE_ULIMIT)
+ SILC_GET32_MSB(channel->user_limit, tmp);
+
+ /* Send the same notify to the channel */
+ silc_server_packet_send_to_channel(server, NULL, channel, packet->type,
+ FALSE, TRUE, packet->buffer->data,
+ packet->buffer->len, FALSE);
+
+ /* Change mode */
+ channel->mode = mode;
+
+ /* Cleanup if some modes are removed */
+
+ if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) &&
+ channel->founder_key) {
+ silc_pkcs_public_key_free(channel->founder_key);
+ channel->founder_key = NULL;
+ }
+
+ if (!(channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) &&
+ channel->channel_pubkeys) {
+ silc_hash_table_free(channel->channel_pubkeys);
+ channel->channel_pubkeys = NULL;
+ }
+