// This is just for testing func main() { var pubKey, privKey []byte pubKey, privKey = nil, nil if defaultSettings.StoragePath == "" { fmt.Println("Error: Storage path not configured") os.Exit(1) } if defaultSettings.PeeringPublicKey != "" && defaultSettings.PeeringPrivateKey != "" { pubKey = utils.B58decode(defaultSettings.PeeringPublicKey) privKey = utils.B58decode(defaultSettings.PeeringPrivateKey) } runtime.GOMAXPROCS(runtime.NumCPU() - 1) ms, err := handlers.New(defaultSettings.StoragePath, pubKey, privKey) if err != nil { fmt.Printf("Error: %s\n", err) os.Exit(1) } applyConfig(ms) ms.Stat = *stat if *start { ms.RunServer() } else { fmt.Println("Server not started. Enable with --start") os.Exit(1) } os.Exit(0) }
func TestIDSpecific(t *testing.T) { var privKey, pubKey message.Curve25519Key var pk []byte //pk = utils.B58decode("i2BNvH9h85NWDxDZj2VpF8nuvUpSQy57ud3hrzo3gxM") pk = utils.B58decode("ATWZibbLy5CFE5atp98hxFRAvFcjN7kNn16WtP43tnJ6") pk = utils.B58decode("FpYAGsxrpmgh8CUJkFEnz1CCY9ZUhbVxtTekfkFyWxdQ") copy(privKey[:], pk[:]) pubKey = *message.GenPubKey(&privKey) // long test with local server if testing.Short() { t.Skip("test skipped in -short run") } proto := New("", "http://127.0.0.1:8080") info, err := proto.Auth("http://127.0.0.1:8080", privKey[:]) if err != nil { t.Fatalf("ID: %s", err) } _ = info msgs, more, err := proto.ListSpecific("http://127.0.0.1:8080", pubKey[:], privKey[:], 0, 10) if err != nil { t.Fatalf("ListSpecific: %s", err) } // fmt.Printf("%+v\n", msgs) _, _ = msgs, more }
// SignerStructDecode decodes an encoded signerstruct func SignerStructDecode(d SignerStructEncoded) *SignerStruct { if len(d) < SignerStructMin { return nil } fields := bytes.Fields(d) if len(fields) != 8 { return nil } cur := 0 ss := new(SignerStruct) t := utils.B58decode(string(fields[cur])) copy(ss.PublicKey[:], t) cur++ t = utils.B58decode(string(fields[cur])) copy(ss.Nonce[:], t) cur++ tb, _ := strconv.ParseUint(string(fields[cur]), 10, 64) ss.Bits = byte(tb) cur++ ss.MessagesPosted, _ = strconv.ParseUint(string(fields[cur]), 10, 64) cur++ ss.MessagesRetained, _ = strconv.ParseUint(string(fields[cur]), 10, 64) cur++ ss.MaxMessagesPosted, _ = strconv.ParseUint(string(fields[cur]), 10, 64) cur++ ss.MaxMessagesRetained, _ = strconv.ParseUint(string(fields[cur]), 10, 64) cur++ ss.ExpireTarget, _ = strconv.ParseUint(string(fields[cur]), 10, 64) return ss }
// ExpireStructDecode decodes an encoded ExpireStruct func ExpireStructDecode(d ExpireStructEncoded) *ExpireStruct { if len(d) < ExpireStructMin { return nil } fields := bytes.Fields(d) if len(fields) < 3 { return nil } cur := 0 es := new(ExpireStruct) es.ExpireTime, _ = strconv.ParseUint(string(fields[cur]), 10, 64) cur++ t := utils.B58decode(string(fields[cur])) copy(es.MessageID[:], t) cur++ t = utils.B58decode(string(fields[cur])) copy(es.SignerPubKey[:], t) return es }
// GetNotify receives notifications. func (ms MessageServer) GetNotify(w http.ResponseWriter, r *http.Request) { var proof [keyproof.ProofTokenSize]byte w.Header().Set("Content-Type", "text/plain; charset=us-ascii") getValues := r.URL.Query() if getValues != nil { if v, ok := getValues["auth"]; ok { if len(v[0]) > keyproof.ProofTokenMax { io.WriteString(w, "ERROR: Bad Param\n") return } auth := utils.B58decode(v[0]) if auth == nil || len(auth) > keyproof.ProofTokenSize { io.WriteString(w, "ERROR: Bad Param\n") return } copy(proof[:], auth) ok, timeStamp, senderPubKey := keyproof.VerifyProofToken(&proof, ms.TokenPubKey) if !ok { io.WriteString(w, "ERROR: Authentication failure\n") if senderPubKey == nil { log.Errorf("VerifyProofToken failed: (proof) %s\n", utils.B58encode(proof[:])) } else { log.Errorf("VerifyProofToken failed: (pubkey) %s\n", utils.B58encode(senderPubKey[:])) } return } // verify that we know the peer url := ms.PeerURL(senderPubKey) if url == "" { io.WriteString(w, "ERROR: Bad peer\n") log.Errorf("Notify, bad peer: %s\n", utils.B58encode(senderPubKey[:])) return } now := CurrentTime() // Test too old, too young if enforceTimeOuts && (now > timeStamp+DefaultAuthTokenAge+ms.MaxTimeSkew || now < timeStamp-DefaultAuthTokenAge-ms.MaxTimeSkew) { io.WriteString(w, "ERROR: Authentication expired\n") log.Errorf("VerifyProofToken replay by %s\n", url) return } ok, signedToken := keyproof.CounterSignToken(&proof, ms.TokenPubKey, ms.TokenPrivKey) if !ok { io.WriteString(w, "ERROR: Authentication failure\n") return } ms.DB.UpdatePeerAuthToken(senderPubKey, signedToken) log.Debugf("Notified by %s\n", url) io.WriteString(w, "SUCCESS: Notified\n") return } } io.WriteString(w, "ERROR: Missing Param\n") return }
// Delete implements the delete call for messages. func (ms MessageServer) Delete(w http.ResponseWriter, r *http.Request) { var messageID *[message.MessageIDSize]byte var privateKey *message.Curve25519Key for i := 0; i < 4; i++ { ms.RandomSleep() // Let's not give instant gratification here } w.Header().Set("Content-Type", "text/plain; charset=us-ascii") getValues := r.URL.Query() if getValues != nil { if v, ok := getValues["messageid"]; ok { t := utils.B58decode(v[0]) if len(t) < message.MessageIDSize || len(t) > message.MessageIDSize { io.WriteString(w, "ERROR: Bad parameter\n") return } messageID = new([message.MessageIDSize]byte) copy(messageID[:], t) } if v, ok := getValues["privkey"]; ok { t := utils.B58decode(v[0]) if len(t) < message.Curve25519KeySize || len(t) > message.Curve25519KeySize { io.WriteString(w, "ERROR: Bad parameter\n") return } privateKey = new(message.Curve25519Key) copy(privateKey[:], t) } if privateKey != nil && messageID != nil { publicKey := message.GenPubKey(privateKey) err := ms.DB.PreExpire(messageID, publicKey) if err == nil { log.Errorf("Message censored: %x, asshole.\n", *messageID) io.WriteString(w, "SUCCESS: If you want to call it that\n") return } log.Errorf("Message censoring failed! %s\n", err) } } io.WriteString(w, "ERROR: Missing parameters\n") return }
// cmdlineURLparse parses the commandline into server, messageID and key func cmdlineURLparse(args ...string) (string, []byte, string) { // server,messageID,key = server/messageID_key | server/messageID | messageID_key | messageID key | messageID var server, messageID, key string if len(args) == 2 { // messageid key return "", utils.B58decode(args[0]), args[1] } fsplit := strings.SplitN(args[0], "_", 2) if len(fsplit) == 2 { // last is key key = fsplit[1] } ssep := strings.LastIndex(fsplit[0], "/") if ssep == -1 { // No server data contained messageID = fsplit[0] } else { messageID = fsplit[0][ssep+1:] // last part is messageID server = fsplit[0][:ssep] // first part is server } return server, utils.B58decode(messageID), key }
// Auth creates an authentication for server and privKey func (proto *Proto) Auth(server string, privKey []byte) (string, error) { var challenge [keyauth.ChallengeSize]byte var secret [keyauth.PrivateKeySize]byte info, err := proto.ID(server) if err != nil { return "", err } challengeS := utils.B58decode(info.AuthChallenge) copy(challenge[:], challengeS) copy(secret[:], privKey[:]) answer := keyauth.Answer(&challenge, &secret) return utils.B58encode(answer[:]), nil }
// LoadPeers from file. func (ms MessageServer) LoadPeers() { var prePeerlist PeerListEncoded var myPeerURLs []string myPeers := make(PeerList) peersEncoded, err := ioutil.ReadFile(ms.PeerFile) if err != nil { example := make(PeerListEncoded, 1) example[0].PubKey = "Example ed25519 public key encoded in base58" example[0].URL = exampleURL dat, _ := json.MarshalIndent(example, "", " ") _ = dat err := ioutil.WriteFile(ms.PeerFile, dat, 0600) if err != nil { log.Errorf("Could not write peerfile: %s\n", err) return } log.Debugs("Example peerfile written\n") return } err = json.Unmarshal(peersEncoded, &prePeerlist) if err != nil { log.Errorf("Could not read peerfile: %s\n", err) return } if ms.AddToPeer && !ms.HubOnly { myPeerURLs = append(myPeerURLs, ms.URL) } for _, p := range prePeerlist { if p.URL != exampleURL { var tkey [ed25519.PublicKeySize]byte t := utils.B58decode(p.PubKey) copy(tkey[:], t) if *ms.TokenPubKey != tkey || debug { myPeers[tkey] = Peer{ URL: p.URL, PubKey: tkey, } if !p.IsHub { myPeerURLs = append(myPeerURLs, p.URL) } // Create Peer Index File ms.DB.TouchPeer(&tkey) } } } defer ms.setPeerURLs(myPeerURLs) systemPeersMutex.Lock() defer systemPeersMutex.Unlock() systemPeers = myPeers log.Debugs("Peers loaded\n") }
// Fetch returns a single message. func (ms MessageServer) Fetch(w http.ResponseWriter, r *http.Request) { var messageID *[message.MessageIDSize]byte w.Header().Set("Content-Type", "text/plain; charset=us-ascii") getValues := r.URL.Query() if getValues != nil { if v, ok := getValues["messageid"]; ok { t := utils.B58decode(v[0]) if len(t) < message.MessageIDSize || len(t) > message.MessageIDSize { io.WriteString(w, "ERROR: Bad parameter\n") return } messageID = new([message.MessageIDSize]byte) copy(messageID[:], t) } if ms.HubOnly { if v, ok := getValues["auth"]; ok { err := ms.AuthenticatePeer(v[0]) if err != nil { io.WriteString(w, fmt.Sprintf("Error: %s", err)) return } } else { io.WriteString(w, "ERROR: Missing param\n") return } } } if messageID == nil { io.WriteString(w, "ERROR: Missing parameter\n") return } data, err := ms.DB.Fetch(messageID) if err != nil { log.Debugf("Fetch: %s\n", err) io.WriteString(w, "ERROR: No data") return } io.WriteString(w, "SUCCESS: Data follows\n") _, err = w.Write(data) if err != nil { log.Debugf("Write: %s\n", err) return } log.Debugs("Fetch OK\n") if ms.Stat { stat.Input <- stat.Fetch } return }
// MessageStructDecode decodes bytes to MessageStruct func MessageStructDecode(d MessageStructEncoded) *MessageStruct { fields := bytes.Fields(d) l := len(fields) if l < 10 || l > 11 || len(d) < MessageStructMin { // with or without counter return nil } cur := 0 ms := new(MessageStruct) if l == 11 { // with counter\ ms.Counter, _ = strconv.ParseUint(string(fields[0]), 10, 64) cur++ } ms.PostTime, _ = strconv.ParseUint(string(fields[cur]), 10, 64) cur++ ms.ExpireTime, _ = strconv.ParseUint(string(fields[cur]), 10, 64) cur++ ms.ExpireRequest, _ = strconv.ParseUint(string(fields[cur]), 10, 64) cur++ t := utils.B58decode(string(fields[cur])) copy(ms.MessageID[:], t) cur++ t = utils.B58decode(string(fields[cur])) copy(ms.ReceiverConstantPubKey[:], t) cur++ t = utils.B58decode(string(fields[cur])) copy(ms.SignerPub[:], t) cur++ ms.Distance, _ = strconv.ParseUint(string(fields[cur]), 10, 64) cur++ ms.OneTime = StringToBool(string(fields[cur])) cur++ ms.Sync = StringToBool(string(fields[cur])) cur++ ms.Hidden = StringToBool(string(fields[cur])) return ms }
// FetchListStructDecode decodes human readable to struct func FetchListStructDecode(d FetchListStructEncoded) *FetchListStruct { if len(d) < FetchListStructMin { return nil } fields := bytes.Fields(d) if len(fields) != 2 { return nil } fs := new(FetchListStruct) cur := 0 t := utils.B58decode(string(fields[cur])) copy(fs.MessageID[:], t) cur++ fs.TimeEntered, _ = strconv.ParseUint(string(fields[cur]), 10, 64) return fs }
// CmdGenTempKey generates a temporary key for a given private key func CmdGenTempKey() int { var privkey message.Curve25519Key privkeystr := selectPrivKey(OptionsVar.Privkey, GlobalConfigVar.PrivateKey, "tty") if privkeystr == "" { log.Fatal("No private key given (-privkey)") return 1 } copy(privkey[:], utils.B58decode(privkeystr)) pubkey := message.GenPubKey(&privkey) privkeytemp, err := message.GenRandomKey() if err != nil { log.Errorf("Key generation error:%s\n", err) return 1 } pubkeytemp := message.GenPubKey(privkeytemp) log.Dataf("STATUS (PrivateKey):\t%s_%s\n", utils.B58encode(privkey[:]), utils.B58encode(privkeytemp[:])) log.Dataf("STATUS (PublicKey):\t%s_%s\n", utils.B58encode(pubkey[:]), utils.B58encode(pubkeytemp[:])) log.Printf("PRIVATE key: %s_%s\n\n", utils.B58encode(privkey[:]), utils.B58encode(privkeytemp[:])) log.Printf("Public key: %s_%s\n", utils.B58encode(pubkey[:]), utils.B58encode(pubkeytemp[:])) return 0 }
// AuthenticatePeer verifies an existing authStr and matches it to the known peers. func (ms MessageServer) AuthenticatePeer(authStr string) error { var counterSig [keyproof.ProofTokenSignedSize]byte var auth []byte if len(authStr) > keyproof.ProofTokenSignedMax { return fmt.Errorf("Bad param") } auth = utils.B58decode(authStr) if len(auth) > keyproof.ProofTokenSignedSize { return fmt.Errorf("Bad param") } copy(counterSig[:], auth) ok, timestamp := keyproof.VerifyCounterSig(&counterSig, ms.TokenPubKey) if !ok { log.Debugs("List:Auth no verify\n") return fmt.Errorf("Authentication failed: No match") } now := CurrentTime() if enforceTimeOuts && (timestamp < now-ms.MaxAuthTokenAge-ms.MaxTimeSkew || timestamp > now+ms.MaxAuthTokenAge+ms.MaxTimeSkew) { return fmt.Errorf("Authentication failed: Timeout") } return nil }
// PeerStructDecode decodes an encoded peer struct func PeerStructDecode(d PeerStructEncoded) *PeerStruct { if len(d) < PeerStructMin { return nil } fields := bytes.Fields(d) if len(fields) != 6 { return nil } ps := new(PeerStruct) cur := 0 t := utils.B58decode(string(fields[cur])) copy(ps.AuthToken[:], t) cur++ ps.LastNotifySend, _ = strconv.ParseUint(string(fields[cur]), 10, 64) cur++ ps.LastNotifyFrom, _ = strconv.ParseUint(string(fields[cur]), 10, 64) cur++ ps.LastFetch, _ = strconv.ParseUint(string(fields[cur]), 10, 64) cur++ ps.ErrorCount, _ = strconv.ParseUint(string(fields[cur]), 10, 64) cur++ ps.LastPosition, _ = strconv.ParseUint(string(fields[cur]), 10, 64) return ps }
// CmdEncrypt encrypts data. func CmdEncrypt() int { var privkey, embedConstantPrivKey, embedTemporaryPrivKey, embedConstantPubKey, embedTemporaryPubKey *message.Curve25519Key var err error var inData, encMessage []byte var meta *message.MetaDataSend var signKeyPair *message.SignKeyPair var removeFile string if OptionsVar.Server == "" { getPeers(false) } // OptionsVar.anonymous . disable private key and signkey if OptionsVar.Anonymous { OptionsVar.Signkey = "" OptionsVar.Privkey = "" GlobalConfigVar.PrivateKey = "" } mindelay := uint32(OptionsVar.Mindelay) maxdelay := uint32(OptionsVar.Maxdelay) // Read input data maxInData := int64(GlobalConfigVar.BodyLength - (message.Curve25519KeySize * 2) - innerHeader) //maxInData := int64(MsgSizeLimit) if OptionsVar.Repost { maxInData -= utils.RepostHeaderSize - message.KeyHeaderSize - message.SignHeaderSize } log.Debugf("Size limit: %d\n", maxInData) inData, err = inputData(OptionsVar.Infile, maxInData) if err != nil { log.Fatalf("No input data: %s\n", err) return 1 } // Verify list contents if OptionsVar.MessageType == message.MsgTypeList { err := utils.VerifyListContent(inData) if err != nil { log.Errorf("Could not verify list input: %s\n", err) return 1 } } // Select private key to use privkeystr := selectPrivKey(OptionsVar.Privkey, GlobalConfigVar.PrivateKey, "") // Parse privkey if privkeystr != "" { privkey = new(message.Curve25519Key) copy(privkey[:], utils.B58decode(privkeystr)) } // Generate embedded keypairs if OptionsVar.Embedkey { if OptionsVar.Notrace || privkey == nil { embedConstantPrivKey, err = message.GenLongTermKey(OptionsVar.Hidden, OptionsVar.Sync) if err != nil { log.Errorf("Key generation error:%s\n", err) return 1 } } else { embedConstantPrivKey = privkey } embedConstantPubKey = message.GenPubKey(embedConstantPrivKey) embedTemporaryPrivKey, err = message.GenRandomKey() if err != nil { log.Errorf("Key generation error:%s\n", err) return 1 } embedTemporaryPubKey = message.GenPubKey(embedTemporaryPrivKey) } embedded := utils.EncodeEmbedded(embedConstantPubKey, embedTemporaryPubKey) recipientConstantPubKey, recipientTemporaryPubKey := utils.ParseKeyPair(OptionsVar.Recipientkey) // Find a signature keypair if we can signKeyDir := "" if GlobalConfigVar.KeyDir != "" { signKeyDir = GlobalConfigVar.KeyDir } if OptionsVar.Signdir != "" { signKeyDir = OptionsVar.Signdir } if OptionsVar.Signkey != "" { var d []byte d, err = utils.MaxReadFile(2048, OptionsVar.Signkey) if err == nil { signKeyPair = new(message.SignKeyPair) kp, err := signKeyPair.Unmarshal(d) if err != nil { log.Errorf("Sign keypair decode error: %s\n", err) signKeyPair = nil } else { signKeyPair = kp } } else { log.Errorf("Sign keypair read error: %s\n", err) } } if signKeyPair == nil && signKeyDir != "" { var d []byte d, removeFile, err = utils.ReadRandomFile(signKeyDir, 2048) if err == nil { signKeyPair = new(message.SignKeyPair) kp, err := signKeyPair.Unmarshal(d) if err != nil { log.Errorf("Sign keypair decode error: %s\n", err) signKeyPair = nil removeFile = "" } else { signKeyPair = kp } } else { log.Errorf("Sign keypair read error: %s\n", err) } } // Set up sender parameters sender := message.Sender{ Signer: signKeyPair, SenderPrivateKey: privkey, ReceiveConstantPublicKey: recipientConstantPubKey, ReceiveTemporaryPublicKey: recipientTemporaryPubKey, TotalLength: GlobalConfigVar.BodyLength, PadToLength: GlobalConfigVar.PadToLength, HashCashBits: GlobalConfigVar.MinHashCash, } // We want encryption output in realtime log.Sync() inData = append(embedded, inData...) if OptionsVar.Repost { // Generate a repost-message encMessage, meta, err = sender.EncryptRepost(byte(OptionsVar.MessageType), inData) if err == nil { rph := utils.EncodeRepostHeader(meta.PadKey, mindelay, maxdelay) encMessage = append(rph[:], encMessage...) log.Datas("STATUS (Process):\tPREPOST\n") log.Dataf("STATUS (RepostSettings):\t%d %d\n", mindelay, maxdelay) } } else { // Generate a normal message encMessage, meta, err = sender.Encrypt(byte(OptionsVar.MessageType), inData) if err == nil { log.Datas("STATUS (Process):\tPOST\n") } } if err != nil { log.Fatalf("Encryption failed: %s\n", err) return 1 } log.Sync() // Output. repost is only written to stdout or file if OptionsVar.Outfile == "-" || (OptionsVar.Repost && OptionsVar.Outfile == "") { err = utils.WriteStdout(encMessage) // Display data as necessary if err == nil { log.Dataf("STATUS (RecPubKey):\t%s\n", utils.B58encode(meta.ReceiverConstantPubKey[:])) if OptionsVar.Embedkey { log.Dataf("STATUS (EmbedPublicKey):\t%s_%s\n", utils.B58encode(embedConstantPubKey[:]), utils.B58encode(embedTemporaryPubKey[:])) log.Dataf("STATUS (EmbedPrivateKey):\t%s_%s\n", utils.B58encode(embedConstantPrivKey[:]), utils.B58encode(embedTemporaryPrivKey[:])) } if meta.MessageKey != nil { log.Dataf("STATUS (ListInput):\tNULL %s %s\n", utils.B58encode(meta.MessageID[:]), utils.B58encode(meta.MessageKey[:])) log.Dataf("STATUS (Message):\t%s_%s\n", utils.B58encode(meta.MessageID[:]), utils.B58encode(meta.MessageKey[:])) } else { log.Dataf("STATUS (ListInput):\tNULL %s NULL\n", utils.B58encode(meta.MessageID[:])) log.Dataf("STATUS (MessageID):\t%s\n", utils.B58encode(meta.MessageID[:])) } } } else if OptionsVar.Outfile != "" || OptionsVar.Repost { err = utils.WriteNewFile(OptionsVar.Outfile, encMessage) // Display data as necessary log.Dataf("STATUS (RecPubKey):\t%s\n", utils.B58encode(meta.ReceiverConstantPubKey[:])) if err == nil { if OptionsVar.Embedkey { log.Dataf("STATUS (EmbedPublicKey):\t%s_%s\n", utils.B58encode(embedConstantPubKey[:]), utils.B58encode(embedTemporaryPubKey[:])) log.Dataf("STATUS (EmbedPrivateKey):\t%s_%s\n", utils.B58encode(embedConstantPrivKey[:]), utils.B58encode(embedTemporaryPrivKey[:])) } if meta.MessageKey != nil { log.Dataf("STATUS (ListInput):\tNULL %s %s\n", utils.B58encode(meta.MessageID[:]), utils.B58encode(meta.MessageKey[:])) log.Dataf("STATUS (Message):\t%s_%s\n", utils.B58encode(meta.MessageID[:]), utils.B58encode(meta.MessageKey[:])) log.Printf("Pastebin Address:\t%s_%s\n", utils.B58encode(meta.MessageID[:]), utils.B58encode(meta.MessageKey[:])) } else { log.Dataf("STATUS (ListInput):\tNULL %s NULL\n", utils.B58encode(meta.MessageID[:])) log.Dataf("STATUS (MessageID):\t%s\n", utils.B58encode(meta.MessageID[:])) log.Printf("Pastebin Address:\t%s\n", utils.B58encode(meta.MessageID[:])) } } } else { // Post to server server := OptionsVar.Server proto := repproto.New(OptionsVar.Socksserver, OptionsVar.Server, GlobalConfigVar.PasteServers...) if server == "" { server, err = proto.Post(meta.MessageID[:], encMessage) } else { err = proto.PostSpecific(server, encMessage) } sep := "/" if server != "" && server[len(server)-1] == '/' { sep = "" } if err == nil { if meta.MessageKey != nil { log.Dataf("STATUS (URL):\t%s/%s_%s\n", server, utils.B58encode(meta.MessageID[:]), utils.B58encode(meta.MessageKey[:])) } if OptionsVar.Embedkey { log.Dataf("STATUS (EmbedPublicKey):\t%s_%s\n", utils.B58encode(embedConstantPubKey[:]), utils.B58encode(embedTemporaryPubKey[:])) log.Dataf("STATUS (EmbedPrivateKey):\t%s_%s\n", utils.B58encode(embedConstantPrivKey[:]), utils.B58encode(embedTemporaryPrivKey[:])) } if meta.MessageKey != nil { log.Dataf("STATUS (ListInput):\t%s %s %s\n", server, utils.B58encode(meta.MessageID[:]), utils.B58encode(meta.MessageKey[:])) log.Dataf("STATUS (Message):\t%s_%s\n", utils.B58encode(meta.MessageID[:]), utils.B58encode(meta.MessageKey[:])) log.Printf("Pastebin Address:\t%s%s%s_%s\n", server, sep, utils.B58encode(meta.MessageID[:]), utils.B58encode(meta.MessageKey[:])) } else { log.Dataf("STATUS (ListInput):\t%s %s NULL\n", server, utils.B58encode(meta.MessageID[:])) log.Dataf("STATUS (MessageID):\t%s\n", utils.B58encode(meta.MessageID[:])) log.Printf("Pastebin Address:\t%s%s%s\n", server, sep, utils.B58encode(meta.MessageID[:])) } } } if err != nil { log.Fatalf("Output failed: %s\n", err) log.Sync() return 1 } if removeFile != "" { // Operation has been successful, remove signer keyfile (if any) os.Remove(removeFile) } return 0 }
// CmdIndex returns the index for a private key func CmdIndex() int { var server string var err error var pubkey *message.Curve25519Key var privkey message.Curve25519Key var messages []*structs.MessageStruct var moreMessages bool if OptionsVar.Server == "" { // getPeers(false). Meaningless for index calls log.Fatal("--index requires --server to be specified.\n") return 1 } server = OptionsVar.Server if OptionsVar.Outdir != "" && !isDir(OptionsVar.Outdir) { log.Fatalf("outdir does not exist or is no directory: %s", OptionsVar.Outdir) return 1 } // privkey must be set privkeystr := selectPrivKey(OptionsVar.Privkey, GlobalConfigVar.PrivateKey, "tty") if privkeystr == "" { log.Fatal("Private key missing: --privkey\n") return 1 } // Test if long key is given, if yes, use only first part if pos := strings.Index(privkeystr, "_"); pos > 0 { privkeystr = privkeystr[:pos] } privT := utils.B58decode(privkeystr) copy(privkey[:], privT) pubkey = message.CalcPub(&privkey) proto := repproto.New(OptionsVar.Socksserver, OptionsVar.Server) // If we want to change to using the server list instead. Not a great idea // proto := repproto.New(OptionsVar.Socksserver, OptionsVar.Server, GlobalConfigVar.PasteServers...) // re-enable if we want to use the server list: server, messages, moreMessages, err = proto.List(pubkey[:], privkey[:], OptionsVar.Start, OptionsVar.Count) log.Dataf("STATUS (Process):\tLIST\n") messages, moreMessages, err = proto.ListSpecific(server, pubkey[:], privkey[:], OptionsVar.Start, OptionsVar.Count) if err != nil { log.Fatalf("List error: %s\n", err) return 1 } if len(messages) > 0 { fmt.Print("Index\t\tMessageID\n") fmt.Print("------------------------------------------------------------\n") } for _, msg := range messages { log.Dataf("STATUS (MessageList):\t%d %s %s %d %d\n", msg.Counter, utils.B58encode(msg.MessageID[:]), utils.B58encode(msg.SignerPub[:]), msg.PostTime, msg.ExpireTime) fmt.Printf("%d\t\t%s\n", msg.Counter, utils.B58encode(msg.MessageID[:])) } log.Dataf("STATUS (ListResult):\t%d %d %t\n", OptionsVar.Start, OptionsVar.Count, moreMessages) if len(messages) > 0 { fmt.Print("------------------------------------------------------------\n") } if moreMessages { fmt.Print("More messages may be available\n") } else { fmt.Print("Listing complete\n") } if OptionsVar.Outdir != "" { log.Dataf("STATUS (Process):\tFETCHMANY\n") fmt.Print("Fetching messages...") hasErrors := 0 for _, msg := range messages { log.Dataf("STATUS (Fetch):\t%s\n", utils.B58encode(msg.MessageID[:])) err = loadStoreMessage(server, msg.MessageID[:], OptionsVar.Outdir+string(os.PathSeparator)+utils.B58encode(msg.MessageID[:])) // use index server for download, store with name messageID if err != nil { fmt.Print(".F") hasErrors++ log.Dataf("STATUS (FetchError):\t%s\n", utils.B58encode(msg.MessageID[:])) } else { fmt.Print(".o") log.Dataf("STATUS (FetchComplete):\t%s\n", utils.B58encode(msg.MessageID[:])) } } if hasErrors > 0 { fmt.Print(". Some errors during download.\n") log.Dataf("STATUS (FetchResult):\tERROS %d\n", hasErrors) } else { fmt.Print(". Download complete.\n") log.Dataf("STATUS (FetchResult):\tOK\n") } } log.Sync() // server can be set return 0 }
// CmdIndex returns the index for a private key func CmdIndex() int { var server string var err error var pubkey *message.Curve25519Key var privkey message.Curve25519Key var messages []*structs.MessageStruct var moreMessages bool if OptionsVar.Server == "" { getPeers(false) } if OptionsVar.Outdir != "" && !isDir(OptionsVar.Outdir) { log.Fatalf("outdir does not exist or is no directory: %s", OptionsVar.Outdir) return 1 } // privkey must be set privkeystr := selectPrivKey(OptionsVar.Privkey, GlobalConfigVar.PrivateKey, "tty") if privkeystr == "" { log.Fatal("Private key missing: --privkey\n") return 1 } privT := utils.B58decode(privkeystr) copy(privkey[:], privT) pubkey = message.CalcPub(&privkey) if OptionsVar.Server != "" { server = OptionsVar.Server } proto := repproto.New(OptionsVar.Socksserver, OptionsVar.Server) log.Dataf("STATUS (Process):\tLIST\n") if server != "" { fmt.Println("Specific server") messages, moreMessages, err = proto.ListSpecific(server, pubkey[:], privkey[:], OptionsVar.Start, OptionsVar.Count) } else { fmt.Println("Any server") server, messages, moreMessages, err = proto.List(pubkey[:], privkey[:], OptionsVar.Start, OptionsVar.Count) } if err != nil { log.Fatalf("List error: %s\n", err) return 1 } if len(messages) > 0 { fmt.Print("Index\t\tMessageID\n") fmt.Print("------------------------------------------------------------\n") } for _, msg := range messages { log.Dataf("STATUS (MessageList):\t%d %s %s %d %d\n", msg.Counter, utils.B58encode(msg.MessageID[:]), utils.B58encode(msg.SignerPub[:]), msg.PostTime, msg.ExpireTime) fmt.Printf("%d\t\t%s\n", msg.Counter, utils.B58encode(msg.MessageID[:])) } log.Dataf("STATUS (ListResult):\t%d %d %t\n", OptionsVar.Start, OptionsVar.Count, moreMessages) if len(messages) > 0 { fmt.Print("------------------------------------------------------------\n") } if moreMessages { fmt.Print("More messages may be available\n") } else { fmt.Print("Listing complete\n") } if OptionsVar.Outdir != "" { log.Dataf("STATUS (Process):\tFETCHMANY\n") fmt.Print("Fetching messages...") hasErrors := 0 for _, msg := range messages { log.Dataf("STATUS (Fetch):\t%s\n", utils.B58encode(msg.MessageID[:])) err = loadStoreMessage(server, msg.MessageID[:], OptionsVar.Outdir+string(os.PathSeparator)+utils.B58encode(msg.MessageID[:])) // use index server for download, store with name messageID if err != nil { fmt.Print(".F") hasErrors++ log.Dataf("STATUS (FetchError):\t%s\n", utils.B58encode(msg.MessageID[:])) } else { fmt.Print(".o") log.Dataf("STATUS (FetchComplete):\t%s\n", utils.B58encode(msg.MessageID[:])) } } if hasErrors > 0 { fmt.Print(". Some errors during download.\n") log.Dataf("STATUS (FetchResult):\tERROS %d\n", hasErrors) } else { fmt.Print(". Download complete.\n") log.Dataf("STATUS (FetchResult):\tOK\n") } } log.Sync() // server can be set return 0 }
// 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") } }