Esempio n. 1
0
SilcBuffer silc_attribute_payload_encode_data(SilcBuffer attrs,
					      SilcAttribute attribute,
					      SilcAttributeFlags flags,
					      const unsigned char *data,
					      SilcUInt32 data_len)
{
  SilcBuffer buffer = attrs;
  SilcUInt32 len;

  len = 4 + (SilcUInt16)data_len;
  buffer = silc_buffer_realloc(buffer,
			       (buffer ? silc_buffer_truelen(buffer) +
				len : len));
  if (!buffer)
    return NULL;
  silc_buffer_pull(buffer, silc_buffer_len(buffer));
  silc_buffer_pull_tail(buffer, len);
  silc_buffer_format(buffer,
		     SILC_STR_UI_CHAR(attribute),
		     SILC_STR_UI_CHAR(flags),
		     SILC_STR_UI_SHORT((SilcUInt16)data_len),
		     SILC_STR_UI_XNSTRING(data, (SilcUInt16)data_len),
		     SILC_STR_END);
  silc_buffer_push(buffer, buffer->data - buffer->head);

  return buffer;
}
Esempio n. 2
0
SilcBuffer silc_sftp_packet_encode_vp(SilcSFTPPacket packet,
				      SilcBuffer packet_buf, SilcUInt32 len,
				      va_list vp)
{
  SilcBuffer buffer;
  bool dyn;
  int ret;

  if (packet_buf) {
    if (silc_buffer_truelen(packet_buf) < 4 + 1 + len) {
      packet_buf = silc_buffer_realloc(packet_buf, 4 + 1 + len);
      if (!packet_buf)
	return NULL;
    }

    buffer = packet_buf;
    dyn = FALSE;
  } else {
    buffer = silc_buffer_alloc(4 + 1 + len);
    if (!buffer)
      return NULL;
    dyn = TRUE;
  }

  silc_buffer_pull_tail(buffer, 4 + 1 + len);
  silc_buffer_format(buffer,
		     SILC_STR_UI_INT(len),
		     SILC_STR_UI_CHAR(packet),
		     SILC_STR_END);
  silc_buffer_pull(buffer, 5);

  ret = silc_buffer_format_vp(buffer, vp);
  if (ret < 0) {
    if (dyn)
      silc_buffer_free(buffer);
    return NULL;
  }

  silc_buffer_push(buffer, 5);

  return buffer;
}
Esempio n. 3
0
unsigned char *silc_mime_encode(SilcMime mime, SilcUInt32 *encoded_len)
{
    SilcMime part;
    SilcHashTableList htl;
    SilcBufferStruct buf;
    SilcBuffer buffer;
    char *field, *value, tmp[1024], tmp2[4];
    unsigned char *ret;
    int i;

    SILC_LOG_DEBUG(("Encoding MIME message"));

    if (!mime)
        return NULL;

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

    /* Encode the headers. Order doesn't matter */
    i = 0;
    silc_hash_table_list(mime->fields, &htl);
    while (silc_hash_table_get(&htl, (void *)&field, (void *)&value)) {
        memset(tmp, 0, sizeof(tmp));
        SILC_LOG_DEBUG(("Header %s: %s", field, value));
        silc_snprintf(tmp, sizeof(tmp) - 1, "%s: %s\r\n", field, value);
        silc_buffer_strformat(&buf, tmp, SILC_STRFMT_END);
        i++;
    }
    silc_hash_table_list_reset(&htl);
    if (i)
        silc_buffer_strformat(&buf, "\r\n", SILC_STRFMT_END);

    /* Assemble the whole buffer */
    buffer = silc_buffer_alloc_size(mime->data_len + silc_buffer_len(&buf));
    if (!buffer)
        return NULL;

    /* Add headers */
    if (silc_buffer_len(&buf)) {
        silc_buffer_put(buffer, buf.head, silc_buffer_len(&buf));
        silc_buffer_pull(buffer, silc_buffer_len(&buf));
        silc_buffer_purge(&buf);
    }

    /* Add data */
    if (mime->data) {
        SILC_LOG_DEBUG(("Data len %d", mime->data_len));
        silc_buffer_put(buffer, mime->data, mime->data_len);
    }

    /* Add multiparts */
    if (mime->multiparts) {
        SILC_LOG_DEBUG(("Encoding multiparts"));

        silc_dlist_start(mime->multiparts);
        i = 0;
        while ((part = silc_dlist_get(mime->multiparts)) != SILC_LIST_END) {
            unsigned char *pd;
            SilcUInt32 pd_len;

            /* Recursive encoding */
            pd = silc_mime_encode(part, &pd_len);
            if (!pd)
                return NULL;

            memset(tmp, 0, sizeof(tmp));
            memset(tmp2, 0, sizeof(tmp2));

            /* If fields are not present, add extra CRLF */
            if (!silc_hash_table_count(part->fields))
                silc_snprintf(tmp2, sizeof(tmp2) - 1, "\r\n");
            silc_snprintf(tmp, sizeof(tmp) - 1, "%s--%s\r\n%s",
                          i != 0 ? "\r\n" : "", mime->boundary, tmp2);
            i = 1;

            buffer = silc_buffer_realloc(buffer, silc_buffer_truelen(buffer) +
                                         pd_len + strlen(tmp));
            if (!buffer)
                return NULL;
            silc_buffer_put_tail(buffer, tmp, strlen(tmp));
            silc_buffer_pull_tail(buffer, strlen(tmp));
            silc_buffer_put_tail(buffer, pd, pd_len);
            silc_buffer_pull_tail(buffer, pd_len);
            silc_free(pd);
        }

        memset(tmp, 0, sizeof(tmp));
        silc_snprintf(tmp, sizeof(tmp) - 1, "\r\n--%s--\r\n", mime->boundary);
        buffer = silc_buffer_realloc(buffer, silc_buffer_truelen(buffer) +
                                     strlen(tmp));
        if (!buffer)
            return NULL;
        silc_buffer_put_tail(buffer, tmp, strlen(tmp));
        silc_buffer_pull_tail(buffer, strlen(tmp));
    }

    ret = silc_buffer_steal(buffer, encoded_len);
    silc_buffer_free(buffer);

    return ret;
}
Esempio n. 4
0
SilcMime silc_mime_assemble(SilcMimeAssembler assembler, SilcMime partial)
{
    char *type, *id = NULL, *tmp;
    SilcHashTable f;
    SilcMime p, complete;
    int i, number, total = -1;
    const unsigned char *data;
    SilcUInt32 data_len;
    SilcBuffer compbuf = NULL;

    SILC_LOG_DEBUG(("Assembling MIME fragments"));

    if (!assembler || !partial)
        goto err;

    type = (char *)silc_mime_get_field(partial, "Content-Type");
    if (!type)
        goto err;

    /* Get ID */
    tmp = strstr(type, "id=");
    if (!tmp)
        goto err;
    if (strlen(tmp) <= 4)
        goto err;
    tmp += 3;
    if (*tmp == '"')
        tmp++;
    id = strdup(tmp);
    if (strchr(id, ';'))
        *strchr(id, ';') = '\0';
    if (strrchr(id, '"'))
        *strrchr(id, '"') = '\0';

    SILC_LOG_DEBUG(("Fragment ID %s", id));

    /* Get fragment number */
    tmp = strstr(type, "number=");
    if (!tmp)
        goto err;
    tmp = strchr(tmp, '=');
    if (strlen(tmp) < 2)
        goto err;
    tmp++;
    if (strchr(tmp, ';')) {
        tmp = strdup(tmp);
        *strchr(tmp, ';') = '\0';
        number = atoi(tmp);
        silc_free(tmp);
    } else {
        number = atoi(tmp);
    }

    SILC_LOG_DEBUG(("Fragment number %d", number));

    /* Find fragments with this ID. */
    if (!silc_hash_table_find(assembler->fragments, (void *)id,
                              NULL, (void *)&f)) {
        /* This is new fragment to new message.  Add to hash table and return. */
        f = silc_hash_table_alloc(0, silc_hash_uint, NULL, NULL, NULL,
                                  silc_mime_assemble_dest, NULL, TRUE);
        if (!f)
            goto err;
        silc_hash_table_add(f, SILC_32_TO_PTR(number), partial);
        silc_hash_table_add(assembler->fragments, id, f);
        return NULL;
    }

    /* Try to get total number */
    tmp = strstr(type, "total=");
    if (tmp) {
        tmp = strchr(tmp, '=');
        if (strlen(tmp) < 2)
            goto err;
        tmp++;
        if (strchr(tmp, ';')) {
            tmp = strdup(tmp);
            *strchr(tmp, ';') = '\0';
            total = atoi(tmp);
            silc_free(tmp);
        } else {
            total = atoi(tmp);
        }

        SILC_LOG_DEBUG(("Fragment total %d", total));
    }

    /* If more fragments to come, add to hash table */
    if (number != total) {
        silc_hash_table_add(f, SILC_32_TO_PTR(number), partial);
        return NULL;
    }

    silc_hash_table_add(f, SILC_32_TO_PTR(number), partial);

    /* Verify that we really have all the fragments */
    if (silc_hash_table_count(f) < total)
        return NULL;

    /* Assemble the complete MIME message now. We get them in order from
       the hash table. */
    for (i = 1; i <= total; i++) {
        if (!silc_hash_table_find(f, SILC_32_TO_PTR(i), NULL, (void *)&p))
            goto err;

        /* The fragment is in the data portion of the partial message */
        data = silc_mime_get_data(p, &data_len);
        if (!data)
            goto err;

        /* Assemble */
        if (!compbuf) {
            compbuf = silc_buffer_alloc_size(data_len);
            if (!compbuf)
                goto err;
            silc_buffer_put(compbuf, data, data_len);
        } else {
            compbuf = silc_buffer_realloc(compbuf, silc_buffer_truelen(compbuf) +
                                          data_len);
            if (!compbuf)
                goto err;
            silc_buffer_put_tail(compbuf, data, data_len);
            silc_buffer_pull_tail(compbuf, data_len);
        }
    }

    /* Now parse the complete MIME message and deliver it */
    complete = silc_mime_decode(NULL, (const unsigned char *)compbuf->head,
                                silc_buffer_truelen(compbuf));
    if (!complete)
        goto err;

    /* Delete the hash table entry. Destructors will free memory */
    silc_hash_table_del(assembler->fragments, (void *)id);
    silc_free(id);
    silc_buffer_free(compbuf);

    return complete;

err:
    silc_free(id);
    if (compbuf)
        silc_buffer_free(compbuf);
    silc_mime_free(partial);
    return NULL;
}
Esempio n. 5
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);
  }
}