Skip to content
Snippets Groups Projects
ssh.c 74.4 KiB
Newer Older
  • Learn to ignore specific revisions
  •     return "Link points to itself";
      }
      return "Unknown error in libssh2";
    }
    
    /* BLOCKING */
    static CURLcode sftp_sendquote(struct connectdata *conn,
                                   struct curl_slist *quote)
    {
      struct curl_slist *item=quote;
      const char *cp;
      long err;
      struct SessionHandle *data = conn->data;
      LIBSSH2_SFTP *sftp_session = data->reqdata.proto.ssh->sftp_session;
    
    
      while (item) {
        if (item->data) {
          char *path1 = NULL;
          char *path2 = NULL;
    
          /* the arguments following the command must be separated from the
             command with a space so we can check for it unconditionally */
          cp = strchr(item->data, ' ');
          if (cp == NULL) {
            failf(data, "Syntax error in SFTP command. Supply parameter(s)!");
            return CURLE_FTP_QUOTE_ERROR;
          }
    
          /* also, every command takes at least one argument so we get that first
             argument right now */
          err = get_pathname(&cp, &path1);
          if (err) {
            if (err == CURLE_OUT_OF_MEMORY)
              failf(data, "Out of memory");
            else
              failf(data, "Syntax error: Bad first parameter");
            return err;
          }
    
          /* SFTP is a binary protocol, so we don't send text commands to the
             server. Instead, we scan for commands for commands used by OpenSSH's
             sftp program and call the appropriate libssh2 functions. */
          if (curl_strnequal(item->data, "chgrp ", 6) ||
              curl_strnequal(item->data, "chmod ", 6) ||
              curl_strnequal(item->data, "chown ", 6) ) { /* attribute change */
            LIBSSH2_SFTP_ATTRIBUTES attrs;
    
            /* path1 contains the mode to set */
            err = get_pathname(&cp, &path2);  /* get the destination */
            if (err) {
              if (err == CURLE_OUT_OF_MEMORY)
                failf(data, "Out of memory");
              else
                failf(data,
                      "Syntax error in chgrp/chmod/chown: Bad second parameter");
              free(path1);
              return err;
            }
            memset(&attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
    
    #if (LIBSSH2_APINO >= 200706012030)
            while ((ret = libssh2_sftp_stat(sftp_session,
                                            path2, &attrs)) ==
                   LIBSSH2_ERROR_EAGAIN);
            if (ret != 0) { /* get those attributes */
              err = libssh2_sftp_last_error(sftp_session);
              free(path1);
              free(path2);
              failf(data, "Attempt to get SFTP stats failed: %s",
                    sftp_libssh2_strerror(err));
              return CURLE_FTP_QUOTE_ERROR;
            }
    #else /* !(LIBSSH2_APINO >= 200706012030) */
            if (libssh2_sftp_stat(sftp_session,
                                  path2, &attrs) != 0) { /* get those attributes */
              err = libssh2_sftp_last_error(sftp_session);
              free(path1);
              free(path2);
              failf(data, "Attempt to get SFTP stats failed: %s",
                    sftp_libssh2_strerror(err));
              return CURLE_FTP_QUOTE_ERROR;
            }
    #endif /* !(LIBSSH2_APINO >= 200706012030) */
    
    
            /* Now set the new attributes... */
            if (curl_strnequal(item->data, "chgrp", 5)) {
              attrs.gid = strtol(path1, NULL, 10);
    
              if (attrs.gid == 0 && !ISDIGIT(path1[0])) {
    
                free(path1);
                free(path2);
                failf(data, "Syntax error: chgrp gid not a number");
                return CURLE_FTP_QUOTE_ERROR;
              }
            }
            else if (curl_strnequal(item->data, "chmod", 5)) {
              attrs.permissions = strtol(path1, NULL, 8);/* permissions are octal */
    
              if (attrs.permissions == 0 && !ISDIGIT(path1[0])) {
    
                free(path1);
                free(path2);
                failf(data, "Syntax error: chmod permissions not a number");
                return CURLE_FTP_QUOTE_ERROR;
              }
            }
            else if (curl_strnequal(item->data, "chown", 5)) {
              attrs.uid = strtol(path1, NULL, 10);
    
              if (attrs.uid == 0 && !ISDIGIT(path1[0])) {
    
                free(path1);
                free(path2);
                failf(data, "Syntax error: chown uid not a number");
                return CURLE_FTP_QUOTE_ERROR;
              }
            }
    
            /* Now send the completed structure... */
    
    #if (LIBSSH2_APINO >= 200706012030)
            while ((ret = libssh2_sftp_setstat(sftp_session, path2, &attrs)) ==
                   LIBSSH2_ERROR_EAGAIN);
            if (ret != 0) {
              err = libssh2_sftp_last_error(sftp_session);
              free(path1);
              free(path2);
              failf(data, "Attempt to set SFTP stats failed: %s",
                    sftp_libssh2_strerror(err));
              return CURLE_FTP_QUOTE_ERROR;
            }
    #else /* !(LIBSSH2_APINO >= 200706012030) */
    
            if (libssh2_sftp_setstat(sftp_session, path2, &attrs) != 0) {
              err = libssh2_sftp_last_error(sftp_session);
              free(path1);
              free(path2);
              failf(data, "Attempt to set SFTP stats failed: %s",
                    sftp_libssh2_strerror(err));
              return CURLE_FTP_QUOTE_ERROR;
            }
    
    #endif /* !(LIBSSH2_APINO >= 200706012030) */
    
          }
          else if (curl_strnequal(item->data, "ln ", 3) ||
                   curl_strnequal(item->data, "symlink ", 8)) {
            /* symbolic linking */
            /* path1 is the source */
            err = get_pathname(&cp, &path2);  /* get the destination */
            if (err) {
              if (err == CURLE_OUT_OF_MEMORY)
                failf(data, "Out of memory");
              else
                failf(data,
                      "Syntax error in ln/symlink: Bad second parameter");
              free(path1);
              return err;
            }
    
    #if (LIBSSH2_APINO >= 200706012030)
            while ((ret = libssh2_sftp_symlink(sftp_session, path1, path2)) ==
                   LIBSSH2_ERROR_EAGAIN);
            if (ret != 0) {
              err = libssh2_sftp_last_error(sftp_session);
              free(path1);
              free(path2);
              failf(data, "symlink command failed: %s",
                    sftp_libssh2_strerror(err));
              return CURLE_FTP_QUOTE_ERROR;
            }
    #else /* !(LIBSSH2_APINO >= 200706012030) */
    
            if (libssh2_sftp_symlink(sftp_session, path1, path2) != 0) {
              err = libssh2_sftp_last_error(sftp_session);
              free(path1);
              free(path2);
              failf(data, "symlink command failed: %s",
                    sftp_libssh2_strerror(err));
              return CURLE_FTP_QUOTE_ERROR;
            }
    
    #endif /* !(LIBSSH2_APINO >= 200706012030) */
    
          }
          else if (curl_strnequal(item->data, "mkdir ", 6)) { /* create dir */
    
    #if (LIBSSH2_APINO >= 200706012030)
            while ((ret = libssh2_sftp_mkdir(sftp_session, path1, 0744)) ==
                   LIBSSH2_ERROR_EAGAIN);
            if (ret != 0) {
              err = libssh2_sftp_last_error(sftp_session);
              free(path1);
              failf(data, "mkdir command failed: %s", sftp_libssh2_strerror(err));
              return CURLE_FTP_QUOTE_ERROR;
            }
    #else /* !(LIBSSH2_APINO >= 200706012030) */
    
            if (libssh2_sftp_mkdir(sftp_session, path1, 0744) != 0) {
              err = libssh2_sftp_last_error(sftp_session);
              free(path1);
              failf(data, "mkdir command failed: %s",
                    sftp_libssh2_strerror(err));
              return CURLE_FTP_QUOTE_ERROR;
            }
    
    #endif /* !(LIBSSH2_APINO >= 200706012030) */
    
          }
          else if (curl_strnequal(item->data, "rename ", 7)) { /* rename file */
            /* first param is the source path */
            err = get_pathname(&cp, &path2);  /* second param is the dest. path */
            if (err) {
              if (err == CURLE_OUT_OF_MEMORY)
                failf(data, "Out of memory");
              else
                failf(data,
                      "Syntax error in rename: Bad second parameter");
              free(path1);
              return err;
            }
    
    #if (LIBSSH2_APINO >= 200706012030)
            while ((ret = libssh2_sftp_rename(sftp_session, path1, path2)) ==
                   LIBSSH2_ERROR_EAGAIN);
            if (ret != 0) {
              err = libssh2_sftp_last_error(sftp_session);
              free(path1);
              free(path2);
              failf(data, "rename command failed: %s", sftp_libssh2_strerror(err));
              return CURLE_FTP_QUOTE_ERROR;
            }
    #else /* !(LIBSSH2_APINO >= 200706012030) */
    
            if (libssh2_sftp_rename(sftp_session,
                                    path1, path2) != 0) {
              err = libssh2_sftp_last_error(sftp_session);
              free(path1);
              free(path2);
              failf(data, "rename command failed: %s",
                    sftp_libssh2_strerror(err));
              return CURLE_FTP_QUOTE_ERROR;
            }
    
    #endif /* !(LIBSSH2_APINO >= 200706012030) */
    
          }
          else if (curl_strnequal(item->data, "rmdir ", 6)) { /* delete dir */
    
    #if (LIBSSH2_APINO >= 200706012030)
            while ((ret = libssh2_sftp_rmdir(sftp_session, path1)) ==
                   LIBSSH2_ERROR_EAGAIN);
            if (ret != 0) {
              err = libssh2_sftp_last_error(sftp_session);
              free(path1);
              failf(data, "rmdir command failed: %s", sftp_libssh2_strerror(err));
              return CURLE_FTP_QUOTE_ERROR;
            }
    #else /* !(LIBSSH2_APINO >= 200706012030) */
    
            if (libssh2_sftp_rmdir(sftp_session,
                                   path1) != 0) {
              err = libssh2_sftp_last_error(sftp_session);
              free(path1);
              failf(data, "rmdir command failed: %s",
                    sftp_libssh2_strerror(err));
              return CURLE_FTP_QUOTE_ERROR;
            }
    
    #endif /* !(LIBSSH2_APINO >= 200706012030) */
    
          }
          else if (curl_strnequal(item->data, "rm ", 3)) { /* delete file */
    
    #if (LIBSSH2_APINO >= 200706012030)
            while ((ret = libssh2_sftp_unlink(sftp_session, path1)) ==
                   LIBSSH2_ERROR_EAGAIN);
            if (ret != 0) {
              err = libssh2_sftp_last_error(sftp_session);
              free(path1);
              failf(data, "rm command failed: %s", sftp_libssh2_strerror(err));
              return CURLE_FTP_QUOTE_ERROR;
            }
    #else /* !(LIBSSH2_APINO >= 200706012030) */
    
            if (libssh2_sftp_unlink(sftp_session, path1) != 0) {
              err = libssh2_sftp_last_error(sftp_session);
              free(path1);
              failf(data, "rm command failed: %s",
                    sftp_libssh2_strerror(err));
              return CURLE_FTP_QUOTE_ERROR;
            }
    
    #endif /* !(LIBSSH2_APINO >= 200706012030) */
    
          }
    
          if (path1)
            free(path1);
          if (path2)
            free(path2);
        }
        item = item->next;
      }
    
      (void)ret;    /* possibly unused */
    
    
     * Create the path sftp->path on the remote site
     * returns CURL_OK on success, -1 on failure
    
    static CURLcode sftp_create_dirs(struct connectdata *conn) {
      CURLcode result = CURLE_OK;
      unsigned int sftp_err = 0;
      int rc;
      struct SSHPROTO *sftp = conn->data->reqdata.proto.ssh;
    
      if (strlen(sftp->path) > 1) {
        char *slash_pos = sftp->path + 1; /* ignore the leading '/' */
    
        while ((slash_pos = strchr(slash_pos, '/')) != NULL) {
          *slash_pos = 0;
    
          infof(conn->data, "Creating directory '%s'\n", sftp->path);
          /* 'mode' - parameter is preliminary - default to 0644 */
    #if (LIBSSH2_APINO >= 200706012030)
    
          while ((rc = libssh2_sftp_mkdir(sftp->sftp_session, sftp->path,
    
                                          conn->data->set.new_directory_perms)) ==
    
                 LIBSSH2_ERROR_EAGAIN);
    #else /* !(LIBSSH2_APINO >= 200706012030) */
    
          rc = libssh2_sftp_mkdir(sftp->sftp_session, sftp->path,
    
                                   conn->data->set.new_directory_perms);
    
    #endif /* !(LIBSSH2_APINO >= 200706012030) */
          *slash_pos = '/';
          ++slash_pos;
    
            /* abort if failure wasn't that the dir already exists or the
    
             * permission was denied (creation might succeed further
    
             * down the path) - retry on unspecific FAILURE also
             */
            sftp_err = libssh2_sftp_last_error(sftp->sftp_session);
    
            if ((sftp_err != LIBSSH2_FX_FILE_ALREADY_EXISTS) &&
                (sftp_err != LIBSSH2_FX_FAILURE) &&
    
                (sftp_err != LIBSSH2_FX_PERMISSION_DENIED)) {
              result = -1;
              break;
            }
          }
        }
      }
      return result;