Пример #1
0
Файл: scp.c Проект: Paxxi/libssh
/**
 * @brief Create a new scp session.
 *
 * @param[in]  session  The SSH session to use.
 *
 * @param[in]  mode     One of SSH_SCP_WRITE or SSH_SCP_READ, depending if you
 *                      need to drop files remotely or read them.
 *                      It is not possible to combine read and write.
 *                      SSH_SCP_RECURSIVE Flag can be or'ed to this to indicate
 *                      that you're going to use recursion. Browsing through
 *                      directories is not possible without this.
 *
 * @param[in]  location The directory in which write or read will be done. Any
 *                      push or pull will be relative to this place.
 *                      This can also be a pattern of files to download (read).
 *
 * @returns             A ssh_scp handle, NULL if the creation was impossible.
 */
ssh_scp ssh_scp_new(ssh_session session, int mode, const char *location){
  ssh_scp scp=malloc(sizeof(struct ssh_scp_struct));
  if(scp == NULL){
    ssh_set_error(session,SSH_FATAL,"Error allocating memory for ssh_scp");
    return NULL;
  }
  ZERO_STRUCTP(scp);
  if((mode&~SSH_SCP_RECURSIVE) != SSH_SCP_WRITE && (mode &~SSH_SCP_RECURSIVE) != SSH_SCP_READ){
    ssh_set_error(session,SSH_FATAL,"Invalid mode %d for ssh_scp_new()",mode);
    ssh_scp_free(scp);
    return NULL;
  }
  scp->location=strdup(location);
  if (scp->location == NULL) {
    ssh_set_error(session,SSH_FATAL,"Error allocating memory for ssh_scp");
    ssh_scp_free(scp);
    return NULL;
  }
  scp->session=session;
  scp->mode=mode & ~SSH_SCP_RECURSIVE;
  scp->recursive = (mode & SSH_SCP_RECURSIVE) != 0;
  scp->channel=NULL;
  scp->state=SSH_SCP_NEW;
  return scp;
}
Пример #2
0
static int open_location(struct location *loc, int flag){
  if(loc->is_ssh && flag==WRITE){
    loc->session=connect_ssh(loc->host,loc->user,verbosity);
    if(!loc->session){
      fprintf(stderr,"Couldn't connect to %s\n",loc->host);
      return -1;
    }
    loc->scp=ssh_scp_new(loc->session,SSH_SCP_WRITE,loc->path);
    if(!loc->scp){
      fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
      return -1;
    }
    if(ssh_scp_init(loc->scp)==SSH_ERROR){
      fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
      ssh_scp_free(loc->scp);
      return -1;
    }
    return 0;
  } else if(loc->is_ssh && flag==READ){
    loc->session=connect_ssh(loc->host, loc->user,verbosity);
    if(!loc->session){
      fprintf(stderr,"Couldn't connect to %s\n",loc->host);
      return -1;
    }
    loc->scp=ssh_scp_new(loc->session,SSH_SCP_READ,loc->path);
    if(!loc->scp){
      fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
      return -1;
    }
    if(ssh_scp_init(loc->scp)==SSH_ERROR){
      fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
      ssh_scp_free(loc->scp);
      return -1;
    }
    return 0;
  } else {
    loc->file=fopen(loc->path,flag==READ ? "r":"w");
    if(!loc->file){
        if(errno==EISDIR){
                if(chdir(loc->path)){
                        fprintf(stderr,"Error changing directory to %s: %s\n",loc->path,strerror(errno));
                        return -1;
                }
                return 0;
        }
        fprintf(stderr,"Error opening %s: %s\n",loc->path,strerror(errno));
        return -1;
        }
    return 0;
  }
  return -1;
}
Пример #3
0
int doCopy(int argc, char **argv){
  struct location *dest, *src;
  int i;
  int r;
  if(opts(argc,argv)<0)
    return EXIT_FAILURE;
  dest=parse_location(destination);
  if(open_location(dest,WRITE)<0)
    return EXIT_FAILURE;
  for(i=0;i<nsources;++i){
    src=parse_location(sources[i]);
    if(open_location(src,READ)<0){
      return EXIT_FAILURE;
    }
    if(do_copy(src,dest,0) < 0){
        break;
    }
  }
  if(dest->is_ssh){
          r=ssh_scp_close(dest->scp);
          if(r == SSH_ERROR){
                  fprintf(stderr,"Error closing scp: %s\n",ssh_get_error(dest->session));
                  ssh_scp_free(dest->scp);
                  dest->scp=NULL;
                  return -1;
          }
  } else {
          fclose(dest->file);
          dest->file=NULL;
  }
  ssh_disconnect(dest->session);
  ssh_finalize();
  return 0;
}
Пример #4
0
static void close_location(struct location *loc) {
    int rc;

    if (loc) {
        if (loc->is_ssh) {
            if (loc->scp) {
                rc = ssh_scp_close(loc->scp);
                if (rc == SSH_ERROR) {
                    fprintf(stderr,
                            "Error closing scp: %s\n",
                            ssh_get_error(loc->session));
                }
                ssh_scp_free(loc->scp);
                loc->scp = NULL;
            }
            if (loc->session) {
                ssh_disconnect(loc->session);
                ssh_free(loc->session);
                loc->session = NULL;
            }
        } else {
            if (loc->file) {
                fclose(loc->file);
                loc->file = NULL;
            }
        }
    }
}
Пример #5
0
static ssh_session scp_close(struct scp_ud *scpud){
	if (scpud == NULL || scpud->scp == NULL)return NULL;
	ssh_session session= scpud->scp->session;
	ssh_scp_close(scpud->scp);
	ssh_scp_free(scpud->scp);
	scpud->scp=NULL;
	return session;
}
Пример #6
0
int scp_write(ssh_session session)
{
    ssh_scp scp;
    int rc;

    scp = ssh_scp_new(session, SSH_SCP_WRITE | SSH_SCP_RECURSIVE, ".");
    if(scp == NULL)
    {
        fprintf(stderr, "Error allocation scp session: %s\n", ssh_get_error(session));
        return SSH_ERROR;
    }

    rc = ssh_scp_init(scp);
    if(rc != SSH_OK)
    {
        fprintf(stderr, "Error initializing scp session: %s\n", ssh_get_error(session));
        ssh_scp_free(scp);
        return rc;
    }

    ssh_scp_close(scp);
    ssh_scp_free(scp);
    return SSH_OK;
}
Пример #7
0
int 
lscp_new(lua_State *L) {
	ssh_session session=get_session(L);
    const char * location  = luaL_checkstring(L, 2);
	int mode=get_scp_mode(L,3);
	ssh_scp scp=ssh_scp_new(session, mode, location);

	if(ssh_scp_init(scp) != SSH_OK){
		ssh_scp_free(scp);
		luaL_error(L,ssh_get_error(session));
	}

	struct scp_ud * scpud = lua_newuserdata(L, sizeof(*scpud));
	scpud->scp	=scp;
	
    if (luaL_newmetatable(L, "scpmeta")) {
        lua_pushcfunction(L, lscp_close);
        lua_setfield(L, -2, "__gc");
        luaL_Reg l[] = {
			{"close",lscp_close},
			{"write",lscp_write},
			{"read",lscp_read},
			{"pull_request",lscp_pull_request},
			{"request_get_warning",lscp_request_get_warning},
			{"request_get_size",lscp_request_get_size},
			{"request_get_filename",lscp_request_get_filename},
			{"request_get_permissions",lscp_request_get_permissions},
			{"accept_request",lscp_accept_request},
			{"leave_directory",lscp_leave_directory},
			{"push_directory",lscp_push_directory},
			{"push_file",lscp_push_file},
			{"deny_request",lscp_deny_request},
            { NULL, NULL },
        };
        luaL_newlib(L, l);
        lua_setfield(L, -2, "__index");
    }
    lua_setmetatable(L, -2);
    return 1;
}
Пример #8
0
    int SSH::scp(const std::string& filePath, const byte* data, size_t size) {
        ssh_scp scp;
        int rc;

        size_t found = filePath.find_last_of("/\\");
        std::string filename = filePath.substr(found+1);
        std::string path = filePath.substr(0, found+1);

        scp = ssh_scp_new(session_, SSH_SCP_WRITE, path.c_str());
        if (scp == NULL) {
            throw Error(1, ssh_get_error(session_));
            rc = SSH_ERROR;
        } else {
            rc = ssh_scp_init(scp);
            if (rc != SSH_OK) {
                throw Error(1, ssh_get_error(session_));
            } else {
#ifdef  _MSC_VER
// S_IRUSR & S_IWUSR not in MSVC (0000400 & 0000200 in /usr/include/sys/stat.h on MacOS-X 10.8) 
#define S_IRUSR S_IREAD
#define S_IWUSR S_IWRITE
#endif
                rc = ssh_scp_push_file (scp, filename.c_str(), size, S_IRUSR |  S_IWUSR);
                if (rc != SSH_OK) {
                    throw Error(1, ssh_get_error(session_));
                } else {
                    rc = ssh_scp_write(scp, data, size);
                    if (rc != SSH_OK) {
                        throw Error(1, ssh_get_error(session_));
                    }
                }
                ssh_scp_close(scp);
            }
            ssh_scp_free(scp);
        }

        return rc;
    }
Пример #9
0
/** @brief copies files from source location to destination
 * @param src source location
 * @param dest destination location
 * @param recursive Copy also directories
 */
static int do_copy(struct location *src, struct location *dest, int recursive){
  int size;
  socket_t fd;
  struct stat s;
  int w,r;
  char buffer[16384];
  int total=0;
  int mode;
  char *filename;
  /* recursive mode doesn't work yet */
  (void)recursive;
  /* Get the file name and size*/
  if(!src->is_ssh){
    fd=fileno(src->file);
    fstat(fd,&s);
    size=s.st_size;
    mode = s.st_mode & S_IFMT;
    filename=ssh_basename(src->path);
  } else {
    size=0;
    do {
        r=ssh_scp_pull_request(src->scp);
        if(r==SSH_SCP_REQUEST_NEWDIR){
                ssh_scp_deny_request(src->scp,"Not in recursive mode");
                continue;
        }
        if(r==SSH_SCP_REQUEST_NEWFILE){
                size=ssh_scp_request_get_size(src->scp);
                filename=strdup(ssh_scp_request_get_filename(src->scp));
                mode=ssh_scp_request_get_permissions(src->scp);
                //ssh_scp_accept_request(src->scp);
                break;
        }
        if(r==SSH_ERROR){
                fprintf(stderr,"Error: %s\n",ssh_get_error(src->session));
                return -1;
        }
    } while(r != SSH_SCP_REQUEST_NEWFILE);
  }

  if(dest->is_ssh){
          r=ssh_scp_push_file(dest->scp,src->path, size, mode);
          //  snprintf(buffer,sizeof(buffer),"C0644 %d %s\n",size,src->path);
          if(r==SSH_ERROR){
                  fprintf(stderr,"error: %s\n",ssh_get_error(dest->session));
                  ssh_scp_free(dest->scp);
                  return -1;
          }
  } else {
          if(!dest->file){
                  dest->file=fopen(filename,"w");
                  if(!dest->file){
                          fprintf(stderr,"Cannot open %s for writing: %s\n",filename,strerror(errno));
                          if(src->is_ssh)
                                  ssh_scp_deny_request(src->scp,"Cannot open local file");
                          return -1;
                  }
          }
          if(src->is_ssh){
                  ssh_scp_accept_request(src->scp);
          }
  }
  do {
          if(src->is_ssh){
                  r=ssh_scp_read(src->scp,buffer,sizeof(buffer));
                  if(r==SSH_ERROR){
                          fprintf(stderr,"Error reading scp: %s\n",ssh_get_error(src->session));
                          return -1;
                  }
                  if(r==0)
                          break;
          } else {
                  r=fread(buffer,1,sizeof(buffer),src->file);
                  if(r==0)
                          break;
                  if(r<0){
                          fprintf(stderr,"Error reading file: %s\n",strerror(errno));
                          return -1;
                  }
          }
          if(dest->is_ssh){
                  w=ssh_scp_write(dest->scp,buffer,r);
                  if(w == SSH_ERROR){
                          fprintf(stderr,"Error writing in scp: %s\n",ssh_get_error(dest->session));
                          ssh_scp_free(dest->scp);
                          dest->scp=NULL;
                          return -1;
                  }
          } else {
                  w=fwrite(buffer,r,1,dest->file);
                  if(w<=0){
                          fprintf(stderr,"Error writing in local file: %s\n",strerror(errno));
                          return -1;
                  }
          }
          total+=r;

  } while(total < size);
 printf("wrote %d bytes\n",total);
 return 0;
}
Пример #10
0
static int do_write(const char* path, FILE* fp, ftp_transfer_func hookf,
                    uint64_t offset)
{
  /* try to set up a scp connection */
  if (gvSSHTrySCP && !offset)
  {
    ssh_scp scp = ssh_scp_new(ftp->session, SSH_SCP_WRITE, path);
    if (scp != NULL)
    {
      int rc = ssh_scp_init(scp);
      if (rc == SSH_OK)
        return do_scp_write(scp, path, fp, hookf);
      ssh_scp_free(scp);
    }
  }

  time_t then = time(NULL) - 1;
  ftp_set_close_handler();

  if (hookf)
    hookf(&ftp->ti);
  ftp->ti.begin = false;

  struct stat sb;
  errno = 0;
  if (fstat(fileno(fp), &sb) == -1)
  {
    ftp_err(_("Couldn't fstat local file: %s\n"), strerror(errno));
    return -1;
  }

  /* open remote file */
  sftp_file file = sftp_open(ftp->sftp_session, path, O_WRONLY | O_CREAT |
      (offset == 0u ? O_TRUNC : 0), sb.st_mode);
  if (!file)
  {
    ftp_err(_("Cannot open file for writing: %s\n"), ssh_get_error(ftp->session));
    return -1;
  }

  /* seek to offset */
  int r = sftp_seek64(file, offset);
  if (r != SSH_OK)
  {
    ftp_err(_("Failed to seek: %s\n"), ssh_get_error(ftp->session));
    sftp_close(file);
    return -1;
  }

  /* read file */
  char buffer[SSH_BUFSIZ];
  ssize_t nbytes = 0;
  errno = 0;
  while ((nbytes = fread(buffer, sizeof(char), sizeof(buffer), fp)) > 0)
  {
    if (ftp_sigints() > 0)
    {
      ftp_trace("break due to sigint\n");
      break;
    }

    ssize_t nwritten = sftp_write(file, buffer, nbytes);
    if (nwritten != nbytes)
    {
      ftp_err(_("Error while writing to file: %s\n"), ssh_get_error(ftp->session));
      sftp_close(file);
      return -1;
    }

    ftp->ti.size += nbytes;
    if (hookf)
    {
      time_t now = time(NULL);
      if (now > then)
      {
        hookf(&ftp->ti);
        then = now;
      }
    }
    errno = 0;
  }

  if (ferror(fp))
  {
    ftp_err(_("Failed to read from file: %s\n"), strerror(errno));
    r = -1;
  }

  sftp_close(file);
  return r;

}
Пример #11
0
static int do_scp_write(ssh_scp scp, const char* path, FILE* fp,
                        ftp_transfer_func hookf)
{
  time_t then = time(NULL) - 1;
  ftp_set_close_handler();

  if (hookf)
    hookf(&ftp->ti);
  ftp->ti.begin = false;

  struct stat sb;
  errno = 0;
  if (fstat(fileno(fp), &sb) == -1)
  {
    ftp_err(_("Couldn't fstat local file: %s\n"), strerror(errno));
    ssh_scp_free(scp);
    return -1;
  }

  int rc = ssh_scp_push_file(scp, path, sb.st_size, sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO));
  if (rc != SSH_OK)
  {
    ftp_err(_("Failed to start scp upload: %s\n"),
            ssh_get_error(ftp->session));
    ssh_scp_close(scp);
    ssh_scp_free(scp);
    return -1;
  }

  /* read file */
  char buffer[SSH_BUFSIZ];
  ssize_t nbytes = 0;
  errno = 0;
  while ((nbytes = fread(buffer, sizeof(char), sizeof(buffer), fp)) > 0)
  {
    if (ftp_sigints() > 0)
    {
      ftp_trace("break due to sigint\n");
      break;
    }

    rc = ssh_scp_write(scp, buffer, nbytes);
    if (rc != SSH_OK)
    {
      ftp_err(_("Error while writing to file: %s\n"), ssh_get_error(ftp->session));
      ssh_scp_close(scp);
      ssh_scp_free(scp);
      return -1;
    }

    ftp->ti.size += nbytes;
    if (hookf)
    {
      time_t now = time(NULL);
      if (now > then)
      {
        hookf(&ftp->ti);
        then = now;
      }
    }
    errno = 0;
  }

  if (ferror(fp))
  {
    ftp_err(_("Failed to read from file: %s\n"), strerror(errno));
    rc = -1;
  }

  ssh_scp_close(scp);
  ssh_scp_free(scp);
  return rc;
}
Пример #12
0
static int do_read(const char* infile, FILE* fp, getmode_t mode,
                   ftp_transfer_func hookf, uint64_t offset)
{
  if (gvSSHTrySCP && !offset)
  {
    char* escaped = bash_backslash_quote(infile);
    /* try to set up a scp connection */
    ssh_scp scp = ssh_scp_new(ftp->session, SSH_SCP_READ, escaped);
    free(escaped);
    if (scp != NULL)
    {
      int rc = ssh_scp_init(scp);
      if (rc == SSH_OK)
        return do_scp_read(scp, infile, fp, mode, hookf);
      ssh_scp_free(scp);
    }
  }

  time_t then = time(NULL) - 1;
  ftp_set_close_handler();

  if (hookf)
    hookf(&ftp->ti);
  ftp->ti.begin = false;

  /* check if remote file is not a directory */
  sftp_attributes attrib = sftp_stat(ftp->sftp_session, infile);
  if (!attrib)
    return -1;

  if (S_ISDIR(attrib->permissions))
  {
    ftp_err(_("Cannot download a directory: %s\n"), infile);
    sftp_attributes_free(attrib);
    return -1;
  }
  sftp_attributes_free(attrib);

  /* open remote file */
  sftp_file file = sftp_open(ftp->sftp_session, infile, O_RDONLY, 0);
  if (!file)
  {
    ftp_err(_("Cannot open file for reading: %s\n"), ssh_get_error(ftp->session));
    return -1;
  }

  /* seek to offset */
  int r = sftp_seek64(file, offset);
  if (r != SSH_OK)
  {
    ftp_err(_("Failed to seek: %s\n"), ssh_get_error(ftp->session));
    sftp_close(file);
    return -1;
  }

  /* read file */
  char buffer[SSH_BUFSIZ];
  ssize_t nbytes = 0;
  while ((nbytes = sftp_read(file, buffer, sizeof(buffer))) > 0)
  {
    if (ftp_sigints() > 0)
    {
      ftp_trace("break due to sigint\n");
      break;
    }

    errno = 0;
    if (fwrite(buffer, nbytes, 1, fp) != 1)
    {
      ftp_err(_("Error while writing to file: %s\n"), strerror(errno));
      ftp->ti.ioerror = true;
      sftp_close(file);
      return -1;
    }

    ftp->ti.size += nbytes;
    if (hookf)
    {
      time_t now = time(NULL);
      if (now > then)
      {
        hookf(&ftp->ti);
        then = now;
      }
    }
  }

  if (nbytes < 0)
  {
    ftp_err(_("Error while reading from file: %s\n"), ssh_get_error(ftp->session));
    r = -1;
  }

  sftp_close(file);
  return r;
}
Пример #13
0
static int do_scp_read(ssh_scp scp, const char* infile, FILE* fp,
                       getmode_t mode, ftp_transfer_func hookf)
{
  time_t then = time(NULL) - 1;
  ftp_set_close_handler();

  if (hookf)
    hookf(&ftp->ti);
  ftp->ti.begin = false;

  int rc = ssh_scp_pull_request(scp);
  if (rc != SSH_SCP_REQUEST_NEWFILE)
  {
    ftp_err(_("Failed to start scp download: %s\n"),
            ssh_get_error(ftp->session));
    ssh_scp_close(scp);
    ssh_scp_free(scp);
    return -1;
  }

  size_t size = ssh_scp_request_get_size(scp);
  ssh_scp_accept_request(scp);

  /* read file */
  char buffer[SSH_BUFSIZ];
  int r = 0;
  while (size && (r = ssh_scp_read(scp, buffer, MIN(SSH_BUFSIZ, size))) != SSH_ERROR)
  {
    if (ftp_sigints() > 0)
    {
      ftp_trace("break due to sigint\n");
      break;
    }

    errno = 0;
    if (fwrite(buffer, r, 1, fp) != 1)
    {
      ftp_err(_("Error while writing to file: %s\n"), strerror(errno));
      ssh_scp_close(scp);
      ssh_scp_free(scp);
      return -1;
    }

    ftp->ti.size += r;
    if (hookf)
    {
      time_t now = time(NULL);
      if (now > then)
      {
        hookf(&ftp->ti);
        then = now;
      }
    }
    size -= r;
  }

  if (r == SSH_ERROR)
  {
    ftp_err(_("Error while reading from file: %s\n"), ssh_get_error(ftp->session));
    r = -1;
  }
  else
  {
    r = ssh_scp_pull_request(scp);
    if (r != SSH_SCP_REQUEST_EOF)
      ftp_err(_("Unexpected request: %s %lu\n"), ssh_get_error(ftp->session), size);
    else
      r = 0;
  }

  ssh_scp_close(scp);
  ssh_scp_free(scp);
  return r;
}