// FetchPost fetches a post from a peer and adds it. func (ms MessageServer) FetchPost(url, auth string, msgID [message.MessageIDSize]byte, expireRequest uint64) error { // Fetch the post proto := repproto.New(ms.SocksProxy, "") data, err := proto.GetSpecificAuth(url, auth, msgID[:]) // data, err := proto.GetSpecific(url, msgID[:]) if err != nil { return err } // Verify and use it signheader, err := message.Base64Message(data).GetSignHeader() if err != nil { log.Debugf("Bad fetch:GetSignHeader: %s\n", err) return err } details, err := message.VerifySignature(*signheader, ms.MinHashCashBits) if err != nil { log.Debugf("Bad fetch:VerifySignature: %s\n", err) return err } constantRecipientPub, MessageID, err := deferVerify(data) if err != nil { log.Debugf("Bad fetch:deferVerify: %s\n", err) return err } if *MessageID != details.MsgID { log.Debugs("Bad fetch:MessageID\n") return ErrBadMessageID } msgStruct := &structs.MessageStruct{ MessageID: *MessageID, ReceiverConstantPubKey: *constantRecipientPub, SignerPub: details.PublicKey, OneTime: false, Sync: false, Hidden: false, ExpireRequest: expireRequest, } if message.KeyIsSync(constantRecipientPub) { msgStruct.Sync = true } if message.KeyIsHidden(constantRecipientPub) { msgStruct.Hidden = true } sigStruct := &structs.SignerStruct{ PublicKey: details.PublicKey, Nonce: details.HashCashNonce, Bits: details.HashCashBits, } sigStruct.MaxMessagesPosted, sigStruct.MaxMessagesRetained, sigStruct.ExpireTarget = ms.calcLimits(details.HashCashBits) return ms.DB.Put(msgStruct, sigStruct, data) }
// ListSpecific lists the messages for pubKey from a specific server func (proto *Proto) ListSpecific(server string, pubKey, privKey []byte, start, count int) (messages []*structs.MessageStruct, more bool, err error) { var authStr string var myPubKey message.Curve25519Key copy(myPubKey[:], pubKey) if message.KeyIsHidden(&myPubKey) { if privKey == nil { return nil, false, ErrPrivKey } auth, err := proto.Auth(server, privKey) if err != nil { return nil, false, err } authStr = "&auth=" + auth } url := constructURL(server, "/keyindex?key=", utils.B58encode(pubKey[:]), "&start=", strconv.Itoa(start), "count=", strconv.Itoa(count), authStr) body, err := socks.Proxy(proto.SocksServer).LimitGet(url, 512000) if err != nil { return nil, false, err } return parseListResponse(body) }
// ProcessPost verifies and adds a post to the database. func (ms MessageServer) ProcessPost(postdata io.ReadCloser, oneTime bool, expireRequest uint64) string { data, err := utils.MaxRead(ms.MaxPostSize, postdata) if err != nil { return "ERROR: Message too big\n" } if len(data) < ms.MinPostSize { return "ERROR: Message too small\n" } signheader, err := message.Base64Message(data).GetSignHeader() if err != nil { log.Debugf("Post:GetSignHeader: %s\n", err) return "ERROR: Sign Header\n" } details, err := message.VerifySignature(*signheader, ms.MinHashCashBits) if err != nil { log.Debugf("Post:VerifySignature: %s\n", err) return "ERROR: HashCash\n" } constantRecipientPub, MessageID, err := deferVerify(data) if err != nil { log.Debugf("Post:deferVerify: %s\n", err) return "ERROR: Verify\n" } if *MessageID != details.MsgID { log.Debugs("Post:MessageID\n") return "ERROR: MessageID\n" } msgStruct := &structs.MessageStruct{ MessageID: *MessageID, ReceiverConstantPubKey: *constantRecipientPub, SignerPub: details.PublicKey, OneTime: oneTime, Sync: false, Hidden: false, ExpireRequest: expireRequest, } if !oneTime { if message.KeyIsSync(constantRecipientPub) { msgStruct.Sync = true } } else { msgStruct.Sync = false } if message.KeyIsHidden(constantRecipientPub) { msgStruct.Hidden = true } sigStruct := &structs.SignerStruct{ PublicKey: details.PublicKey, Nonce: details.HashCashNonce, Bits: details.HashCashBits, } sigStruct.MaxMessagesPosted, sigStruct.MaxMessagesRetained, sigStruct.ExpireTarget = ms.calcLimits(details.HashCashBits) _, _ = msgStruct, sigStruct ms.RandomSleep() // err = ms.DB.Put(msgStruct, sigStruct, data) err = ms.DB.PutNotify(msgStruct, sigStruct, data, ms.notifyChan) ms.RandomSleep() if err != nil { log.Debugf("Post:MessageDB: %s\n", err) return fmt.Sprintf("ERROR: %s\n", err) } log.Debugf("Post:Added: %x\n", MessageID[:12]) if ms.Stat { stat.Input <- stat.Post } return "SUCCESS: Connection close\n" }
// GetKeyIndex returns the index for a key. func (ms MessageServer) GetKeyIndex(w http.ResponseWriter, r *http.Request) { var pubKey *message.Curve25519Key var auth []byte start := int64(0) count := int64(10) w.Header().Set("Content-Type", "text/plain; charset=us-ascii") getValues := r.URL.Query() if getValues != nil { if v, ok := getValues["start"]; ok { t, err := strconv.Atoi(v[0]) if err == nil { start = int64(t) } } if v, ok := getValues["count"]; ok { t, err := strconv.Atoi(v[0]) if err == nil { count = int64(t) if count > ms.MaxIndexKey { count = ms.MaxIndexKey } } } if v, ok := getValues["key"]; ok { if len(v[0]) > message.Curve25519KeySize*10 { io.WriteString(w, "ERROR: Bad param\n") return } t := utils.B58decode(v[0]) if len(t) != message.Curve25519KeySize { io.WriteString(w, "ERROR: Bad param\n") return } pubKey = new(message.Curve25519Key) copy(pubKey[:], t) if v, ok := getValues["auth"]; ok { if len(v[0]) > keyauth.AnswerSize*10 { io.WriteString(w, "ERROR: Bad param\n") return } auth = utils.B58decode(v[0]) if len(auth) != keyauth.AnswerSize { io.WriteString(w, "ERROR: Bad param\n") return } } } else { io.WriteString(w, "ERROR: Missing param\n") return } } else { io.WriteString(w, "ERROR: Missing param\n") return } if pubKey == nil { io.WriteString(w, "ERROR: Missing param\n") return } if message.KeyIsHidden(pubKey) { if auth == nil { log.Debugs("List:Auth missing\n") io.WriteString(w, "ERROR: Authentication required\n") return } answer := [keyauth.AnswerSize]byte{} copy(answer[:], auth) now := uint64(time.Now().Unix() + ms.TimeSkew) if !keyauth.VerifyTime(&answer, now, ms.TimeGrace) { log.Debugs("List:Auth timeout\n") io.WriteString(w, "ERROR: Authentication failed: Timeout\n") return } privK := [32]byte(*ms.authPrivKey) testK := [32]byte(*pubKey) if !keyauth.Verify(&answer, &privK, &testK) { log.Debugs("List:Auth no verify\n") io.WriteString(w, "ERROR: Authentication failed: No Match\n") return } } messages, found, err := ms.DB.GetIndex(pubKey, start, count) if err != nil && err != fileback.ErrNoMore { log.Debugf("List:GetIndex: %s\n", err) log.Debugf("List:GetIndex: Key %x\n", pubKey) io.WriteString(w, "ERROR: List failed\n") return } io.WriteString(w, "SUCCESS: Data follows\n") for _, msg := range messages { io.WriteString(w, "IDX: "+strings.Trim(string(msg), " \t\n\r")+"\n") } if int64(found) < count { io.WriteString(w, "CMD: Exceeded\n") } else { io.WriteString(w, "CMD: Continue\n") } }