go: x/term: "Access is denied." error with ReadPassword on Windows

What version of Go are you using (go version)?

$ go version
go version go1.16.2 openbsd/amd64

Does this issue reproduce with the latest release?

It reproduces with the latest version of x/term (v0.0.0-20210503060354-a79de5458b56).

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/fooman/.cache/go-build"
GOENV="/home/fooman/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="openbsd"
GOINSECURE=""
GOMODCACHE="/home/fooman/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="openbsd"
GOPATH="/home/fooman/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/openbsd_amd64"
GOVCS=""
GOVERSION="go1.16.2"
GCCGO="gccgo"
AR="ar"
CC="cc"
CXX="c++"
CGO_ENABLED="1"
GOMOD="/home/fooman/tmp_1m/readpw_win/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build3256633254=/tmp/go-build -gno-record-gcc-switches"

I’m cross compiling from OpenBSD for Windows.

What did you do?

I ran the following program on the Windows 10 operating system:

package main

import (
	"fmt"
	"golang.org/x/term"
	"os"
)

func main() {
	tty, err := os.Open("CON:")
	if err != nil {
		panic(err)
	}
	defer tty.Close()
	pw, err := term.ReadPassword(int(tty.Fd()))
	if err != nil {
		panic(err)
	}
	fmt.Println(string(pw))
}

What did you expect to see?

I expected the program to prompt me for password input and to then print the entered password.

What did you see instead?

When running the program (either as normal user or as administator) I get this output:

panic: Access is denied.

goroutine 1 [running]:
main.main()
        /home/fooman/tmp_1m/readpw_win/readpw_win.go:17 +0x197

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 27 (21 by maintainers)

Most upvoted comments

Thanks for your response. Since we have seemingly reached the limit of what we can do with the available documentation, I’ll accept the behavior of the Windows API for now. If I find the time, I may try to put together a C++ demo of the problem later and ask Microsoft about it.

@networkimprov I think an example in x/term would be more appropriate.

The only thing I’ll change is that I’ll use golang.org/x/sys/windows instead of syscall, since the documentation says this package has been deprecated.

No worries.

As I said before, I can’t really gauge whether this issue still has value or should be closed, so I’ll leave for someone else to close or pick up.

So the problem here appears that os.Open does not work with files like CONIN$, if you want to use returned file handle to call GetConsoleMode or SetConsoleMode Windows API.

I think this scenario is too specific. And we easily solved the problem by calling Windows API directly.

I think this is good enough. So closing the issue. Feel free to re-open if you disagree.

Alex

@codesoap here is version of your program that works:

package main

import (
	"fmt"
	"golang.org/x/term"
	"io"
	"os"
	"syscall"
)

func main() {
	path, err := syscall.UTF16PtrFromString("CONIN$")
	if err != nil {
		panic(err)
	}
	h, err := syscall.CreateFile(path, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.FILE_SHARE_READ, nil, syscall.OPEN_EXISTING, 0, 0)
	if err != nil {
		panic(err)
	}
	defer syscall.CloseHandle(h)

	fmt.Print("Enter password: ")
	pw, err := term.ReadPassword(int(h))
	if err != nil {
		panic(err)
	}

	fmt.Println("")

	decryptStdin(string(pw))
}

// decryptStdin is only a dummy, which prints what was received via
// standard input. In the real world it would use pw to decrypt the
// standard input before printing it.
func decryptStdin(pw string) {
	fmt.Println("Decrypted message:")
	io.Copy(os.Stdout, os.Stdin)
}

I copied part of that code from

https://stackoverflow.com/questions/377152/what-does-createfileconin-do

Alex