예제 #1
0
파일: tunnel.c 프로젝트: Tiedye/seashell
/**
 * seashell_tunnel_connect_password (const char* host, const char* user, const char* password, int* error)
 * Connects to the host via SSH on port 22, and launches a Seashell backend instance for that user
 * on the host.
 *
 * Consults /etc/seashell_hosts for host's SSH public keys.  If this file does not exist,
 * this function will fail for security reasons.  /etc/seashell_hosts is a standard
 * OpenSSH known_hosts file.
 *
 * Arguments:
 *  host - Host to connect to.
 *  user - User to run as.
 *  password - User's password.
 *  error - [optional] denotes error on failure.
 *  remote_addr - Address to which the remote IP address will
 *   be written. Reserve 128 bytes.
 *  family - Address family.
 *  target - Target to execute.
 *
 * Returns:
 *  Handle to connection object on success, NULL otherwise.
 *  If error is NOT null, error will hold more detailed error information.
 */
struct seashell_connection* seashell_tunnel_connect_password (const char* host,
    const char* user,
    const char* password,
    int* error,
    char * remote_addr,
    int* family,
    char* target) {
  struct addrinfo hints;
  struct addrinfo *results, *rp;
  int sockfd;
  int i, e;
  struct seashell_connection* result = NULL;

  /* Resolve the host's address.
   * See getaddrinfo(3) for how this works.
   */
  memset(&hints, 0, sizeof(hints));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = 0;
  hints.ai_protocol = 0;

  e = getaddrinfo(host, "22", &hints, &results);
  if (e != 0) {
    SET_ERROR(TUNNEL_ERROR_RESOLV);
    return NULL;
  }

  for (rp = results; rp != NULL; rp = rp->ai_next) {
    sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
    if (sockfd == -1)
      continue;

    if (connect(sockfd, rp->ai_addr, rp->ai_addrlen) != -1)
      break;

    close(sockfd);
  }

  /* Write address that we're connecting to into
   * remote_addr.
   */

  if(rp != NULL) {
    *family = rp->ai_family;

    switch(rp->ai_family) {
      case AF_INET:
        if(inet_ntop(rp->ai_family, &((struct sockaddr_in *)rp->ai_addr)->sin_addr, remote_addr, 128) == NULL) {
          SET_ERROR(TUNNEL_ERROR_RESOLV);
          return NULL;
        }
        break;
      case AF_INET6:
        if(inet_ntop(rp->ai_family, &((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr, remote_addr, 128) == NULL) {
          SET_ERROR(TUNNEL_ERROR_RESOLV);
          return NULL;
        }
        break;
      default:
        SET_ERROR(TUNNEL_ERROR_RESOLV);
        return NULL;
    }
  }

  freeaddrinfo(results);

  /* Either rp == NULL, in which case we failed at connecting,
   * or sockfd holds our socket.
   */
  if (rp == NULL) {
    SET_ERROR(TUNNEL_ERROR_CONNECT);
    return NULL;
  }

  /** Set up the session */
  LIBSSH2_SESSION* session;
  LIBSSH2_CHANNEL* channel;
  LIBSSH2_KNOWNHOSTS* hosts;
  size_t len;
  int type;

  session = libssh2_session_init();
  if (!session) {
    SET_ERROR(TUNNEL_ERROR_SESSION_START);
    goto session_teardown;
  }

  e = libssh2_session_handshake(session, sockfd);
  if (e) {
    SET_ERROR(TUNNEL_ERROR_SESSION_HANDSHAKE);
    goto session_teardown;
  }

  hosts = libssh2_knownhost_init(session);
  if (!hosts) {
    SET_ERROR(TUNNEL_ERROR_HOSTS_FILE);
    goto session_teardown;
  }

  if (!IS_INSTALLED() && access(DEBUG_HOSTS_FILE, F_OK) != -1) {
    libssh2_knownhost_readfile(hosts, DEBUG_HOSTS_FILE, LIBSSH2_KNOWNHOST_FILE_OPENSSH);
  } else {
    libssh2_knownhost_readfile(hosts, HOSTS_FILE, LIBSSH2_KNOWNHOST_FILE_OPENSSH);
  }

  const char* fingerprint = libssh2_session_hostkey(session, &len, &type);
  if (!fingerprint || type == LIBSSH2_HOSTKEY_TYPE_UNKNOWN) {
    libssh2_knownhost_free(hosts);

    SET_ERROR(TUNNEL_ERROR_HOST);
    goto session_teardown;
  }

  struct libssh2_knownhost *hostkey;
  /** NOTE: Documentation is buggy.  hostkey MUST be passed. */
  int check = libssh2_knownhost_check(hosts, host, fingerprint, len,
      LIBSSH2_KNOWNHOST_TYPE_PLAIN | LIBSSH2_KNOWNHOST_KEYENC_RAW, &hostkey);

  if (check != LIBSSH2_KNOWNHOST_CHECK_MATCH) {
    int keytype = 0;

    switch (type) {
      case LIBSSH2_HOSTKEY_TYPE_RSA:
        keytype = LIBSSH2_KNOWNHOST_KEY_SSHRSA;
        break;
      case LIBSSH2_HOSTKEY_TYPE_DSS:
        keytype = LIBSSH2_KNOWNHOST_KEY_SSHRSA;
        break;
    }

    if (keytype) {
      libssh2_knownhost_addc(hosts, host, NULL, fingerprint, len,
          "Generated from Seashell Tunnel", strlen("Generated from Seashell Tunnel"),
            LIBSSH2_KNOWNHOST_TYPE_PLAIN | LIBSSH2_KNOWNHOST_KEYENC_RAW
          | (type == LIBSSH2_HOSTKEY_TYPE_RSA ? LIBSSH2_KNOWNHOST_KEY_SSHRSA : LIBSSH2_KNOWNHOST_KEY_SSHDSS),
          NULL);

      libssh2_knownhost_writefile(hosts, DUMP_FILE, LIBSSH2_KNOWNHOST_FILE_OPENSSH);
      fprintf(stderr, "%s: Check SSH key for %s! Keys written to %s\n", user, host, DUMP_FILE);
    } else {
      fprintf(stderr, "%s: Check SSH key for %s!\n", user, host, DUMP_FILE);
      fprintf(stderr, "%s: Keys not written to file - contact Seashell Maintainers to add support for the LibSSH2 key format %d\n", user, type);
    }

    libssh2_knownhost_free(hosts);

    SET_ERROR(TUNNEL_ERROR_HOST);
    goto session_teardown;
  }
  libssh2_knownhost_free(hosts);

  FPRINTF_IF_DEBUG(stderr, "%s: Host check passed for %s (fingerprint type %d) - ", user, host, type);
  for(i = 0; i < 20; i++) {
    FPRINTF_IF_DEBUG(stderr, "%02X ", (unsigned char)fingerprint[i]);
  }
  FPRINTF_IF_DEBUG(stderr, "\n");

  e = libssh2_userauth_password(session, user, password);
  if (e) {
    FPRINTF_IF_DEBUG(stderr, "%s: Error authenticating: %d\n", user, e);
    SET_ERROR(TUNNEL_ERROR_CREDS);
    goto session_teardown;
  }

  channel = libssh2_channel_open_session(session);
  if (!channel) {
    SET_ERROR(TUNNEL_ERROR_CHANNEL_OPEN);
    goto session_teardown;
  }

  /**
   * Ideally we'd have a subsystem configured,
   * as I don't see a good way of pulling out of ssh2
   * if the target does not exist.
   */
  e = libssh2_channel_exec(channel, target);
  if (e) {
    SET_ERROR(TUNNEL_ERROR_LAUNCH_SEASHELL);
    goto channel_teardown;
  }

  result = malloc(sizeof(struct seashell_connection));
  if (!result) {
    SET_ERROR(TUNNEL_ERROR_SESSION_START);
    goto channel_teardown;
  }

  result->sockfd = sockfd;
  result->session = session;
  result->channel = channel;

  goto end;
channel_teardown:
  libssh2_channel_free(channel);
session_teardown:
  libssh2_session_free(session);
  close(sockfd);
end:
  return result;
}
예제 #2
0
파일: ssh2_exec.cpp 프로젝트: jabouzi/qt
int main(int argc, char *argv[])
{
    const char *hostname = "184.172.55.146";
    const char *commandline = "cd www/cms.skanderjabouzi.com && svn st -qu > ../file 2>&1  && cat ../file";
    const char *username    = "******";
    const char *password    = "******";
    const int port    = 22;
    unsigned long hostaddr;
    int sock;
    struct sockaddr_in sin;
    const char *fingerprint;
    LIBSSH2_SESSION *session;
    LIBSSH2_CHANNEL *channel;
    int rc;
    int exitcode;
    char *exitsignal=(char *)"none";
    int bytecount = 0;
    size_t len;
    LIBSSH2_KNOWNHOSTS *nh;
    int type;

#ifdef WIN32
    WSADATA wsadata;
    WSAStartup(MAKEWORD(2,0), &wsadata);
#endif
    //if (argc > 1)
    /* must be ip address only */
    //hostname = argv[1];
//
    //if (argc > 2) {
    //username = argv[2];
    //}
    //if (argc > 3) {
    //password = argv[3];
    //}
    //if (argc > 4) {
    //commandline = argv[4];
    //}

    rc = libssh2_init (0);

    if (rc != 0) {
        fprintf (stderr, "libssh2 initialization failed (%d)\n", rc);
        return 1;
    }

    hostaddr = inet_addr(hostname);

    /* Ultra basic "connect to port 22 on localhost"
     * Your code is responsible for creating the socket establishing the
     * connection
     */
    sock = socket(AF_INET, SOCK_STREAM, 0);

    sin.sin_family = AF_INET;
    sin.sin_port = htons(port);
    sin.sin_addr.s_addr = hostaddr;
    if (connect(sock, (struct sockaddr*)(&sin),
                sizeof(struct sockaddr_in)) != 0) {
        fprintf(stderr, "failed to connect!\n");
        return -1;
    }

    /* Create a session instance */
    session = libssh2_session_init();

    if (!session)
        return -1;

    /* tell libssh2 we want it all done non-blocking */
    libssh2_session_set_blocking(session, 0);


    /* ... start it up. This will trade welcome banners, exchange keys,
     * and setup crypto, compression, and MAC layers
     */
    while ((rc = libssh2_session_handshake(session, sock)) ==

            LIBSSH2_ERROR_EAGAIN);
    if (rc) {
        fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
        return -1;
    }

    nh = libssh2_knownhost_init(session);

    if(!nh) {
        /* eeek, do cleanup here */
        return 2;
    }

    /* read all hosts from here */
    libssh2_knownhost_readfile(nh, "known_hosts",

                               LIBSSH2_KNOWNHOST_FILE_OPENSSH);

    /* store all known hosts to here */
    libssh2_knownhost_writefile(nh, "dumpfile",

                                LIBSSH2_KNOWNHOST_FILE_OPENSSH);

    fingerprint = libssh2_session_hostkey(session, &len, &type);

    if(fingerprint) {
        struct libssh2_knownhost *host;
#if LIBSSH2_VERSION_NUM >= 0x010206
        /* introduced in 1.2.6 */
        int check = libssh2_knownhost_checkp(nh, hostname, 22,

                                             fingerprint, len,
                                             LIBSSH2_KNOWNHOST_TYPE_PLAIN|
                                             LIBSSH2_KNOWNHOST_KEYENC_RAW,
                                             &host);
#else
        /* 1.2.5 or older */
        int check = libssh2_knownhost_check(nh, hostname,

                                            fingerprint, len,
                                            LIBSSH2_KNOWNHOST_TYPE_PLAIN|
                                            LIBSSH2_KNOWNHOST_KEYENC_RAW,
                                            &host);
#endif
        fprintf(stderr, "Host check: %d, key: %s\n", check,
                (check <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)?
                host->key:"<none>");

        /*****
         * At this point, we could verify that 'check' tells us the key is
         * fine or bail out.
         *****/
    }
    else {
        /* eeek, do cleanup here */
        return 3;
    }
    libssh2_knownhost_free(nh);


    if ( strlen(password) != 0 ) {
        /* We could authenticate via password */
        while ((rc = libssh2_userauth_password(session, username, password)) ==

                LIBSSH2_ERROR_EAGAIN);
        if (rc) {
            fprintf(stderr, "Authentication by password failed.\n");
            goto shutdown;
        }
    }
    else {
        /* Or by public key */
        while ((rc = libssh2_userauth_publickey_fromfile(session, username,

                     "/home/user/"
                     ".ssh/id_rsa.pub",
                     "/home/user/"
                     ".ssh/id_rsa",
                     password)) ==
                LIBSSH2_ERROR_EAGAIN);
        if (rc) {
            fprintf(stderr, "\tAuthentication by public key failed\n");
            goto shutdown;
        }
    }

#if 0
    libssh2_trace(session, ~0 );

#endif

    /* Exec non-blocking on the remove host */
    while( (channel = libssh2_channel_open_session(session)) == NULL &&

            libssh2_session_last_error(session,NULL,NULL,0) ==

            LIBSSH2_ERROR_EAGAIN )
    {
        waitsocket(sock, session);
    }
    if( channel == NULL )
    {
        fprintf(stderr,"Error1\n");
        exit( 1 );
    }
    while( (rc = libssh2_channel_exec(channel, commandline)) == LIBSSH2_ERROR_EAGAIN )
    {
        waitsocket(sock, session);
    }
    if( rc != 0 )
    {
        fprintf(stderr,"Error2\n");
        exit( 1 );
    }

    for( ;; )
    {
        /* loop until we block */
        int rc;
        do
        {
            char buffer[0x4000];
            rc = libssh2_channel_read( channel, buffer, sizeof(buffer) );

            if( rc > 0 )
            {
                int i;
                bytecount += rc;
                fprintf(stderr, "We read:\n");
                for( i=0; i < rc; ++i )
                    fputc( buffer[i], stderr);
                fprintf(stderr, "\n");
            }
            else {
                if( rc != LIBSSH2_ERROR_EAGAIN )
                    /* no need to output this for the EAGAIN case */
                    fprintf(stderr, "libssh2_channel_read returned %d\n", rc);
            }
        }
        while( rc > 0 );

        /* this is due to blocking that would occur otherwise so we loop on
           this condition */
        if( rc == LIBSSH2_ERROR_EAGAIN )
        {
            waitsocket(sock, session);
        }
        else
            break;
    }
    exitcode = 127;
    while( (rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN )

        waitsocket(sock, session);

    if( rc == 0 )
    {
        exitcode = libssh2_channel_get_exit_status( channel );

        libssh2_channel_get_exit_signal(channel, &exitsignal,

                                        NULL, NULL, NULL, NULL, NULL);
    }

    if (exitsignal)
        fprintf(stderr, "\nGot signal: %s\n", exitsignal);
    else
        fprintf(stderr, "\nEXIT: %d bytecount: %d\n", exitcode, bytecount);

    libssh2_channel_free(channel);

    channel = NULL;

shutdown:

    libssh2_session_disconnect(session,

                               "Normal Shutdown, Thank you for playing");
    libssh2_session_free(session);


#ifdef WIN32
    closesocket(sock);
#else
    close(sock);
#endif
    fprintf(stderr, "all done\n");

    libssh2_exit();


    return 0;
}
예제 #3
0
void CEasyssh::ConnectAP(const std::string str_usr, std::string str_passwd)
{
	WSADATA wsadata;
	WSAStartup(MAKEWORD(2,0), &wsadata);

	int rc = libssh2_init(0);

	if (rc != 0) {
		TRACE(_T("libssh2_init Error\n"));
		m_bIsErr = true;
		return;
	}

	unsigned long hostaddr = inet_addr(m_strIP.c_str());

	m_sock = socket(AF_INET, SOCK_STREAM, 0);

	struct sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(22);
	sin.sin_addr.s_addr = hostaddr;
	if (connect(m_sock, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in)) != 0) {
		TRACE(_T("connect socket Error\n"));
		m_bIsErr = true;
		return;
	}

	/* Create a session instance */ 
	m_ssh_session = libssh2_session_init();
	if (!m_ssh_session)
	{
		TRACE(_T("libssh2_session_init Error\n"));
		m_bIsErr = true;
		return;
	}

    /* tell libssh2 we want it all done non-blocking */ 
    libssh2_session_set_blocking(m_ssh_session, 0);

 
    /* ... start it up. This will trade welcome banners, exchange keys,
     * and setup crypto, compression, and MAC layers
     */ 
    while ((rc = libssh2_session_handshake(m_ssh_session, m_sock)) == LIBSSH2_ERROR_EAGAIN);
    if (rc) {
		TRACE(_T("libssh2_session_handshake Error\n"));
        m_bIsErr = true;
        return;
    }
 
    LIBSSH2_KNOWNHOSTS *nh = libssh2_knownhost_init(m_ssh_session);

    if(!nh) {
        /* eeek, do cleanup here */ 
		TRACE(_T("libssh2_knownhost_init Error\n"));
		m_bIsErr = true;
        return;
    }
 
    /* read all hosts from here */ 
    libssh2_knownhost_readfile(nh, "known_hosts", LIBSSH2_KNOWNHOST_FILE_OPENSSH);
 
    /* store all known hosts to here */ 
    libssh2_knownhost_writefile(nh, "dumpfile",LIBSSH2_KNOWNHOST_FILE_OPENSSH);

    libssh2_knownhost_free(nh);

	while ((rc = libssh2_userauth_password(m_ssh_session, str_usr.c_str(), str_passwd.c_str())) == LIBSSH2_ERROR_EAGAIN);
	if (rc) {
		TRACE(_T("libssh2_userauth_password Error\n"));
		m_bIsErr = true;
		libssh2_session_disconnect(m_ssh_session, "Normal Shutdown, Thank you for playing");
		libssh2_session_free(m_ssh_session);
		closesocket(m_sock);
		libssh2_exit();
	}
	m_bIsErr = false;
}