Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/cmd/initContainer.go
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,16 @@ func configureKerberos() error {
return nil
}

kcmSocketEnabled, err := utils.IsKCMSocketEnabled()
if err != nil {
return fmt.Errorf("failed to check if kcm socket is enabled: %w", err)
}
if !kcmSocketEnabled {
logrus.Debugf("%s: kcm socket not enabled", logPrefix)
logrus.Debugf("%s: skipping", logPrefix)
return nil
}

var builder strings.Builder
builder.WriteString("# Written by Toolbx\n")
builder.WriteString("# https://containertoolbx.org/\n")
Expand Down
44 changes: 44 additions & 0 deletions src/pkg/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package utils

import (
"bufio"
"errors"
"fmt"
"os"
Expand Down Expand Up @@ -892,3 +893,46 @@ func ResolveContainerAndImageNames(container, distroCLI, imageCLI, releaseCLI st

return container, image, release, nil
}

// IsKCMSocketEnabled checks if the KCM cache is enabled or not, by verifying the unix domain socket used
// by kcm exists. Normally, the default path is - /var/run/.heim_org.h5l.kcm-socket.
//
// However, we should be vary that this path is configurable. It can be overridden by setting the
// kcm_socket field in the [libdefaults] section to point to the new path, inside /etc/krb5.conf.
func IsKCMSocketEnabled() (bool, error) {
kcmSocketPath := "/var/run/.heim_org.h5l.kcm-socket"

file, err := os.Open("/etc/krb5.conf")
if err != nil && !errors.Is(err, os.ErrNotExist) {
return false, err
} else if err == nil {
defer file.Close()

scanner := bufio.NewScanner(file)
insideLibdefaultsSection := false

for scanner.Scan() {
text := strings.TrimSpace(scanner.Text())
if strings.HasPrefix(text, "[") {
insideLibdefaultsSection = text == "[libdefaults]"
continue
}

if insideLibdefaultsSection {
parts := strings.SplitN(text, "=", 2)
if len(parts) == 2 && strings.TrimSpace(parts[0]) == "kcm_socket" {
kcmSocketPath = strings.TrimSpace(parts[1])
}
}
}
Comment on lines +914 to +927

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current parsing logic for /etc/krb5.conf is a bit too simple and doesn't handle comments. According to the krb5.conf man page, lines can contain comments starting with # or ;. The current implementation can fail in a few ways:

  1. A section header with a comment (e.g., [libdefaults] # comment) will not be recognized correctly.
  2. A key-value pair with an inline comment (e.g., kcm_socket = /path/to/socket # comment) will result in the comment being part of the path.

I suggest a more robust parsing loop that handles comments and empty lines correctly, and also properly identifies section headers.

for scanner.Scan() {
			line := scanner.Text()
			// Ignore comments, which can start with '#' or ';'.
			if i := strings.IndexAny(line, "#;"); i != -1 {
				line = line[:i]
			}
			text := strings.TrimSpace(line)
			if text == "" {
				continue
			}

			// Check for section headers like '[libdefaults]'.
			if strings.HasPrefix(text, "[") && strings.HasSuffix(text, "]") {
				sectionName := strings.TrimSpace(text[1 : len(text)-1])
				insideLibdefaultsSection = sectionName == "libdefaults"
				continue
			}

			if insideLibdefaultsSection {
				parts := strings.SplitN(text, "=", 2)
				if len(parts) == 2 && strings.TrimSpace(parts[0]) == "kcm_socket" {
					kcmSocketPath = strings.TrimSpace(parts[1])
				}
			}
		}

}

info, err := os.Stat(kcmSocketPath)
if err != nil && !errors.Is(err, os.ErrNotExist) {
return false, err
} else if errors.Is(err, os.ErrNotExist) {
return false, nil
}

return info.Mode()&os.ModeSocket != 0, nil
}