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

x/crypto/ssh: how do you parse the modelist of a ptyRequestMsg? #21781

Closed
nhooyr opened this issue Sep 6, 2017 · 3 comments
Closed

x/crypto/ssh: how do you parse the modelist of a ptyRequestMsg? #21781

nhooyr opened this issue Sep 6, 2017 · 3 comments

Comments

@nhooyr
Copy link
Contributor

nhooyr commented Sep 6, 2017

This is how the modelist is marshalled https://github.com/golang/crypto/blob/81e90905daefcd6fd217b62423c0908922eadb30/ssh/session.go#L192-L199

But how would one cleanly unmarshal it? You can't just unmarshal it into a slice or a struct so the only way I can think of is slicing the modelist into groups of the length of a single key value pair (5, but you'd have to know that before) and then individually marshalling each of those slices into their own structures. That's what I'm doing now and it works, but it's extremely janky because you need to know the length of a single key value pair preemptively.

Is there any better way to do it?

@dmitshur dmitshur changed the title /x/crypto/ssh: how do you parse the modelist of a ptyRequestMsg? x/crypto/ssh: how do you parse the modelist of a ptyRequestMsg? Sep 6, 2017
@gopherbot gopherbot added this to the Unreleased milestone Sep 6, 2017
@jeffallen
Copy link
Contributor

That message format is defined in the RFC: https://www.ietf.org/rfc/rfc4254.txt

See section 8. There are notes there saying parsing should happen pair by pair, and should stop on an unknown pair.

@nhooyr
Copy link
Contributor Author

nhooyr commented Sep 6, 2017

But in order to parse a pair, I need to know that the length of the pair is 5 bytes. It's kinda janky.

In that case, would you say my approach is correct?

If my approach is not clear, here is some example code:

// pretend modelist is the slice of bytes of the modelist.
var modelist []byte
for {
	type mode struct {
		Key byte
		Val uint32
	}
	m := &mode{}
	err := ssh.Unmarshal(modelist[:5], m)
	if err != nil {
		panic(err)
	}
	println(m.Key)
	println(m.Val)
	println("====")

	modelist = modelist[5:]
	if len(modelist) == 1 {
		return
	}
}

@nhooyr
Copy link
Contributor Author

nhooyr commented Sep 6, 2017

Ah, I got it, I need to use binary.Size.

// pretend modelist is the slice of bytes of the modelist.
var modelist []byte
type mode struct {
	Key byte
	Val uint32
}
var m mode
var lenMode = binary.Size(m)
// > and not >= because if it is equal, the modelist is malformed because there needs to be a null terminator.
for len(modelist) > lenMode {
	err := ssh.Unmarshal(modelist[:lenMode], &m)
	if err != nil {
		panic(err)
	}
	println(m.Key)
	println(m.Val)
	println("====")
	modelist = modelist[lenMode:]
}

That LGTM so I'll close this issue.

@nhooyr nhooyr closed this as completed Sep 6, 2017
@golang golang locked and limited conversation to collaborators Sep 6, 2018
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