Ejemplo n.º 1
0
// getOrRequestPublicIdentity retrieves the needed public identity from bmd
// or sends a getpubkey request if it doesn't exist in its database. If both
// return types are nil, it means a getpubkey request has been queued.
func (s *server) getOrRequestPublicIdentity(user uint32, address string) (*identity.Public, error) {
	serverLog.Debug("getOrRequestPublicIdentity called for ", address)
	id, err := s.bmd.GetIdentity(address)
	if err == nil {
		return id, nil
	} else if err != rpc.ErrIdentityNotFound {
		return nil, err
	}

	addr, err := bmutil.DecodeAddress(address)
	if err != nil {
		return nil, fmt.Errorf("Failed to decode address: %v", err)
	}

	serverLog.Debug("getOrRequestPublicIdentity: address not found, send pubkey request.")
	// We don't have the identity so craft a getpubkey request.
	var tag wire.ShaHash
	copy(tag[:], addr.Tag())

	msg := obj.NewGetPubKey(0, time.Now().Add(defaultGetpubkeyExpiry),
		addr.Version, addr.Stream, (*wire.RipeHash)(&addr.Ripe), &tag)

	// Enqueue the request for proof-of-work.
	b := wire.EncodeMessage(msg.MsgObject())[8:] // exclude nonce
	target := pow.CalculateTarget(uint64(len(b)),
		uint64(msg.Header().Expiration().Sub(time.Now()).Seconds()),
		pow.DefaultData)

	s.pow.Run(target, b, func(nonce pow.Nonce) {
		err := s.Send(append(nonce.Bytes(), b...))
		if err != nil {
			serverLog.Error("Could not run pow: ", err)
		}

		// Store a record of the public key request.
		count, _ := s.pk.New(address)
		serverLog.Tracef("getOrRequestPublicIdentity: Requested address %s %d time(s).",
			address, count)
	})

	return nil, nil
}
Ejemplo n.º 2
0
// trySend takes a Bitmessage and does whatever needs to be done to it
// next in order to send it into the network. There are some steps in this
// process that take a bit of time, so they can't all be handled sequentially
// by one function. If we don't have the recipient's private key yet, we
// can't send the message and we have to send a pubkey request to him instead.
// On the other hand, messages might come in for which we already have the
// public key and then we can go on to the next step right away.
//
// The next step is proof-of-work, and that also takes time.
func (u *User) trySend(bmsg *Bmail) error {
	outbox := u.boxes[OutboxFolderName]

	// First we attempt to generate the wire.Object form of the message.
	// If we can't, then it is possible that we don't have the recipient's
	// pubkey. That is not an error state. If no object and no error is
	// returned, this is what has happened. If there is no object, then we
	// can't proceed futher so trySend completes.
	object, powData, err := bmsg.GenerateObject(u.server)
	if object == nil {
		smtpLog.Debug("trySend: could not generate message. Pubkey request sent? ", err == nil)
		if err == nil {
			bmsg.state.PubkeyRequestOutstanding = true

			err := outbox.saveBitmessage(bmsg)
			if err != nil {
				return err
			}
			return nil
		}
		return err
	}

	bmsg.state.PubkeyRequestOutstanding = false

	// sendPow takes a message in wire format with all required information
	// to send it over the network other than having proof-of-work run on it.
	// It generates the correct parameters for running the proof-of-work and
	// sends it to the proof-of-work queue with a function provided by the
	// user that says what to do with the completed message when the
	// proof-of-work is done.
	sendPow := func(object obj.Object, powData *pow.Data, done func([]byte)) {
		encoded := wire.Encode(object)
		q := encoded[8:] // exclude the nonce

		target := pow.CalculateTarget(uint64(len(q)),
			uint64(object.Header().Expiration().Sub(time.Now()).Seconds()), *powData)

		// Attempt to run pow on the message.
		u.server.RunPow(target, q, func(n pow.Nonce) {
			// Put the nonce bytes into the encoded form of the message.
			q = append(n.Bytes(), q...)
			done(q)
		})
	}

	// sendPreparedMessage is used after we have looked up private keys and
	// generated an ack message, if applicable.
	sendPreparedMessage := func() error {
		err := outbox.saveBitmessage(bmsg)
		if err != nil {
			return err
		}

		// Put the prepared object in the pow queue and send it off
		// through the network.
		sendPow(object, powData, func(completed []byte) {
			err := func() error {
				// Save Bitmessage in outbox folder.
				err := u.boxes[OutboxFolderName].saveBitmessage(bmsg)
				if err != nil {
					return err
				}

				u.server.Send(completed)

				// Select new box for the message.
				var newBoxName string
				if bmsg.state.AckExpected {
					newBoxName = LimboFolderName
				} else {
					newBoxName = SentFolderName
				}

				bmsg.state.SendTries++
				bmsg.state.LastSend = time.Now()

				return u.Move(bmsg, OutboxFolderName, newBoxName)
			}()
			// We can't return the error any further because this function
			// isn't even run until long after trySend completes!
			if err != nil {
				smtpLog.Error("trySend: ", err)
			}
		})

		return nil
	}

	// We may desire to receive an ack with this message, which has not yet
	// been created. In that case, we need to do proof-of-work on the ack just
	// as on the entire message.
	if bmsg.Ack != nil && bmsg.state.AckExpected {
		ack, powData, err := bmsg.generateAck(u.server)
		if err != nil {
			return err
		}

		err = outbox.saveBitmessage(bmsg)
		if err != nil {
			return err
		}

		sendPow(ack, powData, func(completed []byte) {
			err := func() error {
				// Add the ack to the message.
				bmsg.Ack = completed

				return sendPreparedMessage()
			}
			// Once again, we can't return the error any further because
			// trySend is over by the time this function is run.
			if err != nil {
				smtpLog.Error("trySend: ", err)
			}
		})
	} else {
		return sendPreparedMessage()
	}

	return nil
}
Ejemplo n.º 3
0
// newGetpubkey is called when a new getpubkey is received by the RPC client.
// Getpubkey requests are guaranteed to be received in ascending order of
// counter value.
func (s *server) newGetpubkey(counter uint64, object []byte) {
	// Store counter value.
	atomic.StoreUint64(&s.getpubkeyCounter, counter)

	msg := &obj.GetPubKey{}
	err := msg.Decode(bytes.NewReader(object))
	if err != nil {
		serverLog.Errorf("Failed to decode getpubkey #%d from bytes: %v",
			counter, err)
		return // Ignore message.
	}

	var privID *keymgr.PrivateID
	header := msg.Header()

	// Check if the getpubkey request corresponds to any of our identities.
	for _, user := range s.users {
		err = user.Keys.ForEach(func(id *keymgr.PrivateID) error {
			if id.Disabled || id.IsChan { // We don't care about these.
				return nil
			}

			var cond bool // condition to satisfy
			switch header.Version {
			case obj.SimplePubKeyVersion, obj.ExtendedPubKeyVersion:
				cond = bytes.Equal(id.Private.Address.Ripe[:], msg.Ripe[:])
			case obj.TagGetPubKeyVersion:
				cond = bytes.Equal(id.Private.Address.Tag(), msg.Tag[:])
			}
			if cond {
				privID = id
				return errors.New("We have a match.")
			}
			return nil
		})
		if err != nil {
			break
		}
	}
	if err == nil {
		return
	}

	addr := privID.Address()
	serverLog.Infof("Received a getpubkey request for %s, sending out the pubkey.", addr)

	// Generate a pubkey message.
	pkMsg, err := cipher.GeneratePubKey(&privID.Private, defaultPubkeyExpiry)
	if err != nil {
		serverLog.Errorf("Failed to generate pubkey for %s: %v", addr, err)
		return
	}

	// Add it to pow queue.
	pkObj := pkMsg.Object().MsgObject()
	pkHeader := pkObj.Header()
	b := wire.EncodeMessage(pkObj)[8:] // exclude nonce
	target := pow.CalculateTarget(uint64(len(b)),
		uint64(pkHeader.Expiration().Sub(time.Now()).Seconds()),
		pow.DefaultData)

	s.pow.Run(target, b, func(nonce pow.Nonce) {
		s.Send(append(nonce.Bytes(), b...))
	})
}