Class: Yast::SuSEFirewall2ServicesClass

Inherits:
SuSEFirewallServicesClass show all
Includes:
Logger
Defined in:
library/network/src/lib/network/susefirewall2services.rb

Overview

Global Definition of Firewall Services Defined using TCP, UDP and RPC ports and IP protocols and Broadcast UDP ports. Results are cached, so repeating requests are answered faster.

Constant Summary collapse

SERVICES_DIR =
"/etc/sysconfig/SuSEfirewall2.d/services/".freeze
SERVICES_TEXTDOMAIN =

please, check it with configuration in refresh-srv-def-by-pkgs-trans.sh script

"firewall-services".freeze
READ_ONLY_SERVICE_FEATURES =
["name", "description"].freeze
IGNORED_SERVICES =
["TEMPLATE", "..", "."].freeze
TEMPLATE_SERVICE_NAME =
"template service".freeze
TEMPLATE_SERVICE_DESCRIPTION =
"opens ports for foo in order to allow bar".freeze

Constants inherited from SuSEFirewallServicesClass

Yast::SuSEFirewallServicesClass::DEFAULT_SERVICE, Yast::SuSEFirewallServicesClass::DEFINED_BY_PKG_PREFIX

Instance Method Summary collapse

Methods inherited from SuSEFirewallServicesClass

#GetDescription, #GetFilenameFromServiceDefinedByPackage, #GetListOfServicesAddedByPackage, #GetMetadataAgent, #GetModified, #GetNeededIPProtocols, #GetNeededPortsAndProtocols, #GetNeededRPCPorts, #GetNeededTCPPorts, #GetNeededUDPPorts, #GetSupportedServices, #IsKnownService, #ResetModified, #ServiceDefinedByPackage, #all_services, #initialize

Constructor Details

This class inherits a constructor from Yast::SuSEFirewallServicesClass

Instance Method Details

#GetNeededBroadcastPorts(service) ⇒ Array<String>

Function returns needed ports allowing broadcast

Parameters:

  • service (String)

    (including the "service:" prefix)

Returns:

  • (Array<String>)

    of needed broadcast ports



383
384
385
# File 'library/network/src/lib/network/susefirewall2services.rb', line 383

def GetNeededBroadcastPorts(service)
  service_details(service)["broadcast_ports"] || []
end

#GetPossiblyConflictServicesArray<String>

Deprecated.

we currently don't have such services - services are defined by packages.

Function returns list of possibly conflicting services. Conflicting services are for instance nis-client and nis-server.

Returns:

  • (Array<String>)

    of conflicting services



503
504
505
# File 'library/network/src/lib/network/susefirewall2services.rb', line 503

def GetPossiblyConflictServices
  []
end

#mainObject



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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# File 'library/network/src/lib/network/susefirewall2services.rb', line 45

def main
  textdomain "base"

  Yast.import "FileUtils"

  #
  # IF YOU NEED TO ADD ANOTHER SERVICE, CREATE THE SERVICE DEFINITION
  # IN A FILE AND ADD IT TO THE PACKAGE TO WHICH IT BELONGS.
  # USE /etc/sysconfig/SuSEfirewall2.d/services/TEMPLATE FOR THAT.
  #
  # MORE INFORMATION IN FEATURE #300687: Ports for SuSEfirewall added via packages.
  # ANOTHER REFERENCE: Bugzilla #246911.
  #
  # See also http://kobliha-suse.blogspot.cz/2008/06/firewall-services-defined-by-packages.html
  #
  #
  # Names assigned to Port and Protocol numbers can be found
  # here:
  #
  # http://www.iana.org/assignments/protocol-numbers
  # http://www.iana.org/assignments/port-numbers
  #
  # Format of SERVICES
  #
  #   "service-id" : $[
  #     "name"            : _("Service Name"),
  #     "tcp_ports"       : list <tcp_ports>,
  #     "udp_ports"       : list <udp_ports>,
  #     "rpc_ports"       : list <rpc_ports>,
  #     "ip_protocols"    : list <ip_protocols>,
  #     "broadcast_ports" : list <broadcast_ports>,
  #   ],
  #
  @services = nil

  # firewall needs restarting
  @sfws_modified = false

  @known_services_features = {
    "TCP"       => "tcp_ports",
    "UDP"       => "udp_ports",
    "RPC"       => "rpc_ports",
    "IP"        => "ip_protocols",
    "BROADCAST" => "broadcast_ports"
  }

  @known_metadata = { "Name" => "name", "Description" => "description" }

  # Services definitions for conversion to the new ones.
  @OLD_SERVICES = {
    "http"         => {
      "tcp_ports"  => ["http"],
      "convert_to" => ["service:apache2", "service:lighttpd"]
    },
    "https"        => {
      "tcp_ports"  => ["https"],
      "convert_to" => ["service:apache2-ssl", "service:lighttpd-ssl"]
    },
    "smtp"         => { "tcp_ports" => ["smtp"], "convert_to" => [] },
    "pop3"         => { "tcp_ports" => ["pop3"], "convert_to" => [] },
    "pop3s"        => { "tcp_ports" => ["pop3s"], "convert_to" => [] },
    "imap"         => {
      "tcp_ports"  => ["imap"],
      "convert_to" => ["service:courier-imapd"]
    },
    "imaps"        => {
      "tcp_ports"  => ["imaps"],
      "convert_to" => ["service:courier-imap-ssl"]
    },
    "samba-server" => {
      "tcp_ports"       => ["netbios-ssn", "microsoft-ds"],
      # TCP: 139, 445
      "udp_ports"       => ["netbios-ns", "netbios-dgm"],
      # UDP: 137, 138
      "broadcast_ports" => ["netbios-ns", "netbios-dgm"],
      # UDP: 137, 138
      "convert_to"      => []
    },
    "ssh"          => {
      "tcp_ports"  => ["ssh"],
      "convert_to" => ["service:sshd"]
    },
    "rsync"        => { "tcp_ports" => ["rsync"], "convert_to" => [] },
    "dhcp-server"  => {
      "udp_ports"       => ["bootps"],
      "broadcast_ports" => ["bootps"],
      "convert_to"      => ["service:dhcp-server"]
    },
    "dhcp-client"  => { "udp_ports" => ["bootpc"], "convert_to" => [] },
    "dns-server"   => {
      "tcp_ports"  => ["domain"],
      "udp_ports"  => ["domain"],
      "convert_to" => ["service:bind"]
    },
    "nfs-client"   => {
      "rpc_ports"  => ["portmap", "status", "nlockmgr"],
      "convert_to" => ["service:nfs-client"]
    },
    "nfs-server"   => {
      "rpc_ports"  => [
        "portmap",
        "status",
        "nlockmgr",
        "mountd",
        "nfs",
        "nfs_acl"
      ],
      "convert_to" => []
    },
    "nis-client"   => {
      "rpc_ports"  => ["portmap", "ypbind"],
      "convert_to" => ["service:ypserv"]
    },
    "nis-server"   => {
      "rpc_ports"  => [
        "portmap",
        "ypserv",
        "fypxfrd",
        "ypbind",
        "yppasswdd"
      ],
      "convert_to" => []
    },
    # Default SUSE installation
    "vnc"          => {
      "tcp_ports"  => ["5801", "5901"],
      "convert_to" => []
    },
    "tftp"         => { "udp_ports" => ["tftp"], "convert_to" => [] },
    # Internet Printing Protocol as a Server
    "ipp-tcp"      => {
      "tcp_ports"  => ["ipp"],
      "convert_to" => []
    },
    # Internet Printing Protocol as a Client
    # IPP Client needs to listen for broadcast messages
    "ipp-udp"      => {
      "udp_ports"       => ["ipp"],
      "broadcast_ports" => ["ipp"],
      "convert_to"      => []
    },
    "ntp-server"   => {
      "udp_ports"       => ["ntp"],
      "broadcast_ports" => ["ntp"],
      "convert_to"      => ["service:ntp"]
    },
    "ldap"         => {
      "tcp_ports"  => ["ldap"],
      "convert_to" => ["service:openldap"]
    },
    "ldaps"        => { "tcp_ports" => ["ldaps"], "convert_to" => [] },
    "ipsec"        => {
      "udp_ports"    => ["isakmp", "ipsec-nat-t"],
      "ip_protocols" => ["esp"],
      "convert_to"   => []
    },
    "slp-daemon"   => {
      "tcp_ports"       => ["svrloc"],
      "udp_ports"       => ["svrloc"],
      "broadcast_ports" => ["svrloc"],
      "convert_to"      => []
    },
    # See bug #118200 for more information
    "xdmcp"        => {
      "tcp_ports"       => ["xdmcp"],
      "udp_ports"       => ["xdmcp"],
      "broadcast_ports" => ["xdmcp"],
      "convert_to"      => []
    },
    # See bug #118196 for more information
    "fam"          => {
      "rpc_ports"  => ["sgi_fam"],
      "convert_to" => []
    },
    # requested by thofmann
    "open-pbs"     => {
      # /etc/services says: The following entries are invalid, but needed
      "tcp_ports"  => [
        "pbs",
        "pbs_mom",
        "pbs_resmom",
        "pbs_sched"
      ],
      "udp_ports"  => ["pbs_resmom"],
      "convert_to" => []
    },
    "mysql-server" => {
      "tcp_ports"  => ["mysql"],
      "convert_to" => ["service:mysql"]
    },
    "iscsi-server" => {
      "tcp_ports"  => ["iscsi-target"],
      "convert_to" => ["service:iscsitarget"]
    }
  }
end

#ReadServicesDefinedByRPMPackagesBoolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Reads definition of services that can be used in FW_CONFIGURATIONS_[EXT|INT|DMZ] in SuSEfirewall2.

Returns:

  • (Boolean)

    if successful



271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
# File 'library/network/src/lib/network/susefirewall2services.rb', line 271

def ReadServicesDefinedByRPMPackages
  log.info "Reading SuSEfirewall2 services from #{SERVICES_DIR}"
  @services ||= {}

  if !FileUtils.Exists(SERVICES_DIR) ||
      !FileUtils.IsDirectory(SERVICES_DIR)
    log.error "Cannot read #{SERVICES_DIR}"
    return false
  end

  all_definitions = SCR.Read(path(".target.dir"), SERVICES_DIR)
  all_definitions.reject! do |service|
    IGNORED_SERVICES.include?(service)
  end

  service_name = nil
  filefullpath = nil

  # for all files in that directory
  Builtins.foreach(all_definitions) do |filename|
    # "service:abc_server" to distinguis between dynamic definition and the static one
    service_name = DEFINED_BY_PKG_PREFIX + filename
    # Do not read already known services
    next unless @services[service_name].nil?

    filefullpath = SERVICES_DIR + filename
    @services[service_name] = {}

    # Registering sysconfig agent for this file
    if !SCR.RegisterAgent(
      path(".firewall_service_definition"),
      term(:ag_ini, term(:SysConfigFile, filefullpath))
    )
      log.error "Cannot register agent for #{filefullpath}"
      next
    end

    definition = nil
    definition_values = nil

    Builtins.foreach(@known_services_features) do |known_feature, map_key|
      definition = Convert.to_string(
        SCR.Read(
          Builtins.add(path(".firewall_service_definition"), known_feature)
        )
      )
      definition = "" if definition.nil?
      # map of services contains list of entries
      definition_values = Builtins.splitstring(definition, " \t\n")
      definition_values = Builtins.filter(definition_values) do |one_value|
        one_value != ""
      end
      @services[service_name][map_key] = definition_values
    end

    # Unregistering sysconfig agent for this file
    SCR.UnregisterAgent(path(".firewall_service_definition"))

    # Fallback for presented service
    @services[service_name]["name"] = format(_("Service: %{filename}"), filename: filename)
    @services[service_name]["description"] = ""

    # Registering sysconfig agent for this file (to get metadata)
    if SCR.RegisterAgent(
      path(".firewall_service_metadata"),
      term(:ag_ini, GetMetadataAgent(filefullpath))
    )
      Builtins.foreach(@known_metadata) do |, |
        definition = Convert.to_string(
          SCR.Read(
            Builtins.add(
              path(".firewall_service_metadata"),
              
            )
          )
        )
        next if definition.nil? || definition.empty?

        # call gettext to translate the metadata
        @services[service_name][] = Builtins.dgettext(SERVICES_TEXTDOMAIN, definition)

        # bnc#893583: Sanitize metadata, do not allow using texts from template service
        case 
        when "name"
          @services[service_name][] = filename if definition == TEMPLATE_SERVICE_NAME
        when "description"
          @services[service_name][] = "" if definition == TEMPLATE_SERVICE_DESCRIPTION
        end
      end

      SCR.UnregisterAgent(path(".firewall_service_metadata"))
    else
      log.error "Cannot register agent for #{filefullpath} (metadata)"
    end
  end

  log.info "Services found: #{@services.keys.sort}"

  true
end

#service_details(service_name, silent = false) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns service definition. See @services for the format. If silent is false (the default), the method throws an exception Yast::SuSEFirewalServiceNotFound if service is not found on disk.

Parameters:

  • service_name (String)

    name including the "service:" prefix

  • silent (String) (defaults to: false)

    whether to silently return nil when service is not found



251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'library/network/src/lib/network/susefirewall2services.rb', line 251

def service_details(service_name, silent = false)
  service = all_services[service_name]
  if service.nil? && !silent
    log.error "Unknown service '#{service_name}'"
    log.info "Known services: #{all_services.keys}"

    raise(
      SuSEFirewalServiceNotFound,
      format(_("Service with name '%{service_name}' does not exist"), service_name: service_name)
    )
  end

  service
end

#SetModifiedObject

Sets that configuration was modified



373
374
375
376
377
# File 'library/network/src/lib/network/susefirewall2services.rb', line 373

def SetModified
  @sfws_modified = true

  nil
end

#SetNeededPortsAndProtocols(service, store_definition) ⇒ Boolean

Immediately writes the configuration of service defined by package to the service definition file. Service must be defined by package, this function doesn't work for hard-coded services (SuSEFirewallServices). Function throws an exception Yast::SuSEFirewalServiceNotFound if service is not known (undefined) or it is not a service defined by package.

Examples:

SetNeededPortsAndProtocols (
        "service:something",
        {
                "tcp_ports"      => [ "22", "ftp-data", "400:420" ],
                "udp_ports"      => [ ],
                "rpc_ports"      => [ "portmap", "ypbind" ],
                "ip_protocols"   => [ "esp" ],
                "broadcast_ports"=> [ ],
        }
)

Parameters:

  • service (String)

    ID (e.g., "service:ssh")

  • store_definition (Hash<String, Array<String>>)

    of full service definition

Returns:

  • (Boolean)

    if successful (nil in case of developer's mistake)

See Also:



412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
# File 'library/network/src/lib/network/susefirewall2services.rb', line 412

def SetNeededPortsAndProtocols(service, store_definition)
  if !IsKnownService(service)
    log.error "Service #{service} is unknown"
    raise(
      SuSEFirewalServiceNotFound,
      format(_("Service with name '%{service_name}' does not exist"), service_name: service)
    )
  end

  # create the filename from service name
  filename = GetFilenameFromServiceDefinedByPackage(service)
  if filename.nil? || filename == ""
    log.error "Can't operate with filename '#{filename}' created from '#{service}'"
    return false
  end

  # full path to the filename
  filefullpath = SERVICES_DIR + filename

  if !FileUtils.Exists(filefullpath)
    log.error "File '#{filefullpath}' doesn't exist"
    return false
  end

  # Registering sysconfig agent for that file
  if !SCR.RegisterAgent(
    path(".firewall_service_definition"),
    term(:ag_ini, term(:SysConfigFile, filefullpath))
  )
    log.error "Cannot register agent for #{filefullpath}"
    return false
  end

  ks_features_backward = Builtins.mapmap(@known_services_features) do |sysconfig_id, ycp_id|
    { ycp_id => sysconfig_id }
  end

  write_ok = true

  # we can have this service already in memory
  new_store_definition = deep_copy(store_definition)

  Builtins.foreach(store_definition) do |ycp_id, one_def|
    # Skipping read-only features
    next if READ_ONLY_SERVICE_FEATURES.include? ycp_id

    sysconfig_id = Ops.get(ks_features_backward, ycp_id)
    if sysconfig_id.nil?
      log.error "Unknown key '#{ycp_id}'"
      write_ok = false
      next
    end
    one_def = Builtins.filter(one_def) do |one_def_item|
      !one_def_item.nil? && one_def_item != "" &&
        !Builtins.regexpmatch(one_def_item, "^ *$")
    end
    service_entry_path = Path.new(".firewall_service_definition.#{sysconfig_id}")
    service_entry_value = one_def.join(" ")
    if !SCR.Write(service_entry_path, service_entry_value)
      log.error "Cannot write #{service_entry_value} to #{service_entry_path}",
        write_ok = false
      next
    end
    # new definition of the service
    Ops.set(new_store_definition, ycp_id, one_def)
  end

  # flush the cache to the disk
  if write_ok
    if SCR.Write(path(".firewall_service_definition"), nil)
      # not only store to disk but also to the memory
      @services[service] = new_store_definition
      SetModified()
    else
      log.error "Cannot write to disk!"
      write_ok = false
    end
  end

  # Unregistering sysconfig agent for that file
  SCR.UnregisterAgent(path(".firewall_service_definition"))

  log.info "Call SetNeededPortsAndProtocols(#{service}, ...) result is #{write_ok}"
  write_ok
end