// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ssh

import (
	"encoding/base64"
	"errors"
	"io"
	"sync"
)

// See [PROTOCOL.agent], section 3.
const (
	// 3.2 Requests from client to agent for protocol 2 key operations
	agentRequestIdentities   = 11
	agentSignRequest         = 13
	agentAddIdentity         = 17
	agentRemoveIdentity      = 18
	agentRemoveAllIdentities = 19
	agentAddIdConstrained    = 25

	// 3.3 Key-type independent requests from client to agent
	agentAddSmartcardKey            = 20
	agentRemoveSmartcardKey         = 21
	agentLock                       = 22
	agentUnlock                     = 23
	agentAddSmartcardKeyConstrained = 26

	// 3.4 Generic replies from agent to client
	agentFailure = 5
	agentSuccess = 6

	// 3.6 Replies from agent to client for protocol 2 key operations
	agentIdentitiesAnswer = 12
	agentSignResponse     = 14

	// 3.7 Key constraint identifiers
	agentConstrainLifetime = 1
	agentConstrainConfirm  = 2
)

// maxAgentResponseBytes is the maximum agent reply size that is accepted. This
// is a sanity check, not a limit in the spec.
const maxAgentResponseBytes = 16 << 20

// Agent messages:
// These structures mirror the wire format of the corresponding ssh agent
// messages found in [PROTOCOL.agent].

type failureAgentMsg struct{}

type successAgentMsg struct{}

// See [PROTOCOL.agent], section 2.5.2.
type requestIdentitiesAgentMsg struct{}

// See [PROTOCOL.agent], section 2.5.2.
type identitiesAnswerAgentMsg struct {
	NumKeys uint32
	Keys    []byte `ssh:"rest"`
}

// See [PROTOCOL.agent], section 2.6.2.
type signRequestAgentMsg struct {
	KeyBlob []byte
	Data    []byte
	Flags   uint32
}

// See [PROTOCOL.agent], section 2.6.2.
type signResponseAgentMsg struct {
	SigBlob []byte
}

// AgentKey represents a protocol 2 key as defined in [PROTOCOL.agent],
// section 2.5.2.
type AgentKey struct {
	blob    []byte
	Comment string
}

// String returns the storage form of an agent key with the format, base64
// encoded serialized key, and the comment if it is not empty.
func (ak *AgentKey) String() string {
	algo, _, ok := parseString(ak.blob)
	if !ok {
		return "ssh: malformed key"
	}

	s := string(algo) + " " + base64.StdEncoding.EncodeToString(ak.blob)

	if ak.Comment != "" {
		s += " " + ak.Comment
	}

	return s
}

// Key returns an agent's public key as one of the supported key or certificate types.
func (ak *AgentKey) Key() (interface{}, error) {
	if key, _, ok := parsePubKey(ak.blob); ok {
		return key, nil
	}
	return nil, errors.New("ssh: failed to parse key blob")
}

func parseAgentKey(in []byte) (out *AgentKey, rest []byte, ok bool) {
	ak := new(AgentKey)

	if ak.blob, in, ok = parseString(in); !ok {
		return
	}

	comment, in, ok := parseString(in)
	if !ok {
		return
	}
	ak.Comment = string(comment)

	return ak, in, true
}

// AgentClient provides a means to communicate with an ssh agent process based
// on the protocol described in [PROTOCOL.agent]?rev=1.6.
type AgentClient struct {
	// conn is typically represented by using a *net.UnixConn
	conn io.ReadWriter
	// mu is used to prevent concurrent access to the agent
	mu sync.Mutex
}

// NewAgentClient creates and returns a new *AgentClient using the
// passed in io.ReadWriter as a connection to a ssh agent.
func NewAgentClient(rw io.ReadWriter) *AgentClient {
	return &AgentClient{conn: rw}
}

// sendAndReceive sends req to the agent and waits for a reply. On success,
// the reply is unmarshaled into reply and replyType is set to the first byte of
// the reply, which contains the type of the message.
func (ac *AgentClient) sendAndReceive(req []byte) (reply interface{}, replyType uint8, err error) {
	// ac.mu prevents multiple, concurrent requests. Since the agent is typically
	// on the same machine, we don't attempt to pipeline the requests.
	ac.mu.Lock()
	defer ac.mu.Unlock()

	msg := make([]byte, stringLength(len(req)))
	marshalString(msg, req)
	if _, err = ac.conn.Write(msg); err != nil {
		return
	}

	var respSizeBuf [4]byte
	if _, err = io.ReadFull(ac.conn, respSizeBuf[:]); err != nil {
		return
	}
	respSize, _, _ := parseUint32(respSizeBuf[:])

	if respSize > maxAgentResponseBytes {
		err = errors.New("ssh: agent reply too large")
		return
	}

	buf := make([]byte, respSize)
	if _, err = io.ReadFull(ac.conn, buf); err != nil {
		return
	}
	return unmarshalAgentMsg(buf)
}

// RequestIdentities queries the agent for protocol 2 keys as defined in
// [PROTOCOL.agent] section 2.5.2.
func (ac *AgentClient) RequestIdentities() ([]*AgentKey, error) {
	req := marshal(agentRequestIdentities, requestIdentitiesAgentMsg{})

	msg, msgType, err := ac.sendAndReceive(req)
	if err != nil {
		return nil, err
	}

	switch msg := msg.(type) {
	case *identitiesAnswerAgentMsg:
		if msg.NumKeys > maxAgentResponseBytes/8 {
			return nil, errors.New("ssh: too many keys in agent reply")
		}
		keys := make([]*AgentKey, msg.NumKeys)
		data := msg.Keys
		for i := uint32(0); i < msg.NumKeys; i++ {
			var key *AgentKey
			var ok bool
			if key, data, ok = parseAgentKey(data); !ok {
				return nil, ParseError{agentIdentitiesAnswer}
			}
			keys[i] = key
		}
		return keys, nil
	case *failureAgentMsg:
		return nil, errors.New("ssh: failed to list keys")
	}
	return nil, UnexpectedMessageError{agentIdentitiesAnswer, msgType}
}

// SignRequest requests the signing of data by the agent using a protocol 2 key
// as defined in [PROTOCOL.agent] section 2.6.2.
func (ac *AgentClient) SignRequest(key interface{}, data []byte) ([]byte, error) {
	req := marshal(agentSignRequest, signRequestAgentMsg{
		KeyBlob: serializePublickey(key),
		Data:    data,
	})

	msg, msgType, err := ac.sendAndReceive(req)
	if err != nil {
		return nil, err
	}

	switch msg := msg.(type) {
	case *signResponseAgentMsg:
		return msg.SigBlob, nil
	case *failureAgentMsg:
		return nil, errors.New("ssh: failed to sign challenge")
	}
	return nil, UnexpectedMessageError{agentSignResponse, msgType}
}

// unmarshalAgentMsg parses an agent message in packet, returning the parsed
// form and the message type of packet.
func unmarshalAgentMsg(packet []byte) (interface{}, uint8, error) {
	if len(packet) < 1 {
		return nil, 0, ParseError{0}
	}
	var msg interface{}
	switch packet[0] {
	case agentFailure:
		msg = new(failureAgentMsg)
	case agentSuccess:
		msg = new(successAgentMsg)
	case agentIdentitiesAnswer:
		msg = new(identitiesAnswerAgentMsg)
	case agentSignResponse:
		msg = new(signResponseAgentMsg)
	default:
		return nil, 0, UnexpectedMessageError{0, packet[0]}
	}
	if err := unmarshal(msg, packet, packet[0]); err != nil {
		return nil, 0, err
	}
	return msg, packet[0], nil
}
