blob: 0cbb2a6f2516255f573f3aa79502639320dbf850 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001'''
2BitBake 'Fetch' implementations
3
4This implementation is for Secure Shell (SSH), and attempts to comply with the
5IETF secsh internet draft:
6 http://tools.ietf.org/wg/secsh/draft-ietf-secsh-scp-sftp-ssh-uri/
7
8 Currently does not support the sftp parameters, as this uses scp
9 Also does not support the 'fingerprint' connection parameter.
10
11 Please note that '/' is used as host, path separator not ':' as you may
12 be used to, also '~' can be used to specify user HOME, but again after '/'
13
14 Example SRC_URI:
15 SRC_URI = "ssh://user@host.example.com/dir/path/file.txt"
16 SRC_URI = "ssh://user@host.example.com/~/file.txt"
17'''
18
19# Copyright (C) 2006 OpenedHand Ltd.
20#
21#
22# Based in part on svk.py:
23# Copyright (C) 2006 Holger Hans Peter Freyther
24# Based on svn.py:
25# Copyright (C) 2003, 2004 Chris Larson
26# Based on functions from the base bb module:
27# Copyright 2003 Holger Schurig
28#
29#
Brad Bishopc342db32019-05-15 21:57:59 -040030# SPDX-License-Identifier: GPL-2.0-only
Patrick Williamsc124f4f2015-09-15 14:41:29 -050031#
Patrick Williamsc124f4f2015-09-15 14:41:29 -050032
33import re, os
Andrew Geisslerc9f78652020-09-18 14:11:35 -050034from bb.fetch2 import check_network_access, FetchMethod, ParameterError, runfetchcmd
Patrick Williams03907ee2022-05-01 06:28:52 -050035import urllib
Patrick Williamsc124f4f2015-09-15 14:41:29 -050036
37
38__pattern__ = re.compile(r'''
39 \s* # Skip leading whitespace
40 ssh:// # scheme
41 ( # Optional username/password block
42 (?P<user>\S+) # username
43 (:(?P<pass>\S+))? # colon followed by the password (optional)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050044 (?P<cparam>(;[^;]+)*)? # connection parameters block (optional)
45 @
Andrew Geissler9aee5002022-03-30 16:27:02 +000046 )?
Patrick Williamsc124f4f2015-09-15 14:41:29 -050047 (?P<host>\S+?) # non-greedy match of the host
48 (:(?P<port>[0-9]+))? # colon followed by the port (optional)
49 /
50 (?P<path>[^;]+) # path on the remote system, may be absolute or relative,
51 # and may include the use of '~' to reference the remote home
52 # directory
53 (?P<sparam>(;[^;]+)*)? # parameters block (optional)
54 $
55''', re.VERBOSE)
56
57class SSH(FetchMethod):
58 '''Class to fetch a module or modules via Secure Shell'''
59
60 def supports(self, urldata, d):
Andrew Geissler82c905d2020-04-13 13:39:40 -050061 return __pattern__.match(urldata.url) is not None
Patrick Williamsc124f4f2015-09-15 14:41:29 -050062
63 def supports_checksum(self, urldata):
64 return False
65
66 def urldata_init(self, urldata, d):
67 if 'protocol' in urldata.parm and urldata.parm['protocol'] == 'git':
Andrew Geisslerc9f78652020-09-18 14:11:35 -050068 raise ParameterError(
Patrick Williamsc124f4f2015-09-15 14:41:29 -050069 "Invalid protocol - if you wish to fetch from a git " +
70 "repository using ssh, you need to use " +
71 "git:// prefix with protocol=ssh", urldata.url)
72 m = __pattern__.match(urldata.url)
73 path = m.group('path')
Patrick Williams03907ee2022-05-01 06:28:52 -050074 path = urllib.parse.unquote(path)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050075 host = m.group('host')
Brad Bishop6e60e8b2018-02-01 10:27:11 -050076 urldata.localpath = os.path.join(d.getVar('DL_DIR'),
Patrick Williamsc124f4f2015-09-15 14:41:29 -050077 os.path.basename(os.path.normpath(path)))
78
79 def download(self, urldata, d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -050080 dldir = d.getVar('DL_DIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050081
82 m = __pattern__.match(urldata.url)
83 path = m.group('path')
84 host = m.group('host')
85 port = m.group('port')
86 user = m.group('user')
87 password = m.group('pass')
88
89 if port:
90 portarg = '-P %s' % port
91 else:
92 portarg = ''
93
94 if user:
95 fr = user
96 if password:
97 fr += ':%s' % password
98 fr += '@%s' % host
99 else:
100 fr = host
Andrew Geissler9aee5002022-03-30 16:27:02 +0000101
102 if path[0] != '~':
103 path = '/%s' % path
Patrick Williams03907ee2022-05-01 06:28:52 -0500104 path = urllib.parse.unquote(path)
Andrew Geissler9aee5002022-03-30 16:27:02 +0000105
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500106 fr += ':%s' % path
107
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500108 cmd = 'scp -B -r %s %s %s/' % (
109 portarg,
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600110 fr,
111 dldir
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500112 )
113
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500114 check_network_access(d, cmd, urldata.url)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500115
116 runfetchcmd(cmd, d)
117
Andrew Geissler9aee5002022-03-30 16:27:02 +0000118 def checkstatus(self, fetch, urldata, d):
119 """
120 Check the status of the url
121 """
122 m = __pattern__.match(urldata.url)
123 path = m.group('path')
124 host = m.group('host')
125 port = m.group('port')
126 user = m.group('user')
127 password = m.group('pass')
128
129 if port:
130 portarg = '-P %s' % port
131 else:
132 portarg = ''
133
134 if user:
135 fr = user
136 if password:
137 fr += ':%s' % password
138 fr += '@%s' % host
139 else:
140 fr = host
141
142 if path[0] != '~':
143 path = '/%s' % path
Patrick Williams03907ee2022-05-01 06:28:52 -0500144 path = urllib.parse.unquote(path)
Andrew Geissler9aee5002022-03-30 16:27:02 +0000145
146 cmd = 'ssh -o BatchMode=true %s %s [ -f %s ]' % (
147 portarg,
148 fr,
149 path
150 )
151
152 check_network_access(d, cmd, urldata.url)
Andrew Geissler87f5cff2022-09-30 13:13:31 -0500153 runfetchcmd(cmd, d)
Andrew Geissler9aee5002022-03-30 16:27:02 +0000154
Andrew Geissler87f5cff2022-09-30 13:13:31 -0500155 return True