Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

affected/package: golang.org/x/crypto #60314

Closed
sourHobbes opened this issue May 19, 2023 · 2 comments
Closed

affected/package: golang.org/x/crypto #60314

sourHobbes opened this issue May 19, 2023 · 2 comments

Comments

@sourHobbes
Copy link

sourHobbes commented May 19, 2023

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

$ go version
go version go1.19.5 darwin/arm64

Does this issue reproduce with the latest release?

Not sure

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

go env Output
$ go env
GO111MODULE=""
GOARCH="arm64"
GOBIN=""
GOCACHE="/Users/sourabhdugar/Library/Caches/go-build"
GOENV="/Users/sourabhdugar/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/sourabhdugar/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/sourabhdugar/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/opt/homebrew/Cellar/go/1.19.5/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/opt/homebrew/Cellar/go/1.19.5/libexec/pkg/tool/darwin_arm64"
GOVCS=""
GOVERSION="go1.19.5"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/sourabhdugar/gogit/go.mod"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/7y/5t4cvr1s27d5dk9j73fk8hf00000gn/T/go-build3027111423=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

I am trying to use gogit to clone an ssh repo
which inturn uses the crypto package to ssh auth
The ssh server returns algo as ssh-rsa, even when the client proposes rsa-sha2-256, this function below is affected:
in ssh/client_auth.go file

Specifically the msg.Algo doesn't match algo arg. Is there a way to override this? and relax the match

func confirmKeyAck(key PublicKey, algo string, c packetConn) (bool, error) {
	pubKey := key.Marshal()

	for {
		packet, err := c.readPacket()
		if err != nil {
			return false, err
		}
		switch packet[0] {
		case msgUserAuthBanner:
			if err := handleBannerResponse(c, packet); err != nil {
				return false, err
			}
		case msgUserAuthPubKeyOk:
			var msg userAuthPubKeyOkMsg
			if err := Unmarshal(packet, &msg); err != nil {
				return false, err
			}
			if msg.Algo != algo || !bytes.Equal(msg.PubKey, pubKey) {
				return false, nil
			}
			return true, nil
		case msgUserAuthFailure:
			return false, nil
		default:
			return false, unexpectedMessageError(msgUserAuthPubKeyOk, packet[0])
		}
	}
}

What did you expect to see?

I would like to see the git clone work, i.e. ssh auth using ssh-rsa key work as it works with the ssh client on Mac.

ssh -V
OpenSSH_9.0p1, LibreSSL 3.3.6

ssh -T git@<privateGitServer> works...

What did you see instead?

The ssh auth doesn't work causing git clone failure...
I managed to make it work when I overwrote the msg.Algo field in the Unmarshal method.

@seankhliao
Copy link
Member

Duplicate of #53391

@seankhliao seankhliao marked this as a duplicate of #53391 May 19, 2023
@seankhliao seankhliao closed this as not planned Won't fix, can't repro, duplicate, stale May 19, 2023
@sourHobbes
Copy link
Author

sourHobbes commented May 20, 2023

I know this is closed as duplicate, but posting a workaround which could be helpful in some cases.
We could monkey patch confirmKeyAck as follows:

import (
	"bou.ke/monkey"
       /// ... other imports
)

// expose types and declare some

// See RFC 4252, section 5.1
const msgUserAuthFailure = 51

//go:linkname unexpectedMessageError golang.org/x/crypto/ssh.unexpectedMessageError
func unexpectedMessageError(expected, got uint8) error

//go:linkname handleBannerResponse golang.org/x/crypto/ssh.handleBannerResponse
func handleBannerResponse(c interface{}, packet []byte) error

// See RFC 4252, section 5.1
const msgUserAuthSuccess = 52

// See RFC 4252, section 5.4
const msgUserAuthBanner = 53

// See RFC 4252, section 7
const msgUserAuthPubKeyOk = 60

//go:linkname algorithmsForKeyFormat golang.org/x/crypto/ssh.algorithmsForKeyFormat
func algorithmsForKeyFormat(string) []string

//go:linkname confirmKeyAck golang.org/x/crypto/ssh.confirmKeyAck
func confirmKeyAck(key ssh.PublicKey, algo string, c packetConn) (bool, error)

type packetConn interface {
	// Encrypt and send a packet of data to the remote peer.
	writePacket(packet []byte) error

	// Read a packet from the connection. The read is blocking,
	// i.e. if error is nil, then the returned byte slice is
	// always non-empty.
	readPacket() ([]byte, error)

	// Close closes the write-side of the connection.
	Close() error
}
type userAuthPubKeyOkMsg struct {
	Algo   string `sshtype:"60"`
	PubKey []byte
}

func main() {
        // ....
	monkey.Patch(confirmKeyAck, func(key ssh.PublicKey, algo string, c packetConn) (bool, error) {
		pubKey := key.Marshal()

		for {
			packet, err := c.readPacket()
			if err != nil {
				return false, err
			}
			switch packet[0] {
			case msgUserAuthBanner:
				if err := handleBannerResponse(c, packet); err != nil {
					return false, err
				}
			case msgUserAuthPubKeyOk:
				log.Printf("the key type is %v", key.Type())
				var msg userAuthPubKeyOkMsg
				if err := ssh.Unmarshal(packet, &msg); err != nil {
					return false, err
				}
                               // the original code fails for keyType ssh-rsa in some cases
                               // as it compares msg.Algo and algo which are not equal
                              // so completely removing the check here, not sure of security implications, so exercise caution 
				if !bytes.Equal(msg.PubKey, pubKey) {
					return false, nil
				}
				log.Printf("Successful auth with %v", key.Type())
				return true, nil
			case msgUserAuthFailure:
				return false, nil
			default:
				return false, unexpectedMessageError(msgUserAuthPubKeyOk, packet[0])
			}
		}
	})

       // ....
}

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants