Beispiel #1
0
// NewEndpoint creates a Ricochet client/server endpoint with the provided
// configuration, including registering the ephemeral HS with Tor.
func NewEndpoint(cfg *EndpointConfig) (e *Endpoint, err error) {
	e = new(Endpoint)
	e.hostname, _ = pkcs1.OnionAddr(&cfg.PrivateKey.PublicKey)
	e.privateKey = cfg.PrivateKey
	e.ctrl = cfg.TorControlPort
	e.isoBase, err = getIsolationAuth()
	if err != nil {
		return nil, err
	}
	e.outgoingQueue = channels.NewInfiniteChannel()
	e.eventQueue = channels.NewInfiniteChannel()
	e.pendingContacts = make(map[string]*ricochetContact)

	e.EventChan = e.eventQueue.Out()

	e.blacklist = make(map[string]bool)
	for _, id := range cfg.BlacklistedContacts {
		if err := e.BlacklistContact(id, true); err != nil {
			return nil, err
		}
	}
	e.contacts = make(map[string]*ricochetContact)
	for _, id := range cfg.KnownContacts {
		if err := e.AddContact(id, nil); err != nil {
			return nil, err
		}
	}
	for id, requestData := range cfg.PendingContacts {
		if err := e.AddContact(id, requestData); err != nil {
			return nil, err
		}
	}

	e.ln, err = e.ctrl.Listener(ricochetPort, e.privateKey)
	if err != nil {
		return nil, err
	}

	logWr := cfg.LogWriter
	if logWr == nil {
		logWr = ioutil.Discard
	}
	e.log = golog.New(logWr, "", golog.LstdFlags)

	e.log.Printf("server: online as '%v'", e.hostname)

	go e.hsAcceptWorker()
	go e.hsConnectWorker()

	return e, nil
}
Beispiel #2
0
func (ch *authHSChan) onPacketServer(authPkt *packet.AuthHSPacket) error {
	log := ch.conn.endpoint.log
	proofMsg := authPkt.GetProof()
	if proofMsg == nil {
		return fmt.Errorf("missing proof")
	}

	// Decode and validate the public key.
	pk, rest, err := pkcs1.DecodePublicKeyDER(proofMsg.GetPublicKey())
	if err != nil {
		return err
	} else if rest != nil && len(rest) > 0 {
		return fmt.Errorf("trailing garbage present after public key")
	} else if pk.N.BitLen() != authHiddenServicePublicKeyBits {
		return fmt.Errorf("invalid public modulus size: %d", pk.N.BitLen())
	}

	// Calculate the client hostname.
	clientHostname, err := pkcs1.OnionAddr(pk)
	if err != nil {
		return err
	}

	sigOk, isKnown := false, false

	// Note: The reference implementation checks against the hostname
	// blacklist for rejected peers, and early rejects clients durring
	// the authentication phase by closing the connection.
	//
	// This is a bit rude.  Check the blacklist and send a rejected
	// response, then close the connection (Done by virtue of returning
	// an error).
	if !ch.conn.endpoint.isBlacklisted(clientHostname) {
		// Calculate the proof.
		proof := ch.calculateProof(clientHostname, ch.conn.endpoint.hostname)

		// Verify proof.
		//
		// The spec neglects to mention PKCS #1 v1.5/SHA256.  Also, not
		// SHA256 suming proof is deliberate because the ricochet code
		// doesn't bother hashing the proof.
		sig := proofMsg.GetSignature()
		err = rsa.VerifyPKCS1v15(pk, crypto.SHA256, proof, sig)
		if err == nil {
			sigOk = true
			ch.conn.getControlChan().isAuthenticated = true
			ch.conn.getControlChan().isKnownToPeer = true
			ch.conn.hostname = clientHostname
			isKnown = ch.conn.endpoint.isKnown(clientHostname)
		}
	} else {
		err = fmt.Errorf("auth from blacklisted peer: '%v'", clientHostname)
	}

	log.Printf("server: auth from client '%s' accepted: %v", clientHostname, sigOk)

	//  Send the result to the client.
	if wrErr := ch.sendResult(sigOk, isKnown); wrErr != nil {
		return wrErr
	}

	if sigOk {
		ch.conn.setEstablished()
		if isKnown {
			ch.conn.authTimer.Stop()
			ch.conn.endpoint.onConnectionEstablished(ch.conn)
		} else {
			// Give them another interval to request contact.
			ch.conn.authTimer.Reset(authenticationTimeout)
		}
	}

	// Close the authentication channel.
	if wrErr := ch.conn.sendChanClose(ch.chanID); wrErr != nil {
		return wrErr
	}
	return err
}