Compare commits
3
Commits
88ce254037
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
373359116c | ||
|
|
1cb2296480 | ||
|
|
0ee10a64c1 |
Binary file not shown.
@@ -47,8 +47,17 @@ func main() {
|
|||||||
Repo: envOrDefault("GITEA_REPO", defaultRepo),
|
Repo: envOrDefault("GITEA_REPO", defaultRepo),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := platformEnsureElevated(); err != nil {
|
||||||
|
printError(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
args := os.Args[1:]
|
args := os.Args[1:]
|
||||||
|
|
||||||
|
if len(args) > 0 && args[0] == "--elevated" {
|
||||||
|
args = args[1:]
|
||||||
|
}
|
||||||
|
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
runTUI(config)
|
runTUI(config)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ func getInstallDir() (string, error) {
|
|||||||
return "/opt/logofclient", nil
|
return "/opt/logofclient", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func platformEnsureElevated() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func platformRunPrivileged(config Config, action string) error {
|
func platformRunPrivileged(config Config, action string) error {
|
||||||
// Bereits als root gestartet.
|
// Bereits als root gestartet.
|
||||||
if os.Geteuid() == 0 {
|
if os.Geteuid() == 0 {
|
||||||
|
|||||||
+102
-46
@@ -6,7 +6,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
@@ -15,10 +14,22 @@ import (
|
|||||||
var (
|
var (
|
||||||
shell32 = syscall.NewLazyDLL("shell32.dll")
|
shell32 = syscall.NewLazyDLL("shell32.dll")
|
||||||
shellExecuteExW = shell32.NewProc("ShellExecuteExW")
|
shellExecuteExW = shell32.NewProc("ShellExecuteExW")
|
||||||
|
|
||||||
|
advapi32 = syscall.NewLazyDLL("advapi32.dll")
|
||||||
|
openProcessToken = advapi32.NewProc("OpenProcessToken")
|
||||||
|
getTokenInformation = advapi32.NewProc("GetTokenInformation")
|
||||||
|
|
||||||
|
kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||||
|
closeHandle = kernel32.NewProc("CloseHandle")
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
seeMaskNocloseprocess = 0x00000040
|
tokenQuery = 0x0008
|
||||||
|
tokenElevationClass = 20
|
||||||
|
|
||||||
|
errorCancelled = 1223
|
||||||
|
|
||||||
|
swShow = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
type shellExecuteInfo struct {
|
type shellExecuteInfo struct {
|
||||||
@@ -39,43 +50,41 @@ type shellExecuteInfo struct {
|
|||||||
hProcess uintptr
|
hProcess uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
func getInstallDir() (string, error) {
|
type tokenElevationData struct {
|
||||||
programFiles := os.Getenv("ProgramFiles")
|
TokenIsElevated uint32
|
||||||
|
|
||||||
if programFiles == "" {
|
|
||||||
return "", errors.New("ProgramFiles ist nicht gesetzt")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return filepath.Join(programFiles, "logofclient"), nil
|
func platformEnsureElevated() error {
|
||||||
|
// Die erhöhte Instanz wurde bereits gestartet.
|
||||||
|
// Sie darf sich nicht noch einmal selbst per runas starten.
|
||||||
|
if hasElevatedFlag() {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func platformRunPrivileged(config Config, action string) error {
|
if isWindowsElevated() {
|
||||||
if isWindowsAdmin() {
|
return nil
|
||||||
return runAction(config, action)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return runElevated(action)
|
return restartElevated()
|
||||||
}
|
}
|
||||||
|
|
||||||
func isWindowsAdmin() bool {
|
func hasElevatedFlag() bool {
|
||||||
// Ein einfacher und robuster Test:
|
for _, arg := range os.Args[1:] {
|
||||||
// Versuch, in das Windows-Systemverzeichnis zu schreiben.
|
if arg == "--elevated" {
|
||||||
//
|
return true
|
||||||
// Da wir dort natürlich nichts verändern wollen, verwenden wir
|
}
|
||||||
// stattdessen "net session". Der Befehl funktioniert nur mit
|
|
||||||
// Administratorrechten.
|
|
||||||
|
|
||||||
cmd := exec.Command("net", "session")
|
|
||||||
cmd.Stdout = nil
|
|
||||||
cmd.Stderr = nil
|
|
||||||
|
|
||||||
return cmd.Run() == nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func runElevated(action string) error {
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func restartElevated() error {
|
||||||
exe, err := os.Executable()
|
exe, err := os.Executable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Pfad des Installers konnte nicht ermittelt werden: %w", err)
|
return fmt.Errorf(
|
||||||
|
"Pfad des Installers konnte nicht ermittelt werden: %w",
|
||||||
|
err,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
verb, err := syscall.UTF16PtrFromString("runas")
|
verb, err := syscall.UTF16PtrFromString("runas")
|
||||||
@@ -88,43 +97,90 @@ func runElevated(action string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
parameters, err := syscall.UTF16PtrFromString(action)
|
// Die erhöhte Instanz bekommt nur das interne Flag.
|
||||||
|
parameters, err := syscall.UTF16PtrFromString("--elevated")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := shellExecuteInfo{
|
info := shellExecuteInfo{
|
||||||
cbSize: uint32(unsafe.Sizeof(shellExecuteInfo{})),
|
cbSize: uint32(unsafe.Sizeof(shellExecuteInfo{})),
|
||||||
fMask: seeMaskNocloseprocess,
|
|
||||||
lpVerb: verb,
|
lpVerb: verb,
|
||||||
lpFile: file,
|
lpFile: file,
|
||||||
lpParameters: parameters,
|
lpParameters: parameters,
|
||||||
nShow: 1, // SW_SHOWNORMAL
|
nShow: swShow,
|
||||||
}
|
}
|
||||||
|
|
||||||
ret, _, callErr := shellExecuteExW.Call(uintptr(unsafe.Pointer(&info)))
|
ret, _, callErr := shellExecuteExW.Call(
|
||||||
|
uintptr(unsafe.Pointer(&info)),
|
||||||
|
)
|
||||||
|
|
||||||
if ret == 0 {
|
if ret == 0 {
|
||||||
// ERROR_CANCELLED = 1223:
|
if errno, ok := callErr.(syscall.Errno); ok &&
|
||||||
// Benutzer hat den UAC-Dialog abgebrochen.
|
errno == errorCancelled {
|
||||||
if errno, ok := callErr.(syscall.Errno); ok && errno == 1223 {
|
|
||||||
fmt.Println("Administratorrechte wurden nicht erteilt.")
|
fmt.Println("Administratorrechte wurden nicht erteilt.")
|
||||||
return nil
|
return errors.New("Administratorrechte erforderlich")
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf("Administratorrechte konnten nicht angefordert werden: %w", callErr)
|
return fmt.Errorf(
|
||||||
|
"Administratorrechte konnten nicht angefordert werden: %w",
|
||||||
|
callErr,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auf die erhöhte Instanz warten.
|
// WICHTIG:
|
||||||
if info.hProcess != 0 {
|
// Die ursprüngliche Instanz beendet sich sofort.
|
||||||
handle := syscall.Handle(info.hProcess)
|
// Nur die erhöhte Instanz führt danach main() weiter aus.
|
||||||
defer syscall.CloseHandle(handle)
|
os.Exit(0)
|
||||||
|
|
||||||
_, err := syscall.WaitForSingleObject(handle, syscall.INFINITE)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("auf erhöhte Instanz konnte nicht gewartet werden: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isWindowsElevated() bool {
|
||||||
|
var token uintptr
|
||||||
|
|
||||||
|
// GetCurrentProcess() = -1
|
||||||
|
ret, _, _ := openProcessToken.Call(
|
||||||
|
uintptr(^uint(0)),
|
||||||
|
tokenQuery,
|
||||||
|
uintptr(unsafe.Pointer(&token)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if ret == 0 || token == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
defer closeHandle.Call(token)
|
||||||
|
|
||||||
|
var elevation tokenElevationData
|
||||||
|
var returned uint32
|
||||||
|
|
||||||
|
ret, _, _ = getTokenInformation.Call(
|
||||||
|
token,
|
||||||
|
tokenElevationClass,
|
||||||
|
uintptr(unsafe.Pointer(&elevation)),
|
||||||
|
uintptr(unsafe.Sizeof(elevation)),
|
||||||
|
uintptr(unsafe.Pointer(&returned)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return elevation.TokenIsElevated != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func platformRunPrivileged(config Config, action string) error {
|
||||||
|
// Die komplette Windows-Anwendung läuft bereits erhöht.
|
||||||
|
return runAction(config, action)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getInstallDir() (string, error) {
|
||||||
|
programFiles := os.Getenv("ProgramFiles")
|
||||||
|
|
||||||
|
if programFiles == "" {
|
||||||
|
return "", errors.New("ProgramFiles ist nicht gesetzt")
|
||||||
|
}
|
||||||
|
|
||||||
|
return filepath.Join(programFiles, "logofclient"), nil
|
||||||
|
}
|
||||||
+2
-2
@@ -11,7 +11,7 @@ import (
|
|||||||
func platformInstallIntegration(installDir string) error {
|
func platformInstallIntegration(installDir string) error {
|
||||||
binaryPath := filepath.Join(
|
binaryPath := filepath.Join(
|
||||||
installDir,
|
installDir,
|
||||||
"Logof Client",
|
"Logofclient",
|
||||||
)
|
)
|
||||||
|
|
||||||
linkPath := "/usr/local/bin/logofclient"
|
linkPath := "/usr/local/bin/logofclient"
|
||||||
@@ -56,7 +56,7 @@ func platformInstallIntegration(installDir string) error {
|
|||||||
|
|
||||||
desktopEntry := fmt.Sprintf(`[Desktop Entry]
|
desktopEntry := fmt.Sprintf(`[Desktop Entry]
|
||||||
Name=Logof Client
|
Name=Logof Client
|
||||||
Comment=Logof Client
|
Comment=Logofclient
|
||||||
Exec=%s
|
Exec=%s
|
||||||
Terminal=false
|
Terminal=false
|
||||||
Type=Application
|
Type=Application
|
||||||
|
|||||||
+3
-3
@@ -26,7 +26,7 @@ func platformInstallIntegration(installDir string) error {
|
|||||||
|
|
||||||
shortcutPath := filepath.Join(
|
shortcutPath := filepath.Join(
|
||||||
startMenuDir,
|
startMenuDir,
|
||||||
"Logof Client.lnk",
|
"Logofclient.lnk",
|
||||||
)
|
)
|
||||||
|
|
||||||
if err := os.MkdirAll(startMenuDir, 0755); err != nil {
|
if err := os.MkdirAll(startMenuDir, 0755); err != nil {
|
||||||
@@ -58,7 +58,7 @@ func platformRemoveIntegration() error {
|
|||||||
|
|
||||||
shortcutPath := filepath.Join(
|
shortcutPath := filepath.Join(
|
||||||
startMenuDir,
|
startMenuDir,
|
||||||
"Logof Client.lnk",
|
"Logofclient.lnk",
|
||||||
)
|
)
|
||||||
|
|
||||||
if err := os.Remove(shortcutPath); err != nil && !os.IsNotExist(err) {
|
if err := os.Remove(shortcutPath); err != nil && !os.IsNotExist(err) {
|
||||||
@@ -117,7 +117,7 @@ func platformCreateShortcut(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Beschreibung.
|
// Beschreibung.
|
||||||
if _, err := oleutil.PutProperty(shortcut, "Description", "Logof Client"); err != nil {
|
if _, err := oleutil.PutProperty(shortcut, "Description", "Logofclient"); err != nil {
|
||||||
return fmt.Errorf("Description konnte nicht gesetzt werden: %w", err)
|
return fmt.Errorf("Description konnte nicht gesetzt werden: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user