diff options
Diffstat (limited to 'sd_login/util_valid.go')
-rw-r--r-- | sd_login/util_valid.go | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/sd_login/util_valid.go b/sd_login/util_valid.go new file mode 100644 index 0000000..e0dd906 --- /dev/null +++ b/sd_login/util_valid.go @@ -0,0 +1,141 @@ +// Copyright (C) 2016 Luke Shumaker <lukeshu@sbcglobal.net> +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sd_login + +import ( + "strings" +) + +func valid_session_name(id string) bool { + if id == "" { + return false + } + + return strings.TrimLeft(id, letters+digits) == "" +} + +func valid_slice_name(s string) bool { + return strings.HasSuffix(s, ".slice") && valid_unit_name(s) == unit_name_plain +} + +func valid_machine_name(s string) bool { + if len(s) > host_name_max { + // Note that Linux HOST_NAME_MAX is 64, but DNS allows + // 255, so names from DNS might be invalid. + return false + } + + n_dots := 0 + dot := true + for _, c := range s { + if c == '.' { + if dot { + return false + } + dot = true + n_dots++ + } else { + if !strings.ContainsRune(letters+digits+"-_.", c) { + return false + } + dot = false + } + } + + if dot { // trailing dot or empty + return false + } + + return true +} + +const ( + unit_name_invalid = 0 + unit_name_plain = 1 << 0 // foo.service + unit_name_instance = 1 << 1 // foo@bar.service + unit_name_template = 1 << 2 // foo@.service + unit_name_any = unit_name_plain | unit_name_instance | unit_name_template +) + +func valid_unit_name(unit string) int { + const_unit_name_max := 256 + const_unit_types := []string{ + "service", + "socket", + "busname", + "target", + "device", + "mount", + "automount", + "swap", + "timer", + "path", + "slice", + "scope", + } + + if unit == "" { + return unit_name_invalid + } + + // If the unit name is too long + if len(unit) >= const_unit_name_max { + return unit_name_invalid + } + + // If there is no dot in the unit name + dot := strings.LastIndexByte(unit, '.') + if dot < 0 || dot == 0 { + return unit_name_invalid + } + + // If the .suffix isn't a real unit type + utype := unit[dot+1:] + found := false + for _, _utype := range const_unit_types { + if utype == _utype { + found = true + break + } + } + if !found { + return unit_name_invalid + } + + at := strings.IndexByte(unit, '@') + + // If the unit has more than one '@' + if at >= 0 && strings.IndexByte(unit[at+1:], '@') >= 0 { + return unit_name_invalid + } + + // If the '@' is at the start of the unit + if at == 0 { + return unit_name_invalid + } + + if at < 0 { + return unit_name_plain + } else { + if dot > at+1 { + return unit_name_instance + } + if dot == at+1 { + return unit_name_template + } + } + + return unit_name_invalid +} |