# Buggy code
def tunnel_to_kernel(connection_info, sshserver, sshkey=None):
    """tunnel connections to a kernel via ssh

    This will open four SSH tunnels from localhost on this machine to the
    ports associated with the kernel.  They can be either direct
    localhost-localhost tunnels, or if an intermediate server is necessary,
    the kernel must be listening on a public IP.

    Parameters
    ----------
    connection_info : dict or str (path)
        Either a connection dict, or the path to a JSON connection file
    sshserver : str
        The ssh sever to use to tunnel to the kernel. Can be a full
        `user@server:port` string. ssh config aliases are respected.
    sshkey : str [optional]
        Path to file containing ssh key to use for authentication.
        Only necessary if your ssh config does not already associate
        a keyfile with the host.

    Returns
    -------

    (shell, iopub, stdin, hb) : ints
        The four ports on localhost that have been forwarded to the kernel.
    """
    if isinstance(connection_info, basestring):
        # it's a path, unpack it
        with open(connection_info) as f:
            connection_info = json.loads(f.read())

    cf = connection_info

    lports = tunnel.select_random_ports(4)
    rports = cf["shell_port"], cf["iopub_port"], cf["stdin_port"], cf["hb_port"]

    remote_ip = cf["ip"]

    if tunnel.try_passwordless_ssh(sshserver, sshkey):
        password = False
    else:
        password = getpass("SSH Password for %s: " % sshserver)

    for lp, rp in zip(lports, rports):
        tunnel.ssh_tunnel(lp, rp, sshserver, remote_ip, sshkey, password)

    return tuple(lports)


# Traceback (TypeError)
[IPythonQtConsoleApp] Could not setup tunnels
Traceback (most recent call last):
File "C:\Python27\lib\site-packages\IPython\frontend\consoleapp.py", line 289, in init_ssh
newports = tunnel_to_kernel(info, self.sshserver, self.sshkey)
File "C:\Python27\lib\site-packages\IPython\lib\kernel.py", line 248, in tunnel_to_kernel
password = getpass("SSH Password for %s: "%sshserver)
File "C:\Python27\lib\getpass.py", line 95, in win_getpass
msvcrt.putch(c)
TypeError: must be char, not unicode

# Fixed code
def tunnel_to_kernel(connection_info, sshserver, sshkey=None):
    """tunnel connections to a kernel via ssh

    This will open four SSH tunnels from localhost on this machine to the
    ports associated with the kernel.  They can be either direct
    localhost-localhost tunnels, or if an intermediate server is necessary,
    the kernel must be listening on a public IP.

    Parameters
    ----------
    connection_info : dict or str (path)
        Either a connection dict, or the path to a JSON connection file
    sshserver : str
        The ssh sever to use to tunnel to the kernel. Can be a full
        `user@server:port` string. ssh config aliases are respected.
    sshkey : str [optional]
        Path to file containing ssh key to use for authentication.
        Only necessary if your ssh config does not already associate
        a keyfile with the host.

    Returns
    -------

    (shell, iopub, stdin, hb) : ints
        The four ports on localhost that have been forwarded to the kernel.
    """
    if isinstance(connection_info, basestring):
        # it's a path, unpack it
        with open(connection_info) as f:
            connection_info = json.loads(f.read())

    cf = connection_info

    lports = tunnel.select_random_ports(4)
    rports = cf["shell_port"], cf["iopub_port"], cf["stdin_port"], cf["hb_port"]

    remote_ip = cf["ip"]

    if tunnel.try_passwordless_ssh(sshserver, sshkey):
        password = False
    else:
        password = getpass("SSH Password for %s: " % cast_bytes_py2(sshserver))

    for lp, rp in zip(lports, rports):
        tunnel.ssh_tunnel(lp, rp, sshserver, remote_ip, sshkey, password)

    return tuple(lports)