Example #1
0
SilcStream silc_fd_stream_file2(const char *read_file, const char *write_file)
{
  SilcStream stream;
  int fd1 = 0, fd2 = 0;

  SILC_LOG_DEBUG(("Creating new fd stream for reading `%s' and writing `%s'",
		  read_file ? read_file : "(none)",
		  write_file ? write_file : "(none)"));

  if (write_file) {
    fd2 = silc_file_open(write_file, O_CREAT | O_WRONLY);
    if (fd2 < 0) {
      silc_file_close(fd1);
      return NULL;
    }
  }

  if (read_file) {
    fd1 = silc_file_open(read_file, O_RDONLY);
    if (fd1 < 0)
      return NULL;
  }

  stream = silc_fd_stream_create2(fd1, fd2);
  if (!stream) {
    silc_file_close(fd1);
    silc_file_close(fd2);
  }

  return stream;
}
Example #2
0
int silc_file_writefile(const char *filename, const char *buffer,
			SilcUInt32 len)
{
  int fd;
  int flags = O_CREAT | O_WRONLY | O_TRUNC;

#if defined(O_BINARY)
  flags |= O_BINARY;
#endif /* O_BINARY */

  if ((fd = open(filename, flags, 0644)) == -1) {
    SILC_LOG_ERROR(("Cannot open file %s for writing: %s", filename,
		    silc_errno_string(silc_errno)));
    return -1;
  }

  if (silc_file_write(fd, buffer, len) == -1) {
    SILC_LOG_ERROR(("Cannot write to file %s: %s", filename,
		    silc_errno_string(silc_errno)));
    silc_file_close(fd);
    return -1;
  }

#ifdef SILC_UNIX
  fsync(fd);
#endif /* SILC_UNIX */

  return silc_file_close(fd);
}
Example #3
0
char *silc_file_readfile(const char *filename, SilcUInt32 *return_len,
			 SilcStack stack)
{
  int fd;
  unsigned char *buffer;
  int filelen;

  fd = silc_file_open(filename, O_RDONLY);
  if (fd < 0) {
    if (silc_errno == SILC_ERR_NO_SUCH_FILE)
      return NULL;
    SILC_LOG_ERROR(("Cannot open file %s: %s", filename,
		    silc_errno_string(silc_errno)));
    return NULL;
  }

  filelen = lseek(fd, (off_t)0L, SEEK_END);
  if (filelen < 0) {
    silc_set_errno_posix(errno);
    silc_file_close(fd);
    return NULL;
  }
  if (lseek(fd, (off_t)0L, SEEK_SET) < 0) {
    silc_set_errno_posix(errno);
    silc_file_close(fd);
    return NULL;
  }

  buffer = silc_calloc(filelen + 1, sizeof(*buffer));
  if (!buffer) {
    silc_set_errno_posix(errno);
    silc_file_close(fd);
    return NULL;
  }

  if ((silc_file_read(fd, buffer, filelen)) == -1) {
    memset(buffer, 0, sizeof(buffer));
    silc_file_close(fd);
    SILC_LOG_ERROR(("Cannot read from file %s: %s", filename,
		    silc_errno_string(silc_errno)));
    return NULL;
  }

  silc_file_close(fd);
  buffer[filelen] = EOF;

  if (return_len)
    *return_len = filelen;

  return (char *)buffer;
}
Example #4
0
char *silc_file_readfile(const char *filename, SilcUInt32 *return_len)
{
  int fd;
  char *buffer;
  int filelen;

  fd = silc_file_open(filename, O_RDONLY);
  if (fd < 0) {
    if (errno == ENOENT)
      return NULL;
    SILC_LOG_ERROR(("Cannot open file %s: %s", filename, strerror(errno)));
    return NULL;
  }

  filelen = lseek(fd, (off_t)0L, SEEK_END);
  if (filelen < 0) {
    silc_file_close(fd);
    return NULL;
  }
  if (lseek(fd, (off_t)0L, SEEK_SET) < 0) {
    silc_file_close(fd);
    return NULL;
  }

  if (filelen < 0) {
    SILC_LOG_ERROR(("Cannot open file %s: %s", filename, strerror(errno)));
    silc_file_close(fd);
    return NULL;
  }

  buffer = silc_calloc(filelen + 1, sizeof(char));

  if ((silc_file_read(fd, buffer, filelen)) == -1) {
    memset(buffer, 0, sizeof(buffer));
    silc_file_close(fd);
    SILC_LOG_ERROR(("Cannot read from file %s: %s", filename,
                    strerror(errno)));
    return NULL;
  }

  silc_file_close(fd);
  buffer[filelen] = EOF;

  if (return_len)
    *return_len = filelen;

  return buffer;
}
Example #5
0
SilcBool silc_fd_stream_close(SilcStream stream)
{
  SilcFDStream fd_stream = stream;

  if (fd_stream->fd1 > 0) {
    silc_file_close(fd_stream->fd1);
    if (fd_stream->schedule) {
      silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd1);
      silc_schedule_task_del_by_fd(fd_stream->schedule, fd_stream->fd1);
    }
  }
  if (fd_stream->fd2 > 0 && fd_stream->fd2 != fd_stream->fd1) {
    silc_file_close(fd_stream->fd2);
    if (fd_stream->schedule) {
      silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd2);
      silc_schedule_task_del_by_fd(fd_stream->schedule, fd_stream->fd2);
    }
  }

  return TRUE;
}
Example #6
0
static void silc_client_ftp_data(SilcSFTP sftp,
				 SilcSFTPStatus status,
				 const unsigned char *data,
				 SilcUInt32 data_len,
				 void *context)
{
  SilcClientFtpSession session = (SilcClientFtpSession)context;

  SILC_LOG_DEBUG(("Start"));

  if (status == SILC_SFTP_STATUS_EOF) {
    /* EOF received */

    /* Close the handle */
    silc_sftp_close(sftp, session->read_handle, NULL, NULL);
    session->read_handle = NULL;

    /* Close the real file descriptor */
    silc_file_close(session->fd);
    return;
  }

  if (status != SILC_SFTP_STATUS_OK) {
    /* Call monitor callback */
    if (session->monitor)
      (*session->monitor)(session->client, session->conn,
			  SILC_CLIENT_FILE_MONITOR_ERROR,
			  (status == SILC_SFTP_STATUS_NO_SUCH_FILE ?
			   SILC_CLIENT_FILE_NO_SUCH_FILE :
			   status == SILC_SFTP_STATUS_PERMISSION_DENIED ?
			   SILC_CLIENT_FILE_PERMISSION_DENIED :
			   SILC_CLIENT_FILE_ERROR), 0, 0,
			  session->client_entry, session->session_id,
			  session->filepath, session->monitor_context);

    /* Close the handle */
    silc_sftp_close(sftp, session->read_handle, NULL, NULL);
    session->read_handle = NULL;

    /* Close the real file descriptor */
    silc_file_close(session->fd);
    return;
  }

  /* Read more, until EOF is received */
  session->read_offset += data_len;
  silc_sftp_read(sftp, session->read_handle, session->read_offset,
                 SILC_PACKET_MAX_LEN - 1024,
		 silc_client_ftp_data, session);

  /* Write the read data to the real file */
  silc_file_write(session->fd, data, data_len);

  /* Call monitor callback */
  if (session->monitor)
    (*session->monitor)(session->client, session->conn,
			SILC_CLIENT_FILE_MONITOR_RECEIVE,
			SILC_CLIENT_FILE_OK,
			session->read_offset, session->filesize,
			session->client_entry, session->session_id,
			session->filepath, session->monitor_context);
}
Example #7
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;
}