aboutsummaryrefslogtreecommitdiffstats
path: root/lib/bb/fetch2/ssh.py
blob: f5be060c439a7e429b908d1a34c8f50c29325717 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
'''
BitBake 'Fetch' implementations

This implementation is for Secure Shell (SSH), and attempts to comply with the
IETF secsh internet draft:
    http://tools.ietf.org/wg/secsh/draft-ietf-secsh-scp-sftp-ssh-uri/

    Currently does not support the sftp parameters, as this uses scp
    Also does not support the 'fingerprint' connection parameter.

    Please note that '/' is used as host, path separator not ':' as you may 
    be used to, also '~' can be used to specify user HOME, but again after '/'
    
    Example SRC_URI:
    SRC_URI = "ssh://user@host.example.com/dir/path/file.txt"
    SRC_URI = "ssh://user@host.example.com/~/file.txt"
'''

# Copyright (C) 2006  OpenedHand Ltd.
#
#
# Based in part on svk.py:
#    Copyright (C) 2006 Holger Hans Peter Freyther
#    Based on svn.py:
#        Copyright (C) 2003, 2004  Chris Larson
#        Based on functions from the base bb module:
#            Copyright 2003 Holger Schurig
#
#
# SPDX-License-Identifier: GPL-2.0-only
#

import re, os
from   bb.fetch2 import FetchMethod
from   bb.fetch2 import FetchError
from   bb.fetch2 import logger
from   bb.fetch2 import runfetchcmd


__pattern__ = re.compile(r'''
 \s*                 # Skip leading whitespace
 ssh://              # scheme
 (                   # Optional username/password block
  (?P<user>\S+)      # username
  (:(?P<pass>\S+))?  # colon followed by the password (optional)
 )?
 (?P<cparam>(;[^;]+)*)?  # connection parameters block (optional)
 @
 (?P<host>\S+?)          # non-greedy match of the host
 (:(?P<port>[0-9]+))?    # colon followed by the port (optional)
 /
 (?P<path>[^;]+)         # path on the remote system, may be absolute or relative,
                         # and may include the use of '~' to reference the remote home
                         # directory
 (?P<sparam>(;[^;]+)*)?  # parameters block (optional)
 $
''', re.VERBOSE)

class SSH(FetchMethod):
    '''Class to fetch a module or modules via Secure Shell'''

    def supports(self, urldata, d):
        return __pattern__.match(urldata.url) != None

    def supports_checksum(self, urldata):
        return False

    def urldata_init(self, urldata, d):
        if 'protocol' in urldata.parm and urldata.parm['protocol'] == 'git':
            raise bb.fetch2.ParameterError(
                "Invalid protocol - if you wish to fetch from a git " +
                "repository using ssh, you need to use " +
                "git:// prefix with protocol=ssh", urldata.url)
        m = __pattern__.match(urldata.url)
        path = m.group('path')
        host = m.group('host')
        urldata.localpath = os.path.join(d.getVar('DL_DIR'),
                os.path.basename(os.path.normpath(path)))

    def download(self, urldata, d):
        dldir = d.getVar('DL_DIR')

        m = __pattern__.match(urldata.url)
        path = m.group('path')
        host = m.group('host')
        port = m.group('port')
        user = m.group('user')
        password = m.group('pass')

        if port:
            portarg = '-P %s' % port
        else:
            portarg = ''

        if user:
            fr = user
            if password:
                fr += ':%s' % password
            fr += '@%s' % host
        else:
            fr = host
        fr += ':%s' % path

        cmd = 'scp -B -r %s %s %s/' % (
            portarg,
            fr,
            dldir
        )

        bb.fetch2.check_network_access(d, cmd, urldata.url)

        runfetchcmd(cmd, d)