Beispiel #1
0
// Generate an outbound TLS connection so we can hand verify the remote side
func (this *LinkMgr) safeDial(net string, host string) (net.Conn, error) {
	var id int
	_, err := fmt.Sscanf(host, "id_%d:80", &id)
	if err != nil {
		return nil, err
	}
	this.cmut.RLock()
	fi, ok := this.friendsId[id]
	if !ok {
		this.cmut.RUnlock()
		this.Log.Printf("No such friend")
		return nil, fmt.Errorf("Dial of removed friend: %s", host)
	}
	this.cmut.RUnlock()
	this.Log.Printf("Dialing(%s:%d)", fi.host, fi.port)
	conn, err := tls.Dial("tcp", fmt.Sprintf("%s:%d", fi.host, fi.port), this.clientTls)
	if err != nil {
		this.cmut.Lock()
		this.UpdateIsGd(fi)
		this.cmut.Unlock()
		return nil, err
	}

	err = conn.Handshake()
	if err != nil {
		return nil, err
	}

	state := conn.ConnectionState()

	if len(state.PeerCertificates) < 1 {
		err = fmt.Errorf("Missing peer certificate")
		return nil, err
	}

	ident, err := crypto.PublicFromCert(state.PeerCertificates[0])
	if err != nil {
		return nil, err
	}
	if ident.Fingerprint().String() != fi.fingerprint.String() {
		err = fmt.Errorf("Invalid peer certificate")
		return nil, err
	}

	return conn, nil
}
Beispiel #2
0
// Handle inbound request, implemented on hideServer to make non-public
func (hthis *hideServer) ServeHTTP(response http.ResponseWriter, request *http.Request) {
	this := hthis.impl
	state := request.TLS
	if state == nil {
		this.respondError(response, http.StatusBadRequest, "Must use TLS")
		return
	}

	if len(state.PeerCertificates) < 1 {
		this.respondError(response, http.StatusForbidden, "Missing peer certificicate")
		return
	}

	id, err := crypto.PublicFromCert(state.PeerCertificates[0])
	if err != nil {
		this.respondError(response, http.StatusForbidden, "Invalid peer certificicate")
		return
	}

	if request.Header.Get("Content-Type") != "application/binary" {
		this.respondError(response, http.StatusBadRequest, "Invalid content type")
		return
	}

	var service int
	_, err = fmt.Sscanf(request.URL.Path, "/h0tb0x/%d", &service)
	if err != nil {
		this.respondError(response, http.StatusNotFound, fmt.Sprintf("Unknown URL: '%s'", request.URL.Path))
		return
	}

	if request.Method != "POST" {
		this.respondError(response, http.StatusMethodNotAllowed, fmt.Sprintf("Invalid method: '%s'", request.Method))
		return
	}

	this.cmut.RLock()
	handler, sok := this.handlers[service]
	if !sok {
		this.cmut.RUnlock()
		this.respondError(response, http.StatusForbidden, fmt.Sprintf("Unknown service: %d", service))
		return
	}

	fi, ok := this.friendsFp[id.Fingerprint().String()]
	if !ok {
		this.cmut.RUnlock()
		this.respondError(response, http.StatusForbidden, fmt.Sprintf("Unknown friend: %s", id.Fingerprint().String()))
		return
	}
	this.wait.Add(1)
	response.Header().Set("Content-Type", "application/binary")
	check := &didWrite{inner: response, wrote: false}
	err = handler(fi.id, id.Fingerprint(), request.Body, check)
	this.cmut.RUnlock()
	this.wait.Done()

	if err != nil && !check.wrote {
		this.respondError(response, http.StatusInternalServerError, err.Error())
		return
	}
}