Ejemplo n.º 1
0
SilcBool silc_client_send_private_message(SilcClient client,
					  SilcClientConnection conn,
					  SilcClientEntry client_entry,
					  SilcMessageFlags flags,
					  SilcHash hash,
					  unsigned char *data,
					  SilcUInt32 data_len)
{
  SilcBuffer buffer;
  SilcBool ret;
  SilcID sid, rid;

  if (silc_unlikely(!client || !conn || !client_entry))
    return FALSE;
  if (silc_unlikely(flags & SILC_MESSAGE_FLAG_SIGNED && !hash))
    return FALSE;
  if (silc_unlikely(conn->internal->disconnected))
    return FALSE;

  SILC_LOG_DEBUG(("Sending private message"));

  sid.type = SILC_ID_CLIENT;
  sid.u.client_id = conn->local_entry->id;
  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"));
    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);

  silc_buffer_free(buffer);
  return ret;
}
Ejemplo n.º 2
0
void *silc_realloc(void *ptr, size_t size)
{
  void *addr;
  if (silc_unlikely(size <= 0 || size >= SILC_MAX_ALLOC)) {
    if (size == 0)
      silc_set_errno_nofail(SILC_ERR_ZERO_ALLOCATION);
    else
      silc_set_errno_reason_nofail(SILC_ERR_TOO_LARGE_ALLOCATION,
				   "Allocation by %d", size);
    return NULL;
  }

  addr = realloc(ptr, size);
  if (silc_unlikely(!addr))
    silc_set_errno_nofail(SILC_ERR_OUT_OF_MEMORY);

  return addr;
}
Ejemplo n.º 3
0
void *silc_memdup(const void *ptr, size_t size)
{
  unsigned char *addr;

  addr = silc_malloc(size + 1);
  if (silc_unlikely(!addr)) {
    silc_set_errno_nofail(SILC_ERR_OUT_OF_MEMORY);
    return NULL;
  }
  memcpy((void *)addr, ptr, size);
  addr[size] = '\0';
  return (void *)addr;
}
Ejemplo n.º 4
0
void *silc_scalloc(SilcStack stack, SilcUInt32 items, SilcUInt32 size)
{
  unsigned char *addr;

  if (!stack)
    return silc_calloc(items, size);

  addr = silc_stack_malloc(stack, items * size);
  if (silc_unlikely(!addr))
    return NULL;
  memset(addr, 0, items * size);
  return (void *)addr;
}
Ejemplo n.º 5
0
SilcBool silc_file_fstat(int fd, SilcFileStat return_stat)
{
  struct stat status;

  if (silc_unlikely(fstat(fd, &status) != 0)) {
    silc_set_errno_posix(errno);
    return FALSE;
  }

  if (return_stat)
    silc_file_fill_stat(&status, return_stat);

  return TRUE;
}
Ejemplo n.º 6
0
void *silc_smemdup(SilcStack stack, const void *ptr, SilcUInt32 size)
{
  unsigned char *addr;

  if (!stack)
    return silc_memdup(ptr, size);

  addr = silc_stack_malloc(stack, size + 1);
  if (silc_unlikely(!addr))
    return NULL;
  memcpy((void *)addr, ptr, size);
  addr[size] = '\0';
  return (void *)addr;
}
Ejemplo n.º 7
0
SilcBool silc_file_stat(const char *filename, SilcBool follow_symlinks,
			SilcFileStat return_stat)
{
  struct stat status;

  if (silc_unlikely(!filename)) {
    silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
    return FALSE;
  }

  SILC_LOG_DEBUG(("Get status for file '%s'", filename));

  if (!follow_symlinks) {
    if (silc_unlikely(stat(filename, &status) != 0)) {
      silc_set_errno_posix(errno);
      return FALSE;
    }
  } else {
#ifdef HAVE_LSTAT
    if (silc_unlikely(lstat(filename, &status) != 0)) {
      silc_set_errno_posix(errno);
      return FALSE;
    }
#else
    if (silc_unlikely(stat(filename, &status) != 0)) {
      silc_set_errno_posix(errno);
      return FALSE;
    }
#endif /* HAVE_LSTAT */
  }

  if (return_stat)
    silc_file_fill_stat(&status, return_stat);

  return TRUE;
}
Ejemplo n.º 8
0
char *silc_sstrdup(SilcStack stack, const char *str)
{
  SilcInt32 size = strlen(str);
  char *addr;

  if (!stack)
    return silc_memdup(str, size);

  addr = silc_stack_malloc(stack, size + 1);
  if (silc_unlikely(!addr))
    return NULL;
  memcpy((void *)addr, str, size);
  addr[size] = '\0';
  return addr;
}
Ejemplo n.º 9
0
SilcBool silc_client_send_channel_message(SilcClient client,
					  SilcClientConnection conn,
					  SilcChannelEntry channel,
					  SilcChannelPrivateKey key,
					  SilcMessageFlags flags,
					  SilcHash hash,
					  unsigned char *data,
					  SilcUInt32 data_len)
{
  SilcChannelUser chu;
  SilcBuffer buffer;
  SilcCipher cipher;
  SilcHmac hmac;
  SilcBool ret;
  SilcID sid, rid;

  SILC_LOG_DEBUG(("Sending channel message"));

  if (silc_unlikely(!client || !conn || !channel))
    return FALSE;
  if (silc_unlikely(flags & SILC_MESSAGE_FLAG_SIGNED && !hash))
    return FALSE;
  if (silc_unlikely(conn->internal->disconnected))
    return FALSE;

  chu = silc_client_on_channel(channel, conn->local_entry);
  if (silc_unlikely(!chu)) {
    client->internal->ops->say(conn->client, conn,
			       SILC_CLIENT_MESSAGE_AUDIT,
			       "Cannot talk to channel: not joined");
    return FALSE;
  }

  /* Check if it is allowed to send messages to this channel by us. */
  if (silc_unlikely(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS &&
		    !chu->mode))
    return FALSE;
  if (silc_unlikely(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS &&
		    chu->mode & SILC_CHANNEL_UMODE_CHANOP &&
		    !(chu->mode & SILC_CHANNEL_UMODE_CHANFO)))
    return FALSE;
  if (silc_unlikely(chu->mode & SILC_CHANNEL_UMODE_QUIET))
    return FALSE;

  /* Take the key to be used */
  if (channel->internal.private_keys) {
    if (key) {
      /* Use key application specified */
      cipher = key->send_key;
      hmac = key->hmac;
    } else if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY &&
	       channel->internal.curr_key) {
      /* Use current private key */
      cipher = channel->internal.curr_key->send_key;
      hmac = channel->internal.curr_key->hmac;
    } else if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY &&
	       !channel->internal.curr_key &&
	       channel->internal.private_keys) {
      /* Use just some private key since we don't know what to use
	 and private keys are set. */
      silc_dlist_start(channel->internal.private_keys);
      key = silc_dlist_get(channel->internal.private_keys);
      cipher = key->send_key;
      hmac = key->hmac;

      /* Use this key as current private key */
      channel->internal.curr_key = key;
    } else {
      /* Use normal channel key generated by the server */
      cipher = channel->internal.send_key;
      hmac = channel->internal.hmac;
    }
  } else {
    /* Use normal channel key generated by the server */
    cipher = channel->internal.send_key;
    hmac = channel->internal.hmac;
  }

  if (silc_unlikely(!cipher || !hmac)) {
    SILC_LOG_ERROR(("No cipher and HMAC for channel"));
    return FALSE;
  }

  /* Encode the message payload. This also encrypts the message payload. */
  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);

  silc_buffer_free(buffer);
  return ret;
}
Ejemplo n.º 10
0
static void silc_buffer_stream_io(SilcStream stream,
				  SilcStreamStatus status,
				  void *context)
{
  SilcBufferStream bs = context;
  SilcBuffer buffer = NULL;
  SilcUInt32 buf_len;
  int ret, len;

  if (bs->closed)
    return;

  if (status == SILC_STREAM_CAN_READ) {
    /* Read data */
    SILC_LOG_DEBUG(("Read data from buffer stream %p", bs));

    while ((ret = silc_stream_read(bs->stream, bs->inbuf->tail,
				   silc_buffer_taillen(bs->inbuf))) > 0) {
      if (!buffer) {
	buffer = silc_buffer_alloc(0);
	if (!buffer)
	  return;
      }

      silc_buffer_pull_tail(bs->inbuf, ret);

      /* Parse the buffer */
      while ((len = silc_buffer_unformat(bs->inbuf,
					 SILC_STR_BUFFER_ALLOC(buffer),
					 SILC_STR_END)) > 0) {
	/* Deliver the buffer */
	SILC_LOG_HEXDUMP(("Received buffer, size %d",
			  silc_buffer_len(buffer)),
			 silc_buffer_data(buffer), silc_buffer_len(buffer));
	bs->receiver(SILC_OK, (SilcStream)bs, buffer, bs->context);
	silc_buffer_pull(bs->inbuf, len);

	buffer = silc_buffer_alloc(0);
	if (!buffer)
	  return;
      }

      if (silc_buffer_len(bs->inbuf) > 0) {
	/* Not complete buffer, read more data */
	buf_len = 4;
	if (silc_buffer_len(bs->inbuf) >= 4) {
	  SILC_GET32_MSB(buf_len, bs->inbuf->data);
	  SILC_LOG_DEBUG(("Incomplete buffer, wait for rest, buffer size %d",
			  buf_len));
	}

	/* Enlarge inbuf if needed */
	if (silc_buffer_taillen(bs->inbuf) < buf_len)
	  silc_buffer_realloc(bs->inbuf, silc_buffer_truelen(bs->inbuf) +
			      buf_len);
	continue;
      }

      /* All data read, read more */
      silc_buffer_reset(bs->inbuf);
    }

    silc_buffer_free(buffer);

    if (ret == 0 || ret == -2) {
      bs->receiver(silc_errno, (SilcStream)bs, NULL, bs->context);
      return;
    }
  } else {
    /* Write any pending data */
    SILC_LOG_DEBUG(("Write pending data to buffer stream %p", bs));

    while (silc_buffer_len(&bs->queue) > 0) {
      ret = silc_stream_write(bs->stream, silc_buffer_data(&bs->queue),
			      silc_buffer_len(&bs->queue));
      if (silc_unlikely(ret == 0))
	return;

      if (silc_unlikely(ret == -2))
	return;

      if (silc_unlikely(ret == -1)) {
	SILC_LOG_DEBUG(("Buffer stream %p would block, send later", bs));
	return;
      }

      /* Wrote data */
      silc_buffer_pull(&bs->queue, ret);
    }

    memset(&bs->queue, 0, sizeof(bs->queue));
    silc_buffer_reset(bs->outbuf);
  }
}
Ejemplo n.º 11
0
SilcBool silc_buffer_stream_send(SilcStream stream,
				 SilcBuffer buffer)
{
  SilcBufferStream bs = stream;
  int ret;

  SILC_LOG_HEXDUMP(("Send to buffer stream %p %d bytes", bs,
		    silc_buffer_len(buffer)),
		   silc_buffer_data(buffer), silc_buffer_len(buffer));

  if (silc_unlikely(!SILC_IS_BUFFER_STREAM(bs))) {
    silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
    return FALSE;
  }

  if (silc_unlikely(!buffer)) {
    silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
    return FALSE;
  }

  if (silc_unlikely(bs->closed)) {
    SILC_LOG_DEBUG(("Buffer stream %p is closed", bs));
    silc_set_errno(SILC_ERR_NOT_VALID);
    return FALSE;
  }

  /* Put to queue */
  if (silc_buffer_format(bs->outbuf,
			 SILC_STR_ADVANCE,
			 SILC_STR_BUFFER(buffer),
			 SILC_STR_END) < 0)
    return FALSE;

  ret = silc_buffer_headlen(&bs->queue);
  bs->queue.head = bs->outbuf->head;
  bs->queue.data = bs->queue.head + ret;
  bs->queue.tail = bs->outbuf->data;
  bs->queue.end  = bs->outbuf->end;

  /* Write the queue buffer */
  while (silc_buffer_len(&bs->queue) > 0) {
    ret = silc_stream_write(bs->stream, silc_buffer_data(&bs->queue),
			    silc_buffer_len(&bs->queue));
    if (silc_unlikely(ret == 0))
      return FALSE;

    if (silc_unlikely(ret == -2))
      return FALSE;

    if (silc_unlikely(ret == -1)) {
      SILC_LOG_DEBUG(("Buffer stream %p would block, send later", bs));
      return TRUE;
    }

    /* Wrote data */
    silc_buffer_pull(&bs->queue, ret);
  }

  memset(&bs->queue, 0, sizeof(bs->queue));
  silc_buffer_reset(bs->outbuf);

  SILC_LOG_DEBUG(("Buffer sent to buffer stream %p", bs));

  return TRUE;
}