// 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) }
// 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" }
// CmdDecrypt implements decryption functions func CmdDecrypt() int { var inData, decMessage []byte var err error var meta *message.MetaDataRecieve var privkeystr string var nullKey message.Curve25519Key if OptionsVar.Server == "" { getPeers(false) } if OptionsVar.Stmdir != "" && !isDir(OptionsVar.Stmdir) { log.Fatalf("stmdir does not exist or is no directory: %s\n", OptionsVar.Stmdir) return 1 } // Read input data maxInData := int64(GlobalConfigVar.BodyLength+message.KeyHeaderSize+message.SignHeaderSize) * 4 // Read data from stdin or file if len(flag.Args()) == 0 { inData, err = inputData(OptionsVar.Infile, maxInData) if err != nil { log.Fatalf("No input data: %s\n", err) return 1 } } else { // read data from server (Get). CMDLine is [server/]messageid[_privatekey] var messageidcl []byte var server string server, messageidcl, privkeystr = cmdlineURLparse(flag.Args()...) if server == "" { server = OptionsVar.Server } proto := repproto.New(OptionsVar.Socksserver, OptionsVar.Server, GlobalConfigVar.PasteServers...) if server == "" { server, inData, err = proto.Get(messageidcl) } else { inData, err = proto.GetSpecific(server, messageidcl) } if err != nil { log.Fatalf("Fetch error: %s\n", err) return 1 } log.Dataf("STATUS (FetchServer):\t%s\n", server) } if len(inData) < (message.KeyHeaderSize+message.SignHeaderSize)*4 { log.Fatals("No input data.\n") return 1 } // Set up receiver parameters receiver := message.Receiver{ HashCashBits: GlobalConfigVar.MinHashCash, } if OptionsVar.Senderkey != "" { receiver.SenderPublicKey, _ = utils.ParseKeyPair(OptionsVar.Senderkey) } // Select private key to use if OptionsVar.Keymgt < 0 { if privkeystr == "" { // might have been set from commandline privkeystr = selectPrivKey(OptionsVar.Privkey, GlobalConfigVar.PrivateKey, "tty") } // Parse privkey if privkeystr != "" { receiver.ReceiveConstantPrivateKey, receiver.ReceiveTemporaryPrivateKey = utils.ParseKeyPair(privkeystr) } } else { // Register callback, OptionsVar.keymgt == fd keyMgtFile, callback := KeyCallBack(OptionsVar.Keymgt) defer keyMgtFile.Close() receiver.KeyCallBack = callback } log.Datas("STATUS (Process):\tREAD\n") // Decrypt decMessage, meta, err = receiver.Decrypt(inData) if err != nil { log.Fatalf("%s\n", err) return 1 } log.Dataf("STATUS (MessageID):\t%s\n", utils.B58encode(meta.MessageID[:])) log.Dataf("STATUS (RecPubKey):\t%s\n", utils.B58encode(meta.ReceiveConstantPublicKey[:])) log.Dataf("STATUS (SenderPubKey):\t%s\n", utils.B58encode(meta.SenderConstantPublicKey[:])) // Get replyKeys embedConstant, embedTemporary := utils.DecodeEmbedded(decMessage[:message.Curve25519KeySize*2]) if *embedConstant != nullKey { log.Dataf("STATUS (EmbedPublicKey):\t%s_%s\n", utils.B58encode(embedConstant[:]), utils.B58encode(embedTemporary[:])) } // If messageType list: print list to DATA if meta.MessageType == message.MsgTypeList { log.Datas("STATUS (Process):\tLIST\n") err := utils.VerifyListContent(decMessage[message.Curve25519KeySize*2:]) if err != nil { log.Fatalf("%s\n", err) return 1 } lines := bytes.Split(decMessage[message.Curve25519KeySize*2:], []byte("\n")) for _, l := range lines { log.Dataf("STATUS (ListItem):\t%s\n", string(l)) } return 0 } decMessage = decMessage[message.Curve25519KeySize*2:] // meta.MessageType if meta.MessageType == message.MsgTypeRepost { log.Datas("STATUS (Process):\tREPOST\n") // If messageType repost: get padkey,mindelay,maxdelay. Repad padkey, minDelay, maxDelay := utils.DecodeRepostHeader(decMessage[:utils.RepostHeaderSize]) timePoint := utils.STM(int(minDelay), int(maxDelay)) log.Dataf("STATUS (STM):\t%d %d %d\n", minDelay, maxDelay, timePoint) repostMsgt := message.RePad(decMessage[utils.RepostHeaderSize:], padkey, GlobalConfigVar.BodyLength) signHeader := new([message.SignHeaderSize]byte) copy(signHeader[:], repostMsgt[:message.SignHeaderSize]) details, err := message.VerifySignature(*signHeader, GlobalConfigVar.MinHashCash) if err != nil { log.Fatalf("%s\n", err) return 1 } msgIDMsg := message.CalcMessageID(repostMsgt) if *msgIDMsg != details.MsgID { log.Fatals("MessageID conflict\n") return 1 } log.Dataf("STATUS (MessageIDSig):\t%s\n", utils.B58encode(details.MsgID[:])) log.Dataf("STATUS (PubKeySig):\t%s\n", utils.B58encode(details.PublicKey[:])) log.Dataf("STATUS (NonceSig):\t%x\n", details.HashCashNonce[:]) log.Dataf("STATUS (BitsSig):\t%d\n", details.HashCashBits) decMessage = message.EncodeBase64(repostMsgt) if OptionsVar.Stmdir != "" { // Exist/Dir test done early filename := fmt.Sprintf("%s%s%d.%s", OptionsVar.Stmdir, string(os.PathSeparator), timePoint, utils.B58encode(msgIDMsg[:])) log.Dataf("STATUS (STMFile):\t%s\n", filename) err := utils.WriteNewFile(filename, decMessage) if err != nil { log.Fatalf("%s\n", err) return 1 } return 0 } } err = outputData(OptionsVar.Outfile, decMessage) if err != nil { log.Fatalf("Output failed: %s\n", err) return 1 } return 0 }