示例#1
0
static void silc_sftp_server_attr(SilcSFTP sftp,
				  SilcSFTPStatus status,
				  const SilcSFTPAttributes attrs,
				  void *context)
{
  SilcSFTPServer server = (SilcSFTPServer)sftp;
  SilcUInt32 id = SILC_PTR_TO_32(context);
  SilcBuffer attr_buf;

  SILC_LOG_DEBUG(("Attr callback"));
  SILC_LOG_DEBUG(("Request ID: %d", id));

  if (status != SILC_SFTP_STATUS_OK) {
    silc_sftp_send_error(server, status, id);
    return;
  }

  attr_buf = silc_sftp_attr_encode(attrs);
  if (!attr_buf) {
    silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);
    return;
  }

  silc_sftp_send_packet(server, SILC_SFTP_ATTRS, 4 + silc_buffer_len(attr_buf),
			SILC_STR_UI_INT(id),
			SILC_STR_DATA(silc_buffer_data(attr_buf),
				      silc_buffer_len(attr_buf)),
			SILC_STR_END);

  silc_buffer_free(attr_buf);
}
示例#2
0
static void silc_sftp_server_name(SilcSFTP sftp,
				  SilcSFTPStatus status,
				  const SilcSFTPName name,
				  void *context)
{
  SilcSFTPServer server = (SilcSFTPServer)sftp;
  SilcUInt32 id = SILC_PTR_TO_32(context);
  SilcBuffer namebuf;

  SILC_LOG_DEBUG(("Name callback"));
  SILC_LOG_DEBUG(("Request ID: %d", id));

  if (status != SILC_SFTP_STATUS_OK) {
    silc_sftp_send_error(server, status, id);
    return;
  }

  namebuf = silc_sftp_name_encode(name);
  if (!namebuf) {
    silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);
    return;
  }

  silc_sftp_send_packet(server, SILC_SFTP_NAME, 4 + silc_buffer_len(namebuf),
			SILC_STR_UI_INT(id),
			SILC_STR_DATA(silc_buffer_data(namebuf),
				      silc_buffer_len(namebuf)),
			SILC_STR_END);
}
示例#3
0
static void silc_sftp_send_packet(SilcSFTPServer sftp,
				  SilcSFTPPacket type,
				  SilcUInt32 len, ...)
{
  SilcBuffer tmp;
  va_list vp;
  int ret;

  va_start(vp, len);
  tmp = silc_sftp_packet_encode_vp(type, sftp->packet, len, vp);
  va_end(vp);
  if (!tmp)
    return;
  sftp->packet = tmp;

  SILC_LOG_HEXDUMP(("SFTP packet to client"), silc_buffer_data(sftp->packet),
		   silc_buffer_len(sftp->packet));

  /* Send the packet */
  while (silc_buffer_len(sftp->packet) > 0) {
    ret = silc_stream_write(sftp->stream, silc_buffer_data(sftp->packet),
			    silc_buffer_len(sftp->packet));
    if (ret == -2) {
      SILC_LOG_ERROR(("Error sending SFTP packet type %d", type));
      sftp->error((SilcSFTP)sftp, SILC_SFTP_STATUS_NO_CONNECTION,
		  sftp->context);
      silc_buffer_reset(sftp->packet);
      return;
    }
    if (ret == 0) {
      sftp->error((SilcSFTP)sftp, SILC_SFTP_STATUS_EOF, sftp->context);
      silc_buffer_reset(sftp->packet);
      return;
    }
    if (ret == -1)
      return;

    silc_buffer_pull(sftp->packet, ret);
  }

  /* Clear packet */
  silc_buffer_reset(sftp->packet);
}
示例#4
0
SilcBuffer silc_sftp_name_encode(SilcSFTPName name)
{
  SilcBuffer buffer;
  int i, len = 4;
  SilcBuffer *attr_buf;

  attr_buf = silc_calloc(name->count, sizeof(*attr_buf));
  if (!attr_buf)
    return NULL;

  for (i = 0; i < name->count; i++) {
    len += (8 + strlen(name->filename[i]) + strlen(name->long_filename[i]));
    attr_buf[i] = silc_sftp_attr_encode(name->attrs[i]);
    if (!attr_buf[i])
      return NULL;
    len += silc_buffer_len(attr_buf[i]);
  }

  buffer = silc_buffer_alloc(len);
  if (!buffer)
    return NULL;
  silc_buffer_end(buffer);

  silc_buffer_format(buffer,
		     SILC_STR_UI_INT(name->count),
		     SILC_STR_END);
  silc_buffer_pull(buffer, 4);

  for (i = 0; i < name->count; i++) {
    len =
      silc_buffer_format(buffer,
			 SILC_STR_UI_INT(strlen(name->filename[i])),
			 SILC_STR_UI32_STRING(name->filename[i]),
			 SILC_STR_UI_INT(strlen(name->long_filename[i])),
			 SILC_STR_UI32_STRING(name->long_filename[i]),
			 SILC_STR_DATA(silc_buffer_data(attr_buf[i]),
				       silc_buffer_len(attr_buf[i])),
			 SILC_STR_END);

    silc_buffer_pull(buffer, len);
    silc_free(attr_buf[i]);
  }
  silc_free(attr_buf);

  silc_buffer_push(buffer, buffer->data - buffer->head);

  return buffer;
}
示例#5
0
SilcBool silc_client_private_message_wait(SilcClient client,
					  SilcClientConnection conn,
					  SilcClientEntry client_entry,
					  SilcMessagePayload *payload)
{
  SilcPacket packet;

  if (!client_entry->internal.prv_waiter)
    return FALSE;

  /* Block until private message arrives */
  do {
    if ((silc_packet_wait(client_entry->internal.prv_waiter, 0, &packet)) < 0)
      return FALSE;

    /* Parse the payload and decrypt it also if private message key is set */
    *payload =
      silc_message_payload_parse(silc_buffer_data(&packet->buffer),
				 silc_buffer_len(&packet->buffer),
				 TRUE, !client_entry->internal.generated,
				 client_entry->internal.receive_key,
				 client_entry->internal.hmac_receive,
				 packet->src_id, packet->src_id_len,
				 packet->dst_id, packet->dst_id_len,
				 NULL, FALSE, NULL);
    if (!(*payload)) {
      silc_packet_free(packet);
      continue;
    }

    break;
  } while (1);

  silc_packet_free(packet);
  return TRUE;
}
示例#6
0
int main(int argc, char **argv)
{
  int opt, ret, i;
  SilcAsn1 asn1;
  SilcBufferStruct buf;
  unsigned char *data, *tmp;
  SilcUInt32 data_len;

  if (argc < 2) {
    usage();
    return 1;
  }

  while ((opt = getopt(argc, argv, "hxbai")) != EOF) {
    switch (opt) {
    case 'h':
      usage();
      return 1;
      break;

    case 'x':
      hexdump = TRUE;
      break;

    case 'b':
      dec_base64 = TRUE;
      break;

    case 'i':
      ignore_header = TRUE;
      break;

    case 'a':
      parse_all = TRUE;
      break;

    default:
      usage();
      return 1;
    }
  }

  data = tmp = silc_file_readfile(argv[argc - 1], &data_len, NULL);
  if (!data) {
    fprintf(stderr, "Error: Cannot read file '%s': %s\n", argv[argc - 1],
	    silc_errno_string(silc_errno));
    return 1;
  }

  silc_buffer_set(&buf, data, data_len);

  if (ignore_header) {
    SilcBool header = FALSE;
    for (i = 0; i < data_len; i++) {
      if (data_len > i + 4 &&
	  data[i    ] == '-' && data[i + 1] == '-' &&
	  data[i + 2] == '-' && data[i + 3] == '-') {

	if (data_len > i + 5 && (data[i + 4] == '\r' ||
				 tmp[i + 4] == '\n')) {
	  /* End of line, header */
	  if (data_len > i + 6 && data[i + 4] == '\r' &&
	      data[i + 5] == '\n')
	    i++;
	  i += 5;
	  silc_buffer_pull(&buf, i);
	  header = TRUE;
	} else if (i > 0 && data_len > i + 5 && data[i + 4] != '-' &&
		   header) {
	  /* Start of line, footer */
	  silc_buffer_push_tail(&buf, silc_buffer_truelen(&buf) - i);
	  break;
	}
      }
    }
  }

  if (dec_base64) {
    data = silc_base64_decode(NULL, silc_buffer_data(&buf),
			      silc_buffer_len(&buf), &data_len);
    if (!data) {
      fprintf(stderr, "Error: Cannot decode Base64 encoding\n");
      return 1;
    }
    silc_buffer_set(&buf, data, data_len);
    silc_free(tmp);
  }

  asn1 = silc_asn1_alloc(NULL);

  ret = asn1_dump(asn1, &buf, 0);

  silc_asn1_free(asn1);
  silc_free(data);

  return ret;
}
示例#7
0
int main(int argc, char **argv)
{
  SilcBool success = FALSE;
  SilcMessagePayload message;
  SilcBuffer buf;
  const char *msg = "FOOBAR MESSAGE";
  unsigned char *data, tmp[1023], *tmp2;
  SilcUInt32 data_len;
  SilcUInt16 flags;
  int i, n;

  if (argc > 1 && !strcmp(argv[1], "-d")) {
    silc_log_debug(TRUE);
    silc_log_debug_hexdump(TRUE);
    silc_log_set_debug_string("*message*");
  }

  silc_cipher_register_default();
  silc_hash_register_default();
  silc_hmac_register_default();
  silc_pkcs_register_default();

  SILC_LOG_DEBUG(("Load keypair"));
  if (!silc_load_key_pair("pubkey.pub", "privkey.prv", "",
			  &public_key, &private_key)) {
    SILC_LOG_DEBUG(("Create keypair"));
    if (!silc_create_key_pair("rsa", 2048, "pubkey.pub", "privkey.prv",
			      NULL, "", &public_key, &private_key, FALSE))
      goto err;
  }

  SILC_LOG_DEBUG(("Alloc RNG"));
  rng = silc_rng_alloc();
  silc_rng_init(rng);

  SILC_LOG_DEBUG(("Alloc AES"));
  if (!silc_cipher_alloc("aes-128-cbc", &key))
    goto err;

  SILC_LOG_DEBUG(("Alloc SHA-256"));
  if (!silc_hash_alloc("sha256", &hash))
    goto err;

  SILC_LOG_DEBUG(("Alloc HMAC"));
  if (!silc_hmac_alloc("hmac-sha256-96", hash, &hmac))
    goto err;

  SILC_LOG_DEBUG(("Set static key: '1234567890123456'"));
  if (!silc_cipher_set_key(key, "1234567890123456", 16 * 8))
    goto err;
  SILC_LOG_DEBUG(("Set HMAC key: '1234567890123456'"));
  silc_hmac_set_key(hmac, "1234567890123456", 16);

  /* Simple private message */
  SILC_LOG_DEBUG(("Encoding private message len %d (static key)",
		  strlen(msg)));
  buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION |
				    SILC_MESSAGE_FLAG_UTF8 |
				    SILC_MESSAGE_FLAG_ACK,
				    msg, strlen(msg), TRUE, TRUE,
				    key, hmac, rng, NULL, NULL, NULL, NULL);
  if (!buf)
    goto err;
  SILC_LOG_HEXDUMP(("message"), buf->data, silc_buffer_len(buf));
  SILC_LOG_DEBUG(("Parsing private messsage (static key)"));
  message = silc_message_payload_parse(silc_buffer_data(buf),
				       silc_buffer_len(buf), TRUE, TRUE,
				       key, hmac, NULL, FALSE, NULL);
  if (!message)
    goto err;
  flags = silc_message_get_flags(message);
  SILC_LOG_DEBUG(("Flags: %x", flags));
  if (!(flags & SILC_MESSAGE_FLAG_ACTION))
    goto err;
  if (!(flags & SILC_MESSAGE_FLAG_UTF8))
    goto err;
  if (!(flags & SILC_MESSAGE_FLAG_ACK))
    goto err;
  data = silc_message_get_data(message, &data_len);
  SILC_LOG_HEXDUMP(("Data"), data, data_len);
  if (data_len != strlen(msg) || memcmp(data, msg, strlen(msg)))
    goto err;
  SILC_LOG_HEXDUMP(("MAC"), silc_message_get_mac(message),
		   silc_hmac_len(hmac));
  silc_message_payload_free(message);

  /* Simple private message */
  n = 10;
  SILC_LOG_DEBUG(("Encoding private message len %d (static key)", n));
  buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION |
				    SILC_MESSAGE_FLAG_UTF8 |
				    SILC_MESSAGE_FLAG_ACK,
				    msg, n, TRUE, TRUE,
				    key, hmac, rng, NULL, NULL, NULL, buf);
  if (!buf)
    goto err;
  SILC_LOG_HEXDUMP(("message"), buf->data, silc_buffer_len(buf));
  SILC_LOG_DEBUG(("Parsing private messsage (static key)"));
  message = silc_message_payload_parse(silc_buffer_data(buf),
				       silc_buffer_len(buf), TRUE, TRUE,
				       key, hmac, NULL, FALSE, NULL);
  if (!message)
    goto err;
  flags = silc_message_get_flags(message);
  SILC_LOG_DEBUG(("Flags: %x", flags));
  if (!(flags & SILC_MESSAGE_FLAG_ACTION))
    goto err;
  if (!(flags & SILC_MESSAGE_FLAG_UTF8))
    goto err;
  if (!(flags & SILC_MESSAGE_FLAG_ACK))
    goto err;
  data = silc_message_get_data(message, &data_len);
  SILC_LOG_HEXDUMP(("Data"), data, data_len);
  if (data_len != n || memcmp(data, msg, n))
    goto err;
  SILC_LOG_HEXDUMP(("MAC"), silc_message_get_mac(message),
		   silc_hmac_len(hmac));
  silc_message_payload_free(message);

  /* Simple private message */
  n = 1;
  SILC_LOG_DEBUG(("Encoding private message len %d (static key)", n));
  buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION |
				    SILC_MESSAGE_FLAG_UTF8 |
				    SILC_MESSAGE_FLAG_ACK,
				    msg, n, TRUE, TRUE,
				    key, hmac, rng, NULL, NULL, NULL, buf);
  if (!buf)
    goto err;
  SILC_LOG_HEXDUMP(("message"), buf->data, silc_buffer_len(buf));
  SILC_LOG_DEBUG(("Parsing private messsage (static key)"));
  message = silc_message_payload_parse(silc_buffer_data(buf),
				       silc_buffer_len(buf), TRUE, TRUE,
				       key, hmac, NULL, FALSE, NULL);
  if (!message)
    goto err;
  flags = silc_message_get_flags(message);
  SILC_LOG_DEBUG(("Flags: %x", flags));
  if (!(flags & SILC_MESSAGE_FLAG_ACTION))
    goto err;
  if (!(flags & SILC_MESSAGE_FLAG_UTF8))
    goto err;
  if (!(flags & SILC_MESSAGE_FLAG_ACK))
    goto err;
  data = silc_message_get_data(message, &data_len);
  SILC_LOG_HEXDUMP(("Data"), data, data_len);
  if (data_len != n || memcmp(data, msg, n))
    goto err;
  SILC_LOG_HEXDUMP(("MAC"), silc_message_get_mac(message),
		   silc_hmac_len(hmac));
  silc_message_payload_free(message);

  /* Simple private message */
  for (i = 0; i < sizeof(tmp); i++)
    tmp[i] = (32 + i) & 127;
  SILC_LOG_DEBUG(("Encoding private message len %d (static key)",
		  sizeof(tmp)));
  buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION |
				    SILC_MESSAGE_FLAG_UTF8 |
				    SILC_MESSAGE_FLAG_ACK,
				    tmp, sizeof(tmp), TRUE, TRUE,
				    key, hmac, rng, NULL, NULL, NULL, buf);
  if (!buf)
    goto err;
  SILC_LOG_HEXDUMP(("message"), buf->data, silc_buffer_len(buf));
  SILC_LOG_DEBUG(("Parsing private messsage (static key)"));
  message = silc_message_payload_parse(silc_buffer_data(buf),
				       silc_buffer_len(buf), TRUE, TRUE,
				       key, hmac, NULL, FALSE, NULL);
  if (!message)
    goto err;
  flags = silc_message_get_flags(message);
  SILC_LOG_DEBUG(("Flags: %x", flags));
  if (!(flags & SILC_MESSAGE_FLAG_ACTION))
    goto err;
  if (!(flags & SILC_MESSAGE_FLAG_UTF8))
    goto err;
  if (!(flags & SILC_MESSAGE_FLAG_ACK))
    goto err;
  data = silc_message_get_data(message, &data_len);
  SILC_LOG_HEXDUMP(("Data"), data, data_len);
  if (data_len != sizeof(tmp) || memcmp(data, tmp, sizeof(tmp)))
    goto err;
  SILC_LOG_HEXDUMP(("MAC"), silc_message_get_mac(message),
		   silc_hmac_len(hmac));
  silc_message_payload_free(message);

  /* Digitally signed private message */
  for (i = 0; i < sizeof(tmp); i++)
    tmp[i] = (32 + i) & 127;
  SILC_LOG_DEBUG(("Encoding private message len %d (static key) SIGNED",
		  sizeof(tmp)));
  buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION |
				    SILC_MESSAGE_FLAG_UTF8 |
				    SILC_MESSAGE_FLAG_ACK |
				    SILC_MESSAGE_FLAG_SIGNED,
				    tmp, sizeof(tmp), TRUE, TRUE,
				    key, hmac, rng,
				    public_key, private_key, hash, buf);
  if (!buf)
    goto err;
  SILC_LOG_HEXDUMP(("message"), buf->data, silc_buffer_len(buf));
  SILC_LOG_DEBUG(("Parsing private messsage (static key)"));
  message = silc_message_payload_parse(silc_buffer_data(buf),
				       silc_buffer_len(buf), TRUE, TRUE,
				       key, hmac, NULL, FALSE, NULL);
  if (!message)
    goto err;
  flags = silc_message_get_flags(message);
  SILC_LOG_DEBUG(("Flags: %x", flags));
  if (!(flags & SILC_MESSAGE_FLAG_ACTION))
    goto err;
  if (!(flags & SILC_MESSAGE_FLAG_UTF8))
    goto err;
  if (!(flags & SILC_MESSAGE_FLAG_ACK))
    goto err;
  if (!(flags & SILC_MESSAGE_FLAG_SIGNED))
    goto err;
  data = silc_message_get_data(message, &data_len);
  SILC_LOG_HEXDUMP(("Data"), data, data_len);
  if (data_len != sizeof(tmp) || memcmp(data, tmp, sizeof(tmp)))
    goto err;
  SILC_LOG_HEXDUMP(("MAC"), silc_message_get_mac(message),
		   silc_hmac_len(hmac));
  SILC_LOG_DEBUG(("Verifying signature"));
  if (silc_message_signed_verify(message, public_key, hash) !=
      SILC_AUTH_OK)
    goto err;
  SILC_LOG_DEBUG(("Signature Ok"));
  SILC_LOG_DEBUG(("Get public key"));
  pk2 = silc_message_signed_get_public_key(message, NULL, NULL);
  if (!pk2)
    goto err;
  SILC_LOG_DEBUG(("Verify public key"));
  if (!silc_pkcs_public_key_compare(public_key, pk2))
    goto err;
  SILC_LOG_DEBUG(("Public key Ok"));
  silc_pkcs_public_key_free(pk2);
  silc_message_payload_free(message);

  /* Digitally signed channel message */
  for (i = 0; i < sizeof(tmp) / 2; i++)
    tmp[i] = (32 + i) & 127;
  SILC_LOG_DEBUG(("Encoding channel message len %d (static key) SIGNED",
		  sizeof(tmp) / 2));
  buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION |
				    SILC_MESSAGE_FLAG_UTF8 |
				    SILC_MESSAGE_FLAG_ACK |
				    SILC_MESSAGE_FLAG_SIGNED,
				    tmp, sizeof(tmp) / 2, TRUE, FALSE,
				    key, hmac, rng,
				    public_key, private_key, hash, buf);
  if (!buf)
    goto err;
  SILC_LOG_HEXDUMP(("message"), buf->data, silc_buffer_len(buf));
  SILC_LOG_DEBUG(("Parsing channel messsage (static key)"));
  message = silc_message_payload_parse(silc_buffer_data(buf),
				       silc_buffer_len(buf), FALSE, TRUE,
				       key, hmac, NULL, FALSE, NULL);
  if (!message)
    goto err;
  flags = silc_message_get_flags(message);
  SILC_LOG_DEBUG(("Flags: %x", flags));
  if (!(flags & SILC_MESSAGE_FLAG_ACTION))
    goto err;
  if (!(flags & SILC_MESSAGE_FLAG_UTF8))
    goto err;
  if (!(flags & SILC_MESSAGE_FLAG_ACK))
    goto err;
  if (!(flags & SILC_MESSAGE_FLAG_SIGNED))
    goto err;
  data = silc_message_get_data(message, &data_len);
  SILC_LOG_HEXDUMP(("Data"), data, data_len);
  if (data_len != sizeof(tmp) / 2 || memcmp(data, tmp, sizeof(tmp) / 2))
    goto err;
  SILC_LOG_HEXDUMP(("MAC"), silc_message_get_mac(message),
		   silc_hmac_len(hmac));
  SILC_LOG_DEBUG(("Verifying signature"));
  if (silc_message_signed_verify(message, public_key, hash) !=
      SILC_AUTH_OK)
    goto err;
  SILC_LOG_DEBUG(("Signature Ok"));
  SILC_LOG_DEBUG(("Get public key"));
  pk2 = silc_message_signed_get_public_key(message, NULL, NULL);
  if (!pk2)
    goto err;
  SILC_LOG_DEBUG(("Verify public key"));
  if (!silc_pkcs_public_key_compare(public_key, pk2))
    goto err;
  SILC_LOG_DEBUG(("Public key Ok"));
  silc_pkcs_public_key_free(pk2);
  silc_message_payload_free(message);

  /* Digitally signed private message (no encryption) */
  for (i = 0; i < sizeof(tmp) / 2; i++)
    tmp[i] = (32 + i) & 127;
  SILC_LOG_DEBUG(("Encoding private message len %d SIGNED",
		  sizeof(tmp) / 2));
  buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION |
				    SILC_MESSAGE_FLAG_UTF8 |
				    SILC_MESSAGE_FLAG_ACK |
				    SILC_MESSAGE_FLAG_SIGNED,
				    tmp, sizeof(tmp) / 2, FALSE, TRUE,
				    NULL, NULL, rng,
				    public_key, private_key, hash, buf);
  if (!buf)
    goto err;
  SILC_LOG_HEXDUMP(("message"), buf->data, silc_buffer_len(buf));
  SILC_LOG_DEBUG(("Parsing private messsage (static key)"));
  message = silc_message_payload_parse(silc_buffer_data(buf),
				       silc_buffer_len(buf), TRUE, FALSE,
				       NULL, NULL, NULL, FALSE, NULL);
  if (!message)
    goto err;
  flags = silc_message_get_flags(message);
  SILC_LOG_DEBUG(("Flags: %x", flags));
  if (!(flags & SILC_MESSAGE_FLAG_ACTION))
    goto err;
  if (!(flags & SILC_MESSAGE_FLAG_UTF8))
    goto err;
  if (!(flags & SILC_MESSAGE_FLAG_ACK))
    goto err;
  if (!(flags & SILC_MESSAGE_FLAG_SIGNED))
    goto err;
  data = silc_message_get_data(message, &data_len);
  SILC_LOG_HEXDUMP(("Data"), data, data_len);
  if (data_len != sizeof(tmp) / 2 || memcmp(data, tmp, sizeof(tmp) / 2))
    goto err;
  SILC_LOG_DEBUG(("Verifying signature"));
  if (silc_message_signed_verify(message, public_key, hash) !=
      SILC_AUTH_OK)
    goto err;
  SILC_LOG_DEBUG(("Signature Ok"));
  SILC_LOG_DEBUG(("Get public key"));
  pk2 = silc_message_signed_get_public_key(message, NULL, NULL);
  if (!pk2)
    goto err;
  SILC_LOG_DEBUG(("Verify public key"));
  if (!silc_pkcs_public_key_compare(public_key, pk2))
    goto err;
  SILC_LOG_DEBUG(("Public key Ok"));
  silc_pkcs_public_key_free(pk2);
  silc_message_payload_free(message);

  /* Digitally signed channel message (LARGE) */
  n = 65550;
  tmp2 = silc_malloc(n);
  if (!tmp2)
    goto err;
  SILC_LOG_DEBUG(("Encoding channel message len %d (static key) SIGNED LARGE",
		  n));
  buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION |
				    SILC_MESSAGE_FLAG_UTF8 |
				    SILC_MESSAGE_FLAG_ACK |
				    SILC_MESSAGE_FLAG_SIGNED,
				    tmp2, n, TRUE, FALSE,
				    key, hmac, rng,
				    public_key, private_key, hash, buf);
  if (!buf)
    goto err;
  SILC_LOG_DEBUG(("Message length: %d", silc_buffer_len(buf)));
  if (silc_buffer_len(buf) > SILC_PACKET_MAX_LEN)
    goto err;
  SILC_LOG_DEBUG(("Parsing channel messsage (static key)"));
  message = silc_message_payload_parse(silc_buffer_data(buf),
				       silc_buffer_len(buf), FALSE, TRUE,
				       key, hmac, NULL, FALSE, NULL);
  if (!message)
    goto err;
  flags = silc_message_get_flags(message);
  SILC_LOG_DEBUG(("Flags: %x", flags));
  if (!(flags & SILC_MESSAGE_FLAG_ACTION))
    goto err;
  if (!(flags & SILC_MESSAGE_FLAG_UTF8))
    goto err;
  if (!(flags & SILC_MESSAGE_FLAG_ACK))
    goto err;
  if (!(flags & SILC_MESSAGE_FLAG_SIGNED))
    goto err;
  data = silc_message_get_data(message, &data_len);
  SILC_LOG_DEBUG(("Data len: %d", data_len));
  if (silc_buffer_len(buf) > SILC_PACKET_MAX_LEN)
    goto err;
  SILC_LOG_HEXDUMP(("MAC"), silc_message_get_mac(message),
		   silc_hmac_len(hmac));
  SILC_LOG_DEBUG(("Verifying signature"));
  if (silc_message_signed_verify(message, public_key, hash) !=
      SILC_AUTH_OK)
    goto err;
  SILC_LOG_DEBUG(("Signature Ok"));
  SILC_LOG_DEBUG(("Get public key"));
  pk2 = silc_message_signed_get_public_key(message, NULL, NULL);
  if (!pk2)
    goto err;
  SILC_LOG_DEBUG(("Verify public key"));
  if (!silc_pkcs_public_key_compare(public_key, pk2))
    goto err;
  SILC_LOG_DEBUG(("Public key Ok"));
  silc_pkcs_public_key_free(pk2);
  silc_message_payload_free(message);
  silc_free(tmp2);


  success = TRUE;
  SILC_LOG_DEBUG(("Cleanup"));
  silc_pkcs_public_key_free(public_key);
  silc_pkcs_private_key_free(private_key);
  silc_cipher_free(key);
  silc_hash_free(hash);
  silc_rng_free(rng);

 err:
  silc_cipher_unregister_all();
  silc_hash_unregister_all();
  silc_hmac_unregister_all();
  silc_pkcs_unregister_all();

  SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE"));
  fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE");

  return success;
}
示例#8
0
SilcBuffer silc_sftp_attr_encode(SilcSFTPAttributes attr)
{
  SilcBuffer buffer;
  int i, ret;
  SilcUInt32 len = 4;

  if (attr->flags & SILC_SFTP_ATTR_SIZE)
    len += 8;
  if (attr->flags & SILC_SFTP_ATTR_UIDGID)
    len += 8;
  if (attr->flags & SILC_SFTP_ATTR_PERMISSIONS)
    len += 4;
  if (attr->flags & SILC_SFTP_ATTR_ACMODTIME)
    len += 8;
  if (attr->flags & SILC_SFTP_ATTR_EXTENDED) {
    len += 4;
    for (i = 0; i < attr->extended_count; i++) {
      len += 8;
      len += silc_buffer_len(attr->extended_type[i]);
      len += silc_buffer_len(attr->extended_data[i]);
    }
  }

  buffer = silc_buffer_alloc_size(len);
  if (!buffer)
    return NULL;

  silc_buffer_format(buffer,
		     SILC_STR_UI_INT(attr->flags),
		     SILC_STR_END);
  silc_buffer_pull(buffer, 4);

  if (attr->flags & SILC_SFTP_ATTR_SIZE) {
    silc_buffer_format(buffer,
		       SILC_STR_UI_INT64(attr->size),
		       SILC_STR_END);
    silc_buffer_pull(buffer, 8);
  }

  if (attr->flags & SILC_SFTP_ATTR_UIDGID) {
    silc_buffer_format(buffer,
		       SILC_STR_UI_INT(attr->uid),
		       SILC_STR_UI_INT(attr->gid),
		       SILC_STR_END);
    silc_buffer_pull(buffer, 8);
  }

  if (attr->flags & SILC_SFTP_ATTR_PERMISSIONS) {
    silc_buffer_format(buffer,
		       SILC_STR_UI_INT(attr->permissions),
		       SILC_STR_END);
    silc_buffer_pull(buffer, 4);
  }

  if (attr->flags & SILC_SFTP_ATTR_ACMODTIME) {
    silc_buffer_format(buffer,
		       SILC_STR_UI_INT(attr->atime),
		       SILC_STR_UI_INT(attr->mtime),
		       SILC_STR_END);
    silc_buffer_pull(buffer, 8);
  }

  if (attr->flags & SILC_SFTP_ATTR_EXTENDED) {
    silc_buffer_format(buffer,
		       SILC_STR_UI_INT(attr->extended_count),
		       SILC_STR_END);
    silc_buffer_pull(buffer, 4);

    for (i = 0; i < attr->extended_count; i++) {
      ret =
	silc_buffer_format(
		   buffer,
		   SILC_STR_UI_INT(silc_buffer_len(attr->extended_type[i])),
		   SILC_STR_DATA(silc_buffer_data(attr->extended_type[i]),
				 silc_buffer_len(attr->extended_type[i])),
		   SILC_STR_UI_INT(silc_buffer_len(attr->extended_data[i])),
		   SILC_STR_DATA(silc_buffer_data(attr->extended_data[i]),
				 silc_buffer_len(attr->extended_data[i])),
		   SILC_STR_END);
      silc_buffer_pull(buffer, ret);
    }
  }

  silc_buffer_push(buffer, buffer->data - buffer->head);

  return buffer;
}
示例#9
0
static void silc_pkcs_ssh_sign_cb(SilcBool success,
				  const unsigned char *signature,
				  SilcUInt32 signature_len,
				  void *context)
{
  SilcSshSign sign = context;
  SilcStack stack = sign->stack;
  unsigned char rbuf[20], sbuf[20];
  SilcBufferStruct sig;
  SilcAsn1 asn1;
  SilcMPInt r, s;

  memset(&sig, 0, sizeof(sig));

  /* Format the signature.  RSA is easy because PKCS#1 is already in
     correct format.  For DSA the returned signature is in PKIX compliant
     format and we have to reformat it for SSH2. */
  if (!strcmp(sign->privkey->pkcs->name, "dsa")) {
    asn1 = silc_asn1_alloc(stack);
    if (!asn1) {
      sign->sign_cb(FALSE, NULL, 0, sign->context);
      silc_sfree(stack, sign);
      silc_stack_free(stack);
      return;
    }

    /* Decode the signature */
    silc_buffer_set(&sig, (unsigned char *)signature, signature_len);
    if (!silc_asn1_decode(asn1, &sig,
			  SILC_ASN1_SEQUENCE,
			    SILC_ASN1_INT(&r),
			    SILC_ASN1_INT(&s),
			  SILC_ASN1_END, SILC_ASN1_END)) {
      sign->sign_cb(FALSE, NULL, 0, sign->context);
      silc_asn1_free(asn1);
      silc_sfree(stack, sign);
      silc_stack_free(stack);
      return;
    }

    /* Encode the integers */
    memset(rbuf, 0, sizeof(rbuf));
    memset(sbuf, 0, sizeof(sbuf));
    silc_mp_mp2bin_noalloc(&r, rbuf, sizeof(rbuf));
    silc_mp_mp2bin_noalloc(&s, sbuf, sizeof(sbuf));

    silc_asn1_free(asn1);

    /* Encode SSH2 DSS signature */
    if (silc_buffer_sformat(stack, &sig,
			    SILC_STR_UI_INT(7),
			    SILC_STR_UI32_STRING("ssh-dss"),
			    SILC_STR_UI_INT(sizeof(rbuf) + sizeof(sbuf)),
			    SILC_STR_DATA(rbuf, sizeof(rbuf)),
			    SILC_STR_DATA(sbuf, sizeof(sbuf)),
			    SILC_STR_END) < 0) {
      sign->sign_cb(FALSE, NULL, 0, sign->context);
      silc_sfree(stack, sign);
      silc_stack_free(stack);
      return;
    }
  } else {
    /* Encode SSH2 RSA signature */
    if (silc_buffer_sformat(stack, &sig,
			    SILC_STR_UI_INT(7),
			    SILC_STR_UI32_STRING("ssh-rsa"),
			    SILC_STR_UI_INT(signature_len),
			    SILC_STR_DATA(signature, signature_len),
			    SILC_STR_END) < 0) {
      sign->sign_cb(FALSE, NULL, 0, sign->context);
      silc_sfree(stack, sign);
      silc_stack_free(stack);
      return;
    }
  }

  /* Deliver result */
  sign->sign_cb(TRUE, silc_buffer_data(&sig), silc_buffer_len(&sig),
		sign->context);

  silc_buffer_spurge(stack, &sig);
  silc_sfree(stack, sign);
  silc_stack_free(stack);
}
示例#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);
  }
}
示例#11
0
SilcBuffer silc_client_attributes_process(SilcClient client,
					  SilcClientConnection conn,
					  SilcDList attrs)
{
  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"));

  /* If nothing is set by application assume that we don't want to use
     attributes, ignore the request. */
  if (!conn->internal->attrs) {
    SILC_LOG_DEBUG(("User has not set any attributes"));
    return NULL;
  }

  /* Always put our public key. */
  pk.type = "silc-rsa";
  pk.data = silc_pkcs_public_key_encode(conn->public_key, &pk.data_len);
  buffer = silc_attribute_payload_encode(buffer,
					 SILC_ATTRIBUTE_USER_PUBLIC_KEY,
					 pk.data ? SILC_ATTRIBUTE_FLAG_VALID :
					 SILC_ATTRIBUTE_FLAG_INVALID,
					 &pk, sizeof(pk));
  silc_free(pk.data);

  /* Go through all requested attributes */
  f.buffer = buffer;
  silc_dlist_start(attrs);
  while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) {
    /* Put all attributes of this type */
    attribute = silc_attribute_get_attribute(attr);

    /* Ignore signature since we will compute it later */
    if (attribute == SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE)
      continue;

    silc_hash_table_find_foreach(conn->internal->attrs,
				 SILC_32_TO_PTR(attribute),
				 silc_client_attributes_process_foreach,
				 &f);
  }
  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));
  }

  return buffer;
}
示例#12
0
SilcBool silc_client_save_channel_key(SilcClient client,
				      SilcClientConnection conn,
				      SilcBuffer key_payload,
				      SilcChannelEntry channel)
{
  unsigned char *id_string, *key, *cipher, *hmac, hash[SILC_HASH_MAXLEN];
  SilcUInt32 tmp_len;
  SilcChannelID id;
  SilcChannelKeyPayload payload;

  SILC_LOG_DEBUG(("New channel key"));

  payload = silc_channel_key_payload_parse(silc_buffer_data(key_payload),
					   silc_buffer_len(key_payload));
  if (!payload)
    return FALSE;

  id_string = silc_channel_key_get_id(payload, &tmp_len);
  if (!id_string) {
    silc_channel_key_payload_free(payload);
    return FALSE;
  }

  if (!silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL, &id, sizeof(id))) {
    silc_channel_key_payload_free(payload);
    return FALSE;
  }

  /* Find channel. */
  if (!channel) {
    channel = silc_client_get_channel_by_id(client, conn, &id);
    if (!channel) {
      SILC_LOG_DEBUG(("Key for unknown channel"));
      silc_channel_key_payload_free(payload);
      return FALSE;
    }
  } else {
    silc_client_ref_channel(client, conn, channel);
  }

  /* Save the old key for a short period of time so that we can decrypt
     channel message even after the rekey if some client would be sending
     messages with the old key after the rekey. */
  if (!channel->internal.old_channel_keys)
    channel->internal.old_channel_keys = silc_dlist_init();
  if (!channel->internal.old_hmacs)
    channel->internal.old_hmacs = silc_dlist_init();
  if (channel->internal.old_channel_keys && channel->internal.old_hmacs) {
    silc_dlist_add(channel->internal.old_channel_keys,
		   channel->internal.receive_key);
    silc_dlist_add(channel->internal.old_hmacs, channel->internal.hmac);
    silc_schedule_task_add_timeout(client->schedule,
				   silc_client_save_channel_key_rekey,
				   channel, 15, 0);
  }

  /* Get channel cipher */
  cipher = silc_channel_key_get_cipher(payload, NULL);
  if (!silc_cipher_alloc(cipher, &channel->internal.send_key)) {
    client->internal->ops->say(
			   conn->client, conn,
			   SILC_CLIENT_MESSAGE_AUDIT,
			   "Cannot talk to channel: unsupported cipher %s",
			   cipher);
    silc_client_unref_channel(client, conn, channel);
    silc_channel_key_payload_free(payload);
    return FALSE;
  }
  if (!silc_cipher_alloc(cipher, &channel->internal.receive_key)) {
    client->internal->ops->say(
			   conn->client, conn,
			   SILC_CLIENT_MESSAGE_AUDIT,
			   "Cannot talk to channel: unsupported cipher %s",
			   cipher);
    silc_client_unref_channel(client, conn, channel);
    silc_channel_key_payload_free(payload);
    return FALSE;
  }

  /* Set the cipher key.  Both sending and receiving keys are same */
  key = silc_channel_key_get_key(payload, &tmp_len);
  silc_cipher_set_key(channel->internal.send_key, key, tmp_len * 8, TRUE);
  silc_cipher_set_key(channel->internal.receive_key, key, tmp_len * 8, FALSE);

  /* Get channel HMAC */
  hmac = (channel->internal.hmac ?
	  (char *)silc_hmac_get_name(channel->internal.hmac) :
	  SILC_DEFAULT_HMAC);
  if (!silc_hmac_alloc(hmac, NULL, &channel->internal.hmac)) {
    client->internal->ops->say(
			   conn->client, conn,
			   SILC_CLIENT_MESSAGE_AUDIT,
			   "Cannot talk to channel: unsupported HMAC %s",
			   hmac);
    silc_client_unref_channel(client, conn, channel);
    silc_channel_key_payload_free(payload);
    return FALSE;
  }

  channel->cipher = silc_cipher_get_name(channel->internal.send_key);
  channel->hmac = silc_hmac_get_name(channel->internal.hmac);

  /* Set HMAC key */
  silc_hash_make(silc_hmac_get_hash(channel->internal.hmac), key,
		 tmp_len, hash);
  silc_hmac_set_key(channel->internal.hmac, hash,
		    silc_hash_len(silc_hmac_get_hash(channel->internal.hmac)));
  memset(hash, 0, sizeof(hash));
  silc_channel_key_payload_free(payload);

  silc_client_unref_channel(client, conn, channel);

  return TRUE;
}
示例#13
0
SilcBool silc_pkcs1_verify(void *public_key,
			   unsigned char *signature,
			   SilcUInt32 signature_len,
			   unsigned char *data,
			   SilcUInt32 data_len,
			   SilcHash hash)
{
  RsaPublicKey *key = public_key;
  SilcBool ret = FALSE;
  SilcMPInt mp_tmp2;
  SilcMPInt mp_dst;
  unsigned char *verify, unpadded[2048 + 1], hashr[SILC_HASH_MAXLEN];
  SilcUInt32 verify_len, len = (key->bits + 7) / 8;
  SilcBufferStruct di, ldi;
  SilcHash ihash = NULL;
  SilcAsn1 asn1 = NULL;
  char *oid;

  SILC_LOG_DEBUG(("Verify signature"));

  asn1 = silc_asn1_alloc();
  if (!asn1)
    return FALSE;

  silc_mp_init(&mp_tmp2);
  silc_mp_init(&mp_dst);

  /* Format the signature into MP int */
  silc_mp_bin2mp(signature, signature_len, &mp_tmp2);

  /* Verify */
  silc_rsa_public_operation(key, &mp_tmp2, &mp_dst);

  /* MP to data */
  verify = silc_mp_mp2bin(&mp_dst, len, &verify_len);

  /* Unpad data */
  if (!silc_pkcs1_decode(SILC_PKCS1_BT_PRV1, verify, verify_len,
			 unpadded, sizeof(unpadded), &len))
    goto err;
  silc_buffer_set(&di, unpadded, len);

  /* If hash isn't given, allocate the one given in digest info */
  if (!hash) {
    /* Decode digest info */
    if (!silc_asn1_decode(asn1, &di,
			  SILC_ASN1_OPTS(SILC_ASN1_ACCUMUL),
			  SILC_ASN1_SEQUENCE,
			    SILC_ASN1_SEQUENCE,
			      SILC_ASN1_OID(&oid),
			    SILC_ASN1_END,
			  SILC_ASN1_END, SILC_ASN1_END))
      goto err;

    if (!silc_hash_alloc_by_oid(oid, &ihash)) {
      SILC_LOG_DEBUG(("Unknown OID %s", oid));
      goto err;
    }
    hash = ihash;
  }

  /* Hash the data */
  silc_hash_make(hash, data, data_len, hashr);
  data = hashr;
  data_len = silc_hash_len(hash);
  oid = (char *)silc_hash_get_oid(hash);

  /* Encode digest info for comparison */
  memset(&ldi, 0, sizeof(ldi));
  if (!silc_asn1_encode(asn1, &ldi,
			SILC_ASN1_OPTS(SILC_ASN1_ACCUMUL),
			SILC_ASN1_SEQUENCE,
			  SILC_ASN1_SEQUENCE,
			    SILC_ASN1_OID(oid),
			    SILC_ASN1_NULL,
			  SILC_ASN1_END,
			  SILC_ASN1_OCTET_STRING(data, data_len),
			SILC_ASN1_END, SILC_ASN1_END))
    goto err;

  SILC_LOG_HEXDUMP(("DigestInfo remote"), silc_buffer_data(&di),
		   silc_buffer_len(&di));
  SILC_LOG_HEXDUMP(("DigestInfo local"), silc_buffer_data(&ldi),
		   silc_buffer_len(&ldi));

  /* Compare */
  if (silc_buffer_len(&di) == silc_buffer_len(&ldi) &&
      !memcmp(silc_buffer_data(&di), silc_buffer_data(&ldi),
	      silc_buffer_len(&ldi)))
    ret = TRUE;

  memset(verify, 0, verify_len);
  memset(unpadded, 0, sizeof(unpadded));
  silc_free(verify);
  silc_mp_uninit(&mp_tmp2);
  silc_mp_uninit(&mp_dst);
  if (hash)
    memset(hashr, 0, sizeof(hashr));
  if (ihash)
    silc_hash_free(ihash);
  silc_asn1_free(asn1);

  return ret;

 err:
  memset(verify, 0, verify_len);
  silc_free(verify);
  silc_mp_uninit(&mp_tmp2);
  silc_mp_uninit(&mp_dst);
  if (ihash)
    silc_hash_free(ihash);
  silc_asn1_free(asn1);
  return FALSE;
}
示例#14
0
SilcBool silc_pkcs1_sign(void *private_key,
			 unsigned char *src,
			 SilcUInt32 src_len,
			 unsigned char *signature,
			 SilcUInt32 signature_size,
			 SilcUInt32 *ret_signature_len,
			 SilcBool compute_hash,
			 SilcHash hash)
{
  RsaPrivateKey *key = private_key;
  unsigned char padded[2048 + 1], hashr[SILC_HASH_MAXLEN];
  SilcMPInt mp_tmp;
  SilcMPInt mp_dst;
  SilcBufferStruct di;
  SilcUInt32 len = (key->bits + 7) / 8;
  const char *oid;
  SilcAsn1 asn1;

  SILC_LOG_DEBUG(("Sign"));

  if (sizeof(padded) < len)
    return FALSE;
  if (signature_size < len)
    return FALSE;

  oid = silc_hash_get_oid(hash);
  if (!oid)
    return FALSE;

  asn1 = silc_asn1_alloc();
  if (!asn1)
    return FALSE;

  /* Compute hash */
  if (compute_hash) {
    silc_hash_make(hash, src, src_len, hashr);
    src = hashr;
    src_len = silc_hash_len(hash);
  }

  /* Encode digest info */
  memset(&di, 0, sizeof(di));
  if (!silc_asn1_encode(asn1, &di,
			SILC_ASN1_SEQUENCE,
			  SILC_ASN1_SEQUENCE,
			    SILC_ASN1_OID(oid),
			    SILC_ASN1_NULL,
			  SILC_ASN1_END,
			  SILC_ASN1_OCTET_STRING(src, src_len),
			SILC_ASN1_END, SILC_ASN1_END)) {
    silc_asn1_free(asn1);
    return FALSE;
  }
  SILC_LOG_HEXDUMP(("DigestInfo"), silc_buffer_data(&di),
		   silc_buffer_len(&di));

  /* Pad data */
  if (!silc_pkcs1_encode(SILC_PKCS1_BT_PRV1, silc_buffer_data(&di),
			 silc_buffer_len(&di), padded, len, NULL)) {
    silc_asn1_free(asn1);
    return FALSE;
  }

  silc_mp_init(&mp_tmp);
  silc_mp_init(&mp_dst);

  /* Data to MP */
  silc_mp_bin2mp(padded, len, &mp_tmp);

  /* Sign */
  silc_rsa_private_operation(key, &mp_tmp, &mp_dst);

  /* MP to data */
  silc_mp_mp2bin_noalloc(&mp_dst, signature, len);
  *ret_signature_len = len;

  memset(padded, 0, sizeof(padded));
  silc_mp_uninit(&mp_tmp);
  silc_mp_uninit(&mp_dst);
  if (compute_hash)
    memset(hashr, 0, sizeof(hashr));
  silc_asn1_free(asn1);

  return TRUE;
}
示例#15
0
SilcClientFileError
silc_client_file_send(SilcClient client,
		      SilcClientConnection conn,
		      SilcClientEntry client_entry,
		      SilcClientConnectionParams *params,
		      SilcPublicKey public_key,
		      SilcPrivateKey private_key,
		      SilcClientFileMonitor monitor,
		      void *monitor_context,
		      const char *filepath,
		      SilcUInt32 *session_id)
{
  SilcClientFtpSession session;
  SilcBuffer keyagr;
  char *filename, *path;
  int fd;

  SILC_LOG_DEBUG(("File send request (file: %s)", filepath));

  if (!client || !client_entry || !filepath || !params ||
      !public_key || !private_key)
    return SILC_CLIENT_FILE_ERROR;

  /* Check for existing session for `filepath'. */
  silc_dlist_start(client->internal->ftp_sessions);
  while ((session = silc_dlist_get(client->internal->ftp_sessions))) {
    if (session->filepath && !strcmp(session->filepath, filepath) &&
	session->client_entry == client_entry)
      return SILC_CLIENT_FILE_ALREADY_STARTED;
  }

  /* See whether the file exists and can be opened */
  fd = silc_file_open(filepath, O_RDONLY);
  if (fd < 0)
    return SILC_CLIENT_FILE_NO_SUCH_FILE;
  silc_file_close(fd);

  /* Add new session */
  session = silc_calloc(1, sizeof(*session));
  if (!session)
    return SILC_CLIENT_FILE_ERROR;
  session->session_id = ++client->internal->next_session_id;
  session->client = client;
  session->server_conn = conn;
  session->initiator = TRUE;
  session->client_entry = silc_client_ref_client(client, conn, client_entry);
  session->monitor = monitor;
  session->monitor_context = monitor_context;
  session->filepath = strdup(filepath);
  session->params = *params;
  session->public_key = public_key;
  session->private_key = private_key;

  if (silc_asprintf(&path, "file://%s", filepath) < 0) {
    silc_free(session);
    return SILC_CLIENT_FILE_NO_MEMORY;
  }

  /* Allocate memory filesystem and put the file to it */
  if (strrchr(path, '/'))
    filename = strrchr(path, '/') + 1;
  else
    filename = (char *)path;
  session->fs = silc_sftp_fs_memory_alloc(SILC_SFTP_FS_PERM_READ |
					  SILC_SFTP_FS_PERM_EXEC);
  silc_sftp_fs_memory_add_file(session->fs, NULL, SILC_SFTP_FS_PERM_READ,
			       filename, path);

  session->filesize = silc_file_size(filepath);

  /* If local IP is provided, create listener for incoming key exchange */
  if (params->local_ip || params->bind_ip) {
    session->listener =
      silc_client_listener_add(client,
			       conn->internal->schedule,
			       params, public_key, private_key,
			       silc_client_ftp_connect_completion,
			       session);
    if (!session->listener) {
      client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
				 "Cannot create listener for file transfer: "
				 "%s", strerror(errno));
      silc_free(session);
      return SILC_CLIENT_FILE_NO_MEMORY;
    }

    session->hostname = (params->bind_ip ? strdup(params->bind_ip) :
			 strdup(params->local_ip));
    session->port = silc_client_listener_get_local_port(session->listener);
  }

  SILC_LOG_DEBUG(("Sending key agreement for file transfer"));

  /* Send the key agreement inside FTP packet */
  keyagr = silc_key_agreement_payload_encode(session->hostname, 0,
					     session->port);
  if (!keyagr) {
    if (session->listener)
      silc_client_listener_free(session->listener);
    silc_free(session);
    return SILC_CLIENT_FILE_NO_MEMORY;
  }
  silc_packet_send_va_ext(conn->stream, SILC_PACKET_FTP, 0, 0, NULL,
			  SILC_ID_CLIENT, &client_entry->id, NULL, NULL,
			  SILC_STR_UI_CHAR(1),
			  SILC_STR_DATA(silc_buffer_data(keyagr),
					silc_buffer_len(keyagr)),
			  SILC_STR_END);

  silc_buffer_free(keyagr);
  silc_free(path);

  silc_dlist_add(client->internal->ftp_sessions, session);
  if (session_id)
    *session_id = session->session_id;

  /* Add session request timeout */
  if (params && params->timeout_secs)
    silc_schedule_task_add_timeout(client->schedule,
				   silc_client_ftp_timeout, session,
				   params->timeout_secs, 0);

  return SILC_CLIENT_FILE_OK;
}
示例#16
0
SilcClientFileError
silc_client_file_receive(SilcClient client,
			 SilcClientConnection conn,
			 SilcClientConnectionParams *params,
			 SilcPublicKey public_key,
			 SilcPrivateKey private_key,
			 SilcClientFileMonitor monitor,
			 void *monitor_context,
			 const char *path,
			 SilcUInt32 session_id,
			 SilcClientFileAskName ask_name,
			 void *ask_name_context)
{
  SilcClientFtpSession session;
  SilcBuffer keyagr;

  if (!client || !conn)
    return SILC_CLIENT_FILE_ERROR;

  SILC_LOG_DEBUG(("Start, Session ID: %d", session_id));

  /* Get the session */
  silc_dlist_start(client->internal->ftp_sessions);
  while ((session = silc_dlist_get(client->internal->ftp_sessions))
	 != SILC_LIST_END) {
    if (session->session_id == session_id) {
      break;
    }
  }

  if (session == SILC_LIST_END) {
    SILC_LOG_DEBUG(("Unknown session ID: %d\n", session_id));
    return SILC_CLIENT_FILE_UNKNOWN_SESSION;
  }

  /* See if we have this session running already */
  if (session->sftp || session->listener) {
    SILC_LOG_DEBUG(("Session already started"));
    return SILC_CLIENT_FILE_ALREADY_STARTED;
  }

  session->monitor = monitor;
  session->monitor_context = monitor_context;
  session->ask_name = ask_name;
  session->ask_name_context = ask_name_context;
  session->path = path ? strdup(path) : NULL;

  /* If the hostname and port already exists then the remote client did
     provide the connection point to us and we won't create listener, but
     create the connection ourselves. */
  if (session->hostname && session->port) {
    SILC_LOG_DEBUG(("Connecting to remote client"));
    /* Connect to the remote client.  Performs key exchange automatically. */
    session->op =
      silc_client_connect_to_client(client, params, public_key, private_key,
				    session->hostname, session->port,
				    silc_client_ftp_connect_completion,
				    session);
    if (!session->op) {
      silc_free(session);
      return SILC_CLIENT_FILE_ERROR;
    }
  } else {
    /* Add the listener for the key agreement */
    SILC_LOG_DEBUG(("Creating listener for file transfer"));
    if (!params || (!params->local_ip && !params->bind_ip)) {
      session->client->internal->ops->say(session->client, session->conn,
					  SILC_CLIENT_MESSAGE_ERROR,
					  "Cannot create listener for file "
					  "transfer; IP address and/or port "
					  "not provided");
      silc_free(session);
      return SILC_CLIENT_FILE_ERROR;
    }
    session->listener =
      silc_client_listener_add(client, conn->internal->schedule, params,
			       public_key, private_key,
			       silc_client_ftp_connect_completion,
			       session);
    if (!session->listener) {
      client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
				 "Cannot create listener for file transfer: "
				 "%s", strerror(errno));
      silc_free(session);
      return SILC_CLIENT_FILE_NO_MEMORY;
    }
    session->hostname = (params->bind_ip ? strdup(params->bind_ip) :
			 strdup(params->local_ip));
    session->port = silc_client_listener_get_local_port(session->listener);

    /* Send the key agreement inside FTP packet */
    SILC_LOG_DEBUG(("Sending key agreement for file transfer"));
    keyagr = silc_key_agreement_payload_encode(session->hostname, 0,
					       session->port);
    if (!keyagr) {
      silc_client_listener_free(session->listener);
      silc_free(session);
      return SILC_CLIENT_FILE_NO_MEMORY;
    }
    silc_packet_send_va_ext(conn->stream, SILC_PACKET_FTP, 0, 0, NULL,
			    SILC_ID_CLIENT, &session->client_entry->id,
			    NULL, NULL,
			    SILC_STR_UI_CHAR(1),
			    SILC_STR_DATA(silc_buffer_data(keyagr),
					  silc_buffer_len(keyagr)),
			    SILC_STR_END);
    silc_buffer_free(keyagr);

    /* Add session request timeout */
    if (params && params->timeout_secs)
      silc_schedule_task_add_timeout(client->schedule,
				     silc_client_ftp_timeout, session,
				     params->timeout_secs, 0);
  }

  return SILC_CLIENT_FILE_OK;
}
示例#17
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;
}