def verify(self, certificate): if self.datastore.exists('crypto.certificates', ('name', '=', certificate['name'])): raise VerifyException(errno.EEXIST, 'Certificate with given name already exists') if certificate['type'] not in ('CERT_EXISTING', 'CA_EXISTING'): raise VerifyException(errno.EINVAL, 'Invalid certificate type') errors = ValidationException() for i in ('country', 'state', 'city', 'organization', 'email', 'common'): if i in certificate: errors.add((0, i), '{0} is not valid in certificate import'.format(i)) if errors: raise errors if certificate['type'] == 'CERT_EXISTING' and ( 'privatekey' not in certificate or 'passphrase' not in certificate ): raise VerifyException( errno.EINVAL, 'privatekey and passphrase required to import certificate' ) try: if 'privatekey' in certificate: load_privatekey(certificate['privatekey'], certificate.get('passphrase')) except Exception: raise VerifyException(errno.EINVAL, 'Invalid passphrase') return ['system']
def verify(self, smb): errors = ValidationException() node = ConfigNode('service.smb', self.configstore).__getstate__() netbiosname = smb.get('netbiosname') if netbiosname is not None: for n in netbiosname: if not validate_netbios_name(n): errors.add((0, 'netbiosname'), 'Invalid name {0}'.format(n)) else: netbiosname = node['netbiosname'] workgroup = smb.get('workgroup') if workgroup is not None: if not validate_netbios_name(workgroup): errors.add((0, 'workgroup'), 'Invalid name') else: workgroup = node['workgroup'] if workgroup.lower() in [i.lower() for i in netbiosname]: errors.add((0, 'netbiosname'), 'NetBIOS and Workgroup must be unique') dirmask = smb.get('dirmask') if dirmask and (int(dirmask, 8) & ~0o11777): errors.add((0, 'dirmask'), 'This is not a valid mask') filemask = smb.get('filemask') if filemask and (int(filemask, 8) & ~0o11777): errors.add((0, 'filemask'), 'This is not a valid mask') if errors: raise errors return ['system']
def verify(self, id, updated_fields): tunable = self.datastore.get_by_id('tunables', id) if tunable is None: raise VerifyException(errno.ENOENT, 'Tunable with given ID does not exist') errors = ValidationException() if 'var' in updated_fields and self.datastore.exists( 'tunables', ('and', [('var', '=', updated_fields['var']), ('id', '!=', id)]) ): errors.add((1, 'var'), 'This variable already exists.', code=errno.EEXIST) if 'value' in updated_fields and '"' in updated_fields['value'] or "'" in updated_fields['value']: errors.add((1, 'value'), 'Quotes are not allowed') if 'type' in updated_fields: if updated_fields['type'] in ('LOADER', 'RC') and not VAR_LOADER_RC_RE.match(tunable['var']): errors.add((1, 'var'), VAR_SYSCTL_FORMAT) elif updated_fields['type'] == 'SYSCTL': if not VAR_SYSCTL_RE.match(tunable['var']): errors.add((1, 'var'), VAR_LOADER_RC_FORMAT) try: sysctl.sysctlnametomib(tunable['var']) except OSError: errors.add((1, 'var'), 'Sysctl variable does not exist') if errors: raise errors return ['system']
def verify(self, path, logs=True, cores=False): errors = ValidationException() if path in [None, ''] or path.isspace(): errors.add((0, 'path'), 'The Path is required', code=errno.EINVAL) if errors: raise errors return []
def verify(self, id, updated_fields): errors = ValidationException() normalize_name(updated_fields, 'username') if updated_fields.get('full_name') and ':' in updated_fields['full_name']: errors.add((1, 'full_name'), 'The character ":" is not allowed') if 'groups' in updated_fields and len(updated_fields['groups']) > 64: errors.add((1, 'groups'), 'User cannot belong to more than 64 auxiliary groups') if 'username' in updated_fields: for code, message in check_unixname(updated_fields['username']): errors.add((1, 'username'), message, code=code) if updated_fields.get('email'): if not EMAIL_REGEX.match(updated_fields['email']): errors.add( (1, 'email'), "{0} is an invalid email address".format(updated_fields['email']) ) if 'home' in updated_fields and updated_fields['home'] not in (None, '/nonexistent'): volumes_root = self.dispatcher.call_sync('volume.get_volumes_root') updated_fields['home'] = os.path.normpath(updated_fields['home']) if not updated_fields['home'].startswith(volumes_root) or updated_fields['home'] == volumes_root: errors.add( (1, 'home directory'), "Invalid mountpoint specified for home directory: {0}.\n".format(updated_fields['home']) + "Provide a path within zfs pool or dataset mounted under {0}".format(volumes_root) ) if errors: raise errors return ['system']
def verify(self, path): errors = ValidationException() if path in [None, ''] or path.isspace(): errors.add((0, 'path'), 'The Path is required', code=errno.EINVAL) if errors: raise errors return ['system']
def verify(self, rsyncmod): errors = ValidationException() if re.search(r'[/\]]', rsyncmod['name']): errors.add((0, 'name'), 'The name cannot contain slash or a closing square backet.') if errors: raise errors return ['system']
def verify(self, group): errors = ValidationException() normalize_name(group, 'name') for code, message in check_unixname(group['name']): errors.add((0, 'name'), message, code=code) if errors: raise errors return ['system']
def verify(self, ipfs): errors = ValidationException() if 'path' in ipfs: if ipfs['path'] in [None, ''] or ipfs['path'].isspace(): errors.add((0, path), "The provided path: '{0}' is not valid".format(ipfs['path'])) if errors: raise errors return ['system']
def verify(self, props): errors = ValidationException() if 'timezone' in props: timezones = self.dispatcher.call_sync('system.general.timezones') if props['timezone'] not in timezones: errors.add((0, 'timezone'), 'Invalid timezone: {0}'.format(props['timezone'])) if errors: raise errors return ['system']
def verify(self, id, updated_fields): errors = ValidationException() normalize_name(updated_fields, 'name') if 'name' in updated_fields: for code, message in check_unixname(updated_fields['name']): errors.add((1, 'name'), message, code=code) if errors: raise errors return ['system']
def verify(self, afp): errors = ValidationException() dbpath = afp.get('dbpath') if dbpath: if not os.path.exists(dbpath): errors.add((0, 'dbpath'), 'Path does not exist', code=errno.ENOENT) elif not os.path.isdir(dbpath): errors.add((0, 'dbpath'), 'Path is not a directory') if errors: raise errors return ['system']
def verify(self, user): errors = ValidationException() normalize_name(user, 'username') for code, message in check_unixname(user['username']): errors.add((0, 'username'), message, code=code) if self.datastore.exists('users', ('username', '=', user['username'])): raise VerifyException(errno.EEXIST, 'User with given name already exists') if 'groups' in user and len(user['groups']) > 64: errors.add( (0, 'groups'), 'User cannot belong to more than 64 auxiliary groups' ) if user.get('full_name') and ':' in user['full_name']: errors.add((0, 'full_name'), 'The character ":" is not allowed') if 'email' in user: if not EMAIL_REGEX.match(user['email']): errors.add( (0, 'email'), "{0} is an invalid email address".format(user['email']) ) if errors: raise errors return ['system']
def verify(self, lldp): errors = ValidationException() node = ConfigNode('service.lldp', self.configstore).__getstate__() node.update(lldp) # Lazy load pycountry due to extra verbose DEBUG logging import pycountry if node['country_code'] and node['country_code'] not in pycountry.countries.indices['alpha2']: errors.add((0, 'country_code'), 'Invalid ISO-3166 alpha 2 code') if errors: raise errors return ['system']
def verify(self, certificate): errors = ValidationException() if certificate['type'] == 'CERT_INTERNAL': if self.datastore.exists('crypto.certificates', ('name', '=', certificate['name'])): errors.add((0, 'name'), 'Certificate with given name already exists', code=errno.EEXIST) if not self.datastore.exists('crypto.certificates', ('id', '=', certificate['signedby'])): errors.add((0, 'signedby'), 'Signing certificate does not exist', code=errno.EEXIST) if '"' in certificate['name']: errors.add(( (0, 'name'), 'You cannot issue a certificate with a `"` in its name') ) if certificate['type'] in ('CERT_INTERNAL', 'CA_INTERMEDIATE'): if 'signedby' not in certificate or not self.datastore.exists('crypto.certificates', ('id', '=', certificate['signedby'])): errors.add((0, 'signedby'), 'Signing Certificate does not exist', code=errno.EEXIST) if errors: raise errors return ['system']
def verify(self, mail): errors = ValidationException() node = ConfigNode('mail', self.configstore).__getstate__() if mail.get('auth'): if not mail.get('user') and not node['user']: errors.add((0, 'auth'), 'Mail authorization requires a username') if not mail.get('pass') and not node['pass']: errors.add((0, 'auth'), 'Mail authorization requires a password') if errors: raise errors return []
def verify(self, mail): errors = ValidationException() node = ConfigNode("mail", self.configstore).__getstate__() if mail.get("auth"): if not mail.get("user") and not node["user"]: errors.add((0, "auth"), "Mail authorization requires a username") if not mail.get("pass") and not node["pass"]: errors.add((0, "auth"), "Mail authorization requires a password") if errors: raise errors return []
def verify(self, id, updated_fields): errors = ValidationException() if 'var' in updated_fields and self.datastore.exists( 'tunables', ('and', [('var', '=', updated_fields['var']), ('id', '!=', id)]) ): errors.add((1, 'var'), 'This variable already exists.', code=errno.EEXIST) if 'value' in updated_fields: if '"' in updated_fields['value'] or "'" in updated_fields['value']: errors.add((1, 'value'), 'Quotes are not allowed') if errors: raise errors return ['system']
def verify(self, uuid, updated_fields): rsyncmod = self.datastore.get_by_id('rsyncd-module', uuid) if rsyncmod is None: raise VerifyException(errno.ENOENT, 'Rsync module {0} does not exist'.format(uuid)) rsyncmod.update(updated_fields) errors = ValidationException() if re.search(r'[/\]]', rsyncmod['name']): errors.add((1, 'name'), 'The name cannot contain slash or a closing square backet.') if errors: raise errors return ['system']
def verify(self, id, updated_fields): errors = ValidationException() if 'name' in updated_fields: for code, message in check_unixname(updated_fields['name']): errors.add((1, 'name'), message, code=code) # Check if there is another group with same name being renamed to if self.datastore.exists('groups', ('name', '=', updated_fields['name']), ('id', '!=', id)): errors.add( (1, "name"), 'Group {0} already exists'.format(updated_fields['name']), code=errno.EEXIST ) if errors: raise errors return ['system']
def verify(self, id, updated_fields): errors = ValidationException() if 'var' in updated_fields and self.datastore.exists( 'tunables', ('and', [('var', '=', updated_fields['var']), ('id', '!=', id)])): errors.add((1, 'var'), 'This variable already exists.', code=errno.EEXIST) if 'value' in updated_fields: if '"' in updated_fields['value'] or "'" in updated_fields['value']: errors.add((1, 'value'), 'Quotes are not allowed') if errors: raise errors return ['system']
def verify(self, group): errors = ValidationException() normalize_name(group, 'name') for code, message in check_unixname(group['name']): errors.add((0, 'name'), message, code=code) if self.datastore.exists('groups', ('name', '=', group['name'])): errors.add( (0, "name"), 'Group {0} already exists'.format(group['name']), code=errno.EEXIST ) if 'gid' in group and self.datastore.exists('groups', ('gid', '=', group['gid'])): errors.add( (0, "gid"), 'Group with GID {0} already exists'.format(group['gid']), code=errno.EEXIST ) if errors: raise errors return ['system']
def verify(self, id, updated_fields): errors = ValidationException() normalize_name(updated_fields, 'username') if updated_fields.get( 'full_name') and ':' in updated_fields['full_name']: errors.add((1, 'full_name'), 'The character ":" is not allowed') if 'groups' in updated_fields and len(updated_fields['groups']) > 64: errors.add((1, 'groups'), 'User cannot belong to more than 64 auxiliary groups') if 'username' in updated_fields: for code, message in check_unixname(updated_fields['username']): errors.add((1, 'username'), message, code=code) if updated_fields.get('email'): if not EMAIL_REGEX.match(updated_fields['email']): errors.add((1, 'email'), "{0} is an invalid email address".format( updated_fields['email'])) if 'home' in updated_fields and updated_fields['home'] not in ( None, '/nonexistent'): volumes_root = self.dispatcher.call_sync('volume.get_volumes_root') updated_fields['home'] = os.path.normpath(updated_fields['home']) if not updated_fields['home'].startswith( volumes_root) or updated_fields['home'] == volumes_root: errors.add( (1, 'home directory'), "Invalid mountpoint specified for home directory: {0}.\n". format(updated_fields['home']) + "Provide a path within zfs pool or dataset mounted under {0}" .format(volumes_root)) if errors: raise errors return ['system']
def verify(self, ntp, force=False): errors = ValidationException() try: system('ntpdate', '-q', ntp['address']) except SubprocessException: if not force: errors.add( (0, 'address'), 'Server could not be reached. Check "Force" to continue regardless.' ) minpoll = ntp.get('minpoll', 6) maxpoll = ntp.get('maxpoll', 10) if not maxpoll > minpoll: errors.add((0, 'maxpoll'), 'Max Poll should be higher than Min Poll') if errors: raise errors return ['system']
def verify(self, tunable): errors = ValidationException() if self.datastore.exists('tunables', ('var', '=', tunable['var'])): errors.add((1, 'var'), 'This variable already exists.', code=errno.EEXIST) if '"' in tunable['value'] or "'" in tunable['value']: errors.add((1, 'value'), 'Quotes are not allowed') if tunable['type'] in ('LOADER', 'RC') and not VAR_LOADER_RC_RE.match(tunable['var']): errors.add((1, 'var'), VAR_SYSCTL_FORMAT) elif tunable['type'] == 'SYSCTL': if not VAR_SYSCTL_RE.match(tunable['var']): errors.add((1, 'var'), VAR_LOADER_RC_FORMAT) try: sysctl.sysctlnametomib(tunable['var']) except OSError: errors.add((1, 'var'), 'Sysctl variable does not exist') if errors: raise errors return ['system']
def verify(self, params): errors = ValidationException() path = params.get('path') rmode = params.get('rsync_mode') remote_path = params.get('remote_path') remote_host = params.get('remote_host') remote_module = params.get('remote_module') if path in [None, ''] or path.isspace(): errors.add('path', errno.EINVAL, 'The Path is required') elif not os.path.exists(path): raise VerifyException( errno.ENOENT, "The specified path: '{0}'' does not exist".format( params.get('path'))) if (params.get('remote_host') in ['127.0.0.1', 'localhost'] and rmode == 'SSH' and remote_path is not None and not os.path.exists(remote_path)): raise VerifyException( errno.ENOENT, "The specified path: '{0}'' does not exist".format( remote_path)) if rmode == 'SSH' and (remote_path in [None, ''] or remote_path.isspace()): errors.add('remote_path', errno.EINVAL, 'The Remote Path is required') elif rmode == 'MODULE' and (remote_module in [None, ''] or remote_module.isspace()): errors.add('remote_module', errno.EINVAL, 'The Remote Module is required') if remote_host in [None, ''] or remote_host.isspace(): errors.add('remote_host', errno.EINVAL, 'A Remote Host needs to be specified') if errors: raise ValidationException(errors) return []
def verify(self, tunable): errors = ValidationException() if '"' in tunable['value'] or "'" in tunable['value']: errors.add((1, 'value'), 'Quotes are not allowed') if tunable['type'] in ('LOADER', 'RC') and not VAR_LOADER_RC_RE.match( tunable['var']): errors.add((1, 'var'), VAR_SYSCTL_FORMAT) elif tunable['type'] == 'SYSCTL': if not VAR_SYSCTL_RE.match(tunable['var']): errors.add((1, 'var'), VAR_LOADER_RC_FORMAT) try: sysctl.sysctlnametomib(tunable['var']) except OSError: errors.add((1, 'var'), 'Sysctl variable does not exist') if errors: raise errors return ['system']
def verify(self, ups): errors = ValidationException() node = ConfigNode('service.ups', self.configstore).__getstate__() node.update(ups) if node['mode'] == 'MASTER' and not node['driver_port']: errors.add((0, 'driver_port'), 'This field is required') if node['mode'] == 'SLAVE' and not node['remote_host']: errors.add((0, 'remote_host'), 'This field is required') if not re.search(r'^[a-z0-9\.\-_]+$', node['identifier'], re.I): errors.add((0, 'identifier'), 'Use alphanumeric characters, ".", "-" and "_"') for i in ('monitor_user', 'monitor_password'): if re.search(r'[ #]', node[i], re.I): errors.add((0, i), 'Spaces or number signs are not allowed') if errors: raise errors return ['system']
def verify(self, params): errors = ValidationException() path = params.get('path') rmode = params.get('rsync_mode') remote_path = params.get('remote_path') remote_host = params.get('remote_host') remote_module = params.get('remote_module') if path in [None, ''] or path.isspace(): errors.add('path', errno.EINVAL, 'The Path is required') elif not os.path.exists(path): raise VerifyException( errno.ENOENT, "The specified path: '{0}'' does not exist".format(params.get('path')) ) if ( params.get('remote_host') in ['127.0.0.1', 'localhost'] and rmode == 'SSH' and remote_path is not None and not os.path.exists(remote_path) ): raise VerifyException( errno.ENOENT, "The specified path: '{0}'' does not exist".format(remote_path) ) if rmode == 'SSH' and (remote_path in [None, ''] or remote_path.isspace()): errors.add('remote_path', errno.EINVAL, 'The Remote Path is required') elif rmode == 'MODULE' and (remote_module in [None, ''] or remote_module.isspace()): errors.add('remote_module', errno.EINVAL, 'The Remote Module is required') if remote_host in [None, ''] or remote_host.isspace(): errors.add('remote_host', errno.EINVAL, 'A Remote Host needs to be specified') if errors: raise ValidationException(errors) return []
def verify(self, webdav): errors = ValidationException() node = ConfigNode('service.webdav', self.configstore).__getstate__() node.update(webdav) if node['http_port'] == node['https_port']: errors.add((0, 'http_port'), 'HTTP and HTTPS ports cannot be the same') if 'HTTPS' in node['protocol'] and not node['certificate']: errors.add((0, 'certificate'), 'SSL protocol specified without choosing a certificate') if node['certificate']: cert = self.dispatcher.call_sync('crypto.certificate.query', [('id', '=', node['certificate'])]) if not cert: errors.add((0, 'certificate'), 'SSL Certificate not found.') if errors: raise errors return ['system']
def verify(self, ftp): errors = ValidationException() node = ConfigNode('service.ftp', self.configstore).__getstate__() node.update(ftp) pmin = node['passive_ports_min'] if 'passive_ports_min' in ftp: if pmin and (pmin < 1024 or pmin > 65535): errors.add((0, 'passive_ports_min'), 'This value must be between 1024 and 65535, inclusive.') pmax = node['passive_ports_max'] if 'passive_ports_max' in ftp: if pmax and (pmax < 1024 or pmax > 65535): errors.add((0, 'passive_ports_max'), 'This value must be between 1024 and 65535, inclusive.') elif pmax and pmin and pmin >= pmax: errors.add((0, 'passive_ports_max'), 'This value must be higher than minimum passive port.') if node['only_anonymous'] and not node['anonymous_path']: errors.add( ((0, 'anonymous_path'), errno.EINVAL, 'This field is required for anonymous login.') ) if node['tls'] is True and not node['tls_ssl_certificate']: errors.add((0, 'tls_ssl_certificate'), 'TLS specified without certificate.') if node['tls_ssl_certificate']: cert = self.dispatcher.call_sync('crypto.certificate.query', [('id', '=', node['tls_ssl_certificate'])]) if not cert: errors.add((0, 'tls_ssl_certificate'), 'SSL Certificate not found.') if errors: raise errors return ['system']
def verify(self, id, updated_fields): user = self.datastore.get_by_id('users', id) errors = ValidationException() normalize_name(updated_fields, 'username') if user is None: errors.add( (1, 'id'), "User with id: {0} does not exist".format(id), code=errno.ENOENT ) raise errors if user.get('builtin'): if 'home' in updated_fields: errors.add( (1, 'home'), "Cannot change builtin user's home directory", code=errno.EPERM ) # Similarly ignore uid changes for builtin users if 'uid' in updated_fields: errors.add((1, 'uid'), "Cannot change builtin user's UID", code=errno.EPERM) if 'username' in updated_fields: errors.add( (1, 'username'), "Cannot change builtin user's username", code=errno.EPERM ) if 'locked' in updated_fields: errors.add( (1, 'locked'), "Cannot change builtin user's locked flag", code=errno.EPERM ) if updated_fields.get('full_name') and ':' in updated_fields['full_name']: errors.add((1, 'full_name'), 'The character ":" is not allowed') if 'groups' in updated_fields and len(updated_fields['groups']) > 64: errors.add((1, 'groups'), 'User cannot belong to more than 64 auxiliary groups') if 'username' in updated_fields: for code, message in check_unixname(updated_fields['username']): errors.add((1, 'username'), message, code=code) if updated_fields.get('email'): if not EMAIL_REGEX.match(updated_fields['email']): errors.add( (1, 'email'), "{0} is an invalid email address".format(updated_fields['email']) ) if errors: raise errors return ['system']
def verify(self, id, updated_fields): user = self.datastore.get_by_id('users', id) errors = ValidationException() normalize_name(updated_fields, 'username') if user is None: errors.add( (1, 'id'), "User with id: {0} does not exist".format(id), code=errno.ENOENT ) raise errors if user.get('builtin'): if 'home' in updated_fields: errors.add( (1, 'home'), "Cannot change builtin user's home directory", code=errno.EPERM ) # Similarly ignore uid changes for builtin users if 'uid' in updated_fields: errors.add((1, 'uid'), "Cannot change builtin user's UID", code=errno.EPERM) if 'username' in updated_fields: errors.add( (1, 'username'), "Cannot change builtin user's username", code=errno.EPERM ) if 'locked' in updated_fields: errors.add( (1, 'locked'), "Cannot change builtin user's locked flag", code=errno.EPERM ) if updated_fields.get('full_name') and ':' in updated_fields['full_name']: errors.add((1, 'full_name'), 'The character ":" is not allowed') if 'groups' in updated_fields and len(updated_fields['groups']) > 64: errors.add((1, 'groups'), 'User cannot belong to more than 64 auxiliary groups') if 'username' in updated_fields: for code, message in check_unixname(updated_fields['username']): errors.add((1, 'username'), message, code=code) if updated_fields.get('email'): if not EMAIL_REGEX.match(updated_fields['email']): errors.add( (1, 'email'), "{0} is an invalid email address".format(updated_fields['email']) ) if 'home' in updated_fields: volumes_root = self.dispatcher.call_sync('volume.get_volumes_root') if updated_fields['home'].startswith(volumes_root): updated_fields['home'] = os.path.normpath(updated_fields['home']) if len(updated_fields['home'].split('/')) < 3: errors.add( (0, 'home'), "Invalid mountpoint specified for home directory: {0}.".format(updated_fields['home']) + " Provide directory located in '{0}' instead as the mountpoint".format(volumes_root) ) elif updated_fields['home'] not in (None, '/nonexistent'): errors.add( (0, 'home'), "Invalid mountpoint specified for home directory: {0}.".format(updated_fields['home']) + " Provide directory located in '{0}' instead as the mountpoint".format(volumes_root) ) if errors: raise errors return ['system']
def verify(self, ftp): errors = ValidationException() node = ConfigNode('service.ftp', self.configstore).__getstate__() node.update(ftp) pmin = node['passive_ports_min'] if 'passive_ports_min' in ftp: if pmin and (pmin < 1024 or pmin > 65535): errors.add( (0, 'passive_ports_min'), 'This value must be between 1024 and 65535, inclusive.') pmax = node['passive_ports_max'] if 'passive_ports_max' in ftp: if pmax and (pmax < 1024 or pmax > 65535): errors.add( (0, 'passive_ports_max'), 'This value must be between 1024 and 65535, inclusive.') elif pmax and pmin and pmin >= pmax: errors.add( (0, 'passive_ports_max'), 'This value must be higher than minimum passive port.') if node['only_anonymous'] and not node['anonymous_path']: errors.add((0, 'anonymous_path'), 'This field is required for anonymous login.') if node['tls'] is True and not node['tls_ssl_certificate']: errors.add((0, 'tls_ssl_certificate'), 'TLS specified without certificate.') if node['tls_ssl_certificate']: cert = self.dispatcher.call_sync( 'crypto.certificate.query', [('id', '=', node['tls_ssl_certificate'])]) if not cert: errors.add((0, 'tls_ssl_certificate'), 'SSL Certificate not found.') if node['only_anonymous'] and node['only_local']: errors.add(( 0, 'only_anonymous' ), 'Anonymous only and local only types of authentication cannot be enabled together.' ) if errors: raise errors return ['system']
def verify(self, ftp): errors = ValidationException() node = ConfigNode('service.ftp', self.configstore).__getstate__() node.update(ftp) pmin = node['passive_ports_min'] if 'passive_ports_min' in ftp: if pmin and (pmin < 1024 or pmin > 65535): errors.add((0, 'passive_ports_min'), 'This value must be between 1024 and 65535, inclusive.') pmax = node['passive_ports_max'] if 'passive_ports_max' in ftp: if pmax and (pmax < 1024 or pmax > 65535): errors.add((0, 'passive_ports_max'), 'This value must be between 1024 and 65535, inclusive.') elif pmax and pmin and pmin >= pmax: errors.add((0, 'passive_ports_max'), 'This value must be higher than minimum passive port.') if not all((pmax, pmin)) and any((pmax, pmin)): errors.add( (0, 'passive_ports_max' if pmin else 'passive_ports_min'), 'You cannot just supply only one of "passive_ports_max" or "passive_ports_min"' + 'Either both stay none or both have valid values in them' ) if node['only_anonymous'] and not node['anonymous_path']: errors.add( (0, 'anonymous_path'), 'This field is required for anonymous login.' ) if node['tls'] is True and not node['tls_ssl_certificate']: errors.add((0, 'tls_ssl_certificate'), 'TLS specified without certificate.') if node['tls_ssl_certificate']: cert = self.dispatcher.call_sync('crypto.certificate.query', [('id', '=', node['tls_ssl_certificate'])]) if not cert: errors.add((0, 'tls_ssl_certificate'), 'SSL Certificate not found.') if node['only_anonymous'] and node['only_local']: errors.add( (0, 'only_anonymous'), 'Anonymous only and local only types of authentication cannot be enabled together.' ) if errors: raise errors return ['system']