golang.zx2c4.com/wireguard/windows@v0.5.4-0.20230123132234-dcc0eb72a04b/tunnel/scriptrunner.go (about)

     1  /* SPDX-License-Identifier: MIT
     2   *
     3   * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
     4   */
     5  
     6  package tunnel
     7  
     8  import (
     9  	"bufio"
    10  	"fmt"
    11  	"log"
    12  	"os"
    13  	"path/filepath"
    14  	"syscall"
    15  
    16  	"golang.org/x/sys/windows"
    17  
    18  	"golang.zx2c4.com/wireguard/windows/conf"
    19  )
    20  
    21  func runScriptCommand(command, interfaceName string) error {
    22  	if len(command) == 0 {
    23  		return nil
    24  	}
    25  	if !conf.AdminBool("DangerousScriptExecution") {
    26  		log.Printf("Skipping execution of script, because dangerous script execution is safely disabled: %#q", command)
    27  		return nil
    28  	}
    29  	log.Printf("Executing: %#q", command)
    30  	comspec, _ := os.LookupEnv("COMSPEC")
    31  	if len(comspec) == 0 {
    32  		system32, err := windows.GetSystemDirectory()
    33  		if err != nil {
    34  			return err
    35  		}
    36  		comspec = filepath.Join(system32, "cmd.exe")
    37  	}
    38  
    39  	devNull, err := os.OpenFile(os.DevNull, os.O_RDWR, 0)
    40  	if err != nil {
    41  		return err
    42  	}
    43  	defer devNull.Close()
    44  	reader, writer, err := os.Pipe()
    45  	if err != nil {
    46  		return err
    47  	}
    48  	process, err := os.StartProcess(comspec, nil /* CmdLine below */, &os.ProcAttr{
    49  		Files: []*os.File{devNull, writer, writer},
    50  		Env:   append(os.Environ(), "WIREGUARD_TUNNEL_NAME="+interfaceName),
    51  		Sys: &syscall.SysProcAttr{
    52  			HideWindow: true,
    53  			CmdLine:    fmt.Sprintf("cmd /c %s", command),
    54  		},
    55  	})
    56  	writer.Close()
    57  	if err != nil {
    58  		reader.Close()
    59  		return err
    60  	}
    61  	go func() {
    62  		scanner := bufio.NewScanner(reader)
    63  		for scanner.Scan() {
    64  			log.Printf("cmd> %s", scanner.Text())
    65  		}
    66  	}()
    67  	state, err := process.Wait()
    68  	reader.Close()
    69  	if err != nil {
    70  		return err
    71  	}
    72  	if state.ExitCode() == 0 {
    73  		return nil
    74  	}
    75  	log.Printf("Command error exit status: %d", state.ExitCode())
    76  	return windows.ERROR_GENERIC_COMMAND_FAILED
    77  }