Esempio n. 1
0
SilcChannelEntry
silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
			SilcChannelID *id, SilcServerEntry router,
			SilcCipher send_key, SilcCipher receive_key,
			SilcHmac hmac)
{
  SilcChannelEntry channel;
  char *channel_namec = NULL;

  SILC_LOG_DEBUG(("Adding new channel %s", channel_name));

  /* Normalize name.  This is cached, original is in client context.  */
  if (channel_name) {
    channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
					    SILC_STRING_UTF8, 256, NULL);
    if (!channel_namec)
      return NULL;
  }

  channel = silc_calloc(1, sizeof(*channel));
  channel->channel_name = channel_name;
  channel->mode = mode;
  channel->id = id;
  channel->router = router;
  channel->send_key = send_key;
  channel->receive_key = receive_key;
  channel->hmac = hmac;
  channel->created = channel->updated = time(0);
  if (!channel->hmac)
    if (!silc_hmac_alloc(SILC_DEFAULT_HMAC, NULL, &channel->hmac)) {
      silc_free(channel);
      return NULL;
    }

  channel->user_list = silc_hash_table_alloc(3, silc_hash_ptr, NULL, NULL,
					     NULL, NULL, NULL, TRUE);

  if (!silc_idcache_add(id_list->channels, channel_namec,
			(void *)channel->id, (void *)channel)) {
    silc_hmac_free(channel->hmac);
    silc_hash_table_free(channel->user_list);
    silc_free(channel);
    silc_free(channel_namec);
    return NULL;
  }

  return channel;
}
Esempio n. 2
0
static char
silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
{
  SilcServer server = cmd->server;
  SilcUInt32 len, id_len;
  unsigned char *id_data;
  char *name, *info;
  SilcClientID client_id;
  SilcServerID server_id;
  SilcChannelID channel_id;
  SilcClientEntry client;
  SilcServerEntry server_entry;
  SilcChannelEntry channel;
  char global = FALSE;
  char nick[128 + 1];
  SilcIDPayload idp = NULL;
  SilcIdType id_type;

  id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
  if (!id_data)
    return FALSE;
  idp = silc_id_payload_parse(id_data, id_len);
  if (!idp)
    return FALSE;

  name = silc_argument_get_arg_type(cmd->args, 3, &len);
  info = silc_argument_get_arg_type(cmd->args, 4, &len);

  id_type = silc_id_payload_get_type(idp);

  switch (id_type) {
  case SILC_ID_CLIENT:
    if (!silc_id_payload_get_id(idp, &client_id, sizeof(client_id)))
      goto error;

    SILC_LOG_DEBUG(("Received client information"));

    client = silc_idlist_find_client_by_id(server->local_list,
					   &client_id, FALSE, NULL);
    if (!client) {
      client = silc_idlist_find_client_by_id(server->global_list, &client_id,
					     FALSE, NULL);
      global = TRUE;
    }
    if (!client) {
      /* If router did not find such Client ID in its lists then this must
	 be bogus client or some router in the net is buggy. */
      if (server->server_type != SILC_SERVER)
	goto error;

      /* Take nickname */
      if (name)
	silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);

      /* We don't have that client anywhere, add it. The client is added
	 to global list since server didn't have it in the lists so it must be
	 global. */
      client = silc_idlist_add_client(server->global_list,
				      nick[0] ? strdup(nick) : NULL,
				      info ? strdup(info) : NULL, NULL,
				      silc_id_dup(&client_id, SILC_ID_CLIENT),
				      silc_packet_get_context(cmd->sock),
				      NULL);
      if (!client) {
	SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
	goto error;
      }

      client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
      client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
      client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;

      SILC_LOG_DEBUG(("stat.clients %d->%d", server->stat.clients,
		      server->stat.clients + 1));
      server->stat.clients++;
    } else {
      /* We have the client already, update the data */

      SILC_LOG_DEBUG(("Updating client data"));

      /* Take nickname */
      if (name) {
	silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);

	/* Check nickname */
	name = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
				     128, NULL);
	if (!name) {
	  SILC_LOG_ERROR(("Malformed nickname '%s' received in IDENTIFY "
			  "reply ", nick));
	  return FALSE;
	}

	silc_free(client->nickname);
	client->nickname = strdup(nick);

	/* Update the context */
	silc_idcache_update_by_context(global ? server->global_list->clients :
				       server->local_list->clients, client,
				       NULL, name, TRUE);
      }

      if (info) {
	silc_free(client->username);
	client->username = strdup(info);
      }

      client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
      client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
    }

    break;

  case SILC_ID_SERVER:
    if (!name)
      goto error;

    if (!silc_id_payload_get_id(idp, &server_id, sizeof(server_id)))
      goto error;

    SILC_LOG_DEBUG(("Received server information"));

    server_entry = silc_idlist_find_server_by_id(server->local_list,
						 &server_id, FALSE, NULL);
    if (!server_entry)
      server_entry = silc_idlist_find_server_by_id(server->global_list,
						   &server_id, FALSE, NULL);
    if (!server_entry) {
      /* If router did not find such Server ID in its lists then this must
	 be bogus server or some router in the net is buggy. */
      if (server->server_type != SILC_SERVER)
	goto error;

      /* We don't have that server anywhere, add it. */
      server_entry = silc_idlist_add_server(server->global_list,
					    strdup(name), 0,
					    silc_id_dup(&server_id,
							SILC_ID_SERVER),
					    server->router,
					    SILC_PRIMARY_ROUTE(server));
      if (!server_entry)
	goto error;

      server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
      server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
      server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
    }

    break;

  case SILC_ID_CHANNEL:
    if (!name)
      goto error;

    if (!silc_id_payload_get_id(idp, &channel_id, sizeof(channel_id)))
      goto error;

    SILC_LOG_DEBUG(("Received channel information"));

    /* Check channel name */
    info = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
				   256, NULL);
    if (!info)
      goto error;

    channel = silc_idlist_find_channel_by_name(server->local_list,
					       info, NULL);
    if (!channel)
      channel = silc_idlist_find_channel_by_name(server->global_list,
						 info, NULL);
    if (!channel) {
      /* If router did not find such Channel ID in its lists then this must
	 be bogus channel or some router in the net is buggy. */
      if (server->server_type != SILC_SERVER) {
	silc_free(info);
	goto error;
      }

      /* We don't have that channel anywhere, add it. */
      channel = silc_idlist_add_channel(server->global_list, strdup(name),
					SILC_CHANNEL_MODE_NONE,
					silc_id_dup(&channel_id,
						    SILC_ID_CHANNEL),
					server->router, NULL, NULL, 0);
      if (!channel) {
	silc_free(info);
	goto error;
      }
      silc_free(info);
    }

    break;
  }

  silc_id_payload_free(idp);
  return TRUE;

 error:
  silc_id_payload_free(idp);
  return FALSE;
}