Exemple #1
0
def get_identities(self, *anything):
    """
    Sends a message to the client with a list of the identities stored on the
    server for the current user.

    *anything* is just there because the client needs to send *something* along
    with the 'action'.
    """
    self.ssh_log.debug('get_identities()')
    out_dict = {'result': 'Success'}
    users_ssh_dir = get_ssh_dir(self)
    out_dict['identities'] = []
    ssh_keygen_path = '/opt/local/bin/ssh-keygen'
    # TODO:  Switch this from using ssh-keygen to determine the keytype to using the string inside the public key.
    try:
        if os.path.exists(users_ssh_dir):
            ssh_files = os.listdir(users_ssh_dir)
            for f in ssh_files:
                if f.endswith('.pub'):
                    # Double-check there's also a private key...
                    identity = f[:-4] # Will be the same name minus '.pub'
                    if identity in ssh_files:
                        id_path = os.path.join(users_ssh_dir, identity)
                        pub_key_path = os.path.join(users_ssh_dir, f)
                        public_key_contents = open(pub_key_path).read()
                        comment = ' '.join(public_key_contents.split(' ')[2:])
                        if public_key_contents.startswith('ecdsa'):
                            keytype = 'ECDSA'
                        elif public_key_contents.startswith('ssh-dss'):
                            keytype = 'DSA'
                        elif public_key_contents.startswith('ssh-rsa'):
                            keytype = 'RSA'
                        else:
                            keytype = 'Unknown'
                        keygen_cmd = "'%s' -vlf '%s'" % (
                            ssh_keygen_path, id_path)
                        retcode, key_info = shell_command(keygen_cmd)
                        # This will just wind up as an empty string if the
                        # version of ssh doesn't support randomart:
                        randomart = '\n'.join(key_info.splitlines()[1:])
                        bits = key_info.split()[0]
                        fingerprint = key_info.split()[1]
                        retcode, bubblebabble = shell_command(
                            "'%s' -Bf '%s'" % (ssh_keygen_path, id_path))
                        bubblebabble = bubblebabble.split()[1]
                        certinfo = ''
                        cert_path = "'%s-cert.pub'" % id_path
                        if os.path.exists(cert_path):
                            retcode, certinfo = shell_command(
                            "'%s' -Lf '%s'" % (ssh_keygen_path, cert_path))
                        certinfo = ' '.join(certinfo.split(' ')[1:])
                        fixed_certinfo = ''
                        for i, line in enumerate(certinfo.splitlines()):
                            if i == 0:
                                line = line.lstrip()
                            fixed_certinfo += line.replace('    ', ' ')
                            fixed_certinfo += '\n'
                        id_obj = {
                            'name': identity,
                            'public': public_key_contents,
                            'keytype': keytype,
                            'bubblebabble': bubblebabble,
                            'fingerprint': fingerprint,
                            'randomart': randomart,
                            'certinfo': fixed_certinfo,
                            'bits': bits,
                            'comment': comment.rstrip(),
                        }
                        out_dict['identities'].append(id_obj)
        # Figure out which identities are defaults
        default_ids = []
        default_ids_exists = False
        users_ssh_dir = get_ssh_dir(self)
        default_ids_path = os.path.join(users_ssh_dir, '.default_ids')
        if os.path.exists(default_ids_path):
            default_ids_exists = True
            with open(default_ids_path) as f:
                default_ids = f.read().splitlines() # Why not readlines()? \n
        # Convert any absolute paths inside default_ids to just the short names
        default_ids = [os.path.split(a)[1] for a in default_ids]
        if default_ids_exists:
            for i, id_obj in enumerate(out_dict['identities']):
                if id_obj['name'] in default_ids:
                    out_dict['identities'][i]['default'] = True
                else:
                    out_dict['identities'][i]['default'] = False
    except Exception as e:
        error_msg = _("Error getting identities: %s" % e)
        self.ssh_log.error(error_msg)
        out_dict['result'] = error_msg
    message = {
        'terminal:sshjs_identities_list': out_dict
    }
    self.write_message(message)
Exemple #2
0
def openssh_generate_new_keypair(self, name, path,
        keytype=None, passphrase="", bits=None, comment=""):
    """
    Generates a new private and public key pair--stored in the user's directory
    using the given *name* and other optional parameters (using OpenSSH).

    If *keytype* is given, it must be one of "ecdsa", "rsa" or "dsa" (case
    insensitive).  If *keytype* is "rsa" or "ecdsa", *bits* may be specified to
    specify the size of the key.

    .. note:: Defaults to generating a 521-byte ecdsa key if OpenSSH is version 5.7+. Otherwise a 2048-bit rsa key will be used.
    """
    self.ssh_log.debug('openssh_generate_new_keypair()')
    openssh_version = shell_command('ssh -V')[1]
    ssh_major_version = int(
        openssh_version.split()[0].split('_')[1].split('.')[0])
    key_path = os.path.join(path, name)
    ssh_minor_version = int(
        openssh_version.split()[0].split('_')[1].split('.')[1][0])
    ssh_version = "%s.%s" % (ssh_major_version, ssh_minor_version)
    ssh_version = float(ssh_version)
    if not keytype:
        if ssh_version >= 5.7:
            keytype = "ecdsa"
        else:
            keytype = "rsa"
    else:
        keytype = keytype.lower()
    if not bits and keytype == "ecdsa":
        bits = 521 # Not a typo: five-hundred-twenty-one bits
    elif not bits and keytype == "rsa":
        bits = 2048
    if not passphrase: # This just makes sure False and None end up as ''
        passphrase = ''
    hostname = os.uname()[1]
    if not comment:
        now = datetime.now().isoformat()
        comment = "Generated by Gate One on %s %s" % (hostname, now)
    ssh_keygen_path = '/opt/local/bin/ssh-keygen'
    command = (
        "%s "       # Path to ssh-keygen
        "-b %s "    # bits
        "-t %s "    # keytype
        "-C '%s' "  # comment
        "-f '%s'"   # Key path
        % (ssh_keygen_path, bits, keytype, comment, key_path)
    )
    self.ssh_log.debug("Keygen command: %s" % command)
    m = self.new_multiplex(command, "gen_ssh_keypair")
    call_errorback = partial(errorback, self)
    m.expect('^Overwrite.*',
        overwrite, optional=True, preprocess=False, timeout=10)
    passphrase_handler = partial(enter_passphrase, passphrase)
    m.expect('^Enter passphrase',
        passphrase_handler,
        errorback=call_errorback,
        preprocess=False,
        timeout=10)
    m.expect('^Enter same passphrase again',
        passphrase_handler,
        errorback=call_errorback,
        preprocess=False,
        timeout=10)
    finalize = partial(finished, self)
    # The regex below captures the md5 fingerprint which tells us the
    # operation was successful.
    m.expect(
        '(([0-9a-f][0-9a-f]\:){15}[0-9a-f][0-9a-f])',
        finalize,
        errorback=call_errorback,
        preprocess=False,
        timeout=15 # Key generation can take a little while
    )
    m.spawn()
Exemple #3
0
def get_identities(self, *anything):
    """
    Sends a message to the client with a list of the identities stored on the
    server for the current user.

    *anything* is just there because the client needs to send *something* along
    with the 'action'.
    """
    self.ssh_log.debug('get_identities()')
    out_dict = {'result': 'Success'}
    users_ssh_dir = get_ssh_dir(self)
    out_dict['identities'] = []
    ssh_keygen_path = which('ssh-keygen')
    # TODO:  Switch this from using ssh-keygen to determine the keytype to using the string inside the public key.
    try:
        if os.path.exists(users_ssh_dir):
            ssh_files = os.listdir(users_ssh_dir)
            for f in ssh_files:
                if f.endswith('.pub'):
                    # Double-check there's also a private key...
                    identity = f[:-4] # Will be the same name minus '.pub'
                    if identity in ssh_files:
                        id_path = os.path.join(users_ssh_dir, identity)
                        pub_key_path = os.path.join(users_ssh_dir, f)
                        public_key_contents = open(pub_key_path).read()
                        comment = ' '.join(public_key_contents.split(' ')[2:])
                        if public_key_contents.startswith('ecdsa'):
                            keytype = 'ECDSA'
                        elif public_key_contents.startswith('ssh-dss'):
                            keytype = 'DSA'
                        elif public_key_contents.startswith('ssh-rsa'):
                            keytype = 'RSA'
                        else:
                            keytype = 'Unknown'
                        keygen_cmd = "'%s' -vlf '%s'" % (
                            ssh_keygen_path, id_path)
                        retcode, key_info = shell_command(keygen_cmd)
                        # This will just wind up as an empty string if the
                        # version of ssh doesn't support randomart:
                        randomart = '\n'.join(key_info.splitlines()[1:])
                        bits = key_info.split()[0]
                        fingerprint = key_info.split()[1]
                        retcode, bubblebabble = shell_command(
                            "'%s' -Bf '%s'" % (ssh_keygen_path, id_path))
                        bubblebabble = bubblebabble.split()[1]
                        certinfo = ''
                        cert_path = "'%s-cert.pub'" % id_path
                        if os.path.exists(cert_path):
                            retcode, certinfo = shell_command(
                            "'%s' -Lf '%s'" % (ssh_keygen_path, cert_path))
                        certinfo = ' '.join(certinfo.split(' ')[1:])
                        fixed_certinfo = ''
                        for i, line in enumerate(certinfo.splitlines()):
                            if i == 0:
                                line = line.lstrip()
                            fixed_certinfo += line.replace('    ', ' ')
                            fixed_certinfo += '\n'
                        id_obj = {
                            'name': identity,
                            'public': public_key_contents,
                            'keytype': keytype,
                            'bubblebabble': bubblebabble,
                            'fingerprint': fingerprint,
                            'randomart': randomart,
                            'certinfo': fixed_certinfo,
                            'bits': bits,
                            'comment': comment.rstrip(),
                        }
                        out_dict['identities'].append(id_obj)
        # Figure out which identities are defaults
        default_ids = []
        default_ids_exists = False
        users_ssh_dir = get_ssh_dir(self)
        default_ids_path = os.path.join(users_ssh_dir, '.default_ids')
        if os.path.exists(default_ids_path):
            default_ids_exists = True
            with open(default_ids_path) as f:
                default_ids = f.read().splitlines() # Why not readlines()? \n
        # Convert any absolute paths inside default_ids to just the short names
        default_ids = [os.path.split(a)[1] for a in default_ids]
        if default_ids_exists:
            for i, id_obj in enumerate(out_dict['identities']):
                if id_obj['name'] in default_ids:
                    out_dict['identities'][i]['default'] = True
                else:
                    out_dict['identities'][i]['default'] = False
    except Exception as e:
        error_msg = _("Error getting identities: %s" % e)
        self.ssh_log.error(error_msg)
        out_dict['result'] = error_msg
    message = {
        'terminal:sshjs_identities_list': out_dict
    }
    self.write_message(message)
Exemple #4
0
def get_identities(self, *anything):
    """
    Sends a message to the client with a list of the identities stored on the
    server for the current user.

    *anything* is just there because the client needs to send *something* along
    with the 'action'.
    """
    self.ssh_log.debug("get_identities()")
    out_dict = {"result": "Success"}
    users_ssh_dir = get_ssh_dir(self)
    out_dict["identities"] = []
    ssh_keygen_path = which("ssh-keygen")
    # TODO:  Switch this from using ssh-keygen to determine the keytype to using the string inside the public key.
    try:
        if os.path.exists(users_ssh_dir):
            ssh_files = os.listdir(users_ssh_dir)
            for f in ssh_files:
                if f.endswith(".pub"):
                    # Double-check there's also a private key...
                    identity = f[:-4]  # Will be the same name minus '.pub'
                    if identity in ssh_files:
                        id_path = os.path.join(users_ssh_dir, identity)
                        pub_key_path = os.path.join(users_ssh_dir, f)
                        public_key_contents = open(pub_key_path).read()
                        comment = " ".join(public_key_contents.split(" ")[2:])
                        if public_key_contents.startswith("ecdsa"):
                            keytype = "ECDSA"
                        elif public_key_contents.startswith("ssh-dss"):
                            keytype = "DSA"
                        elif public_key_contents.startswith("ssh-rsa"):
                            keytype = "RSA"
                        else:
                            keytype = "Unknown"
                        keygen_cmd = "'%s' -vlf '%s'" % (ssh_keygen_path, id_path)
                        retcode, key_info = shell_command(keygen_cmd)
                        # This will just wind up as an empty string if the
                        # version of ssh doesn't support randomart:
                        randomart = "\n".join(key_info.splitlines()[1:])
                        bits = key_info.split()[0]
                        fingerprint = key_info.split()[1]
                        retcode, bubblebabble = shell_command("'%s' -Bf '%s'" % (ssh_keygen_path, id_path))
                        bubblebabble = bubblebabble.split()[1]
                        certinfo = ""
                        cert_path = "'%s-cert.pub'" % id_path
                        if os.path.exists(cert_path):
                            retcode, certinfo = shell_command("'%s' -Lf '%s'" % (ssh_keygen_path, cert_path))
                        certinfo = " ".join(certinfo.split(" ")[1:])
                        fixed_certinfo = ""
                        for i, line in enumerate(certinfo.splitlines()):
                            if i == 0:
                                line = line.lstrip()
                            fixed_certinfo += line.replace("    ", " ")
                            fixed_certinfo += "\n"
                        id_obj = {
                            "name": identity,
                            "public": public_key_contents,
                            "keytype": keytype,
                            "bubblebabble": bubblebabble,
                            "fingerprint": fingerprint,
                            "randomart": randomart,
                            "certinfo": fixed_certinfo,
                            "bits": bits,
                            "comment": comment.rstrip(),
                        }
                        out_dict["identities"].append(id_obj)
        # Figure out which identities are defaults
        default_ids = []
        default_ids_exists = False
        users_ssh_dir = get_ssh_dir(self)
        default_ids_path = os.path.join(users_ssh_dir, ".default_ids")
        if os.path.exists(default_ids_path):
            default_ids_exists = True
            with open(default_ids_path) as f:
                default_ids = f.read().splitlines()  # Why not readlines()? \n
        # Convert any absolute paths inside default_ids to just the short names
        default_ids = [os.path.split(a)[1] for a in default_ids]
        if default_ids_exists:
            for i, id_obj in enumerate(out_dict["identities"]):
                if id_obj["name"] in default_ids:
                    out_dict["identities"][i]["default"] = True
                else:
                    out_dict["identities"][i]["default"] = False
    except Exception as e:
        error_msg = _("Error getting identities: %s" % e)
        self.ssh_log.error(error_msg)
        out_dict["result"] = error_msg
    message = {"terminal:sshjs_identities_list": out_dict}
    self.write_message(message)
Exemple #5
0
def openssh_generate_new_keypair(self, name, path,
        keytype=None, passphrase="", bits=None, comment=""):
    """
    Generates a new private and public key pair--stored in the user's directory
    using the given *name* and other optional parameters (using OpenSSH).

    If *keytype* is given, it must be one of "ecdsa", "rsa" or "dsa" (case
    insensitive).  If *keytype* is "rsa" or "ecdsa", *bits* may be specified to
    specify the size of the key.

    .. note:: Defaults to generating a 521-byte ecdsa key if OpenSSH is version 5.7+. Otherwise a 2048-bit rsa key will be used.
    """
    self.ssh_log.debug('openssh_generate_new_keypair()')
    openssh_version = shell_command('ssh -V')[1]
    ssh_major_version = int(
        openssh_version.split()[0].split('_')[1].split('.')[0])
    key_path = os.path.join(path, name)
    ssh_minor_version = int(
        openssh_version.split()[0].split('_')[1].split('.')[1][0])
    ssh_version = "%s.%s" % (ssh_major_version, ssh_minor_version)
    ssh_version = float(ssh_version)
    if not keytype:
        if ssh_version >= 5.7:
            keytype = "ecdsa"
        else:
            keytype = "rsa"
    else:
        keytype = keytype.lower()
    if not bits and keytype == "ecdsa":
        bits = 521 # Not a typo: five-hundred-twenty-one bits
    elif not bits and keytype == "rsa":
        bits = 2048
    if not passphrase: # This just makes sure False and None end up as ''
        passphrase = ''
    hostname = os.uname()[1]
    if not comment:
        now = datetime.now().isoformat()
        comment = "Generated by Gate One on %s %s" % (hostname, now)
    ssh_keygen_path = which('ssh-keygen')
    command = (
        "%s "       # Path to ssh-keygen
        "-b %s "    # bits
        "-t %s "    # keytype
        "-C '%s' "  # comment
        "-f '%s'"   # Key path
        % (ssh_keygen_path, bits, keytype, comment, key_path)
    )
    self.ssh_log.debug("Keygen command: %s" % command)
    m = self.new_multiplex(command, "gen_ssh_keypair")
    call_errorback = partial(errorback, self)
    m.expect('^Overwrite.*',
        overwrite, optional=True, preprocess=False, timeout=10)
    passphrase_handler = partial(enter_passphrase, passphrase)
    m.expect('^Enter passphrase',
        passphrase_handler,
        errorback=call_errorback,
        preprocess=False,
        timeout=10)
    m.expect('^Enter same passphrase again',
        passphrase_handler,
        errorback=call_errorback,
        preprocess=False,
        timeout=10)
    finalize = partial(finished, self)
    # The regex below captures the md5 fingerprint which tells us the
    # operation was successful.
    m.expect(
        '(([0-9a-f][0-9a-f]\:){15}[0-9a-f][0-9a-f])',
        finalize,
        errorback=call_errorback,
        preprocess=False,
        timeout=15 # Key generation can take a little while
    )
    m.spawn()