|
@@ -3,149 +3,154 @@ package samba
|
|
|
import (
|
|
|
"bufio"
|
|
|
"fmt"
|
|
|
- "os"
|
|
|
+ "os/exec"
|
|
|
+ "regexp"
|
|
|
"strings"
|
|
|
)
|
|
|
|
|
|
-// injectTdbsamToSmbConfig updates the smb.conf file to set the passdb backend to tdbsam if not already set
|
|
|
-func (m *ShareManager) injectTdbsamToSmbConfig() error {
|
|
|
- // Path to smb.conf file
|
|
|
- smbConfPath := m.SambaConfigPath
|
|
|
+// samba user info
|
|
|
+type UserInfo struct {
|
|
|
+ UnixUsername string
|
|
|
+ UserSID string
|
|
|
+ Domain string
|
|
|
+ LastBadPassword string
|
|
|
+ BadPasswordCount int
|
|
|
+}
|
|
|
|
|
|
- // Open the smb.conf file for reading
|
|
|
- file, err := os.OpenFile(smbConfPath, os.O_RDWR|os.O_APPEND, 0644)
|
|
|
+// AddSambaUser adds a Samba user with the given username
|
|
|
+func (s *ShareManager) AddSambaUser(username string, password string) error {
|
|
|
+ // Check if the user already exists
|
|
|
+ if !unixUserExists(username) {
|
|
|
+ //Create unix user
|
|
|
+ cmd := exec.Command("sudo", "adduser", "--no-create-home", "--disabled-password", "--disabled-login", "--force-badname", username)
|
|
|
+ err := cmd.Run()
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("failed to add unix user: %v", err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //Create samba user
|
|
|
+ err := s.setupSmbUser(username, password)
|
|
|
if err != nil {
|
|
|
- return fmt.Errorf("failed to open smb.conf: %v", err)
|
|
|
+ return err
|
|
|
}
|
|
|
- defer file.Close()
|
|
|
|
|
|
- // Check if passdb backend is already set to tdbsam
|
|
|
- passdbBackendSet := false
|
|
|
- section := "[global]"
|
|
|
- tdbsamLine := "passdb backend = tdbsam"
|
|
|
- scanner := bufio.NewScanner(file)
|
|
|
- for scanner.Scan() {
|
|
|
- line := strings.TrimSpace(scanner.Text())
|
|
|
- if line == section {
|
|
|
- // Inside the [global] section, check for passdb backend setting
|
|
|
- for scanner.Scan() {
|
|
|
- subLine := strings.TrimSpace(scanner.Text())
|
|
|
- if strings.HasPrefix(subLine, "passdb backend") {
|
|
|
- // If passdb backend is already set to tdbsam, no need to update
|
|
|
- if strings.TrimSpace(subLine) == tdbsamLine {
|
|
|
- passdbBackendSet = true
|
|
|
- }
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
- break
|
|
|
- }
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+// userExists checks if a user exists
|
|
|
+func unixUserExists(username string) bool {
|
|
|
+ // Check if the user exists by attempting to get their home directory
|
|
|
+ cmd := exec.Command("getent", "passwd", username)
|
|
|
+ err := cmd.Run()
|
|
|
+ return err == nil
|
|
|
+}
|
|
|
+
|
|
|
+// SetupSmbUser sets up a Samba user account with the given username and password
|
|
|
+func (s *ShareManager) setupSmbUser(username, password string) error {
|
|
|
+ // Execute the smbpasswd command with the specified username
|
|
|
+ cmd := exec.Command("sudo", "smbpasswd", "-a", username)
|
|
|
+
|
|
|
+ // Create a pipe for STDIN to pass the password to the smbpasswd command
|
|
|
+ stdinPipe, err := cmd.StdinPipe()
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("failed to create STDIN pipe: %v", err)
|
|
|
}
|
|
|
- if err := scanner.Err(); err != nil {
|
|
|
- return fmt.Errorf("error reading smb.conf: %v", err)
|
|
|
+
|
|
|
+ // Start the command
|
|
|
+ if err := cmd.Start(); err != nil {
|
|
|
+ return fmt.Errorf("failed to start smbpasswd command: %v", err)
|
|
|
}
|
|
|
|
|
|
- // If passdb backend is not set to tdbsam, append the line to the configuration file
|
|
|
- if !passdbBackendSet {
|
|
|
- if _, err := file.WriteString(fmt.Sprintf("%s\n", tdbsamLine)); err != nil {
|
|
|
- return fmt.Errorf("failed to write to smb.conf: %v", err)
|
|
|
- }
|
|
|
+ // Pass the password twice to the smbpasswd command via STDIN
|
|
|
+ password = fmt.Sprintf("%s\n%s\n", password, password)
|
|
|
+ if _, err := stdinPipe.Write([]byte(password)); err != nil {
|
|
|
+ return fmt.Errorf("failed to write password to smbpasswd command: %v", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ // Close the STDIN pipe to signal the end of input
|
|
|
+ if err := stdinPipe.Close(); err != nil {
|
|
|
+ return fmt.Errorf("failed to close STDIN pipe: %v", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ // Wait for the command to finish
|
|
|
+ if err := cmd.Wait(); err != nil {
|
|
|
+ return fmt.Errorf("smbpasswd command failed: %v", err)
|
|
|
}
|
|
|
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
-// TdbsamInUse checks if the current smb runtime already using Tdbsam as backend
|
|
|
-func (m *ShareManager) TdbsamInUse() (bool, error) {
|
|
|
- // Open the smb.conf file for reading
|
|
|
- file, err := os.OpenFile(m.SambaConfigPath, os.O_RDWR|os.O_APPEND, 0644)
|
|
|
- if err != nil {
|
|
|
- return false, fmt.Errorf("failed to open smb.conf: %v", err)
|
|
|
- }
|
|
|
- defer file.Close()
|
|
|
+// RemoveSmbUser removes a Samba user account with the given username
|
|
|
+func (s *ShareManager) RemoveSmbUser(username string) error {
|
|
|
+ // Execute the smbpasswd command with the -x flag to delete the user
|
|
|
+ cmd := exec.Command("sudo", "smbpasswd", "-x", username)
|
|
|
|
|
|
- // Check if passdb backend is already set to tdbsam
|
|
|
- passdbBackendSet := false
|
|
|
- section := "[global]"
|
|
|
- tdbsamLine := "passdb backend = tdbsam"
|
|
|
- scanner := bufio.NewScanner(file)
|
|
|
- for scanner.Scan() {
|
|
|
- line := strings.TrimSpace(scanner.Text())
|
|
|
- if line == section {
|
|
|
- // Inside the [global] section, check for passdb backend setting
|
|
|
- for scanner.Scan() {
|
|
|
- subLine := strings.TrimSpace(scanner.Text())
|
|
|
- if strings.HasPrefix(subLine, "passdb backend") {
|
|
|
- // If passdb backend is already set to tdbsam, no need to update
|
|
|
- if strings.TrimSpace(subLine) == tdbsamLine {
|
|
|
- passdbBackendSet = true
|
|
|
- }
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
- break
|
|
|
- }
|
|
|
+ // Run the command
|
|
|
+ err := cmd.Run()
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("failed to remove Samba user account: %v", err)
|
|
|
}
|
|
|
|
|
|
- return passdbBackendSet, nil
|
|
|
+ return nil
|
|
|
}
|
|
|
|
|
|
-// removeTdbsamFromSmbConfig removes the line 'passdb backend = tdbsam' from smb.conf
|
|
|
-func (m *ShareManager) removeTdbsamFromSmbConfig() error {
|
|
|
- // Path to smb.conf file
|
|
|
- smbConfPath := "/etc/samba/smb.conf"
|
|
|
+// RemoveUnixUser removes a Unix user account with the given username
|
|
|
+func (s *ShareManager) RemoveUnixUser(username string) error {
|
|
|
+ // Execute the userdel command with the specified username
|
|
|
+ cmd := exec.Command("sudo", "userdel", username)
|
|
|
|
|
|
- // Open the smb.conf file for reading
|
|
|
- file, err := os.OpenFile(smbConfPath, os.O_RDWR, 0644)
|
|
|
+ // Run the command
|
|
|
+ err := cmd.Run()
|
|
|
if err != nil {
|
|
|
- return fmt.Errorf("failed to open smb.conf: %v", err)
|
|
|
+ return fmt.Errorf("failed to remove Unix user account: %v", err)
|
|
|
}
|
|
|
- defer file.Close()
|
|
|
|
|
|
- // Create a temporary file to store the modified content
|
|
|
- tempFile, err := os.CreateTemp("", "smb.conf.temp")
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+// ListSambaUsersInfo lists information about Samba users
|
|
|
+func (s *ShareManager) ListSambaUsersInfo() ([]UserInfo, error) {
|
|
|
+ // Execute pdbedit -L -v command
|
|
|
+ cmd := exec.Command("sudo", "pdbedit", "-L", "-v")
|
|
|
+ output, err := cmd.CombinedOutput()
|
|
|
if err != nil {
|
|
|
- return fmt.Errorf("failed to create temporary file: %v", err)
|
|
|
+ return nil, fmt.Errorf("failed to execute pdbedit command: %v", err)
|
|
|
}
|
|
|
- defer os.Remove(tempFile.Name())
|
|
|
- defer tempFile.Close()
|
|
|
|
|
|
- // Copy lines from smb.conf to the temporary file, omitting the line 'passdb backend = tdbsam'
|
|
|
- section := "[global]"
|
|
|
- tdbsamLine := "passdb backend = tdbsam"
|
|
|
- scanner := bufio.NewScanner(file)
|
|
|
+ // Parse the output and extract user information
|
|
|
+ var usersInfo []UserInfo
|
|
|
+ scanner := bufio.NewScanner(strings.NewReader(string(output)))
|
|
|
+ var userInfo UserInfo
|
|
|
+ re := regexp.MustCompile(`^Unix username:\s+(.*)$`)
|
|
|
for scanner.Scan() {
|
|
|
- line := strings.TrimSpace(scanner.Text())
|
|
|
- if line == section {
|
|
|
- // Inside the [global] section, omit the line 'passdb backend = tdbsam'
|
|
|
- for scanner.Scan() {
|
|
|
- subLine := strings.TrimSpace(scanner.Text())
|
|
|
- if strings.HasPrefix(subLine, "passdb backend") && subLine == tdbsamLine {
|
|
|
- continue
|
|
|
- }
|
|
|
- tempFile.WriteString(fmt.Sprintf("%s\n", subLine))
|
|
|
+ line := scanner.Text()
|
|
|
+ match := re.FindStringSubmatch(line)
|
|
|
+ if len(match) > 0 {
|
|
|
+ if userInfo.UnixUsername != "" {
|
|
|
+ usersInfo = append(usersInfo, userInfo)
|
|
|
+ }
|
|
|
+ userInfo = UserInfo{UnixUsername: match[1]}
|
|
|
+ } else if strings.HasPrefix(line, "User SID:") {
|
|
|
+ userInfo.UserSID = strings.TrimSpace(strings.Split(line, ":")[1])
|
|
|
+ } else if strings.HasPrefix(line, "Domain:") {
|
|
|
+ userInfo.Domain = strings.TrimSpace(strings.Split(line, ":")[1])
|
|
|
+ } else if strings.HasPrefix(line, "Last bad password") {
|
|
|
+ info := strings.TrimSpace(strings.Split(line, ":")[1])
|
|
|
+ if info != "never" {
|
|
|
+ userInfo.LastBadPassword = info
|
|
|
}
|
|
|
+ } else if strings.HasPrefix(line, "Bad password count") {
|
|
|
+ fmt.Sscanf(strings.TrimSpace(strings.Split(line, ":")[1]), "%d", &userInfo.BadPasswordCount)
|
|
|
}
|
|
|
- tempFile.WriteString(fmt.Sprintf("%s\n", line))
|
|
|
}
|
|
|
- if err := scanner.Err(); err != nil {
|
|
|
- return fmt.Errorf("error reading smb.conf: %v", err)
|
|
|
- }
|
|
|
-
|
|
|
- // Close the original smb.conf file
|
|
|
- if err := file.Close(); err != nil {
|
|
|
- return fmt.Errorf("error closing smb.conf: %v", err)
|
|
|
+ if userInfo.UnixUsername != "" {
|
|
|
+ usersInfo = append(usersInfo, userInfo)
|
|
|
}
|
|
|
|
|
|
- // Remove the original smb.conf file
|
|
|
- if err := os.Remove(smbConfPath); err != nil {
|
|
|
- return fmt.Errorf("error removing smb.conf: %v", err)
|
|
|
- }
|
|
|
-
|
|
|
- // Rename the temporary file to smb.conf
|
|
|
- if err := os.Rename(tempFile.Name(), smbConfPath); err != nil {
|
|
|
- return fmt.Errorf("error renaming temporary file: %v", err)
|
|
|
+ if err := scanner.Err(); err != nil {
|
|
|
+ return nil, fmt.Errorf("error scanning pdbedit output: %v", err)
|
|
|
}
|
|
|
|
|
|
- return nil
|
|
|
+ return usersInfo, nil
|
|
|
}
|