Beispiel #1
0
// Push implements storage.Service.
func (s *service) Push(msg *storage.AddressedMessage) error {
	rcptKey, err := sf.DecodePublicKey(msg.Recipient)
	if err != nil {
		return errgo.Notef(err, "invalid recipient %q", msg.Recipient)
	}
	senderKey, err := sf.DecodePublicKey(msg.Sender)
	if err != nil {
		return errgo.Notef(err, "invalid sender %q", msg.Sender)
	}
	nonce, err := sf.DecodeNonce(msg.ID)
	if err != nil {
		return errgo.Notef(err, "invalid nonce %q", msg.ID)
	}

	return s.db.Update(func(tx *bolt.Tx) error {
		rcptBucket, err := tx.CreateBucketIfNotExists(rcptKey[:])
		if err != nil {
			return errgo.Mask(err)
		}
		senderBucket, err := rcptBucket.CreateBucketIfNotExists(senderKey[:])
		if err != nil {
			return errgo.Mask(err)
		}
		err = senderBucket.Put(nonce[:], msg.Contents)
		if err != nil {
			return errgo.Mask(err)
		}
		return nil
	})
}
Beispiel #2
0
// PublicKey requests a shadowfax server's public key. An error is returned
// if the server URL is not https.
func PublicKey(serverURL string, client *http.Client) (*sf.PublicKey, error) {
	u, err := url.Parse(serverURL)
	if err != nil {
		return nil, errgo.Mask(err, errgo.Any)
	}
	if u.Scheme != "https" {
		return nil, errgo.Newf("public key must be requested with https")
	}
	if client == nil {
		client = http.DefaultClient
	}
	req, err := http.NewRequest("GET", serverURL+"/publickey", nil)
	if err != nil {
		return nil, errgo.Mask(err)
	}

	resp, err := client.Do(req)
	if err != nil {
		return nil, errgo.Mask(err)
	}
	defer resp.Body.Close()

	dec := json.NewDecoder(resp.Body)
	var publicKeyResp wire.PublicKeyResponse
	err = dec.Decode(&publicKeyResp)
	if err != nil {
		return nil, errgo.Mask(err)
	}

	publicKey, err := sf.DecodePublicKey(publicKeyResp.PublicKey)
	if err != nil {
		return nil, errgo.Mask(err)
	}
	return publicKey, nil
}
Beispiel #3
0
func (h *Handler) auth(r *http.Request, client string) (*authRequest, error) {
	var msg wire.Message
	dec := json.NewDecoder(r.Body)
	err := dec.Decode(&msg)
	if err != nil {
		return nil, errgo.Mask(err)
	}

	clientKey, err := sf.DecodePublicKey(client)
	if err != nil {
		return nil, errgo.Mask(err)
	}

	nonce, err := sf.DecodeNonce(msg.ID)
	if err != nil {
		return nil, errgo.Mask(err)
	}

	out, ok := box.Open(nil, msg.Contents, (*[24]byte)(nonce), (*[32]byte)(clientKey), (*[32]byte)(h.keyPair.PrivateKey))
	if !ok {
		return nil, errgo.New("authentication failed")
	}

	return &authRequest{
		Handler:   h,
		ClientKey: clientKey,
		Nonce:     nonce,
		Contents:  out,
	}, nil
}
Beispiel #4
0
// Pop implements storage.Service.
func (s *service) Pop(recipient string) (_ []*storage.AddressedMessage, popErr error) {
	rcptKey, err := sf.DecodePublicKey(recipient)
	if err != nil {
		return nil, errgo.Notef(err, "invalid recipient %q", recipient)
	}

	tx, err := s.db.Begin(true)
	if err != nil {
		return nil, errgo.Mask(err)
	}
	defer func() {
		if popErr == nil {
			popErr = errgo.Mask(tx.Commit())
		} else {
			tx.Rollback()
		}
	}()

	var result []*storage.AddressedMessage
	rcptBucket, err := tx.CreateBucketIfNotExists(rcptKey[:])
	if err != nil {
		return nil, errgo.Mask(err)
	}
	senderCursor := rcptBucket.Cursor()
	for sender, v := senderCursor.First(); sender != nil; sender, v = senderCursor.Next() {
		if v != nil {
			continue
		}
		senderBucket := rcptBucket.Bucket(sender)
		if senderBucket == nil {
			err = senderCursor.Delete()
			if err != nil {
				return nil, errgo.Mask(err)
			}
			continue
		}
		senderStr := basen.Base58.EncodeToString(sender)
		msgCursor := senderBucket.Cursor()
		for id, msg := msgCursor.First(); id != nil; id, msg = msgCursor.Next() {
			idStr := basen.Base58.EncodeToString(id)
			msgContents := make([]byte, len(msg))
			copy(msgContents, msg)
			result = append(result, &storage.AddressedMessage{
				Recipient: recipient,
				Sender:    senderStr,
				Message: storage.Message{
					ID:       idStr,
					Contents: msgContents,
				},
			})
			msgCursor.Delete()
			if err != nil {
				return nil, errgo.Mask(err)
			}
		}
	}
	return result, nil
}
Beispiel #5
0
func nameAdd() error {
	contacts, err := newContacts()
	if err != nil {
		return err
	}
	addrPk, err := sf.DecodePublicKey(*nameAddAddrArg)
	if err != nil {
		return errgo.Mask(err)
	}
	err = contacts.Put(*nameAddNameArg, addrPk)
	return errgo.Mask(err)
}
Beispiel #6
0
// Pop retrieves messages addressed to the client.
func (c *Client) Pop() ([]*PopMessage, error) {
	respContents, err := c.Request("DELETE", "/inbox/"+c.keyPair.PublicKey.Encode(), nil)
	if err != nil {
		return nil, errgo.Mask(err)
	}
	var wireMessages []wire.PopMessage
	err = json.Unmarshal(respContents, &wireMessages)
	if err != nil {
		return nil, errgo.Mask(err)
	}

	var popMessages []*PopMessage
	var errors errorSlice
	for _, msg := range wireMessages {
		nonce, err := sf.DecodeNonce(msg.ID)
		if err != nil {
			errors = append(errors, errgo.Notef(err, "ID=%q Sender=%q", msg.ID, msg.Sender))
			continue
		}
		senderKey, err := sf.DecodePublicKey(msg.Sender)
		if err != nil {
			errors = append(errors, errgo.Notef(err, "ID=%q Sender=%q", msg.ID, msg.Sender))
			continue
		}
		contents, ok := box.Open(nil, msg.Contents, (*[24]byte)(nonce), (*[32]byte)(senderKey), (*[32]byte)(c.keyPair.PrivateKey))
		if !ok {
			errors = append(errors, errgo.Newf("invalid message contents: ID=%q Sender=%q", msg.ID, msg.Sender))
			continue
		}
		popMessages = append(popMessages, &PopMessage{
			ID:       msg.ID,
			Contents: contents,
			Sender:   msg.Sender,
		})
	}
	if len(errors) > 0 {
		return popMessages, errors
	}
	return popMessages, nil
}
Beispiel #7
0
// Push pushes a message to a recipient.
func (c *Client) Push(recipient string, contents []byte) error {
	nonce, err := sf.NewNonce()
	if err != nil {
		return errgo.Mask(err)
	}
	rcptKey, err := sf.DecodePublicKey(recipient)
	if err != nil {
		return errgo.Mask(err)
	}
	encMsg := box.Seal(nil, contents, (*[24]byte)(nonce), (*[32]byte)(rcptKey), (*[32]byte)(c.keyPair.PrivateKey))
	pushWire := []wire.PushMessage{{
		Message: wire.Message{
			ID:       nonce.Encode(),
			Contents: encMsg,
		},
		Recipient: recipient,
	}}
	reqContents, err := json.Marshal(&pushWire)
	if err != nil {
		return errgo.Mask(err)
	}

	respContents, err := c.Request("POST", "/outbox/"+c.keyPair.PublicKey.Encode(), reqContents)
	if err != nil {
		return errgo.Mask(err)
	}
	var pushReceipts []wire.PushReceipt
	err = json.Unmarshal(respContents, &pushReceipts)
	if err != nil {
		return errgo.Mask(err)
	}
	for _, receipt := range pushReceipts {
		if receipt.OK && receipt.ID == nonce.Encode() {
			return nil
		}
	}
	return errgo.New("not acknowledged")
}
Beispiel #8
0
func newClient(keyPair *sf.KeyPair) (*sfhttp.Client, error) {
	var err error
	var serverKey *sf.PublicKey
	if *serverKeyFlag == "" {
		serverKey, err = sfhttp.PublicKey((*urlFlagVar).String(), nil)
		if err != nil {
			return nil, errgo.Mask(err)
		}
	} else {
		serverKey, err = sf.DecodePublicKey(*serverKeyFlag)
		if err != nil {
			return nil, errgo.Mask(err)
		}
	}

	return sfhttp.NewClient(keyPair, (*urlFlagVar).String(), serverKey, &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}), nil
}