// Copyright (C) 2016 Luke Shumaker // // 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 }