Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

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

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

# 

# regexes.py: anaconda regular expressions 

# 

# Copyright (C) 2013 Red Hat, Inc. All rights reserved. 

# 

# This program is free software; you can redistribute it and/or modify 

# it under the terms of the GNU General Public License as published by 

# the Free Software Foundation; either version 2 of the License, or 

# (at your option) any later version. 

# 

# This program is distributed in the hope that it will be useful, 

# but WITHOUT ANY WARRANTY; without even the implied warranty of 

# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

# GNU General Public License for more details. 

# 

# You should have received a copy of the GNU General Public License 

# along with this program. If not, see <http://www.gnu.org/licenses/>. 

# 

 

import re 

 

# Validation expressions 

 

# The full name field can contain anything except a colon. 

# The empty string allowed. 

GECOS_VALID = re.compile(r'^[^:]*$') 

 

# Everyone has different ideas for what can go in a username. Here's ours: 

# POSIX recommends that user and group names use only the characters within 

# the portable filesystem character set (ASCII alnum plus dot, underscore, 

# and hyphen), with the additional restriction that names not start with a 

# hyphen. The Red Hat modification to shadow-utils starts with these rules 

# and additionally allows a final $, because Samba. It doesn't allow fully 

# numeric names or just "." or "..". 

# 

# shadow-utils also defines length limits for names: 32 for group names, 

# and UT_NAMESIZE for user names (which is defined as 32 bits/utmp.h). This 

# expression captures all of that: the initial character, followed by either 

# up to 30 portable characters and a dollar sign or up to 31 portable characters, 

# both for a maximum total of 32. The empty string is not allowed. 

 

PORTABLE_FS_CHARS = r'a-zA-Z0-9._-' 

_NAME_BASE = r'[a-zA-Z0-9._][' + PORTABLE_FS_CHARS + r']{0,30}([' + PORTABLE_FS_CHARS + r']|\$)?' 

 

# A regex for user and group names. 

NAME_VALID = re.compile(r'^' + _NAME_BASE + '$') 

 

# A comma-separated list of groups, validated as in NAME_VALID 

# Any number of spaces are allowed at the start and end of the list and 

# before and after the commas. The empty string is allowed. 

GROUPLIST_SIMPLE_VALID = re.compile(r'^\s*(' + _NAME_BASE + r'(\s*,\s*' + _NAME_BASE + r')*)?\s*$') 

 

# Parse the <gr-name> (<gid>) strings in the group list. 

# 

# The name match is non-greedy so that it doesn't match the whitespace betweeen 

# the name and ID. 

# 

# There's some non-capturing groups ("clusters" in the perlre parlance) thrown 

# in there, and, haha, wow, that's confusing to look at. There are two groups 

# that actually end up in the match object, and they're named to try to make 

# it a little easier: the first is "name", and the second is "gid". 

# 

# EVERY STRING IS MATCHED. This expression cannot be used for validation. 

# If there is no GID, or the GID contains non-digits, everything except 

# leading or trailing whitespace ends up in the name group. The result needs to 

# be validated with NAME_VALID. 

GROUPLIST_FANCY_PARSE = re.compile(r'^(?:\s*)(?P<name>.*?)\s*(?:\((?P<gid>\d+)\))?(?:\s*)$') 

 

# IPv4 address without anchors 

IPV4_PATTERN_WITHOUT_ANCHORS = r'(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)' 

 

IPV4_PATTERN_WITH_ANCHORS = re.compile("^" + IPV4_PATTERN_WITHOUT_ANCHORS + "$") 

 

# IPv4 address or dhcp with anchors 

IPV4_OR_DHCP_PATTERN_WITH_ANCHORS = re.compile("^(?:" + IPV4_PATTERN_WITHOUT_ANCHORS + "|dhcp)$") 

 

# IPv6 address without anchors 

# Adapted from the IPv6address ABNF definition in RFC 3986, so it has all those 

# IPv4 compatibility bits too. All groups are non-capturing to make it easy to 

# use in an expression with groups and completely impossible to read 

IPV6_PATTERN_WITHOUT_ANCHORS = r'(?:' + \ 

r'(?:(?:(?:[0-9a-fA-F]{1,4}:){6})(?:(?:(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))|(?:' + IPV4_PATTERN_WITHOUT_ANCHORS + r')))|' + \ 

r'(?:::(?:(?:[0-9a-fA-F]{1,4}:){5})(?:(?:(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))|(?:' + IPV4_PATTERN_WITHOUT_ANCHORS + r')))|' + \ 

r'(?:(?:[0-9a-fA-F]{1,4})?::(?:(?:[0-9a-fA-F]{1,4}:){4})(?:(?:(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))|(?:' + IPV4_PATTERN_WITHOUT_ANCHORS + r')))|' + \ 

r'(?:(?:(?:[0-9a-fA-F]{1,4}:){,1}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}:){3})(?:(?:(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))|(?:' + IPV4_PATTERN_WITHOUT_ANCHORS + r')))|' + \ 

r'(?:(?:(?:[0-9a-fA-F]{1,4}:){,2}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}:){2})(?:(?:(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))|(?:' + IPV4_PATTERN_WITHOUT_ANCHORS + r')))|' + \ 

r'(?:(?:(?:[0-9a-fA-F]{1,4}:){,3}(?:[0-9a-fA-F]{1,4}))?::(?:(?:[0-9a-fA-F]{1,4}:){1})(?:(?:(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))|(?:' + IPV4_PATTERN_WITHOUT_ANCHORS + r')))|' + \ 

r'(?:(?:(?:[0-9a-fA-F]{1,4}:){,4}(?:[0-9a-fA-F]{1,4}))?::(?:(?:(?:[0-9a-fA-F]{1,4}):(?:[0-9a-fA-F]{1,4}))|(?:' + IPV4_PATTERN_WITHOUT_ANCHORS + r')))|' + \ 

r'(?:(?:(?:[0-9a-fA-F]{1,4}:){,5}(?:[0-9a-fA-F]{1,4}))?::(?:[0-9a-fA-F]{1,4}))|' + \ 

r'(?:(?:(?:[0-9a-fA-F]{1,4}:){,6}(?:[0-9a-fA-F]{1,4}))?::)' + \ 

r')' 

 

# IPv4 dotted-quad netmask validation 

IPV4_NETMASK_WITHOUT_ANCHORS = r'((128|192|224|240|248|252|254)\.0\.0\.0)|(255\.(((0|128|192|224|240|248|252|254)\.0\.0)|(255\.(((0|128|192|224|240|248|252|254)\.0)|255\.(0|128|192|224|240|248|252|254)))))' 

 

# IPv4 netmask with anchors 

IPV4_NETMASK_WITH_ANCHORS = re.compile("^" + IPV4_NETMASK_WITHOUT_ANCHORS + "$") 

 

# Hostname validation 

# A hostname consists of sections separated by periods. Each of these sections 

# must be between 1 and 63 characters, contain only alphanumeric characters or 

# hyphens, and may not start or end with a hyphen. The whole string cannot start 

# with a period, but it can end with one. 

# This regex uses negative lookahead and lookback assertions to enforce the 

# hyphen rules and make it way more confusing 

HOSTNAME_PATTERN_WITHOUT_ANCHORS = r'(?:(?!-)[A-Za-z0-9-]{1,63}(?<!-)(?:\.(?!-)[A-Za-z0-9-]{1,63}(?<!-))*\.?)' 

 

# URL Hostname 

# This matches any hostname, IPv4 literal or properly encased IPv6 literal 

# This does not match the "IPvFuture" form because come the hell on 

URL_HOSTNAME_PATTERN_WITHOUT_ANCHORS = r'(?:' + IPV4_PATTERN_WITHOUT_ANCHORS + r')|(?:\[' + IPV6_PATTERN_WITHOUT_ANCHORS + r'])|(?:' + HOSTNAME_PATTERN_WITHOUT_ANCHORS + ')' 

 

# Matches the "scheme" defined by RFC 3986 

URL_SCHEME_PATTERN_WITHOUT_ANCHORS = r'[A-Za-z][A-Za-z0-9+.-]*' 

 

# Matches any unreserved or percent-encoded character 

URL_NORMAL_CHAR = r'[A-Za-z0-9._~-]|(?:%[0-9A-Fa-f]{2})' 

 

# The above but also matches 'sub-delims' and :, @ and / 

URL_PATH_CHAR = URL_NORMAL_CHAR + "|[!$&'()*+,;=:@/]" 

 

# Parse a URL 

# Parses a URL of the form [protocol://][username[:password]@]host[:port][path][?query][#fragment] 

# into the following named groups: 

# 1: protocol (e.g., http://) 

# 2: username 

# 3: password 

# 4: host 

# 5: port 

# 6: path 

# 7: query 

# 8: fragment 

URL_PARSE = re.compile(r'^(?P<protocol>' + URL_SCHEME_PATTERN_WITHOUT_ANCHORS + r'://)?' + 

r'(?:(?P<username>(?:' + URL_NORMAL_CHAR + r')*)(?::(?P<password>(?:' + URL_NORMAL_CHAR + r')*))?@)?' + 

r'(?P<host>' + URL_HOSTNAME_PATTERN_WITHOUT_ANCHORS + ')' + 

r'(?::(?P<port>[0-9]+))?' + 

r'(?P<path>/(?:' + URL_PATH_CHAR + r')*)?' + 

r'(?:\?(?P<query>(?:' + URL_PATH_CHAR + r'|\?)*))?' + 

r'(?:#(?P<fragment>(?:' + URL_PATH_CHAR + r'|\?)*))?$') 

 

 

# Valid characters for repository names 

REPO_NAME_VALID = re.compile(r'^[a-zA-Z0-9_.:-]+$') 

 

# Product Version string, just the starting numbers like 21 or 21.1 

VERSION_DIGITS = r'([\d.]+)' 

 

#Regexes to validate iSCSI Names according to RFC 3720 and RFC 3721 

#The conditions for iSCSI name used in the following regexes are 

#(https://tools.ietf.org/html/rfc3720#section-3.2.6.3.1 , https://tools.ietf.org/html/rfc3721#page-5 and http://standards.ieee.org/regauth/oui/tutorials/EUI64.html): 

#1. For iqn format: 

# a. Starts with string 'iqn.' 

# b. A date code specifying the year and month in which the organization 

# registered the domain or sub-domain name used as the naming authority 

# string. "yyyy-mm" 

# c. A dot (".") 

# d. The organizational naming authority string, which consists of a 

# valid, reversed domain or subdomain name. 

# e. Optionally, a colon (":"), followed by a string of the assigning 

# organization's choosing, which must make each assigned iSCSI name 

# unique. With the exception of the colon prefix, the owner of the domain 

# name can assign everything after the reversed domain name as desired. 

ISCSI_IQN_NAME_REGEX = re.compile(r'^iqn\.\d{4}-\d{2}((?<!-)\.(?!-)[a-zA-Z0-9\-]+){1,63}(?<!-)(?<!\.)(:[^:]+)?$') 

 

#2. For eui format: 

# a. The format is "eui." followed by an EUI-64 identifier (16 ASCII-encoded hexadecimal digits). 

ISCSI_EUI_NAME_REGEX = re.compile(r'^eui\.[a-fA-F0-9]{16}$') 

 

# Device with this name was configured from ibft (and renamed) by dracut 

IBFT_CONFIGURED_DEVICE_NAME = re.compile(r'^ibft\d+$') 

 

# Regex to validate a DASD device number (full or partial). 

# 

# A DASD number has the format n.n.hhhh, where n is any decimal 

# digit and h any hexadecimal digit, e.g., 0.0.abcd, 0.0.002A. 

# 

# The partial form of the DASD number is missing hexadecimal digits, 

# e.g., 0.0.b, or missing a bus number, e.g., 0012. The minimal 

# partial number contains a single digit. For example a. 

DASD_DEVICE_NUMBER = re.compile(r'^(?:[0-9]\.[0-9]\.|\.|)[0-9A-Fa-f]{1,4}$') 

 

# Regex to validate the Logical Unit Number (LUN). 

# The LUN is a 16 digit hexadecimal value padded with zeroes to the right, 

# for example 0x4010403300000000. 

ZFCP_LUN_NUMBER = re.compile(r'^(?:0x|)[0-9A-Fa-f]{1,16}$') 

 

# Regex to validate the Worldwide Port Name (WWPN). 

# The WWPN is a 16 digit hexadecimal number prefixed with 0x, 

# for example 0x5005076303000104. 

ZFCP_WWPN_NUMBER = re.compile(r'^(?:0x|)[0-9A-Fa-f]{16}$')