示例#1
0
static void torture_knownhosts_conflict(void **state)
{
    struct torture_state *s = *state;
    ssh_session session = s->ssh.session;
    char known_hosts_file[1024] = {0};
    enum ssh_known_hosts_e found;
    FILE *file = NULL;
    int rc;

    snprintf(known_hosts_file,
             sizeof(known_hosts_file),
             "%s/%s",
             s->socket_dir,
             TORTURE_KNOWN_HOSTS_FILE);

    file = fopen(known_hosts_file, "w");
    assert_non_null(file);
    fprintf(file,
            "127.0.0.10 %s %s\n",
            "ssh-ed25519",
            BAD_ED25519);
    fclose(file);

    rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file);
    assert_ssh_return_code(session, rc);

    rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "ssh-ed25519");
    assert_ssh_return_code(session, rc);

    rc = ssh_connect(session);
    assert_ssh_return_code(session, rc);

    found = ssh_session_is_known_server(session);
    assert_int_equal(found, SSH_KNOWN_HOSTS_CHANGED);

    rc = ssh_session_update_known_hosts(session);
    assert_ssh_return_code(session, rc);

    ssh_disconnect(session);
    ssh_free(session);

    /* connect again and check host key */
    session = ssh_new();
    assert_non_null(session);

    s->ssh.session = session;

    rc = ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER);
    assert_ssh_return_code(session, rc);

    rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file);
    assert_ssh_return_code(session, rc);

    rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "ssh-ed25519");
    assert_ssh_return_code(session, rc);

    rc = ssh_connect(session);
    assert_ssh_return_code(session, rc);

    found = ssh_session_is_known_server(session);
    assert_int_equal(found, SSH_KNOWN_HOSTS_OK);

    /* session will be freed by session_teardown() */
}
示例#2
0
static ssh_session create_ssh_connection(const char* hostname, const unsigned int port, const char* username,
	const char* password, const char* sshkey_path, const char* sshkey_passphrase)
{
	ssh_session sshs;

	/* Open session and set options */
	sshs = ssh_new();
	if (sshs == NULL) {
		errmsg_print("Can't create ssh session");
		return NULL;
	}

	if (!hostname)
		return NULL;

	if (ssh_options_set(sshs, SSH_OPTIONS_HOST, hostname)) {
		errmsg_print("Can't set the hostname: %s\n", hostname);
		goto failure;
	}

	if (port != 0) {
		if (ssh_options_set(sshs, SSH_OPTIONS_PORT, &port)) {
			errmsg_print("Can't set the port: %d\n", port);
			goto failure;
		}
	}

	if (!username)
		username = g_get_user_name();

	if (ssh_options_set(sshs, SSH_OPTIONS_USER, username)) {
		errmsg_print("Can't set the username: %s\n", username);
		goto failure;
	}

	verbose_print("Opening ssh connection to %s@%s:%u\n", username, hostname, port);

	/* Connect to server */
	if (ssh_connect(sshs) != SSH_OK) {
		errmsg_print("Error connecting to %s@%s:%u (%s)\n", username, hostname, port,
			ssh_get_error(sshs));
		goto failure;
	}

#ifdef HAVE_LIBSSH_USERAUTH_AGENT
	verbose_print("Connecting using ssh-agent...");
	/* Try to authenticate using ssh agent */
	if (ssh_userauth_agent(sshs, NULL) == SSH_AUTH_SUCCESS) {
		verbose_print("done\n");
		return sshs;
	}
	verbose_print("failed\n");
#endif

	/* If a public key path has been provided, try to authenticate using it */
	if (sshkey_path) {
		ssh_key pkey = ssh_key_new();
		int ret;

		verbose_print("Connecting using public key in %s...", sshkey_path);
		ret = ssh_pki_import_privkey_file(sshkey_path, sshkey_passphrase, NULL, NULL, &pkey);

		if (ret == SSH_OK) {
			if (ssh_userauth_publickey(sshs, NULL, pkey) == SSH_AUTH_SUCCESS) {
				verbose_print("done\n");
				ssh_key_free(pkey);
				return sshs;
			}
		}
		ssh_key_free(pkey);
		verbose_print("failed (%s)\n", ssh_get_error(sshs));
	}

	/* Try to authenticate using standard public key */
	verbose_print("Connecting using standard public key...");
	if (ssh_userauth_publickey_auto(sshs, NULL, NULL) == SSH_AUTH_SUCCESS) {
		verbose_print("done\n");
		return sshs;
	}
	verbose_print("failed\n");

	/* If a password has been provided and all previous attempts failed, try to use it */
	if (password) {
		verbose_print("Connecting using password...");
		if (ssh_userauth_password(sshs, username, password) == SSH_AUTH_SUCCESS) {
			verbose_print("done\n");
			return sshs;
		}
		verbose_print("failed\n");
	}

	verbose_print("Can't find a valid authentication. Disconnecting.\n");

	/* All authentication failed. Disconnect and return */
	ssh_disconnect(sshs);

failure:
	ssh_free(sshs);
	return NULL;
}
示例#3
0
文件: ssh.c 项目: marsupial/rikiglue
int
ssh_main(int ac, char **av)
{
	if ( ac < 5 )
	{
		printf("usage: <user> <host> <password> <cmd>\n");
		return ( -1 );
	}

	int i, r, exit_status, use_syslog;
	char *argv0, buf[MAXPATHLEN];
	struct stat st;
	struct passwd *pw;
	int timeout_ms;
	Sensitive sensitive_data;
	extern int optind, optreset;
	extern char *optarg;

	/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
	// sanitise_stdfd();

	__progname = ssh_get_progname(av[0]);
	init_rng();

	/*
	 * Save the original real uid.  It will be needed later (uid-swapping
	 * may clobber the real uid).
	 */
	original_real_uid = getuid();
	original_effective_uid = geteuid();

	/*
	 * Use uid-swapping to give up root privileges for the duration of
	 * option processing.  We will re-instantiate the rights when we are
	 * ready to create the privileged port, and will permanently drop
	 * them when the port has been created (actually, when the connection
	 * has been made, as we may need to create the port several times).
	 */
	PRIV_END;

#ifdef HAVE_SETRLIMIT
	/* If we are installed setuid root be careful to not drop core. */
	if (original_real_uid != original_effective_uid) {
		struct rlimit rlim;
		rlim.rlim_cur = rlim.rlim_max = 0;
		if (setrlimit(RLIMIT_CORE, &rlim) < 0)
			fatal("setrlimit failed: %.100s", strerror(errno));
	}
#endif
	/* Get user data. */
	pw = getpwuid(original_real_uid);
	if (!pw) {
		logit("You don't exist, go away!");
		return (-1);
	}
	/* Take a copy of the returned structure. */
	pw = pwcopy(pw);

	/*
	 * Set our umask to something reasonable, as some files are created
	 * with the default umask.  This will make them world-readable but
	 * writable only by the owner, which is ok for all files for which we
	 * don't set the modes explicitly.
	 */
	umask(022);

	/*
	 * Initialize option structure to indicate that no values have been
	 * set.
	 */
	initialize_options(&options);

	use_syslog = 0;
	argv0 = av[0];
	options.user = av[1]; // xstrdup
	host = av[2]; //xstrdup(av[2]);
	strncpy(options.password, av[3], sizeof(options.password));
	buffer_init(&command);
	buffer_append(&command, av[4], strlen(av[4]));
	tty_flag = 0;
	options.port = 22;
	options.strict_host_key_checking = 0;
	// options.log_level = SYSLOG_LEVEL_DEBUG3;

	SSLeay_add_all_algorithms();
	ERR_load_crypto_strings();

	/*
	 * Initialize "log" output.  Since we are the client all output
	 * actually goes to stderr.
	 */
	log_init(argv0,
	    options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level,
	    SYSLOG_FACILITY_USER, !use_syslog);


	/* Fill configuration defaults. */
	fill_default_options(&options);

	channel_set_af(options.address_family);

	/* reinit */
	log_init(argv0, options.log_level, SYSLOG_FACILITY_USER, !use_syslog);

	seed_rng();

	timeout_ms = options.connection_timeout * 1000;

	/* Open a connection to the remote host. */
	if (ssh_connect(host, &hostaddr, options.port,
	    options.address_family, options.connection_attempts, &timeout_ms,
	    options.tcp_keep_alive, 
#ifdef HAVE_CYGWIN
	    options.use_privileged_port,
#else
	    original_effective_uid == 0 && options.use_privileged_port,
#endif
	    options.proxy_command) != 0)
		return -1;

	if (timeout_ms > 0)
		debug3("timeout: %d ms remain after connect", timeout_ms);

	/*
	 * If we successfully made the connection, load the host private key
	 * in case we will need it later for combined rsa-rhosts
	 * authentication. This must be done before releasing extra
	 * privileges, because the file is only readable by root.
	 * If we cannot access the private keys, load the public keys
	 * instead and try to execute the ssh-keysign helper instead.
	 */
	sensitive_data.nkeys = 0;
	sensitive_data.keys = NULL;
	sensitive_data.external_keysign = 0;

	/*
	 * Get rid of any extra privileges that we may have.  We will no
	 * longer need them.  Also, extra privileges could make it very hard
	 * to read identity files and other non-world-readable files from the
	 * user's home directory if it happens to be on a NFS volume where
	 * root is mapped to nobody.
	 */
	if (original_effective_uid == 0) {
		PRIV_START;
		permanently_set_uid(pw);
	}

	signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */

	/* Log into the remote system.  Never returns if the login fails. */
	ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr,
	    pw, timeout_ms);

	/* We no longer need the private host keys.  Clear them now. */
	if (sensitive_data.nkeys != 0) {
		for (i = 0; i < sensitive_data.nkeys; i++) {
			if (sensitive_data.keys[i] != NULL) {
				/* Destroys contents safely */
				debug3("clear hostkey %d", i);
				key_free(sensitive_data.keys[i]);
				sensitive_data.keys[i] = NULL;
			}
		}
		xfree(sensitive_data.keys);
	}
	for (i = 0; i < options.num_identity_files; i++) {
		if (options.identity_files[i]) {
			xfree(options.identity_files[i]);
			options.identity_files[i] = NULL;
		}
		if (options.identity_keys[i]) {
			key_free(options.identity_keys[i]);
			options.identity_keys[i] = NULL;
		}
	}

	exit_status = compat20 ? ssh_session2() : ssh_session();
	packet_close();

	if (options.control_path != NULL && muxserver_sock != -1)
		unlink(options.control_path);

	/*
	 * Send SIGHUP to proxy command if used. We don't wait() in
	 * case it hangs and instead rely on init to reap the child
	 */
	if (proxy_command_pid > 1)
		kill(proxy_command_pid, SIGHUP);

	return exit_status;
}
示例#4
0
ssh_session connect_ssh(const char *host, const char *user,int verbosity)
{
ssh_session session;

int auth=0;

	session=ssh_new();

	if (NULL == session)
	{
		return NULL;
	}

	if(NULL != user)
	{
		if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0)
		{
			ssh_free(session);

			return NULL;
		}
	}

	if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0)
	{
		ssh_free(session);

		return NULL;
	}

	ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);

	if(ssh_connect(session))
	{
		fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));

		ssh_disconnect(session);

		ssh_free(session);

		return NULL;
	}

	if(verify_knownhost(session)<0)
	{
		ssh_disconnect(session);

		ssh_free(session);

		return NULL;
	}

	auth=authenticate_console(session);

	if(SSH_AUTH_SUCCESS == auth)
	{
		return session;
	}
	else
		if(SSH_AUTH_DENIED == auth)
		{
			fprintf(stderr,"Authentication failed\n");
		}
		else
		{
			fprintf(stderr,"Error while authenticating : %s\n",ssh_get_error(session));
		}

		ssh_disconnect(session);

		ssh_free(session);

		return NULL;
}
示例#5
0
static void
accept_cb(struct evconnlistener *listener, evutil_socket_t fd,
    struct sockaddr *sa, int slen, void *p)
{
	ssh_session_t *session_in = NULL, *session_out = NULL;
	struct bufferevent *b_out, *b_in;
	// Create two linked bufferevent objects: one to connect, one for the new connection
	b_in = bufferevent_socket_new(base, fd,
	    BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
	
	b_out = bufferevent_socket_new(base, -1,
	    BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
	
	do_assert(b_in && b_out);
	
	if (bufferevent_socket_connect(b_out,
		(struct sockaddr*)&connect_to_addr, connect_to_addrlen)<0) {
		perror("bufferevent_socket_connect");
		bufferevent_free(b_out);
		bufferevent_free(b_in);
		return;
	}

	// client
	session_in = ssh_new();
	// server
	session_out = ssh_new();
	
	session_in->proxy = 1;
	session_in->type = SSH_SESSION_CLIENT;
	session_in->owner_ptr =  b_out;
	api_name_from_addr(sa, slen, &(session_in->cip),&(session_in->cport));
	api_name_from_addr((struct sockaddr *)&connect_to_addr, connect_to_addrlen, &(session_in->sip),&(session_in->sport));
	ssh_adapter_accept(adapter, session_in);
	session_in->session_ptr = session_out;
	session_in->evbuffer = bufferevent_get_output(b_in);
	session_in->data_send = session_data_send;
	//session_callback_init(session_in);
	ssh_handle_key_exchange(session_in);
	
	bufferevent_setcb(b_in, data_read_handler, data_write_handler, event_error_handler, session_in);
	
	session_out->proxy = 1;
	session_out->session_state = SSH_SESSION_STATE_SOCKET_CONNECTED;
	session_out->type = SSH_SESSION_SERVER;
	session_out->owner_ptr = b_in;
	api_name_from_addr(sa, slen, &(session_out->cip),&(session_out->cport));
	api_name_from_addr((struct sockaddr*)&connect_to_addr, connect_to_addrlen, 
		&(session_out->sip),&(session_out->sport));
	//ssh_adapter_accept(adapter, session_out);
	session_out->session_ptr = session_in;
	session_out->evbuffer = bufferevent_get_output(b_out);
	session_out->data_send = session_data_send;
	//session_callback_init(session_out);
	{
		int ret = ssh_connect(session_out);
		if(ret != SSH_OK) {
			trace_err("init proxy-client failed.");
		}
		/*
		ret = knownhost_verify(session_out);
		if(ret != SSH_OK) {
			trace_err("iknownhost_verify failed.");
		}*/
	}
	ssh_log(session_in, "accept a new session: [%s:%d] -> [%s:%d]",
			session_in->cip, session_in->cport,
			session_in->sip, session_in->sport);
	
	bufferevent_setcb(b_out, data_read_handler, data_write_handler, event_error_handler, session_out);

	bufferevent_enable(b_in, EV_READ|EV_WRITE);
	bufferevent_enable(b_out, EV_READ|EV_WRITE);
}
示例#6
0
int main(int argc, char **argv)
{
    int verbose = SSH_LOG_PROTOCOL;
    int port = 22;
    int rc = 0;
    char *username = "******";
    char *passwd = "2113";
    ssh_session my_ssh_session = ssh_new();

    if (my_ssh_session == NULL)
        exit(-1);

    ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost");
    ssh_options_set(my_ssh_session, SSH_OPTIONS_LOG_VERBOSITY, &verbose);
    ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT, &port);
  
    rc = ssh_connect(my_ssh_session);
    printf("conn: ok=?%d, %d, %s\n", rc==SSH_OK, rc, ssh_get_error(my_ssh_session));

    rc = ssh_userauth_password(my_ssh_session, username, passwd);
    printf("conn: ok=?%d, %d, %s\n", rc==SSH_OK, rc, ssh_get_error(my_ssh_session));

    ssh_channel channel;

    channel = ssh_channel_new(my_ssh_session);
    if (channel == NULL) {

    }

    rc = ssh_channel_open_session(channel);
    printf("conn: ok=?%d, %d, %s\n", rc==SSH_OK, rc, ssh_get_error(my_ssh_session));
    
    rc = ssh_channel_request_exec(channel, "ls -lh");
    printf("conn: ok=?%d, %d, %s\n", rc==SSH_OK, rc, ssh_get_error(my_ssh_session));

    char buffer[100];
    unsigned int nbytes;


    nbytes = ssh_channel_read(channel, buffer, sizeof(buffer)-1, 0);
    buffer[nbytes] = '\0';
    printf("ssh out byte: %d, %s\n", nbytes, buffer);

    while (nbytes > 0) {
        nbytes = ssh_channel_read(channel, buffer, sizeof(buffer)-1, 0);
        buffer[nbytes] = '\0';
        printf("ssh out byte: %d, %s\n", nbytes, buffer);
    }

    nbytes = ssh_channel_read(channel, buffer, sizeof(buffer)-1, 1);
    buffer[nbytes] = '\0';
    printf("ssh err byte: %d, %s\n", nbytes, buffer);

    while (nbytes > 0) {
        nbytes = ssh_channel_read(channel, buffer, sizeof(buffer)-1, 1);
        buffer[nbytes] = '\0';
        printf("ssh err byte: %d, %s\n", nbytes, buffer);
    } 

    ssh_channel_send_eof(channel);
    ssh_channel_close(channel);
    ssh_channel_free(channel);

    ssh_disconnect(my_ssh_session);

    ssh_free(my_ssh_session);

    return 0;
}
示例#7
0
int start_sshkey(int s, char *ip, int port, unsigned char options, char *miscptr, FILE * fp) {
  char *empty = "";
  char *login, *key, keep_login[300];
  int auth_state = 0, rc = 0;
  ssh_private_key privkey;

  if (strlen(login = hydra_get_next_login()) == 0)
    login = empty;
  if (strlen(key = hydra_get_next_password()) == 0)
    key = empty;

  if (new_session) {
    if (session) {
      ssh_disconnect(session);
      ssh_finalize();
      ssh_free(session);
    }

    session = ssh_new();
    ssh_options_set(session, SSH_OPTIONS_PORT, &port);
    ssh_options_set(session, SSH_OPTIONS_HOST, hydra_address2string(ip));
    ssh_options_set(session, SSH_OPTIONS_USER, login);
    ssh_options_set(session, SSH_OPTIONS_COMPRESSION_C_S, "none");
    ssh_options_set(session, SSH_OPTIONS_COMPRESSION_S_C, "none");
    if (ssh_connect(session) != 0) {
      //if the connection was drop, exit and let hydra main handle it
      if (verbose)
        hydra_report(stderr, "[ERROR] could not connect to target port %d\n", port);
      return 3;
    }

    if ((rc = ssh_userauth_none(session, NULL)) == SSH_AUTH_ERROR) {
      return 3;
    } else if (rc == SSH_AUTH_SUCCESS) {
      hydra_report_found_host(port, ip, "sshkey", fp);
      hydra_completed_pair_found();
      if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
        return 2;
      else
        return 1;
    }
  } else
    new_session = 1;

  auth_state = ssh_auth_list(session);
  if ((auth_state & SSH_AUTH_METHOD_PUBLICKEY) > 0) {
    privkey = privatekey_from_file(session, key, 0, NULL);
    if (!privkey) {
      hydra_report(stderr, "[ERROR] skipping invalid private key: \"%s\"\n", key);
      hydra_completed_pair();
      if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
        return 2;

      return 1;
    }
    auth_state = ssh_userauth_pubkey(session, NULL, NULL, privkey);
  } else {
    return 4;
  }

  if (auth_state == SSH_AUTH_ERROR) {
    new_session = 1;
    return 1;
  }

  if (auth_state == SSH_AUTH_SUCCESS || auth_state == SSH_AUTH_PARTIAL) {
    hydra_report_found_host(port, ip, "sshkey", fp);
    hydra_completed_pair_found();
    if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
      return 2;
    return 1;
  } else {
    strncpy(keep_login, login, sizeof(keep_login) - 1);
    keep_login[sizeof(keep_login) - 1] = '\0';
    hydra_completed_pair();
    if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
      return 2;
    login = hydra_get_next_login();
    if (strcmp(login, keep_login) == 0)
      new_session = 0;
    return 1;
  }

  /* not reached */
  return 1;
}
示例#8
0
文件: ssh_cmd.c 项目: casualuser/yafc
int ssh_open_url(url_t* urlp)
{
  ftp->session = ssh_new();
  if (!ftp->session)
    return -1;

  /* set log level */
  if (ftp_get_verbosity() == vbDebug)
  {
    int verbosity = SSH_LOG_PROTOCOL;
    ssh_options_set(ftp->session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
  }

  /* If we have ssh options from yafcrc, load them */
  if (gvSSHOptions) {
    args_t *args = args_create();
    args_init(args, 0, NULL);
    args_push_back(args, gvSSHOptions);
    int argc = 0;
    if (ssh_options_getopt(ftp->session, &argc, args->argv) != SSH_OK) {
      ftp_err(_("Failed to load SSH options from yafcrc config (ssh_options = '%s')\n"), gvSSHOptions);
      ssh_free(ftp->session);
      ftp->session = NULL;
      return -1;
    }
    args->argc = argc;
    args_destroy(args);
  }

  /* set host name */
  ssh_options_set(ftp->session, SSH_OPTIONS_HOST, urlp->hostname);
  /* if we have port use that one */
  if (urlp->port > 0)
    ssh_options_set(ftp->session, SSH_OPTIONS_PORT, &urlp->port);

  /* parse .ssh/config */
  int r = ssh_options_parse_config(ftp->session, NULL);
  if (r != SSH_OK)
  {
    ftp_err(_("Failed to parse ssh config: %s\n"), ssh_get_error(ftp->session));
    ssh_free(ftp->session);
    ftp->session = NULL;
    return r;
  }

  /* if we have username use that one */
  if (urlp->username)
    ssh_options_set(ftp->session, SSH_OPTIONS_USER, urlp->username);

  /* connect to server */
  r = ssh_connect(ftp->session);
  if (r != SSH_OK)
  {
    ftp_err(_("Couldn't initialise connection to server: %s\n"), ssh_get_error(ftp->session));
    ssh_free(ftp->session);
    ftp->session = NULL;
    return r;
  }

  /* verify server */
  if (verify_knownhost(ftp->session))
  {
    ssh_disconnect(ftp->session);
    ssh_free(ftp->session);
    ftp->session = NULL;
    return -1;
  }

  /* authenticate user */
  r = test_several_auth_methods(ftp->session, urlp);
  if (r != SSH_OK)
  {
    ftp_err(_("Authentication failed: %s\n"), ssh_get_error(ftp->session));
    ssh_disconnect(ftp->session);
    ssh_free(ftp->session);
    ftp->session = NULL;
    return -1;
  }

  ftp->ssh_version = ssh_get_version(ftp->session);
  if (!ftp->ssh_version) {
    ftp_err(_("Couldn't initialise connection to server\n"));
    return -1;
  }

  ftp->sftp_session = sftp_new(ftp->session);
  if (!ftp->sftp_session)
  {
    ftp_err(_("Couldn't initialise ftp subsystem: %s\n"), ssh_get_error(ftp->session));
    ssh_disconnect(ftp->session);
    ssh_free(ftp->session);
    ftp->session = NULL;
    return -1;
  }

  r = sftp_init(ftp->sftp_session);
  if (r != SSH_OK)
  {
    ftp_err(_("Couldn't initialise ftp subsystem: %s\n"), ssh_get_error(ftp->sftp_session));
    sftp_free(ftp->sftp_session);
    ftp->sftp_session = NULL;
    ssh_disconnect(ftp->session);
    ssh_free(ftp->session);
    ftp->session = NULL;
    return r;
  }

  ftp->connected = true;
  ftp->loggedin = true;

  free(ftp->homedir);
  ftp->homedir = ftp_getcurdir();

  url_destroy(ftp->url);
  ftp->url = url_clone(urlp);

  free(ftp->curdir);
  ftp->curdir = xstrdup(ftp->homedir);
  free(ftp->prevdir);
  ftp->prevdir = xstrdup(ftp->homedir);
  if (ftp->url->directory)
    ftp_chdir(ftp->url->directory);

  ftp_get_feat();
  return 0;
}
示例#9
0
int
ssh_connect_p (char *haddr, int hport, char *remote_version, char * remote_fingerprint)
{
	struct timeval tv;
	double elapsed_time;

	ssh_session my_ssh_session;
	int  version;
	int myversion;
	int hlen;
	int rc;
	int state;
	int i;
	unsigned char *hash = NULL;
	char *  fingerprint;
	int in_known_host;

	int sshv1,sshv2,sshv3;

	gettimeofday(&tv, NULL);

	my_ssh_session = ssh_new();

	if (my_ssh_session == NULL)
		return STATE_CRITICAL;

	ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, haddr);
	ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT, &hport);
	rc = ssh_connect(my_ssh_session);
	if (rc != SSH_OK) {
		printf ("Connect to Server failed\n");
		exit (STATE_CRITICAL);
	}
	in_known_host=-1;
	state = ssh_is_server_known(my_ssh_session);
	hlen = ssh_get_pubkey_hash(my_ssh_session, &hash);

	/* Get the finger print as a string */
	fingerprint = ssh_get_hexa(hash, hlen);
	if(remote_fingerprint && strcmp(remote_fingerprint, "known_host") == NULL) {
		if(state != SSH_SERVER_KNOWN_OK) {
			printf ("SSH CRITICAL - Fingerprint (%s) checked in known_hosts failed\n", remote_fingerprint,fingerprint);
			exit(STATE_CRITICAL);
		} else {
			in_known_host=1;
		}
	}

	/* FIXME: This alwats eval to false... */
	if(remote_fingerprint && strcmp(remote_fingerprint, "known_host") && strcmp(remote_fingerprint, fingerprint)) {
		printf ("SSH CRITICAL - Fingerprint (%s) mismatched %s\n", remote_fingerprint,fingerprint);
		free(fingerprint);
		exit(STATE_CRITICAL);
	}

	version = ssh_get_openssh_version(my_ssh_session);
	if(remote_version && sscanf(remote_version, "%d.%d.%d", &sshv1, &sshv2, &sshv3)) {
		myversion = SSH_VERSION_INT(sshv1, sshv2, sshv3);
		if(version < myversion) {
			printf ("SSH WARNING version on server is below %s\n", remote_version);
			exit(STATE_CRITICAL);
		}
	}

	elapsed_time = (double)deltime(tv) / 1.0e6;

	printf (_("SSH OK - fingerprint: %s (Version %d) known_host_check:%d | %s\n"),
	        fingerprint, version,in_known_host, fperfdata("time", elapsed_time, "s",
	        FALSE, 0, FALSE, 0, TRUE, 0, TRUE, (int)socket_timeout));
	free(fingerprint);
	ssh_disconnect(my_ssh_session);
	ssh_free(my_ssh_session);
	exit(STATE_OK);

}
示例#10
0
文件: sshclient.cpp 项目: aopui/gnash
bool
SSHClient::sshConnect(int /* fd */, std::string &hostname)
{
//     GNASH_REPORT_FUNCTION;
    char *password;
    char *banner;
    char *hexa;

    // We always need a hostname to connect to
    if (ssh_options_set(_session, SSH_OPTIONS_HOST, hostname.c_str()) < 0) {
	log_error(_("Couldn't set hostname option"));
	return false;
    }

    // We always need a user name for the connection
    if (_user.empty()) {
	if (ssh_options_set(_session, SSH_OPTIONS_USER, _user.c_str()) < 0) {
	    log_error(_("Couldn't set user name option"));
	    return false;
	}
    }
    
    // Start a new session
    _session = ssh_new();
    if(ssh_connect(_session)){
        log_error(_("Connection failed : %s\n"), ssh_get_error(_session));
	sshShutdown();
        return false;
    }

    _state = ssh_is_server_known(_session);

    unsigned char *hash = 0;
    int hlen = ssh_get_pubkey_hash(_session, &hash);
    if (hlen < 0) {
	sshShutdown();
	return false;
    }
    switch(_state){
      case SSH_SERVER_KNOWN_OK:	// ok
	  log_debug(_("SSH Server is currently known: %d"), _state);
	  break; 
      case SSH_SERVER_KNOWN_CHANGED:
	  log_error(_("Host key for server changed : server's one is now: "));
	  ssh_print_hexa(_("Public key hash"), hash, hlen);
	  free(hash);
	  log_error(_("For security reason, connection will be stopped"));
	  sshShutdown();
	  return false;;
      case SSH_SERVER_FOUND_OTHER:
	  log_error(_("The host key for this server was not found but an other type of key exists."));
	  log_error(_("An attacker might change the default server key to confuse your client"
		    " into thinking the key does not exist"
		      "We advise you to rerun the client with -d or -r for more safety."));
	  sshShutdown();
	  return false;;
      case SSH_SERVER_NOT_KNOWN:
	  hexa = ssh_get_hexa(hash, hlen);
	  free(hash);
	  // FIXME: for now, accecpt all new keys, and update the 
	  // $HOME/.ssh/know_hosts file.
#if 0
	  log_error(_("The server is unknown. Do you trust the host key ? (yes,no)"));
	  log_error(_("Public key hash: %s"), hexa);
	  free(hexa);
	  fgets(buf, sizeof(buf), stdin);
	  if(strncasecmp(buf, "yes", 3) != 0){
	      sshShutdown();
	      return false;
	  }
	  log_error(_("This new key will be written on disk for further usage. do you agree? (yes,no) "));
	  fgets(buf, sizeof(buf), stdin);
	  if(strncasecmp(buf, "yes", 3)==0){
	      if(ssh_write_knownhost(_session))
		  log_error(ssh_get_error(_session));
	  }
#else
	  if(ssh_write_knownhost(_session)) {
	      log_error(ssh_get_error(_session));
	  }
#endif  
	  break;
      case SSH_SERVER_ERROR:
	  free(hash);
	  log_error(ssh_get_error(_session));
	  sshShutdown();
	  return false;
    }
    
    free(hash);
    
    ssh_userauth_none(_session, NULL);
    
    int auth = ssh_auth_list(_session);

//    log_debug("auth: 0x%04x", auth);
    log_debug(_("supported auth methods: "));
    if (auth & SSH_AUTH_METHOD_PUBLICKEY) {
	log_debug(_("\tpublickey"));
    }
    if (auth & SSH_AUTH_METHOD_INTERACTIVE) {
	log_debug(_("\tkeyboard-interactive"));
    }

    /* no ? you should :) */
    auth=ssh_userauth_autopubkey(_session, NULL);
    if(auth == SSH_AUTH_ERROR){
        log_debug(_("Authenticating with pubkey: %s"), ssh_get_error(_session));
	ssh_finalize();
        return false;
    }
    banner = ssh_get_issue_banner(_session);
    if(banner){
        log_debug(banner);
        free(banner);
    }
    if(auth != SSH_AUTH_SUCCESS){
        auth = authKbdint(_session);
        if(auth == SSH_AUTH_ERROR){
            log_error(_("authenticating with keyb-interactive: %s"),
		      ssh_get_error(_session));
	    ssh_finalize();
            return false;
        }
    }
    if(auth != SSH_AUTH_SUCCESS){
        password = getpass("Password: "******"Authentication failed: %s"), ssh_get_error(_session));
            ssh_disconnect(_session);
                ssh_finalize();
            return false;
        }
        memset(password, 0, strlen(password));
    }
    ssh_log(_session, SSH_LOG_FUNCTIONS, "Authentication success");

#if 0
    if(strstr(argv[0],"sftp")){
        sftp = 1;
        ssh_log(_session, SSH_LOG_FUNCTIONS, "Doing sftp instead");
    }
    if(!sftp){
        if(!cmds[0])
            shell(_session);
        else
            batch_shell(_session);
    }
    else
        do_sftp(_session);
    if(!sftp && !cmds[0])
        do_cleanup(0);
#endif
    
    return true;
}
示例#11
0
/*
 * Main program for the ssh client.
 */
int
main(int ac, char **av)
{
	int i, opt, exit_status;
	u_short fwd_port, fwd_host_port;
	char sfwd_port[6], sfwd_host_port[6];
	char *p, *cp, buf[256];
	struct stat st;
	struct passwd *pw;
	int dummy;
	extern int optind, optreset;
	extern char *optarg;

	__progname = get_progname(av[0]);
	init_rng();

	/*
	 * Save the original real uid.  It will be needed later (uid-swapping
	 * may clobber the real uid).
	 */
	original_real_uid = getuid();
	original_effective_uid = geteuid();
 
	/*
	 * Use uid-swapping to give up root privileges for the duration of
	 * option processing.  We will re-instantiate the rights when we are
	 * ready to create the privileged port, and will permanently drop
	 * them when the port has been created (actually, when the connection
	 * has been made, as we may need to create the port several times).
	 */
	PRIV_END;

#ifdef HAVE_SETRLIMIT
	/* If we are installed setuid root be careful to not drop core. */
	if (original_real_uid != original_effective_uid) {
		struct rlimit rlim;
		rlim.rlim_cur = rlim.rlim_max = 0;
		if (setrlimit(RLIMIT_CORE, &rlim) < 0)
			fatal("setrlimit failed: %.100s", strerror(errno));
	}
#endif
	/* Get user data. */
	pw = getpwuid(original_real_uid);
	if (!pw) {
		log("You don't exist, go away!");
		exit(1);
	}
	/* Take a copy of the returned structure. */
	pw = pwcopy(pw);

	/*
	 * Set our umask to something reasonable, as some files are created
	 * with the default umask.  This will make them world-readable but
	 * writable only by the owner, which is ok for all files for which we
	 * don't set the modes explicitly.
	 */
	umask(022);

	/* Initialize option structure to indicate that no values have been set. */
	initialize_options(&options);

	/* Parse command-line arguments. */
	host = NULL;

again:
	while ((opt = getopt(ac, av,
	    "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:NPR:TVX")) != -1) {
		switch (opt) {
		case '1':
			options.protocol = SSH_PROTO_1;
			break;
		case '2':
			options.protocol = SSH_PROTO_2;
			break;
		case '4':
			IPv4or6 = AF_INET;
			break;
		case '6':
			IPv4or6 = AF_INET6;
			break;
		case 'n':
			stdin_null_flag = 1;
			break;
		case 'f':
			fork_after_authentication_flag = 1;
			stdin_null_flag = 1;
			break;
		case 'x':
			options.forward_x11 = 0;
			break;
		case 'X':
			options.forward_x11 = 1;
			break;
		case 'g':
			options.gateway_ports = 1;
			break;
		case 'P':	/* deprecated */
			options.use_privileged_port = 0;
			break;
		case 'a':
			options.forward_agent = 0;
			break;
		case 'A':
			options.forward_agent = 1;
			break;
#ifdef AFS
		case 'k':
			options.kerberos_tgt_passing = 0;
			options.afs_token_passing = 0;
			break;
#endif
		case 'i':
			if (stat(optarg, &st) < 0) {
				fprintf(stderr, "Warning: Identity file %s "
				    "does not exist.\n", optarg);
				break;
			}
			if (options.num_identity_files >=
			    SSH_MAX_IDENTITY_FILES)
				fatal("Too many identity files specified "
				    "(max %d)", SSH_MAX_IDENTITY_FILES);
			options.identity_files[options.num_identity_files++] =
			    xstrdup(optarg);
			break;
		case 'I':
#ifdef SMARTCARD
			options.smartcard_device = xstrdup(optarg);
#else
			fprintf(stderr, "no support for smartcards.\n");
#endif
			break;
		case 't':
			if (tty_flag)
				force_tty_flag = 1;
			tty_flag = 1;
			break;
		case 'v':
			if (0 == debug_flag) {
				debug_flag = 1;
				options.log_level = SYSLOG_LEVEL_DEBUG1;
			} else if (options.log_level < SYSLOG_LEVEL_DEBUG3) {
				options.log_level++;
				break;
			} else
				fatal("Too high debugging level.");
			/* fallthrough */
		case 'V':
			fprintf(stderr,
			    "%s, SSH protocols %d.%d/%d.%d, OpenSSL 0x%8.8lx\n",
			    SSH_VERSION,
			    PROTOCOL_MAJOR_1, PROTOCOL_MINOR_1,
			    PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2,
			    SSLeay());
			if (opt == 'V')
				exit(0);
			break;
		case 'q':
			options.log_level = SYSLOG_LEVEL_QUIET;
			break;
		case 'e':
			if (optarg[0] == '^' && optarg[2] == 0 &&
			    (u_char) optarg[1] >= 64 &&
			    (u_char) optarg[1] < 128)
				options.escape_char = (u_char) optarg[1] & 31;
			else if (strlen(optarg) == 1)
				options.escape_char = (u_char) optarg[0];
			else if (strcmp(optarg, "none") == 0)
				options.escape_char = SSH_ESCAPECHAR_NONE;
			else {
				fprintf(stderr, "Bad escape character '%s'.\n",
				    optarg);
				exit(1);
			}
			break;
		case 'c':
			if (ciphers_valid(optarg)) {
				/* SSH2 only */
				options.ciphers = xstrdup(optarg);
				options.cipher = SSH_CIPHER_ILLEGAL;
			} else {
				/* SSH1 only */
				options.cipher = cipher_number(optarg);
				if (options.cipher == -1) {
					fprintf(stderr,
					    "Unknown cipher type '%s'\n",
					    optarg);
					exit(1);
				}
				if (options.cipher == SSH_CIPHER_3DES)
					options.ciphers = "3des-cbc";
				else if (options.cipher == SSH_CIPHER_BLOWFISH)
					options.ciphers = "blowfish-cbc";
				else
					options.ciphers = (char *)-1;
			}
			break;
		case 'm':
			if (mac_valid(optarg))
				options.macs = xstrdup(optarg);
			else {
				fprintf(stderr, "Unknown mac type '%s'\n",
				    optarg);
				exit(1);
			}
			break;
		case 'p':
			options.port = a2port(optarg);
			if (options.port == 0) {
				fprintf(stderr, "Bad port '%s'\n", optarg);
				exit(1);
			}
			break;
		case 'l':
			options.user = optarg;
			break;

		case 'L':
		case 'R':
			if (sscanf(optarg, "%5[0-9]:%255[^:]:%5[0-9]",
			    sfwd_port, buf, sfwd_host_port) != 3 &&
			    sscanf(optarg, "%5[0-9]/%255[^/]/%5[0-9]",
			    sfwd_port, buf, sfwd_host_port) != 3) {
				fprintf(stderr,
				    "Bad forwarding specification '%s'\n",
				    optarg);
				usage();
				/* NOTREACHED */
			}
			if ((fwd_port = a2port(sfwd_port)) == 0 ||
			    (fwd_host_port = a2port(sfwd_host_port)) == 0) {
				fprintf(stderr,
				    "Bad forwarding port(s) '%s'\n", optarg);
				exit(1);
			}
			if (opt == 'L')
				add_local_forward(&options, fwd_port, buf,
				    fwd_host_port);
			else if (opt == 'R')
				add_remote_forward(&options, fwd_port, buf,
				    fwd_host_port);
			break;

		case 'D':
			fwd_port = a2port(optarg);
			if (fwd_port == 0) {
				fprintf(stderr, "Bad dynamic port '%s'\n",
				    optarg);
				exit(1);
			}
			add_local_forward(&options, fwd_port, "socks4", 0);
			break;

		case 'C':
			options.compression = 1;
			break;
		case 'N':
			no_shell_flag = 1;
			no_tty_flag = 1;
			break;
		case 'T':
			no_tty_flag = 1;
			break;
		case 'o':
			dummy = 1;
			if (process_config_line(&options, host ? host : "",
			    optarg, "command-line", 0, &dummy) != 0)
				exit(1);
			break;
		case 's':
			subsystem_flag = 1;
			break;
		case 'b':
			options.bind_address = optarg;
			break;
		case 'F':
			config = optarg;
			break;
		default:
			usage();
		}
	}

	ac -= optind;
	av += optind;

	if (ac > 0 && !host && **av != '-') {
		if (strrchr(*av, '@')) {
			p = xstrdup(*av);
			cp = strrchr(p, '@');
			if (cp == NULL || cp == p)
				usage();
			options.user = p;
			*cp = '\0';
			host = ++cp;
		} else
			host = *av;
		if (ac > 1) {
			optind = optreset = 1;
			goto again;
		}
		ac--, av++;
	}

	/* Check that we got a host name. */
	if (!host)
		usage();

	SSLeay_add_all_algorithms();
	ERR_load_crypto_strings();
	channel_set_af(IPv4or6);

	/* Initialize the command to execute on remote host. */
	buffer_init(&command);

	/*
	 * Save the command to execute on the remote host in a buffer. There
	 * is no limit on the length of the command, except by the maximum
	 * packet size.  Also sets the tty flag if there is no command.
	 */
	if (!ac) {
		/* No command specified - execute shell on a tty. */
		tty_flag = 1;
		if (subsystem_flag) {
			fprintf(stderr,
			    "You must specify a subsystem to invoke.\n");
			usage();
		}
	} else {
		/* A command has been specified.  Store it into the buffer. */
		for (i = 0; i < ac; i++) {
			if (i)
				buffer_append(&command, " ", 1);
			buffer_append(&command, av[i], strlen(av[i]));
		}
	}

	/* Cannot fork to background if no command. */
	if (fork_after_authentication_flag && buffer_len(&command) == 0 && !no_shell_flag)
		fatal("Cannot fork into background without a command to execute.");

	/* Allocate a tty by default if no command specified. */
	if (buffer_len(&command) == 0)
		tty_flag = 1;

	/* Force no tty */
	if (no_tty_flag)
		tty_flag = 0;
	/* Do not allocate a tty if stdin is not a tty. */
	if (!isatty(fileno(stdin)) && !force_tty_flag) {
		if (tty_flag)
			log("Pseudo-terminal will not be allocated because stdin is not a terminal.");
		tty_flag = 0;
	}

	/*
	 * Initialize "log" output.  Since we are the client all output
	 * actually goes to stderr.
	 */
	log_init(av[0], options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level,
	    SYSLOG_FACILITY_USER, 1);

	/*
	 * Read per-user configuration file.  Ignore the system wide config
	 * file if the user specifies a config file on the command line.
	 */
	if (config != NULL) {
		if (!read_config_file(config, host, &options))
			fatal("Can't open user config file %.100s: "
			    "%.100s", config, strerror(errno));
	} else  {
		snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir,
		    _PATH_SSH_USER_CONFFILE);
		(void)read_config_file(buf, host, &options);

		/* Read systemwide configuration file after use config. */
		(void)read_config_file(_PATH_HOST_CONFIG_FILE, host, &options);
	}

	/* Fill configuration defaults. */
	fill_default_options(&options);

	/* reinit */
	log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 1);

	seed_rng();

	if (options.user == NULL)
		options.user = xstrdup(pw->pw_name);

	if (options.hostname != NULL)
		host = options.hostname;

	if (options.proxy_command != NULL &&
	    strcmp(options.proxy_command, "none") == 0)
		options.proxy_command = NULL;

	/* Disable rhosts authentication if not running as root. */
#ifdef HAVE_CYGWIN
	/* Ignore uid if running under Windows */
	if (!options.use_privileged_port) {
#else
	if (original_effective_uid != 0 || !options.use_privileged_port) {
#endif
		debug("Rhosts Authentication disabled, "
		    "originating port will not be trusted.");
		options.rhosts_authentication = 0;
	}
	/* Open a connection to the remote host. */

	if (ssh_connect(host, &hostaddr, options.port, IPv4or6,
	    options.connection_attempts,
#ifdef HAVE_CYGWIN
	    options.use_privileged_port,
#else
	    original_effective_uid == 0 && options.use_privileged_port,
#endif
	    options.proxy_command) != 0)
		exit(1);

	/*
	 * If we successfully made the connection, load the host private key
	 * in case we will need it later for combined rsa-rhosts
	 * authentication. This must be done before releasing extra
	 * privileges, because the file is only readable by root.
	 * If we cannot access the private keys, load the public keys
	 * instead and try to execute the ssh-keysign helper instead.
	 */
	sensitive_data.nkeys = 0;
	sensitive_data.keys = NULL;
	sensitive_data.external_keysign = 0;
	if (options.rhosts_rsa_authentication ||
	    options.hostbased_authentication) {
		sensitive_data.nkeys = 3;
		sensitive_data.keys = xmalloc(sensitive_data.nkeys *
		    sizeof(Key));

		PRIV_START;
		sensitive_data.keys[0] = key_load_private_type(KEY_RSA1,
		    _PATH_HOST_KEY_FILE, "", NULL);
		sensitive_data.keys[1] = key_load_private_type(KEY_DSA,
		    _PATH_HOST_DSA_KEY_FILE, "", NULL);
		sensitive_data.keys[2] = key_load_private_type(KEY_RSA,
		    _PATH_HOST_RSA_KEY_FILE, "", NULL);
		PRIV_END;

		if (options.hostbased_authentication == 1 &&
		    sensitive_data.keys[0] == NULL &&
		    sensitive_data.keys[1] == NULL &&
		    sensitive_data.keys[2] == NULL) {
			sensitive_data.keys[1] = key_load_public(
			    _PATH_HOST_DSA_KEY_FILE, NULL);
			sensitive_data.keys[2] = key_load_public(
			    _PATH_HOST_RSA_KEY_FILE, NULL);
			sensitive_data.external_keysign = 1;
		}
	}
	/*
	 * Get rid of any extra privileges that we may have.  We will no
	 * longer need them.  Also, extra privileges could make it very hard
	 * to read identity files and other non-world-readable files from the
	 * user's home directory if it happens to be on a NFS volume where
	 * root is mapped to nobody.
	 */
	seteuid(original_real_uid);
	setuid(original_real_uid);

	/*
	 * Now that we are back to our own permissions, create ~/.ssh
	 * directory if it doesn\'t already exist.
	 */
	snprintf(buf, sizeof buf, "%.100s%s%.100s", pw->pw_dir, strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR);
	if (stat(buf, &st) < 0)
		if (mkdir(buf, 0700) < 0)
			error("Could not create directory '%.200s'.", buf);

	/* load options.identity_files */
	load_public_identity_files();

	/* Expand ~ in known host file names. */
	/* XXX mem-leaks: */
	options.system_hostfile =
	    tilde_expand_filename(options.system_hostfile, original_real_uid);
	options.user_hostfile =
	    tilde_expand_filename(options.user_hostfile, original_real_uid);
	options.system_hostfile2 =
	    tilde_expand_filename(options.system_hostfile2, original_real_uid);
	options.user_hostfile2 =
	    tilde_expand_filename(options.user_hostfile2, original_real_uid);

	signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */

	/* Log into the remote system.  This never returns if the login fails. */
	ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr, pw);

	/* We no longer need the private host keys.  Clear them now. */
	if (sensitive_data.nkeys != 0) {
		for (i = 0; i < sensitive_data.nkeys; i++) {
			if (sensitive_data.keys[i] != NULL) {
				/* Destroys contents safely */
				debug3("clear hostkey %d", i);
				key_free(sensitive_data.keys[i]);
				sensitive_data.keys[i] = NULL;
			}
		}
		xfree(sensitive_data.keys);
	}
	for (i = 0; i < options.num_identity_files; i++) {
		if (options.identity_files[i]) {
			xfree(options.identity_files[i]);
			options.identity_files[i] = NULL;
		}
		if (options.identity_keys[i]) {
			key_free(options.identity_keys[i]);
			options.identity_keys[i] = NULL;
		}
	}

	exit_status = compat20 ? ssh_session2() : ssh_session();
	packet_close();

	/*
	 * Send SIGHUP to proxy command if used. We don't wait() in 
	 * case it hangs and instead rely on init to reap the child
	 */
	if (proxy_command_pid > 1)
		kill(proxy_command_pid, SIGHUP);

	return exit_status;
}

static void
x11_get_proto(char **_proto, char **_data)
{
	char line[512];
	static char proto[512], data[512];
	FILE *f;
	int got_data = 0, i;
	char *display;
	struct stat st;

	*_proto = proto;
	*_data = data;
	proto[0] = data[0] = '\0';
	if (!options.xauth_location ||
	    (stat(options.xauth_location, &st) == -1)) {
		debug("No xauth program.");
	} else {
		if ((display = getenv("DISPLAY")) == NULL) {
			debug("x11_get_proto: DISPLAY not set");
			return;
		}
		/* Try to get Xauthority information for the display. */
		if (strncmp(display, "localhost:", 10) == 0)
			/*
			 * Handle FamilyLocal case where $DISPLAY does
			 * not match an authorization entry.  For this we
			 * just try "xauth list unix:displaynum.screennum".
			 * XXX: "localhost" match to determine FamilyLocal
			 *      is not perfect.
			 */
			snprintf(line, sizeof line, "%s list unix:%s 2>"
			    _PATH_DEVNULL, options.xauth_location, display+10);
		else
			snprintf(line, sizeof line, "%s list %.200s 2>"
			    _PATH_DEVNULL, options.xauth_location, display);
		debug2("x11_get_proto: %s", line);
		f = popen(line, "r");
		if (f && fgets(line, sizeof(line), f) &&
		    sscanf(line, "%*s %511s %511s", proto, data) == 2)
			got_data = 1;
		if (f)
			pclose(f);
	}
	/*
	 * If we didn't get authentication data, just make up some
	 * data.  The forwarding code will check the validity of the
	 * response anyway, and substitute this data.  The X11
	 * server, however, will ignore this fake data and use
	 * whatever authentication mechanisms it was using otherwise
	 * for the local connection.
	 */
	if (!got_data) {
		u_int32_t rand = 0;

		log("Warning: No xauth data; using fake authentication data for X11 forwarding.");
		strlcpy(proto, "MIT-MAGIC-COOKIE-1", sizeof proto);
		for (i = 0; i < 16; i++) {
			if (i % 4 == 0)
				rand = arc4random();
			snprintf(data + 2 * i, sizeof data - 2 * i, "%02x", rand & 0xff);
			rand >>= 8;
		}
	}
示例#12
0
int ssh_open_url(url_t *urlp)
{
	char *sftp = gvSFTPServerProgram;
	char *s;
	int r;

	args_clear(ftp->ssh_args);

	if(urlp->sftp_server)
		sftp = urlp->sftp_server;

	args_push_back(ftp->ssh_args, gvSSHProgram);
	if(gvSSHOptions && strlen(gvSSHOptions))
		args_push_back(ftp->ssh_args, gvSSHOptions);
	args_push_back(ftp->ssh_args, urlp->hostname);

	r = get_username(urlp, gvUsername, false);
	if(r != 0)
		return r;

	if(urlp->username) {
		args_push_back(ftp->ssh_args, "-l");
		args_push_back(ftp->ssh_args, urlp->username);
	} else {
		/* we need a username, otherwise other functions will fail
		 */
		urlp->username = xstrdup(gvUsername);
	}

	if(urlp->port) {
		char *p;
		asprintf(&p, "%d", urlp->port);
		args_push_back(ftp->ssh_args, "-p");
		args_push_back(ftp->ssh_args, p);
		free(p);
	}

	if(ftp_get_verbosity() == vbDebug)
		args_push_back(ftp->ssh_args, "-v");

	/* no subsystem if the server-spec contains a '/' */
	if(sftp == 0 || strchr(sftp, '/') == 0)
		args_push_back(ftp->ssh_args, "-s");

	/* Otherwise finish up and return the arg array */
	if(sftp != 0)
		args_push_back(ftp->ssh_args, sftp);
	else
		args_push_back(ftp->ssh_args, "sftp");

	s = args_cat2(ftp->ssh_args, 0);
	ftp_trace("SSH args: %s\n", s);
	if(ftp_get_verbosity() == vbDebug)
		fprintf(stderr, "SSH args: %s\n", s);
	free(s);

	args_add_null(ftp->ssh_args);

	if(ssh_connect(ftp->ssh_args->argv, &ftp->ssh_in, &ftp->ssh_out,
				   &ftp->ssh_pid) == -1)
		{
			return -1;
		}

	ftp->ssh_version = ssh_init();
	if(ftp->ssh_version == -1) {
		ftp_err("Couldn't initialise connection to server\n");
		return -1;
	}

	ftp->connected = true;
	ftp->loggedin = true;

	ftp->homedir = ftp_getcurdir();

	url_destroy(ftp->url);
	ftp->url = url_clone(urlp);

	ftp->curdir = xstrdup(ftp->homedir);
	ftp->prevdir = xstrdup(ftp->homedir);
	if(ftp->url->directory)
		ftp_chdir(ftp->url->directory);

	ftp_get_feat();

	return 0;
}
示例#13
0
文件: torture.c 项目: MachalkA/libssh
ssh_session torture_ssh_session(const char *host,
                                const char *user,
                                const char *password) {
    ssh_session session;
    int rc;

    if (host == NULL) {
        return NULL;
    }

    session = ssh_new();
    if (session == NULL) {
        return NULL;
    }

    if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) {
        goto failed;
    }

    if (user != NULL) {
        if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
            goto failed;
        }
    }

    if (ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity) < 0) {
        goto failed;
    }

    if (ssh_connect(session)) {
        goto failed;
    }

    /* We are in testing mode, so consinder the hostkey as verified ;) */

    /* This request should return a SSH_REQUEST_DENIED error */
    rc = ssh_userauth_none(session, NULL);
    if (rc == SSH_ERROR) {
        goto failed;
    }
    if (!(ssh_auth_list(session) & SSH_AUTH_METHOD_INTERACTIVE)) {
        goto failed;
    }

    if (password != NULL) {
        rc = _torture_auth_kbdint(session, password);
    } else {
        rc = ssh_userauth_autopubkey(session, NULL);
        if (rc == SSH_AUTH_ERROR) {
            goto failed;
        }
    }
    if (rc != SSH_AUTH_SUCCESS) {
        goto failed;
    }

    return session;
failed:
    if (ssh_is_connected(session)) {
        ssh_disconnect(session);
    }
    ssh_free(session);

    return NULL;
}
示例#14
0
bool SSH_Socket::onEnter()
{
    // For testing and getting debugging output
    //int verb = SSH_LOG_PROTOCOL;
    int rc;

    // Setup new SSH Shell
    session = ssh_new();
    if(session == nullptr)
    {
        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION,
            "Closed Session", "User has closed the program.", nullptr);

        TheSocketHandler::Instance()->setActive(false);
        return false;
    }

    std::cout << "Connecting to: " << host << ":" << port << std::endl;
    std::cout << "User: "******"Starting up SSH Connection, this can take few moments" << std::endl;

    // SSH Connect
    rc = ssh_connect(session);
    if(rc != SSH_OK)
    {
        std::cout << "Error: ssh_connect: " << host
            << " " << ssh_get_error(session) << std::endl;

        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION,
            "Closed Session", "Unable to Connect to Server!", nullptr);

        TheSocketHandler::Instance()->setActive(false);
        return false;
    }

    // Verify Server is a known host.
    rc = verify_knownhost();
    if(rc < 0)
    {
        std::cout << "Error: verify_knownhost: " << host
            << " " << ssh_get_error(session) << " " << rc << std::endl;

        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION,
            "Closed Session", "User has closed the program.", nullptr);

        TheSocketHandler::Instance()->setActive(false);
        return false;
    }

    //if ((ssh_userauth_password(session, NULL, password) == SSH_AUTH_SUCCESS)
    rc = authenticate_console();
    if(rc != SSH_AUTH_SUCCESS)
    {
         std::cout << "Error: authenticate: " << host
            << " " << ssh_get_error(session) << " " << rc << std::endl;

        TheSocketHandler::Instance()->setActive(false);
        return false;
    }

    // Setup Channel for Socket Communications
    sshChannel = ssh_channel_new(session);
    if(sshChannel == nullptr)
    {
        std::cout << "Error: ssh_channel_new: " << host
            << " " << ssh_get_error(session) << " " << rc << std::endl;

        TheSocketHandler::Instance()->setActive(false);
        return false;
    }

    // Open A shell Session
    rc = ssh_channel_open_session(sshChannel);
    if(rc != SSH_OK)
    {
        std::cout << "Error: ssh_channel_open_session: " << host
            << " " << ssh_get_error(session) << " " << rc << std::endl;

        TheSocketHandler::Instance()->setActive(false);
        return false;
    }

    /* Don't need this when we use the PTY size, it does both!
    // Setup sockets or "channels" within the session
    if(ssh_channel_request_pty(sshChannel))
    {
        printf("\r\n SSH Error, Request for PTY Failed. %s: %s - %i \r\n",
        host, ssh_get_error(session), rc);
        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION,
             "Closed Session",
             "User has closed the program.",
             NULL);
        onExit();
    }*/

    // Set the term and pty size of the terminal.
    // Only After the Shell has been initialized.
    if(ssh_channel_request_pty_size(sshChannel, "ansi", 80, 25))
    {
        std::cout << "Error: ssh_channel_request_pty_size: " << host
            << " " << ssh_get_error(session) << " " << rc << std::endl;
        // Not an error to exit the connection on.
        //return 0;
    }

    // Now request a shell with the pty to get read/write
    if(ssh_channel_request_shell(sshChannel))
    {
        std::cout << "Error: ssh_channel_request_shell: " << host
            << " " << ssh_get_error(session) << " " << rc << std::endl;

        TheSocketHandler::Instance()->setActive(false);
        return false;
    }
    return true;
}
示例#15
0
int start_ssh(int s, char *ip, int port, unsigned char options, char *miscptr, FILE * fp) {
  char *empty = "";
  char *login, *pass, keep_login[300];
  int auth_state = 0, rc = 0, i = 0;

  if (strlen(login = hydra_get_next_login()) == 0)
    login = empty;
  if (strlen(pass = hydra_get_next_password()) == 0)
    pass = empty;

  if (new_session) {
    if (session) {
      ssh_disconnect(session);
      ssh_finalize();
      ssh_free(session);
    }

    session = ssh_new();
    ssh_options_set(session, SSH_OPTIONS_PORT, &port);
    ssh_options_set(session, SSH_OPTIONS_HOST, hydra_address2string(ip));
    ssh_options_set(session, SSH_OPTIONS_USER, login);
    ssh_options_set(session, SSH_OPTIONS_COMPRESSION_C_S, "none");
    ssh_options_set(session, SSH_OPTIONS_COMPRESSION_S_C, "none");
    if (ssh_connect(session) != 0) {
      //if the connection was drop, trying to reconnect
      if (verbose)
        hydra_report(stderr, "Error: could not connect to target port %d\n", port);
      return 1;
    }

    if ((rc = ssh_userauth_none(session, NULL)) == SSH_AUTH_ERROR) {
      return 3;
    } else if (rc == SSH_AUTH_SUCCESS) {
      hydra_report_found_host(port, ip, "ssh", fp);
      hydra_completed_pair_found();
      if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
        return 2;
      else
        return 1;
    }
  } else
    new_session = 1;

  auth_state = ssh_auth_list(session);
  if ((auth_state & SSH_AUTH_METHOD_PASSWORD) > 0) {
    auth_state = ssh_userauth_password(session, NULL, pass);
  } else if ((auth_state & SSH_AUTH_METHOD_INTERACTIVE) > 0) {
    auth_state = ssh_userauth_kbdint(session, NULL, NULL);
    while (auth_state == SSH_AUTH_INFO) {
      rc = ssh_userauth_kbdint_getnprompts(session);
      for (i = 0; i < rc; i++)
        ssh_userauth_kbdint_setanswer(session, i, pass);
      auth_state = ssh_userauth_kbdint(session, NULL, NULL);
    }
  } else {
    return 4;
  }

  if (auth_state == SSH_AUTH_ERROR) {
    new_session = 1;
    return 1;
  }

  if (auth_state == SSH_AUTH_SUCCESS || auth_state == SSH_AUTH_PARTIAL) {
    hydra_report_found_host(port, ip, "ssh", fp);
    hydra_completed_pair_found();
    if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
      return 2;
    return 1;
  } else {
    strncpy(keep_login, login, sizeof(keep_login) - 1);
    keep_login[sizeof(keep_login) - 1] = '\0';
    hydra_completed_pair();
    if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
      return 2;
    login = hydra_get_next_login();
    if (strcmp(login, keep_login) == 0)
      new_session = 0;
    return 1;
  }

  /* not reached */
  return 1;
}
示例#16
0
int main(int argc, char **argv){
    SSH_SESSION *session;
    SSH_OPTIONS *options;
    int auth=0;
    char *password;
    char *banner;
    int state;
    char buf[10];
    unsigned char hash[MD5_DIGEST_LEN];

    options=ssh_options_new();
    if(ssh_options_getopt(options,&argc, argv))
        usage();
    opts(argc,argv);
    signal(SIGTERM,do_exit);
    if(user)
        ssh_options_set_username(options,user);
    ssh_options_set_host(options,host);
    session=ssh_new();
    ssh_set_options(session,options);
    if(ssh_connect(session)){
        fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
        ssh_disconnect(session);
	ssh_finalize();
        return 1;
    }
    state=ssh_is_server_known(session);
    switch(state){
        case SSH_SERVER_KNOWN_OK:
            break; /* ok */
        case SSH_SERVER_KNOWN_CHANGED:
            fprintf(stderr,"Host key for server changed : server's one is now :\n");
            ssh_get_pubkey_hash(session,hash);
            ssh_print_hexa("Public key hash",hash,MD5_DIGEST_LEN);
            fprintf(stderr,"For security reason, connection will be stopped\n");
            ssh_disconnect(session);
	    ssh_finalize();
            exit(-1);
        case SSH_SERVER_FOUND_OTHER:
            fprintf(stderr,"The host key for this server was not found but an other type of key exists.\n");
            fprintf(stderr,"An attacker might change the default server key to confuse your client"
                "into thinking the key does not exist\n"
                "We advise you to rerun the client with -d or -r for more safety.\n");
                ssh_disconnect(session);
		ssh_finalize();
                exit(-1);
        case SSH_SERVER_NOT_KNOWN:
            fprintf(stderr,"The server is unknown. Do you trust the host key ?\n");
            ssh_get_pubkey_hash(session,hash);
            ssh_print_hexa("Public key hash",hash,MD5_DIGEST_LEN);
            fgets(buf,sizeof(buf),stdin);
            if(strncasecmp(buf,"yes",3)!=0){
                ssh_disconnect(session);
                exit(-1);
            }
            fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n");
            fgets(buf,sizeof(buf),stdin);
            if(strncasecmp(buf,"yes",3)==0){
                if(ssh_write_knownhost(session))
                    fprintf(stderr,"error %s\n",ssh_get_error(session));
            }
            
            break;
        case SSH_SERVER_ERROR:
            fprintf(stderr,"%s",ssh_get_error(session));
            ssh_disconnect(session);
	    ssh_finalize();
            exit(-1);
    }

    /* no ? you should :) */
    auth=ssh_userauth_autopubkey(session);
    if(auth==SSH_AUTH_ERROR){
        fprintf(stderr,"Authenticating with pubkey: %s\n",ssh_get_error(session));
	ssh_finalize();
        return -1;
    }
    banner=ssh_get_issue_banner(session);
    if(banner){
        printf("%s\n",banner);
        free(banner);
    }
    if(auth!=SSH_AUTH_SUCCESS){
        auth=auth_kbdint(session);
        if(auth==SSH_AUTH_ERROR){
            fprintf(stderr,"authenticating with keyb-interactive: %s\n",
                    ssh_get_error(session));
	    ssh_finalize();
            return -1;
        }
    }
    if(auth!=SSH_AUTH_SUCCESS){
        password=getpass("Password : "******"Authentication failed: %s\n",ssh_get_error(session));
            ssh_disconnect(session);
	    ssh_finalize();
            return -1;
        }
        memset(password,0,strlen(password));
    }
    ssh_say(1,"Authentication success\n");
    printf("%s\n",argv[0]);
    if(strstr(argv[0],"sftp")){
        sftp=1;
        ssh_say(1,"doing sftp instead\n");
    }
    if(!sftp){
        if(!cmds[0])
            shell(session);
        else
            batch_shell(session);
    }
    else
        do_sftp(session);    
    if(!sftp && !cmds[0])
        do_cleanup();
    ssh_disconnect(session);
    ssh_finalize();

    return 0;
}
示例#17
0
gboolean remmina_nx_session_open(RemminaNXSession *nx, const gchar *server, guint port, const gchar *private_key_file,
		RemminaNXPassphraseCallback passphrase_func, gpointer userdata)
{
	gint ret;
	ssh_private_key privkey;
	ssh_public_key pubkey;
	ssh_string pubkeystr;
	gint keytype;
	gboolean encrypted;
	gchar *passphrase = NULL;
	gchar tmpfile[L_tmpnam + 1];

nx	->session = ssh_new();
	ssh_options_set(nx->session, SSH_OPTIONS_HOST, server);
	ssh_options_set(nx->session, SSH_OPTIONS_PORT, &port);
	ssh_options_set(nx->session, SSH_OPTIONS_USER, "nx");

	if (private_key_file && private_key_file[0])
	{
		if (!remmina_get_keytype(private_key_file, &keytype, &encrypted))
		{
			remmina_nx_session_set_application_error(nx, "Invalid private key file.");
			return FALSE;
		}
		if (encrypted && !passphrase_func(&passphrase, userdata))
		{
			return FALSE;
		}
		privkey = privatekey_from_file(nx->session, private_key_file, keytype, (passphrase ? passphrase : ""));
		g_free(passphrase);
	}
	else
	{
		/* Use NoMachine's default nx private key */
		if ((tmpnam(tmpfile)) == NULL || !g_file_set_contents(tmpfile, nx_default_private_key, -1, NULL))
		{
			remmina_nx_session_set_application_error(nx, "Failed to create temporary private key file.");
			return FALSE;
		}
		privkey = privatekey_from_file(nx->session, tmpfile, REMMINA_SSH_TYPE_DSS, "");
		g_unlink(tmpfile);
	}

	if (privkey == NULL)
	{
		remmina_nx_session_set_error(nx, "Invalid private key file: %s");
		return FALSE;
	}
	pubkey = publickey_from_privatekey(privkey);
	pubkeystr = publickey_to_string(pubkey);
	publickey_free(pubkey);

	if (ssh_connect(nx->session))
	{
		string_free(pubkeystr);
		privatekey_free(privkey);
		remmina_nx_session_set_error(nx, "Failed to startup SSH session: %s");
		return FALSE;
	}

	ret = ssh_userauth_pubkey(nx->session, NULL, pubkeystr, privkey);
	string_free(pubkeystr);
	privatekey_free(privkey);

	if (ret != SSH_AUTH_SUCCESS)
	{
		remmina_nx_session_set_error(nx, "NX SSH authentication failed: %s");
		return FALSE;
	}

	if ((nx->channel = channel_new(nx->session)) == NULL || channel_open_session(nx->channel))
	{
		return FALSE;
	}

	if (channel_request_shell(nx->channel))
	{
		return FALSE;
	}

	/* NX server starts the session with an initial 105 status */
	if (!remmina_nx_session_expect_status(nx, 105))
		return FALSE;

	/* Say hello to the NX server */
	remmina_nx_session_send_command(nx, "HELLO NXCLIENT - Version %s", nx->version);
	if (!remmina_nx_session_expect_status(nx, 105))
		return FALSE;

	/* Set the NX session environment */
	remmina_nx_session_send_command(nx, "SET SHELL_MODE SHELL");
	if (!remmina_nx_session_expect_status(nx, 105))
		return FALSE;
	remmina_nx_session_send_command(nx, "SET AUTH_MODE PASSWORD");
	if (!remmina_nx_session_expect_status(nx, 105))
		return FALSE;

	nx->server = g_strdup(server);

	return TRUE;
}
示例#18
0
static int _sftp_connect(const char *uri) {
  char *scheme = NULL;
  char *user = NULL;
  char *passwd = NULL;
  char *host = NULL;
  unsigned int port = 0;
  char *path = NULL;
  unsigned char *hash = NULL;
  int hlen;
  int rc = -1;
  int state = SSH_SERVER_ERROR;
  int timeout = 10;
  int method;
  char *verbosity;

  if (_connected) {
    return 0;
  }

  rc = c_parse_uri(uri, &scheme, &user, &passwd, &host, &port, &path);
  if (rc < 0) {
    goto out;
  }

  DEBUG_SFTP(("csync_sftp - conntecting to: %s\n", host));

  /* create the session */
  _ssh_session = ssh_new();
  if (_ssh_session == NULL) {
    fprintf(stderr, "csync_sftp - error creating new connection: %s\n",
        strerror(errno));
    rc = -1;
    goto out;
  }

  rc = ssh_options_set(_ssh_session, SSH_OPTIONS_TIMEOUT, &timeout);
  if (rc < 0) {
    fprintf(stderr, "csync_sftp - error setting options: %s\n",
        strerror(errno));
    goto out;
  }

  rc = ssh_options_set(_ssh_session, SSH_OPTIONS_COMPRESSION_C_S, "none");
  if (rc < 0) {
    fprintf(stderr, "csync_sftp - error setting options: %s\n",
        strerror(errno));
    goto out;
  }

  rc = ssh_options_set(_ssh_session, SSH_OPTIONS_COMPRESSION_S_C, "none");
  if (rc < 0) {
    fprintf(stderr, "csync_sftp - error setting options: %s\n",
        strerror(errno));
    goto out;
  }

  ssh_options_set(_ssh_session, SSH_OPTIONS_HOST, host);
  if (rc < 0) {
    fprintf(stderr, "csync_sftp - error setting options: %s\n",
        strerror(errno));
    goto out;
  }

  if (port) {
    ssh_options_set(_ssh_session, SSH_OPTIONS_PORT, &port);
    if (rc < 0) {
      fprintf(stderr, "csync_sftp - error setting options: %s\n",
          strerror(errno));
      goto out;
    }
    DEBUG_SFTP(("csync_sftp - port set to: %d\n", port));
  }

  if (user && *user) {
    ssh_options_set(_ssh_session, SSH_OPTIONS_USER, user);
    if (rc < 0) {
      fprintf(stderr, "csync_sftp - error setting options: %s\n",
          strerror(errno));
      goto out;
    }
    DEBUG_SFTP(("csync_sftp - username set to: %s\n", user));
  }

  verbosity = getenv("CSYNC_SFTP_LOG_VERBOSITY");
  if (verbosity) {
    rc = ssh_options_set(_ssh_session, SSH_OPTIONS_LOG_VERBOSITY_STR, verbosity);
    if (rc < 0) {
      goto out;
    }
  }

  /* read ~/.ssh/config */
  rc = ssh_options_parse_config(_ssh_session, NULL);
  if (rc < 0) {
    goto out;
  }

  _ssh_callbacks = (ssh_callbacks) c_malloc(sizeof(struct ssh_callbacks_struct));
  if (_ssh_callbacks == NULL) {
    rc = -1;
    goto out;
  }
  ZERO_STRUCTP(_ssh_callbacks);

  _ssh_callbacks->userdata = _userdata;
  _ssh_callbacks->auth_function = _ssh_auth_callback;

  ssh_callbacks_init(_ssh_callbacks);

  ssh_set_callbacks(_ssh_session, _ssh_callbacks);

  rc = ssh_connect(_ssh_session);
  if (rc < 0) {
    fprintf(stderr, "csync_sftp - error connecting to the server: %s\n", ssh_get_error(_ssh_session));
    ssh_disconnect(_ssh_session);
    _ssh_session = NULL;
    ssh_finalize();
    goto out;
  }

  hlen = ssh_get_pubkey_hash(_ssh_session, &hash);
  if (hlen < 0) {
    fprintf(stderr, "csync_sftp - error connecting to the server: %s\n",
        ssh_get_error(_ssh_session));
    ssh_disconnect(_ssh_session);
    _ssh_session = NULL;
    ssh_finalize();
    goto out;
  }

  /* check the server public key hash */
  state = ssh_is_server_known(_ssh_session);
  switch (state) {
    case SSH_SERVER_KNOWN_OK:
      break;
    case SSH_SERVER_KNOWN_CHANGED:
      fprintf(stderr, "csync_sftp - The host key for this server was "
            "not found, but another type of key exists.\n"
            "An attacker might change the default server key to confuse your "
            "client into thinking the key does not exist.\n"
            "Please contact your system administrator.\n"
            "%s\n", ssh_get_error(_ssh_session));
      ssh_print_hexa("csync_sftp - public key hash", hash, hlen);

      ssh_disconnect(_ssh_session);
      _ssh_session = NULL;
      ssh_finalize();
      rc = -1;
      goto out;
      break;
    case SSH_SERVER_FOUND_OTHER:
      fprintf(stderr, "csync_sftp - the host key for this server was not "
          "found but an other type of key exists.\n");
      fprintf(stderr, "csync_sftp - an attacker might change the default "
          "server key to confuse your client into thinking the key does not "
          "exist\n");
      fprintf(stderr, "The host key for the server %s has changed.\n"
          "This could either mean that DNS SPOOFING is happening or the IP "
          "address for the host and its host key have changed at the same time.\n"
          "The fingerprint for the key sent by the remote host is:\n", host);
          ssh_print_hexa("", hash, hlen);
          fprintf(stderr, "Please contact your system administrator.\n"
          "%s\n", ssh_get_error(_ssh_session));

      ssh_disconnect(_ssh_session);
      _ssh_session = NULL;
      ssh_finalize();
      rc = -1;
      goto out;
      break;
    case SSH_SERVER_NOT_KNOWN:
      if (_authcb) {
        char *hexa;
        char *prompt;
        char buf[4] = {0};

        hexa = ssh_get_hexa(hash, hlen);
        if (hexa == NULL) {
          ssh_disconnect(_ssh_session);
          _ssh_session = NULL;
          ssh_finalize();
          rc = -1;
          goto out;
        }

        if (asprintf(&prompt,
              "The authenticity of host '%s' can't be established.\n"
              "RSA key fingerprint is %s.\n"
              "Are you sure you want to continue connecting (yes/no)?",
              host, hexa) < 0 ) {
          free(hexa);
          ssh_disconnect(_ssh_session);
          _ssh_session = NULL;
          ssh_finalize();
          rc = -1;
          goto out;
        }

        free(hexa);

        if ((*_authcb)(prompt, buf, sizeof(buf), 1, 0, _userdata) < 0) {
          free(prompt);
          ssh_disconnect(_ssh_session);
          _ssh_session = NULL;
          ssh_finalize();
          rc = -1;
          goto out;
        }

        free(prompt);

        if (strncasecmp(buf, "yes", 3) != 0) {
          ssh_disconnect(_ssh_session);
          _ssh_session = NULL;
          ssh_finalize();
          rc = -1;
          goto out;
        }

        if (ssh_write_knownhost(_ssh_session) < 0) {
          ssh_disconnect(_ssh_session);
          _ssh_session = NULL;
          ssh_finalize();
          rc = -1;
          goto out;
        }
      } else {
        fprintf(stderr,"csync_sftp - the server is unknown. Connect manually to "
            "the host to retrieve the public key hash, then try again.\n");
      }
      ssh_disconnect(_ssh_session);
      _ssh_session = NULL;
      ssh_finalize();
      rc = -1;
      goto out;
      break;
    case SSH_SERVER_ERROR:
      fprintf(stderr, "%s\n", ssh_get_error(_ssh_session));

      ssh_disconnect(_ssh_session);
      _ssh_session = NULL;
      ssh_finalize();
      rc = -1;
      goto out;
      break;
    default:
      break;
  }

  /* Try to authenticate */
  rc = ssh_userauth_none(_ssh_session, NULL);
  if (rc == SSH_AUTH_ERROR) {
      ssh_disconnect(_ssh_session);
      _ssh_session = NULL;
      ssh_finalize();
      rc = -1;
      goto out;
  }

#if 0
  /* authenticate with the server */
  if (passwd && *passwd) {
    DEBUG_SFTP(("csync_sftp - authenticating with user/password\n"));
    /*
     * This is tunneled cleartext password authentication and possibly needs
     * to be allowed by the ssh server. Set 'PasswordAuthentication yes'
     */
    auth = ssh_userauth_password(_ssh_session, user, passwd);
  } else {
    DEBUG_SFTP(("csync_sftp - authenticating with pubkey\n"));
    auth = ssh_userauth_autopubkey(_ssh_session, NULL);
  }

  if (auth == SSH_AUTH_ERROR) {
    fprintf(stderr, "csync_sftp - authenticating with pubkey: %s\n",
        ssh_get_error(_ssh_session));
    ssh_disconnect(_ssh_session);
    _ssh_session = NULL;
    ssh_finalize();
    rc = -1;
    goto out;
  }

  if (auth != SSH_AUTH_SUCCESS) {
    if (_authcb != NULL) {
      auth = auth_kbdint(_ssh_session);
      if (auth == SSH_AUTH_ERROR) {
        fprintf(stderr,"csync_sftp - authentication failed: %s\n",
            ssh_get_error(_ssh_session));
        ssh_disconnect(_ssh_session);
        _ssh_session = NULL;
        ssh_finalize();
        rc = -1;
        goto out;
      }
    } else {
      ssh_disconnect(_ssh_session);
      _ssh_session = NULL;
      ssh_finalize();
      rc = -1;
      goto out;
    }
  }


#endif
  method = ssh_auth_list(_ssh_session);

  while (rc != SSH_AUTH_SUCCESS) {
    /* Try to authenticate with public key first */
    if (method & SSH_AUTH_METHOD_PUBLICKEY) {
      rc = ssh_userauth_autopubkey(_ssh_session, NULL);
      if (rc == SSH_AUTH_ERROR) {
        ssh_disconnect(_ssh_session);
        _ssh_session = NULL;
        ssh_finalize();
        rc = -1;
        goto out;
      } else if (rc == SSH_AUTH_SUCCESS) {
        break;
      }
    }

    /* Try to authenticate with keyboard interactive */
    if (method & SSH_AUTH_METHOD_INTERACTIVE) {
      rc = auth_kbdint(_ssh_session, user, passwd);
      if (rc == SSH_AUTH_ERROR) {
        ssh_disconnect(_ssh_session);
        _ssh_session = NULL;
        ssh_finalize();
        rc = -1;
        goto out;
      } else if (rc == SSH_AUTH_SUCCESS) {
        break;
      }
    }

    /* Try to authenticate with password */
    if ((method & SSH_AUTH_METHOD_PASSWORD) && passwd && *passwd) {
      rc = ssh_userauth_password(_ssh_session, user, passwd);
      if (rc == SSH_AUTH_ERROR) {
        ssh_disconnect(_ssh_session);
        _ssh_session = NULL;
        ssh_finalize();
        rc = -1;
        goto out;
      } else if (rc == SSH_AUTH_SUCCESS) {
        break;
      }
    }
  }

  DEBUG_SFTP(("csync_sftp - creating sftp channel...\n"));
  /* start the sftp session */
  _sftp_session = sftp_new(_ssh_session);
  if (_sftp_session == NULL) {
    fprintf(stderr, "csync_sftp - sftp error initialising channel: %s\n", ssh_get_error(_ssh_session));
    rc = -1;
    goto out;
  }

  rc = sftp_init(_sftp_session);
  if (rc < 0) {
    fprintf(stderr, "csync_sftp - error initialising sftp: %s\n", ssh_get_error(_ssh_session));
    goto out;
  }

  DEBUG_SFTP(("csync_sftp - connection established...\n"));
  _connected = 1;
  rc = 0;
out:
  SAFE_FREE(scheme);
  SAFE_FREE(user);
  SAFE_FREE(passwd);
  SAFE_FREE(host);
  SAFE_FREE(path);
  SAFE_FREE(hash);

  return rc;
}
示例#19
0
/*
 * Main program for the ssh client.
 */
int
main(int ac, char **av)
{
	int i, r, opt, exit_status, use_syslog;
	char *p, *cp, *line, *argv0, buf[MAXPATHLEN], *host_arg;
	char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
	struct stat st;
	struct passwd *pw;
	int dummy, timeout_ms;
	extern int optind, optreset;
	extern char *optarg;
	struct servent *sp;
	Forward fwd;

	/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
	sanitise_stdfd();

	/*
	 * Discard other fds that are hanging around. These can cause problem
	 * with backgrounded ssh processes started by ControlPersist.
	 */
	closefrom(STDERR_FILENO + 1);

	/*
	 * Save the original real uid.  It will be needed later (uid-swapping
	 * may clobber the real uid).
	 */
	original_real_uid = getuid();
	original_effective_uid = geteuid();

	/*
	 * Use uid-swapping to give up root privileges for the duration of
	 * option processing.  We will re-instantiate the rights when we are
	 * ready to create the privileged port, and will permanently drop
	 * them when the port has been created (actually, when the connection
	 * has been made, as we may need to create the port several times).
	 */
	PRIV_END;

	/* If we are installed setuid root be careful to not drop core. */
	if (original_real_uid != original_effective_uid) {
		struct rlimit rlim;
		rlim.rlim_cur = rlim.rlim_max = 0;
		if (setrlimit(RLIMIT_CORE, &rlim) < 0)
			fatal("setrlimit failed: %.100s", strerror(errno));
	}
	/* Get user data. */
	pw = getpwuid(original_real_uid);
	if (!pw) {
		logit("You don't exist, go away!");
		exit(255);
	}
	/* Take a copy of the returned structure. */
	pw = pwcopy(pw);

	/*
	 * Set our umask to something reasonable, as some files are created
	 * with the default umask.  This will make them world-readable but
	 * writable only by the owner, which is ok for all files for which we
	 * don't set the modes explicitly.
	 */
	umask(022);

	/*
	 * Initialize option structure to indicate that no values have been
	 * set.
	 */
	initialize_options(&options);

	/* Parse command-line arguments. */
	host = NULL;
	use_syslog = 0;
	argv0 = av[0];

 again:
	while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx"
	    "ACD:F:I:KL:MNO:PR:S:TVw:W:XYy")) != -1) {
		switch (opt) {
		case '1':
			options.protocol = SSH_PROTO_1;
			break;
		case '2':
			options.protocol = SSH_PROTO_2;
			break;
		case '4':
			options.address_family = AF_INET;
			break;
		case '6':
			options.address_family = AF_INET6;
			break;
		case 'n':
			stdin_null_flag = 1;
			break;
		case 'f':
			fork_after_authentication_flag = 1;
			stdin_null_flag = 1;
			break;
		case 'x':
			options.forward_x11 = 0;
			break;
		case 'X':
			options.forward_x11 = 1;
			break;
		case 'y':
			use_syslog = 1;
			break;
		case 'Y':
			options.forward_x11 = 1;
			options.forward_x11_trusted = 1;
			break;
		case 'g':
			options.gateway_ports = 1;
			break;
		case 'O':
			if (stdio_forward_host != NULL)
				fatal("Cannot specify multiplexing "
				    "command with -W");
			else if (muxclient_command != 0)
				fatal("Multiplexing command already specified");
			if (strcmp(optarg, "check") == 0)
				muxclient_command = SSHMUX_COMMAND_ALIVE_CHECK;
			else if (strcmp(optarg, "forward") == 0)
				muxclient_command = SSHMUX_COMMAND_FORWARD;
			else if (strcmp(optarg, "exit") == 0)
				muxclient_command = SSHMUX_COMMAND_TERMINATE;
			else if (strcmp(optarg, "stop") == 0)
				muxclient_command = SSHMUX_COMMAND_STOP;
			else
				fatal("Invalid multiplex command.");
			break;
		case 'P':	/* deprecated */
			options.use_privileged_port = 0;
			break;
		case 'a':
			options.forward_agent = 0;
			break;
		case 'A':
			options.forward_agent = 1;
			break;
		case 'k':
			options.gss_deleg_creds = 0;
			break;
		case 'K':
			options.gss_authentication = 1;
			options.gss_deleg_creds = 1;
			break;
		case 'i':
			if (stat(optarg, &st) < 0) {
				fprintf(stderr, "Warning: Identity file %s "
				    "not accessible: %s.\n", optarg,
				    strerror(errno));
				break;
			}
			if (options.num_identity_files >=
			    SSH_MAX_IDENTITY_FILES)
				fatal("Too many identity files specified "
				    "(max %d)", SSH_MAX_IDENTITY_FILES);
			options.identity_files[options.num_identity_files++] =
			    xstrdup(optarg);
			break;
		case 'I':
#ifdef ENABLE_PKCS11
			options.pkcs11_provider = xstrdup(optarg);
#else
			fprintf(stderr, "no support for PKCS#11.\n");
#endif
			break;
		case 't':
			if (options.request_tty == REQUEST_TTY_YES)
				options.request_tty = REQUEST_TTY_FORCE;
			else
				options.request_tty = REQUEST_TTY_YES;
			break;
		case 'v':
			if (debug_flag == 0) {
				debug_flag = 1;
				options.log_level = SYSLOG_LEVEL_DEBUG1;
			} else {
				if (options.log_level < SYSLOG_LEVEL_DEBUG3)
					options.log_level++;
				break;
			}
			/* FALLTHROUGH */
		case 'V':
			fprintf(stderr, "%s, %s\n",
			    SSH_VERSION, SSLeay_version(SSLEAY_VERSION));
			if (opt == 'V')
				exit(0);
			break;
		case 'w':
			if (options.tun_open == -1)
				options.tun_open = SSH_TUNMODE_DEFAULT;
			options.tun_local = a2tun(optarg, &options.tun_remote);
			if (options.tun_local == SSH_TUNID_ERR) {
				fprintf(stderr,
				    "Bad tun device '%s'\n", optarg);
				exit(255);
			}
			break;
		case 'W':
			if (stdio_forward_host != NULL)
				fatal("stdio forward already specified");
			if (muxclient_command != 0)
				fatal("Cannot specify stdio forward with -O");
			if (parse_forward(&fwd, optarg, 1, 0)) {
				stdio_forward_host = fwd.listen_host;
				stdio_forward_port = fwd.listen_port;
				xfree(fwd.connect_host);
			} else {
				fprintf(stderr,
				    "Bad stdio forwarding specification '%s'\n",
				    optarg);
				exit(255);
			}
			options.request_tty = REQUEST_TTY_NO;
			no_shell_flag = 1;
			options.clear_forwardings = 1;
			options.exit_on_forward_failure = 1;
			break;
		case 'q':
			options.log_level = SYSLOG_LEVEL_QUIET;
			break;
		case 'e':
			if (optarg[0] == '^' && optarg[2] == 0 &&
			    (u_char) optarg[1] >= 64 &&
			    (u_char) optarg[1] < 128)
				options.escape_char = (u_char) optarg[1] & 31;
			else if (strlen(optarg) == 1)
				options.escape_char = (u_char) optarg[0];
			else if (strcmp(optarg, "none") == 0)
				options.escape_char = SSH_ESCAPECHAR_NONE;
			else {
				fprintf(stderr, "Bad escape character '%s'.\n",
				    optarg);
				exit(255);
			}
			break;
		case 'c':
			if (ciphers_valid(optarg)) {
				/* SSH2 only */
				options.ciphers = xstrdup(optarg);
				options.cipher = SSH_CIPHER_INVALID;
			} else {
				/* SSH1 only */
				options.cipher = cipher_number(optarg);
				if (options.cipher == -1) {
					fprintf(stderr,
					    "Unknown cipher type '%s'\n",
					    optarg);
					exit(255);
				}
				if (options.cipher == SSH_CIPHER_3DES)
					options.ciphers = __UNCONST("3des-cbc");
				else if (options.cipher == SSH_CIPHER_BLOWFISH)
					options.ciphers =
					    __UNCONST("blowfish-cbc");
				else
					options.ciphers = (char *)-1;
			}
			break;
		case 'm':
			if (mac_valid(optarg))
				options.macs = xstrdup(optarg);
			else {
				fprintf(stderr, "Unknown mac type '%s'\n",
				    optarg);
				exit(255);
			}
			break;
		case 'M':
			if (options.control_master == SSHCTL_MASTER_YES)
				options.control_master = SSHCTL_MASTER_ASK;
			else
				options.control_master = SSHCTL_MASTER_YES;
			break;
		case 'p':
			options.port = a2port(optarg);
			if (options.port <= 0) {
				fprintf(stderr, "Bad port '%s'\n", optarg);
				exit(255);
			}
			break;
		case 'l':
			options.user = optarg;
			break;

		case 'L':
			if (parse_forward(&fwd, optarg, 0, 0))
				add_local_forward(&options, &fwd);
			else {
				fprintf(stderr,
				    "Bad local forwarding specification '%s'\n",
				    optarg);
				exit(255);
			}
			break;

		case 'R':
			if (parse_forward(&fwd, optarg, 0, 1)) {
				add_remote_forward(&options, &fwd);
			} else {
				fprintf(stderr,
				    "Bad remote forwarding specification "
				    "'%s'\n", optarg);
				exit(255);
			}
			break;

		case 'D':
			if (parse_forward(&fwd, optarg, 1, 0)) {
				add_local_forward(&options, &fwd);
			} else {
				fprintf(stderr,
				    "Bad dynamic forwarding specification "
				    "'%s'\n", optarg);
				exit(255);
			}
			break;

		case 'C':
			options.compression = 1;
			break;
		case 'N':
			no_shell_flag = 1;
			options.request_tty = REQUEST_TTY_NO;
			break;
		case 'T':
			options.request_tty = REQUEST_TTY_NO;
			/* ensure that the user doesn't try to backdoor a */
			/* null cipher switch on an interactive session */
			/* so explicitly disable it no matter what */
			options.none_switch = 0;
			break;
		case 'o':
			dummy = 1;
			line = xstrdup(optarg);
			if (process_config_line(&options, host ? host : "",
			    line, "command-line", 0, &dummy) != 0)
				exit(255);
			xfree(line);
			break;
		case 's':
			subsystem_flag = 1;
			break;
		case 'S':
			if (options.control_path != NULL)
				free(options.control_path);
			options.control_path = xstrdup(optarg);
			break;
		case 'b':
			options.bind_address = optarg;
			break;
		case 'F':
			config = optarg;
			break;
		default:
			usage();
		}
	}

	ac -= optind;
	av += optind;

	if (ac > 0 && !host) {
		if (strrchr(*av, '@')) {
			p = xstrdup(*av);
			cp = strrchr(p, '@');
			if (cp == NULL || cp == p)
				usage();
			options.user = p;
			*cp = '\0';
			host = ++cp;
		} else
			host = *av;
		if (ac > 1) {
			optind = optreset = 1;
			goto again;
		}
		ac--, av++;
	}

	/* Check that we got a host name. */
	if (!host)
		usage();

	OpenSSL_add_all_algorithms();
	ERR_load_crypto_strings();

	/* Initialize the command to execute on remote host. */
	buffer_init(&command);

	if (options.request_tty == REQUEST_TTY_YES ||
	    options.request_tty == REQUEST_TTY_FORCE)
		tty_flag = 1;

	/*
	 * Save the command to execute on the remote host in a buffer. There
	 * is no limit on the length of the command, except by the maximum
	 * packet size.  Also sets the tty flag if there is no command.
	 */
	if (!ac) {
		/* No command specified - execute shell on a tty. */
		tty_flag = options.request_tty != REQUEST_TTY_NO;
		if (subsystem_flag) {
			fprintf(stderr,
			    "You must specify a subsystem to invoke.\n");
			usage();
		}
	} else {
		/* A command has been specified.  Store it into the buffer. */
		for (i = 0; i < ac; i++) {
			if (i)
				buffer_append(&command, " ", 1);
			buffer_append(&command, av[i], strlen(av[i]));
		}
	}

	/* Cannot fork to background if no command. */
	if (fork_after_authentication_flag && buffer_len(&command) == 0 &&
	    !no_shell_flag)
		fatal("Cannot fork into background without a command "
		    "to execute.");

	/* Allocate a tty by default if no command specified. */
	if (buffer_len(&command) == 0)
		tty_flag = options.request_tty != REQUEST_TTY_NO;

	/* Force no tty */
	if (options.request_tty == REQUEST_TTY_NO || muxclient_command != 0)
		tty_flag = 0;
	/* Do not allocate a tty if stdin is not a tty. */
	if ((!isatty(fileno(stdin)) || stdin_null_flag) &&
	    options.request_tty != REQUEST_TTY_FORCE) {
		if (tty_flag)
			logit("Pseudo-terminal will not be allocated because "
			    "stdin is not a terminal.");
		tty_flag = 0;
	}

	/*
	 * Initialize "log" output.  Since we are the client all output
	 * actually goes to stderr.
	 */
	log_init(argv0,
	    options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level,
	    SYSLOG_FACILITY_USER, !use_syslog);

	/*
	 * Read per-user configuration file.  Ignore the system wide config
	 * file if the user specifies a config file on the command line.
	 */
	if (config != NULL) {
		if (!read_config_file(config, host, &options, 0))
			fatal("Can't open user config file %.100s: "
			    "%.100s", config, strerror(errno));
	} else {
		r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir,
		    _PATH_SSH_USER_CONFFILE);
		if (r > 0 && (size_t)r < sizeof(buf))
			(void)read_config_file(buf, host, &options, 1);

		/* Read systemwide configuration file after user config. */
		(void)read_config_file(_PATH_HOST_CONFIG_FILE, host,
		    &options, 0);
	}

	/* Fill configuration defaults. */
	fill_default_options(&options);

	channel_set_af(options.address_family);

	/* reinit */
	log_init(argv0, options.log_level, SYSLOG_FACILITY_USER, !use_syslog);

	if (options.user == NULL)
		options.user = xstrdup(pw->pw_name);

	/* Get default port if port has not been set. */
	if (options.port == 0) {
		sp = getservbyname(SSH_SERVICE_NAME, "tcp");
		options.port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
	}

	/* preserve host name given on command line for %n expansion */
	host_arg = host;
	if (options.hostname != NULL) {
		host = percent_expand(options.hostname,
		    "h", host, (char *)NULL);
	}

	if (gethostname(thishost, sizeof(thishost)) == -1)
		fatal("gethostname: %s", strerror(errno));
	strlcpy(shorthost, thishost, sizeof(shorthost));
	shorthost[strcspn(thishost, ".")] = '\0';
	snprintf(portstr, sizeof(portstr), "%d", options.port);

	if (options.local_command != NULL) {
		debug3("expanding LocalCommand: %s", options.local_command);
		cp = options.local_command;
		options.local_command = percent_expand(cp, "d", pw->pw_dir,
		    "h", host, "l", thishost, "n", host_arg, "r", options.user,
		    "p", portstr, "u", pw->pw_name, "L", shorthost,
		    (char *)NULL);
		debug3("expanded LocalCommand: %s", options.local_command);
		xfree(cp);
	}

	/* force lowercase for hostkey matching */
	if (options.host_key_alias != NULL) {
		for (p = options.host_key_alias; *p; p++)
			if (isupper((unsigned char)*p))
				*p = (char)tolower((unsigned char)*p);
	}

	if (options.proxy_command != NULL &&
	    strcmp(options.proxy_command, "none") == 0) {
		xfree(options.proxy_command);
		options.proxy_command = NULL;
	}
	if (options.control_path != NULL &&
	    strcmp(options.control_path, "none") == 0) {
		xfree(options.control_path);
		options.control_path = NULL;
	}

	if (options.control_path != NULL) {
		cp = tilde_expand_filename(options.control_path,
		    original_real_uid);
		xfree(options.control_path);
		options.control_path = percent_expand(cp, "h", host,
		    "l", thishost, "n", host_arg, "r", options.user,
		    "p", portstr, "u", pw->pw_name, "L", shorthost,
		    (char *)NULL);
		xfree(cp);
	}
	if (muxclient_command != 0 && options.control_path == NULL)
		fatal("No ControlPath specified for \"-O\" command");
	if (options.control_path != NULL)
		muxclient(options.control_path);

	timeout_ms = options.connection_timeout * 1000;

	/* Open a connection to the remote host. */
	if (ssh_connect(host, &hostaddr, options.port,
	    options.address_family, options.connection_attempts, &timeout_ms,
	    options.tcp_keep_alive, 
	    original_effective_uid == 0 && options.use_privileged_port,
	    options.proxy_command) != 0)
		exit(255);

	if (timeout_ms > 0)
		debug3("timeout: %d ms remain after connect", timeout_ms);

	/*
	 * If we successfully made the connection, load the host private key
	 * in case we will need it later for combined rsa-rhosts
	 * authentication. This must be done before releasing extra
	 * privileges, because the file is only readable by root.
	 * If we cannot access the private keys, load the public keys
	 * instead and try to execute the ssh-keysign helper instead.
	 */
	sensitive_data.nkeys = 0;
	sensitive_data.keys = NULL;
	sensitive_data.external_keysign = 0;
	if (options.rhosts_rsa_authentication ||
	    options.hostbased_authentication) {
		sensitive_data.nkeys = 7;
		sensitive_data.keys = xcalloc(sensitive_data.nkeys,
		    sizeof(Key));

		PRIV_START;
		sensitive_data.keys[0] = key_load_private_type(KEY_RSA1,
		    _PATH_HOST_KEY_FILE, "", NULL, NULL);
		sensitive_data.keys[1] = key_load_private_cert(KEY_DSA,
		    _PATH_HOST_DSA_KEY_FILE, "", NULL);
		sensitive_data.keys[2] = key_load_private_cert(KEY_ECDSA,
		    _PATH_HOST_ECDSA_KEY_FILE, "", NULL);
		sensitive_data.keys[3] = key_load_private_cert(KEY_RSA,
		    _PATH_HOST_RSA_KEY_FILE, "", NULL);
		sensitive_data.keys[4] = key_load_private_type(KEY_DSA,
		    _PATH_HOST_DSA_KEY_FILE, "", NULL, NULL);
		sensitive_data.keys[5] = key_load_private_type(KEY_ECDSA,
		    _PATH_HOST_ECDSA_KEY_FILE, "", NULL, NULL);
		sensitive_data.keys[6] = key_load_private_type(KEY_RSA,
		    _PATH_HOST_RSA_KEY_FILE, "", NULL, NULL);
		PRIV_END;

		if (options.hostbased_authentication == 1 &&
		    sensitive_data.keys[0] == NULL &&
		    sensitive_data.keys[4] == NULL &&
		    sensitive_data.keys[5] == NULL &&
		    sensitive_data.keys[6] == NULL) {
			sensitive_data.keys[1] = key_load_cert(
			    _PATH_HOST_DSA_KEY_FILE);
			sensitive_data.keys[2] = key_load_cert(
			    _PATH_HOST_ECDSA_KEY_FILE);
			sensitive_data.keys[3] = key_load_cert(
			    _PATH_HOST_RSA_KEY_FILE);
			sensitive_data.keys[4] = key_load_public(
			    _PATH_HOST_DSA_KEY_FILE, NULL);
			sensitive_data.keys[5] = key_load_public(
			    _PATH_HOST_ECDSA_KEY_FILE, NULL);
			sensitive_data.keys[6] = key_load_public(
			    _PATH_HOST_RSA_KEY_FILE, NULL);
			sensitive_data.external_keysign = 1;
		}
	}
	/*
	 * Get rid of any extra privileges that we may have.  We will no
	 * longer need them.  Also, extra privileges could make it very hard
	 * to read identity files and other non-world-readable files from the
	 * user's home directory if it happens to be on a NFS volume where
	 * root is mapped to nobody.
	 */
	if (original_effective_uid == 0) {
		PRIV_START;
		permanently_set_uid(pw);
	}

	/*
	 * Now that we are back to our own permissions, create ~/.ssh
	 * directory if it doesn't already exist.
	 */
	r = snprintf(buf, sizeof buf, "%s%s%s", pw->pw_dir,
	    strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR);
	if (r > 0 && (size_t)r < sizeof(buf) && stat(buf, &st) < 0)
		if (mkdir(buf, 0700) < 0)
			error("Could not create directory '%.200s'.", buf);

	/* load options.identity_files */
	load_public_identity_files();

	/* Expand ~ in known host file names. */
	tilde_expand_paths(options.system_hostfiles,
	    options.num_system_hostfiles);
	tilde_expand_paths(options.user_hostfiles, options.num_user_hostfiles);

	signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */
	signal(SIGCHLD, main_sigchld_handler);

	/* Log into the remote system.  Never returns if the login fails. */
	ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr,
	    options.port, pw, timeout_ms);

	if (packet_connection_is_on_socket()) {
		verbose("Authenticated to %s ([%s]:%d).", host,
		    get_remote_ipaddr(), get_remote_port());
	} else {
		verbose("Authenticated to %s (via proxy).", host);
	}

	/* We no longer need the private host keys.  Clear them now. */
	if (sensitive_data.nkeys != 0) {
		for (i = 0; i < sensitive_data.nkeys; i++) {
			if (sensitive_data.keys[i] != NULL) {
				/* Destroys contents safely */
				debug3("clear hostkey %d", i);
				key_free(sensitive_data.keys[i]);
				sensitive_data.keys[i] = NULL;
			}
		}
		xfree(sensitive_data.keys);
	}
	for (i = 0; i < options.num_identity_files; i++) {
		if (options.identity_files[i]) {
			xfree(options.identity_files[i]);
			options.identity_files[i] = NULL;
		}
		if (options.identity_keys[i]) {
			key_free(options.identity_keys[i]);
			options.identity_keys[i] = NULL;
		}
	}

	exit_status = compat20 ? ssh_session2() : ssh_session();
	packet_close();

	if (options.control_path != NULL && muxserver_sock != -1)
		unlink(options.control_path);

	/* Kill ProxyCommand if it is running. */
	ssh_kill_proxy_command();

	return exit_status;
}
示例#20
0
int FSSftp::CheckSession( int* err, FSCInfo* info )
{
	if ( sshSession ) { return 0; }

	try
	{
		sshSession = ssh_new();

		if ( !sshSession ) { throw int( SSH_INTERROR_X3 ); }

		if ( ssh_options_set( sshSession, SSH_OPTIONS_HOST, unicode_to_utf8( _operParam.server.Data() ).ptr() ) )
		{
			throw int( SSH_INTERROR_X3 );
		}

		int port = _operParam.port;

		if ( ssh_options_set( sshSession, SSH_OPTIONS_PORT, &port ) )
		{
			throw int( SSH_INTERROR_X3 );
		}


		FSString userName = "";

		if ( _operParam.user.Data()[0] )
		{
			userName = _operParam.user.Data();
		}
		else
		{
			char* ret = getenv( "LOGNAME" );

			if ( ret )
			{
				userName = FSString( sys_charset_id, ret );
				_operParam.user = userName.GetUnicode();

				MutexLock infoLock( &infoMutex );
				_infoParam.user = userName.GetUnicode();
			}
		};

		if ( ssh_options_set( sshSession, SSH_OPTIONS_USER, ( char* )userName.Get( _operParam.charset ) ) ) //есть сомнения, что надо все таки в utf8
		{
			throw int( SSH_INTERROR_X3 );
		}

		if ( ssh_connect( sshSession ) != SSH_OK )
		{
			throw int( SSH_INTERROR_CONNECT );
		}


		int method = ssh_userauth_list( sshSession, 0 );

		int ret;


		static unicode_t userSymbol = '@';

		if ( method & SSH_AUTH_METHOD_PASSWORD )
		{
			FSPromptData data;
			data.visible = false;
			data.prompt = utf8_to_unicode( "Password:"******"SFTP_" ).ptr(),
			        carray_cat<unicode_t>( userName.GetUnicode(), &userSymbol, _operParam.server.Data() ).ptr(),
			        &data, 1 ) ) { throw int( SSH_INTERROR_STOPPED ); }

			ret = ssh_userauth_password( sshSession,
			                             ( char* )FSString( _operParam.user.Data() ).Get( _operParam.charset ),
			                             ( char* )FSString( data.prompt.Data() ).Get( _operParam.charset ) );
		}

		if ( ret != SSH_AUTH_SUCCESS &&
		     ( method & SSH_AUTH_METHOD_INTERACTIVE ) != 0 )
		{
			while ( true )
			{
				ret = ssh_userauth_kbdint( sshSession, 0, 0 );

				if ( ret != SSH_AUTH_INFO ) { break; }

				const char* instruction = ssh_userauth_kbdint_getinstruction( sshSession );

				if ( !instruction ) { instruction = ""; }

				int n = ssh_userauth_kbdint_getnprompts( sshSession );

				if ( n <= 0 ) { continue; }

				std::vector<FSPromptData> pData( n );
				int i;

				for ( i = 0; i < n; i++ )
				{
					char echo;
					const char* prompt = ssh_userauth_kbdint_getprompt( sshSession, i, &echo );

					if ( !prompt ) { break; }

					pData[i].visible = echo != 0;
					pData[i].prompt = utf8_to_unicode( prompt ).ptr();
				}

				if ( !info ) { throw int( SSH_INTERROR_AUTH ); }

				if ( !info->Prompt(
				        utf8_to_unicode( "SFTP" ).ptr(),
				        carray_cat<unicode_t>( userName.GetUnicode(), &userSymbol, _operParam.server.Data() ).ptr(),
				        pData.ptr(), n ) ) { throw int( SSH_INTERROR_STOPPED ); }

				for ( i = 0; i < n; i++ )
				{
					if ( ssh_userauth_kbdint_setanswer( sshSession, i, ( char* )FSString( pData[i].prompt.Data() ).Get( _operParam.charset ) ) < 0 )
					{
						throw int( SSH_INTERROR_AUTH );
					}
				}
			}
		}

		if ( ret != SSH_AUTH_SUCCESS )
		{
			if ( ret == SSH_AUTH_PARTIAL )
			{
				throw int( SSH_INTERROR_UNSUPPORTED_AUTH );
			}
			else
			{
				throw int( SSH_INTERROR_AUTH );
			}
		}

		sftpSession = sftp_new( sshSession );

		if ( !sftpSession ) { throw int( SSH_INTERROR_FATAL ); }

		if ( sftp_init( sftpSession ) != SSH_OK ) { throw int( SSH_INTERROR_FATAL ); }

	}
	catch ( int e )
	{
		if ( err ) { *err = e; }

		if ( sftpSession ) { sftp_free( sftpSession ); }

		if ( sshSession ) { ssh_free( sshSession ); }

		sshSession = 0;
		sftpSession = 0;
		return ( e == SSH_INTERROR_STOPPED ) ? -2 : -1;
	}

	return 0;
}