예제 #1
0
SilcBool silc_client_attribute_del(SilcClient client,
				   SilcClientConnection conn,
				   SilcAttribute attribute,
				   SilcAttributePayload attr)
{
  SilcBool ret;

  if (!conn->internal->attrs)
    return FALSE;

  if (attr) {
    attribute = silc_attribute_get_attribute(attr);
    ret = silc_hash_table_del_by_context(conn->internal->attrs,
					 SILC_32_TO_PTR(attribute), attr);
  } else if (attribute) {
    silc_hash_table_find_foreach(conn->internal->attrs,
				 SILC_32_TO_PTR(attribute),
				 silc_client_attribute_del_foreach, conn);
    ret = TRUE;
  } else{
    return FALSE;
  }

  if (ret)
    if (!silc_hash_table_count(conn->internal->attrs)) {
      silc_hash_table_free(conn->internal->attrs);
      conn->internal->attrs = NULL;
    }

  return ret;
}
예제 #2
0
SilcServerPending silc_server_command_pending_get(SilcServerThread thread,
						  SilcUInt16 cmd_ident)
{
  SilcServerPending pending = NULL;

  silc_mutex_lock(thread->server->lock);
  silc_hash_table_find(thread->server->pending_commands,
		       SILC_32_TO_PTR(cmd_ident), NULL, (void **)&pending);
  silc_mutex_unlock(thread->server->lock);

  return pending;
}
예제 #3
0
static void silc_client_attribute_del_foreach(void *key, void *context,
					      void *user_context)
{
  SilcClientConnection conn = user_context;
  SilcAttributePayload attr = context;
  SilcAttribute attribute;
  if (!attr)
    return;
  attribute = silc_attribute_get_attribute(attr);
  silc_hash_table_del_by_context(conn->internal->attrs,
				 SILC_32_TO_PTR(attribute), attr);
}
예제 #4
0
SilcServerPending silc_server_command_pending(SilcServerThread thread,
					      SilcUInt16 cmd_ident)
{
  SilcServerPending pending;

  silc_mutex_lock(thread->server->lock);

  /* Check if pending already */
  if (silc_hash_table_find(thread->server->pending_commands,
			   SILC_32_TO_PTR(cmd_ident), NULL,
			   (void **)&pending)) {
    pending->refcnt++;
    silc_mutex_unlock(thread->server->lock);
    return pending;
  }

  pending = silc_calloc(1, sizeof(*pending));
  if (!pending) {
    silc_mutex_unlock(thread->server->lock);
    return NULL;
  }

  silc_fsm_event_init(&pending->wait_reply, &thread->fsm, 0);
  pending->refcnt = 1;
  pending->cmd_ident = cmd_ident;

  /* Add to pending commands hash table */
  if (!silc_hash_table_add(thread->server->pending_commands,
			   SILC_32_TO_PTR(cmd_ident), pending)) {
    silc_mutex_unlock(thread->server->lock);
    silc_free(pending);
    return NULL;
  }

  silc_mutex_unlock(thread->server->lock);

  return pending;
}
예제 #5
0
void silc_server_command_pending_signal(SilcServerCommand cmd)
{
  SilcServerThread thread = cmd->thread;
  SilcServerPending pending = cmd->pending;

  if (!pending)
    return;

  silc_mutex_lock(thread->server->lock);

  /* Signal */
  pending->reply = cmd;
  SILC_FSM_EVENT_SIGNAL(&pending->wait_reply);

  /* Remove from pending */
  silc_hash_table_del_by_context(thread->server->pending_commands,
				 SILC_32_TO_PTR(pending->cmd_ident), pending);

  silc_mutex_unlock(thread->server->lock);
}
예제 #6
0
SilcAttributePayload silc_client_attribute_add(SilcClient client,
					       SilcClientConnection conn,
					       SilcAttribute attribute,
					       void *object,
					       SilcUInt32 object_size)
{
  SilcAttributePayload attr;

  attr = silc_attribute_payload_alloc(attribute, SILC_ATTRIBUTE_FLAG_VALID,
				      object, object_size);
  if (!attr)
    return NULL;

  if (!conn->internal->attrs)
    conn->internal->attrs =
      silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL,
			    NULL, silc_client_attribute_destruct,
			    NULL, TRUE);
  silc_hash_table_add(conn->internal->attrs,
		      SILC_32_TO_PTR(attribute), attr);
  return attr;
}
예제 #7
0
void silc_server_command_pending_free(SilcServerThread thread,
				      SilcServerPending pending)
{
  silc_mutex_lock(thread->server->lock);

  pending->refcnt--;
  if (pending->refcnt > 0) {
    silc_mutex_unlock(thread->server->lock);
    return;
  }

  /* If command reply context set, free it also */
  if (pending->reply) {
    pending->reply->pending = NULL;
    silc_server_command_free(pending->reply);
  }

  /* Remove from pending commands */
  silc_hash_table_del_by_context(thread->server->pending_commands,
				 SILC_32_TO_PTR(pending->cmd_ident), pending);
  silc_free(pending);

  silc_mutex_unlock(thread->server->lock);
}
예제 #8
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;
}
예제 #9
0
static void silc_sftp_server_receive_process(SilcSFTP sftp, SilcBuffer buffer)
{
  SilcSFTPServer server = (SilcSFTPServer)sftp;
  SilcSFTPPacket type;
  char *filename = NULL, *path = NULL;
  unsigned char *payload = NULL;
  SilcUInt32 payload_len;
  int ret;
  SilcBufferStruct buf;
  SilcUInt32 id;
  SilcSFTPAttributes attrs;
  SilcSFTPHandle handle;
  SilcSFTPMonitorDataStruct mdata;

  SILC_LOG_DEBUG(("Start"));

  /* Parse the packet */
  type = silc_sftp_packet_decode(buffer, &payload, &payload_len);
  if (type <= 0)
    return;

  silc_buffer_set(&buf, payload, payload_len);

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

  switch (type) {
  case SILC_SFTP_READ:
    {
      unsigned char *hdata;
      SilcUInt32 hdata_len;
      SilcUInt64 offset;
      SilcUInt32 len;

      SILC_LOG_DEBUG(("Read request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_NSTRING(&hdata,
						       &hdata_len),
				 SILC_STR_UI_INT64(&offset),
				 SILC_STR_UI_INT(&len),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Get the handle */
      handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
					       (const unsigned char *)hdata,
					       hdata_len);
      if (!handle) {
	silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
	break;
      }

      /* Read operation */
      server->fs->fs->sftp_read(server->fs->fs_context, sftp,
				handle, offset, len,
				silc_sftp_server_data, SILC_32_TO_PTR(id));

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_READ && server->monitor) {
	mdata.offset = offset;
	mdata.data_len = len;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_READ, &mdata,
			   server->monitor_context);
      }
    }
    break;

  case SILC_SFTP_WRITE:
    {
      unsigned char *hdata;
      SilcUInt32 hdata_len;
      SilcUInt64 offset;
      unsigned char *data;
      SilcUInt32 data_len;

      SILC_LOG_DEBUG(("Read request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_NSTRING(&hdata,
						       &hdata_len),
				 SILC_STR_UI_INT64(&offset),
				 SILC_STR_UI32_NSTRING(&data,
						       &data_len),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Get the handle */
      handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
					       (const unsigned char *)hdata,
					       hdata_len);
      if (!handle) {
	silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
	break;
      }

      /* Write operation */
      server->fs->fs->sftp_write(server->fs->fs_context, sftp, handle, offset,
				 (const unsigned char *)data, data_len,
				 silc_sftp_server_status, SILC_32_TO_PTR(id));

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_WRITE && server->monitor) {
	mdata.offset = offset;
	mdata.data_len = data_len;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_WRITE, &mdata,
			   server->monitor_context);
      }
    }
    break;

  case SILC_SFTP_INIT:
    {
      SilcSFTPVersion version;

      SILC_LOG_DEBUG(("Init request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&version),
				 SILC_STR_END);
      if (ret < 0)
	break;

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_INIT && server->monitor) {
	mdata.version = version;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_INIT, &mdata,
			   server->monitor_context);
      }

      silc_sftp_send_packet(server, SILC_SFTP_VERSION, 4,
			    SILC_STR_UI_INT(SILC_SFTP_PROTOCOL_VERSION),
			    SILC_STR_END);
    }
    break;

  case SILC_SFTP_OPEN:
    {
      SilcSFTPFileOperation pflags;
      unsigned char *attr_buf;
      SilcUInt32 attr_len = 0;
      SilcBufferStruct tmpbuf;

      SILC_LOG_DEBUG(("Open request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&filename),
				 SILC_STR_UI_INT(&pflags),
				 SILC_STR_UI32_NSTRING(&attr_buf,
						       &attr_len),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      if (attr_len) {
	silc_buffer_set(&tmpbuf, attr_buf, attr_len);
	attrs = silc_sftp_attr_decode(&tmpbuf);
	if (!attrs)
	  goto failure;
      } else {
	attrs = silc_calloc(1, sizeof(*attrs));
	if (!attrs)
	  goto failure;
      }

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_OPEN && server->monitor) {
	mdata.name = filename;
	mdata.pflags = pflags;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_OPEN, &mdata,
			   server->monitor_context);
      }

      /* Open operation */
      server->fs->fs->sftp_open(server->fs->fs_context, sftp, filename, pflags,
				attrs, silc_sftp_server_handle,
				SILC_32_TO_PTR(id));

      silc_free(filename);
      silc_sftp_attr_free(attrs);
    }
    break;

  case SILC_SFTP_CLOSE:
    {
      unsigned char *hdata;
      SilcUInt32 hdata_len;

      SILC_LOG_DEBUG(("Close request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_NSTRING(&hdata,
						       &hdata_len),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Get the handle */
      handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
					       (const unsigned char *)hdata,
					       hdata_len);
      if (!handle) {
	silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
	break;
      }

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_CLOSE && server->monitor) {
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_CLOSE, &mdata,
			   server->monitor_context);
      }

      /* Close operation */
      server->fs->fs->sftp_close(server->fs->fs_context, sftp, handle,
				 silc_sftp_server_status, SILC_32_TO_PTR(id));

    }
    break;

  case SILC_SFTP_REMOVE:
    {
      SILC_LOG_DEBUG(("Remove request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&filename),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_REMOVE && server->monitor) {
	mdata.name = filename;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_REMOVE, &mdata,
			   server->monitor_context);
      }

      /* Remove operation */
      server->fs->fs->sftp_remove(server->fs->fs_context, sftp, filename,
				  silc_sftp_server_status, SILC_32_TO_PTR(id));

      silc_free(filename);
    }
    break;

  case SILC_SFTP_RENAME:
    {
      char *newname = NULL;

      SILC_LOG_DEBUG(("Rename request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&filename),
				 SILC_STR_UI32_STRING_ALLOC(&newname),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_RENAME && server->monitor) {
	mdata.name = filename;
	mdata.name2 = newname;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_RENAME, &mdata,
			   server->monitor_context);
      }

      /* Rename operation */
      server->fs->fs->sftp_rename(server->fs->fs_context, sftp,
				  filename, newname,
				  silc_sftp_server_status, SILC_32_TO_PTR(id));

      silc_free(filename);
      silc_free(newname);
    }
    break;

  case SILC_SFTP_MKDIR:
    {
      unsigned char *attr_buf;
      SilcUInt32 attr_len = 0;
      SilcBufferStruct tmpbuf;

      SILC_LOG_DEBUG(("Mkdir request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&path),
				 SILC_STR_UI32_NSTRING(&attr_buf,
						       &attr_len),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      if (attr_len) {
	silc_buffer_set(&tmpbuf, attr_buf, attr_len);
	attrs = silc_sftp_attr_decode(&tmpbuf);
	if (!attrs)
	  goto failure;
      } else {
	attrs = silc_calloc(1, sizeof(*attrs));
	if (!attrs)
	  goto failure;
      }

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_MKDIR && server->monitor) {
	mdata.name = path;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_MKDIR, &mdata,
			   server->monitor_context);
      }

      /* Mkdir operation */
      server->fs->fs->sftp_mkdir(server->fs->fs_context, sftp, path, attrs,
				 silc_sftp_server_status, SILC_32_TO_PTR(id));

      silc_sftp_attr_free(attrs);
      silc_free(path);
    }
    break;

  case SILC_SFTP_RMDIR:
    {
      SILC_LOG_DEBUG(("Rmdir request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&path),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_RMDIR && server->monitor) {
	mdata.name = path;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_RMDIR, &mdata,
			   server->monitor_context);
      }

      /* Rmdir operation */
      server->fs->fs->sftp_rmdir(server->fs->fs_context, sftp, path,
				 silc_sftp_server_status, SILC_32_TO_PTR(id));

      silc_free(path);
    }
    break;

  case SILC_SFTP_OPENDIR:
    {
      SILC_LOG_DEBUG(("Opendir request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&path),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_OPENDIR && server->monitor) {
	mdata.name = path;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_OPENDIR, &mdata,
			   server->monitor_context);
      }

      /* Opendir operation */
      server->fs->fs->sftp_opendir(server->fs->fs_context, sftp, path,
				   silc_sftp_server_handle, SILC_32_TO_PTR(id));

      silc_free(path);
    }
    break;

  case SILC_SFTP_READDIR:
    {
      unsigned char *hdata;
      SilcUInt32 hdata_len;

      SILC_LOG_DEBUG(("Readdir request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_NSTRING(&hdata,
						       &hdata_len),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Get the handle */
      handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
					       (const unsigned char *)hdata,
					       hdata_len);
      if (!handle) {
	silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
	break;
      }

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_READDIR && server->monitor) {
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_READDIR, &mdata,
			   server->monitor_context);
      }

      /* Readdir operation */
      server->fs->fs->sftp_readdir(server->fs->fs_context, sftp, handle,
				   silc_sftp_server_name, SILC_32_TO_PTR(id));
    }
    break;

  case SILC_SFTP_STAT:
    {
      SILC_LOG_DEBUG(("Stat request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&path),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_STAT && server->monitor) {
	mdata.name = path;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_STAT, &mdata,
			   server->monitor_context);
      }

      /* Stat operation */
      server->fs->fs->sftp_stat(server->fs->fs_context, sftp, path,
				silc_sftp_server_attr, SILC_32_TO_PTR(id));

      silc_free(path);
    }
    break;

  case SILC_SFTP_LSTAT:
    {
      SILC_LOG_DEBUG(("Lstat request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&path),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_LSTAT && server->monitor) {
	mdata.name = path;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_LSTAT, &mdata,
			   server->monitor_context);
      }

      /* Lstat operation */
      server->fs->fs->sftp_lstat(server->fs->fs_context, sftp, path,
				 silc_sftp_server_attr, SILC_32_TO_PTR(id));

      silc_free(path);
    }
    break;

  case SILC_SFTP_FSTAT:
    {
      unsigned char *hdata;
      SilcUInt32 hdata_len;

      SILC_LOG_DEBUG(("Fstat request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_NSTRING(&hdata,
						       &hdata_len),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Get the handle */
      handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
					       (const unsigned char *)hdata,
					       hdata_len);
      if (!handle) {
	silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
	break;
      }

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_FSTAT && server->monitor) {
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_FSTAT, &mdata,
			   server->monitor_context);
      }

      /* Fstat operation */
      server->fs->fs->sftp_fstat(server->fs->fs_context, sftp, handle,
				 silc_sftp_server_attr, SILC_32_TO_PTR(id));
    }
    break;

  case SILC_SFTP_SETSTAT:
    {
      unsigned char *attr_buf;
      SilcUInt32 attr_len = 0;
      SilcBufferStruct tmpbuf;

      SILC_LOG_DEBUG(("Setstat request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&path),
				 SILC_STR_UI32_NSTRING(&attr_buf,
						       &attr_len),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      if (attr_len) {
	silc_buffer_set(&tmpbuf, attr_buf, attr_len);
	attrs = silc_sftp_attr_decode(&tmpbuf);
	if (!attrs)
	  goto failure;
      } else {
	attrs = silc_calloc(1, sizeof(*attrs));
	if (!attrs)
	  goto failure;
      }

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_SETSTAT && server->monitor) {
	mdata.name = path;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_SETSTAT, &mdata,
			   server->monitor_context);
      }

      /* Setstat operation */
      server->fs->fs->sftp_setstat(server->fs->fs_context, sftp, path, attrs,
				   silc_sftp_server_status,
				   SILC_32_TO_PTR(id));

      silc_sftp_attr_free(attrs);
      silc_free(path);
    }
    break;

  case SILC_SFTP_FSETSTAT:
    {
      unsigned char *hdata, *attr_buf;
      SilcUInt32 hdata_len, attr_len = 0;
      SilcBufferStruct tmpbuf;

      SILC_LOG_DEBUG(("Fsetstat request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_NSTRING(&hdata,
						       &hdata_len),
				 SILC_STR_UI32_NSTRING(&attr_buf,
						       &attr_len),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      if (attr_len) {
	silc_buffer_set(&tmpbuf, attr_buf, attr_len);
	attrs = silc_sftp_attr_decode(&tmpbuf);
	if (!attrs)
	  goto failure;
      } else {
	attrs = silc_calloc(1, sizeof(*attrs));
	if (!attrs)
	  goto failure;
      }

      /* Get the handle */
      handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
					       (const unsigned char *)hdata,
					       hdata_len);
      if (!handle) {
	silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
	break;
      }

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_FSETSTAT && server->monitor) {
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_FSETSTAT, &mdata,
			   server->monitor_context);
      }

      /* Fsetstat operation */
      server->fs->fs->sftp_fsetstat(server->fs->fs_context, sftp,
				    handle, attrs,
				    silc_sftp_server_status,
				    SILC_32_TO_PTR(id));

      silc_sftp_attr_free(attrs);
    }
    break;

  case SILC_SFTP_READLINK:
    {
      SILC_LOG_DEBUG(("Readlink request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&path),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_READLINK && server->monitor) {
	mdata.name = path;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_READLINK, &mdata,
			   server->monitor_context);
      }

      /* Readlink operation */
      server->fs->fs->sftp_readlink(server->fs->fs_context, sftp, path,
				    silc_sftp_server_name, SILC_32_TO_PTR(id));

      silc_free(path);
    }
    break;

  case SILC_SFTP_SYMLINK:
    {
      char *target = NULL;

      SILC_LOG_DEBUG(("Symlink request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&path),
				 SILC_STR_UI32_STRING_ALLOC(&target),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_SYMLINK && server->monitor) {
	mdata.name = path;
	mdata.name2 = target;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_SYMLINK, &mdata,
			   server->monitor_context);
      }

      /* Symlink operation */
      server->fs->fs->sftp_symlink(server->fs->fs_context, sftp, path, target,
				   silc_sftp_server_status,
				   SILC_32_TO_PTR(id));

      silc_free(path);
      silc_free(target);
    }
    break;

  case SILC_SFTP_REALPATH:
    {
      SILC_LOG_DEBUG(("Realpath request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&path),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_REALPATH && server->monitor) {
	mdata.name = path;
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_REALPATH, &mdata,
			   server->monitor_context);
      }

      /* Realpath operation */
      server->fs->fs->sftp_realpath(server->fs->fs_context, sftp, path,
				    silc_sftp_server_name, SILC_32_TO_PTR(id));

      silc_free(path);
    }
    break;

  case SILC_SFTP_EXTENDED:
    {
      char *request = NULL;
      unsigned char *data;
      SilcUInt32 data_len;

      SILC_LOG_DEBUG(("Extended request"));

      ret = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&id),
				 SILC_STR_UI32_STRING_ALLOC(&request),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;

      data_len = 8 + strlen(request);
      silc_buffer_pull(&buf, data_len);
      ret = silc_buffer_unformat(&buf,
				 SILC_STR_DATA(&data, silc_buffer_len(&buf)),
				 SILC_STR_END);
      if (ret < 0)
	goto failure;
      data_len = silc_buffer_len(&buf);

      /* Call monitor */
      if (server->monitors & SILC_SFTP_MONITOR_EXTENDED && server->monitor) {
	(*server->monitor)(sftp, SILC_SFTP_MONITOR_EXTENDED, &mdata,
			   server->monitor_context);
      }

      /* Extended operation */
      server->fs->fs->sftp_extended(server->fs->fs_context, sftp,
				    request, data, data_len,
				    silc_sftp_server_extended,
				    SILC_32_TO_PTR(id));

      silc_free(request);
    }
    break;

  default:
    break;
  }

  return;

 failure:
  silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);
}
예제 #10
0
int main(int argc, char **argv)
{
  SilcBool success = FALSE;
  SilcAtomic32 ref32;
  SilcAtomic16 ref16;
  SilcAtomic8 ref8;
  SilcAtomicPointer refptr;
  SilcUInt8 ret8;
  SilcUInt16 ret16;
  SilcUInt32 ret32;

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

  silc_atomic_init8(&ref8, 1);
  silc_atomic_init16(&ref16, 1);
  silc_atomic_init32(&ref32, 1);
  silc_atomic_init_pointer(&refptr, SILC_32_TO_PTR(0xdeadbeef));

  ret8 = silc_atomic_add_int8(&ref8, 7);
  SILC_LOG_DEBUG(("ref8: 1 + 7 = %d (8)", ret8));
  ret8 = silc_atomic_add_int8(&ref8, 3);
  SILC_LOG_DEBUG(("ref8: 8 + 3 = %d (11)", ret8));
  ret8 = silc_atomic_sub_int8(&ref8, 10);
  SILC_LOG_DEBUG(("ref8: 11 - 10 = %d (1)", ret8));

  ret16 = silc_atomic_add_int16(&ref16, 1);
  SILC_LOG_DEBUG(("ref16: 1 + 1 = %d (2)", ret16));
  ret16 = silc_atomic_add_int16(&ref16, 31020);
  SILC_LOG_DEBUG(("ref16: 2 + 31020 = %d (31022)", ret16));
  ret16 = silc_atomic_add_int16(&ref16, 34000);
  SILC_LOG_DEBUG(("ref16: 31022 + 34000 = %d (65022)", ret16));
  ret16 = silc_atomic_sub_int16(&ref16, 0);
  SILC_LOG_DEBUG(("ref16: 65022 - 0 = %d (65022)", ret16));
  ret16 = silc_atomic_sub_int16(&ref16, (SilcInt16)0xffff);
  SILC_LOG_DEBUG(("ref16: 65022 - 0xffff = %d (65023) (underflow)", ret16));

  SILC_LOG_DEBUG(("Current value: %d (-513)",
		  (SilcInt16)silc_atomic_get_int16(&ref16)));

  SILC_LOG_DEBUG(("Swapping -513 with 57392"));
  if (!silc_atomic_cas16(&ref16, silc_atomic_get_int16(&ref16), 57392))
    goto err;
  SILC_LOG_DEBUG(("Current value: %d (57392)",
		  silc_atomic_get_int16(&ref16)));
  SILC_LOG_DEBUG(("Swapping 57392 with -500"));
  if (!silc_atomic_cas16(&ref16, silc_atomic_get_int16(&ref16), -500))
    goto err;
  SILC_LOG_DEBUG(("Current value: %d (-500)",
		  (SilcInt16)silc_atomic_get_int16(&ref16)));

  ret32 = silc_atomic_add_int32(&ref32, 1);
  SILC_LOG_DEBUG(("ref32: 1 + 1 = %d (2)", ret32));
  ret32 = silc_atomic_add_int32(&ref32, 310200);
  SILC_LOG_DEBUG(("ref32: 2 + 310200 = %d (310202)", ret32));
  ret32 = silc_atomic_add_int32(&ref32, 34000000);
  SILC_LOG_DEBUG(("ref32: 310202 + 34000000 = %d (34310202)", ret32));
  ret32 = silc_atomic_sub_int32(&ref32, 0);
  SILC_LOG_DEBUG(("ref32: 34310202 - 0 = %d (34310202)", ret32));
  ret32 = silc_atomic_sub_int32(&ref32, 0xfffffff);
  SILC_LOG_DEBUG(("ref32: 34310202 - 0xfffffff = %d (-234125253) "
		  "(underflow)", ret32));

  SILC_LOG_DEBUG(("Current value: %d (-234125253)",
		  silc_atomic_get_int32(&ref32)));

  SILC_LOG_DEBUG(("Swapping -234125253 with 76327681"));
  if (!silc_atomic_cas32(&ref32, silc_atomic_get_int32(&ref32), 76327681))
    goto err;
  SILC_LOG_DEBUG(("Current value: %d (76327681)",
		  silc_atomic_get_int32(&ref32)));

  SILC_LOG_DEBUG(("Current ptr: %p (0xdeadbeef)",
		  silc_atomic_get_pointer(&refptr)));
  SILC_LOG_DEBUG(("Swapping %p with NULL", silc_atomic_get_pointer(&refptr)));
  if (!silc_atomic_cas_pointer(&refptr,
			       silc_atomic_get_pointer(&refptr), NULL))
    goto err;
  SILC_LOG_DEBUG(("Current ptr: %p (NULL)",
		  silc_atomic_get_pointer(&refptr)));

  SILC_LOG_DEBUG(("Setting val 34322111 (32-bit)"));
  silc_atomic_set_int32(&ref32, 34322111);
  if (silc_atomic_get_int32(&ref32) != 34322111)
    goto err;
  SILC_LOG_DEBUG(("Setting val 1432211119 (32-bit)"));
  silc_atomic_set_int32(&ref32, 1432211119);
  if (silc_atomic_get_int32(&ref32) != 1432211119)
    goto err;
  SILC_LOG_DEBUG(("Setting val 23422 (16-bit)"));
  silc_atomic_set_int16(&ref16, 23422);
  if (silc_atomic_get_int16(&ref16) != 23422)
    goto err;
  SILC_LOG_DEBUG(("Setting val 124 (8-bit)"));
  silc_atomic_set_int8(&ref8, 124);
  if (silc_atomic_get_int8(&ref8) != 124)
    goto err;

  silc_atomic_uninit8(&ref8);
  silc_atomic_uninit16(&ref16);
  silc_atomic_uninit32(&ref32);
  silc_atomic_uninit_pointer(&refptr);

  success = TRUE;

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

  return !success;
}
예제 #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;
}