This commit is contained in:
2026-05-29 17:13:42 -03:00
parent 26777dbb89
commit b581561a63

74
main.go
View File

@@ -608,32 +608,66 @@ func linuxExpiryForAccount(expiresAt time.Time) time.Time {
}
func runUserAdd(args []string) error {
out, err := exec.Command("useradd", args...).CombinedOutput()
if err == nil {
return nil
}
firstErr := fmt.Errorf("useradd: %v: %s", err, strings.TrimSpace(string(out)))
text := strings.ToLower(string(out))
nameRejected := strings.Contains(text, "invalid user name") ||
strings.Contains(text, "invalid username") ||
strings.Contains(text, "bad name") ||
strings.Contains(text, "does not match")
if !nameRejected {
return firstErr
username := ""
if len(args) > 0 {
username = args[len(args)-1]
}
// DragonCore test usernames can start with numbers, for example 820etl.
// Some Linux distributions reject those by default. Debian/Ubuntu shadow-utils
// accept --badname; a few adduser wrappers use --force-badname. Try both as a
// compatibility fallback, keeping the same password, shell and expiry args.
for _, opt := range []string{"--badname", "--force-badname"} {
retryArgs := append([]string{opt}, args...)
out, err = exec.Command("useradd", retryArgs...).CombinedOutput()
attempts := [][]string{}
// DragonCore test usernames are intentionally short and can start with digits
// like 820etl/897blb. Several distros reject those unless --badname is passed.
// Try the permissive flags first for numeric-start names, then fall back to the
// plain useradd call for distros that do not support those options.
if username != "" && username[0] >= '0' && username[0] <= '9' {
attempts = append(attempts,
append([]string{"--badname"}, args...),
append([]string{"--force-badname"}, args...),
)
}
attempts = append(attempts, args)
var firstErr error
var firstOut string
var lastErr error
var lastOut string
for _, tryArgs := range attempts {
out, err := exec.Command("useradd", tryArgs...).CombinedOutput()
if err == nil {
return nil
}
if firstErr == nil {
firstErr = err
firstOut = strings.TrimSpace(string(out))
}
lastErr = err
lastOut = strings.TrimSpace(string(out))
}
return firstErr
// If the plain call failed because of username policy, retry permissive flags
// even for non-numeric names. This keeps compatibility with strict distros.
if firstErr != nil && len(attempts) == 1 {
text := strings.ToLower(firstOut)
nameRejected := strings.Contains(text, "invalid user name") ||
strings.Contains(text, "invalid username") ||
strings.Contains(text, "bad name") ||
strings.Contains(text, "does not match")
if nameRejected {
for _, opt := range []string{"--badname", "--force-badname"} {
retryArgs := append([]string{opt}, args...)
out, err := exec.Command("useradd", retryArgs...).CombinedOutput()
if err == nil {
return nil
}
lastErr = err
lastOut = strings.TrimSpace(string(out))
}
}
}
if lastErr != nil {
return fmt.Errorf("useradd: %v: %s", lastErr, lastOut)
}
return fmt.Errorf("useradd failed: %v: %s", firstErr, firstOut)
}
func (a *App) deleteSSH(username, uuid string) error {