Esempio n. 1
0
// Encode an expireStruct
func (es ExpireStruct) Encode() ExpireStructEncoded {
	out := make([]byte, 0, ExpireStructSize)
	out = append(out, []byte(strconv.FormatUint(es.ExpireTime, 10)+" ")...)
	out = append(out, []byte(utils.B58encode(es.MessageID[:])+" ")...)
	out = append(out, []byte(utils.B58encode(es.SignerPubKey[:])+" ")...)
	return out[:len(out)]
}
Esempio n. 2
0
// ServeID returns server information.
func (ms MessageServer) ServeID(w http.ResponseWriter, r *http.Request) {
	ms.RandomSleep()
	now := CurrentTime() + ms.TimeSkew
	privK := [32]byte(*ms.authPrivKey)
	_, pubkey, challenge := keyauth.GenTempKeyTime(uint64(now), &privK)
	info := &ServerInfo{
		Time:            now,
		AuthPubKey:      utils.B58encode(pubkey[:]),
		AuthChallenge:   utils.B58encode(challenge[:]),
		MaxPostSize:     int64(messagestore.MaxMessageSize),
		MinPostSize:     ms.InfoStruct.MinPostSize,
		MinHashCashBits: ms.InfoStruct.MinHashCashBits,
	}
	if ms.EnablePeerHandler {
		info.Peers = ms.getPeerURLs()
	}
	ms.RandomSleep()
	w.Header().Set("Content-Type", "text/json")
	b, err := json.Marshal(info)
	if err != nil {
		log.Debugf("Info: %s\n", err)
	}
	w.Write(b)
	w.Write([]byte("\n"))
	return
}
Esempio n. 3
0
// ExpireFromIndex reads the expire index and expires messages as they are recorded
func (store Store) ExpireFromIndex() {
	// ExpireRun
	delMessages, err := store.db.SelectMessageExpire(CurrentTime())
	if err != nil {
		log.Errorf("ExpireFromIndex, SelectMessageExpire: %s\n", err)
		return
	}
	for _, msg := range delMessages {
		err := store.db.DeleteBlob(&msg.MessageID)
		if err != nil {
			log.Errorf("ExpireFromIndex, DeleteBlob: %s %s\n", err, utils.B58encode(msg.MessageID[:]))
			continue
		}
		err = store.db.DeleteMessageByID(&msg.MessageID)
		if err != nil {
			log.Errorf("ExpireFromIndex, DeleteMessageByID: %s %s\n", err, utils.B58encode(msg.MessageID[:]))
		}
	}
	_, _, err = store.db.ExpireSigners(MaxAgeSigners)
	if err != nil {
		log.Errorf("ExpireFromIndex, ExpireSigners: %s\n", err)
	}
	err = store.db.ExpireMessageCounter(MaxAgeRecipients)
	if err != nil {
		log.Errorf("ExpireFromIndex, ExpireMessageCounter: %s\n", err)
	}
	err = store.db.ForgetMessages(CurrentTime() - MaxAgeRecipients)
	if err != nil {
		log.Errorf("ExpireFromIndex, ForgetMessages: %s\n", err)
	}
}
Esempio n. 4
0
// New returns a MessageServer.
func New(driver, url, path string, pubKey, privKey []byte) (*MessageServer, error) {
	var err error
	ms := new(MessageServer)
	ms.DB = messagestore.New(driver, url, path, Workers)
	if err != nil {
		return nil, err
	}
	ms.path = path
	ms.PeerFile = path + "peers.config"
	ms.AddToPeer = DefaultAddToPeer
	ms.MaxTimeSkew = DefaultMaxTimeSkew
	ms.MinPostSize = MinPostSize
	ms.MaxPostSize = MaxPostSize
	ms.MinHashCashBits = MinHashCashBits
	ms.MaxSleep = DefaultMaxSleep
	ms.MaxIndexGlobal = DefaultIndexGlobal
	ms.MaxIndexKey = DefaultIndexKey
	ms.TimeGrace = DefaultTimeGrace
	ms.MaxAuthTokenAge = DefaultAuthTokenAge
	ms.NotifyDuration = DefaultNotifyDuration
	ms.FetchDuration = DefaultFetchDuration
	ms.FetchMax = DefaultFetchMax
	ms.ExpireDuration = DefaultExpireDuration
	ms.ExpireFSDuration = DefaultExpireFSDuration
	ms.StepLimit = DefaultStepLimit
	ms.ListenPort = DefaultListenPort
	ms.MinStoreTime = DefaultMinStoreTime
	ms.MaxStoreTime = DefaultMaxStoreTime
	ms.MaxAgeSigners = DefaultMaxAgeSigners
	ms.MaxAgeRecipients = DefaultMaxAgeRecipients
	messagestore.MaxAgeRecipients = DefaultMaxAgeRecipients
	messagestore.MaxAgeSigners = DefaultMaxAgeSigners
	ms.EnablePeerHandler = true

	ms.authPrivKey, err = message.GenLongTermKey(true, false)
	if err != nil {
		return nil, err
	}
	ms.AuthPubKey = message.GenPubKey(ms.authPrivKey)
	if pubKey != nil && privKey != nil {
		ms.TokenPubKey = new([ed25519.PublicKeySize]byte)
		ms.TokenPrivKey = new([ed25519.PrivateKeySize]byte)
		copy(ms.TokenPubKey[:], pubKey)
		copy(ms.TokenPrivKey[:], privKey)
	} else {
		ms.TokenPubKey, ms.TokenPrivKey, err = ed25519.GenerateKey(rand.Reader)
		log.Printf("Peer authentication public key: %s\n", utils.B58encode(ms.TokenPubKey[:]))
		log.Printf("Peer authentication private key: %s\n", utils.B58encode(ms.TokenPrivKey[:]))
		if err != nil {
			return nil, err
		}
	}
	ms.InfoStruct = new(ServerInfo)
	ms.InfoStruct.MinHashCashBits = ms.MinHashCashBits
	ms.InfoStruct.MinPostSize = ms.MinPostSize
	ms.InfoStruct.MaxPostSize = ms.MaxPostSize
	ms.InfoStruct.AuthPubKey = utils.B58encode(ms.AuthPubKey[:])
	return ms, nil
}
Esempio n. 5
0
// 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
}
Esempio n. 6
0
// showConfig shows current (default) config
func showConfig() {
	if defaultSettings.PeeringPrivateKey == "" {
		pubkey, privkey, err := ed25519.GenerateKey(rand.Reader)
		if err == nil {
			defaultSettings.PeeringPrivateKey = utils.B58encode(privkey[:])
			defaultSettings.PeeringPublicKey = utils.B58encode(pubkey[:])
		}
	}
	config, _ := json.MarshalIndent(defaultSettings, "", "    ")
	fmt.Println(string(config))
}
Esempio n. 7
0
// Encode a SignerStruct to human readable representation
func (ss SignerStruct) Encode() SignerStructEncoded {
	out := make([]byte, 0, SignerStructSize)
	out = append(out, []byte(utils.B58encode(ss.PublicKey[:])+" ")...)
	out = append(out, []byte(utils.B58encode(ss.Nonce[:])+" ")...)
	out = append(out, []byte(strconv.FormatUint(uint64(ss.Bits), 10)+" ")...)
	out = append(out, []byte(strconv.FormatUint(ss.MessagesPosted, 10)+" ")...)
	out = append(out, []byte(strconv.FormatUint(ss.MessagesRetained, 10)+" ")...)
	out = append(out, []byte(strconv.FormatUint(ss.MaxMessagesPosted, 10)+" ")...)
	out = append(out, []byte(strconv.FormatUint(ss.MaxMessagesRetained, 10)+" ")...)
	out = append(out, []byte(strconv.FormatUint(ss.ExpireTarget, 10)+" ")...)
	return out[:len(out)]
}
Esempio n. 8
0
// CmdGenKey generates a long-term public key
func CmdGenKey() int {
	privkey, err := message.GenLongTermKey(OptionsVar.Hidden, OptionsVar.Sync)
	if err != nil {
		log.Errorf("Key generation error:%s\n", err)
		return 1
	}
	pubkey := message.GenPubKey(privkey)
	log.Dataf("STATUS (PrivateKey):\t%s\n", utils.B58encode(privkey[:]))
	// log.Dataf("STATUS (PublicKey):\t%s\n", utils.B58encode(pubkey[:]))
	log.Printf("PRIVATE key: %s\n\n", utils.B58encode(privkey[:]))
	// log.Printf("Public key: %s\n", utils.B58encode(pubkey[:]))
	_ = pubkey
	return 0
}
Esempio n. 9
0
// Encode encodes a MessageStruct in human-readable format for storage
func (ms MessageStruct) Encode() MessageStructEncoded {
	out := make([]byte, 0, MessageStructSize)
	out = append(out, []byte(strconv.FormatUint(ms.Counter, 10)+" ")...)
	out = append(out, []byte(strconv.FormatUint(ms.PostTime, 10)+" ")...)
	out = append(out, []byte(strconv.FormatUint(ms.ExpireTime, 10)+" ")...)
	out = append(out, []byte(strconv.FormatUint(ms.ExpireRequest, 10)+" ")...)
	out = append(out, []byte(utils.B58encode(ms.MessageID[:])+" ")...)
	out = append(out, []byte(utils.B58encode(ms.ReceiverConstantPubKey[:])+" ")...)
	out = append(out, []byte(utils.B58encode(ms.SignerPub[:])+" ")...)
	out = append(out, []byte(strconv.FormatUint(ms.Distance, 10)+" ")...)
	out = append(out, []byte(BoolToString(ms.OneTime)+" ")...)
	out = append(out, []byte(BoolToString(ms.Sync)+" ")...)
	out = append(out, []byte(BoolToString(ms.Hidden))...)
	return out[:len(out)]
}
Esempio n. 10
0
// KeyCallBack implements a callback function to request keys from file-descriptor
func KeyCallBack(keyMgtFd int) (*os.File, func(*message.Curve25519Key) *message.Curve25519Key) {
	knownKeys := make(map[message.Curve25519Key]message.Curve25519Key)
	fd := os.NewFile(uintptr(keyMgtFd), "fd/"+strconv.Itoa(keyMgtFd))
	return fd, func(pubkey *message.Curve25519Key) *message.Curve25519Key {
		// KeyCallBack func(*Curve25519Key) *Curve25519Key
		log.Sync()
		if v, ok := knownKeys[*pubkey]; ok { // Return from cache if we can
			return &v
		}
		b := make([]byte, 120)
		log.Dataf("STATUS (KeyMGTRequest):\t%s\n", utils.B58encode(pubkey[:]))
		log.Sync()
		n, _ := fd.Read(b)
		if n == 0 {
			log.Datas("STATUS (KeyMGT):\tREAD FAILURE\n")
			return nil
		}
		log.Datas("STATUS (KeyMGT):\tREAD DONE\n")
		k1, k2 := utils.ParseKeyPair(strings.Trim(string(b[:n]), " \t\r\n"))
		if k1 != nil {
			pub1 := message.GenPubKey(k1) // Add to cache
			knownKeys[*pub1] = *k1
		}
		if k2 != nil {
			pub2 := message.GenPubKey(k2) // Add to cache
			knownKeys[*pub2] = *k2
		}
		if v, ok := knownKeys[*pubkey]; ok { // Return from cache if we can
			return &v
		}
		return nil
	}
}
Esempio n. 11
0
// GetPeerStat returns the last entry of peer statistics for pubkey
func (store Store) GetPeerStat(pubkey *[ed25519.PublicKeySize]byte) *structs.PeerStruct {
	st, err := store.db.SelectPeer(pubkey)
	if err != nil {
		log.Errorf("GetPeerStat: %s, %s\n", err, utils.B58encode(pubkey[:]))
		return nil
	}
	return st
}
Esempio n. 12
0
// GetSpecificAuth fetches a message from a specific server using authentication
func (proto *Proto) GetSpecificAuth(server, auth string, messageID []byte) ([]byte, error) {
	messageIDenc := utils.B58encode(messageID)
	body, err := socks.Proxy(proto.SocksServer).LimitGet(constructURL(server, "/fetch", "?messageid=", messageIDenc, "&auth=", auth), 512000)
	if err != nil {
		return nil, err
	}
	return parseError(body)
}
Esempio n. 13
0
// Encode peerstruct into human readable form
func (ps PeerStruct) Encode() PeerStructEncoded {
	out := make([]byte, 0, PeerStructSize)
	out = append(out, []byte(utils.B58encode(ps.AuthToken[:])+" ")...)
	out = append(out, []byte(strconv.FormatUint(ps.LastNotifySend, 10)+" ")...)
	out = append(out, []byte(strconv.FormatUint(ps.LastNotifyFrom, 10)+" ")...)
	out = append(out, []byte(strconv.FormatUint(ps.LastFetch, 10)+" ")...)
	out = append(out, []byte(strconv.FormatUint(ps.ErrorCount, 10)+" ")...)
	out = append(out, []byte(strconv.FormatUint(ps.LastPosition, 10)+" ")...)
	return out[:len(out)]
}
Esempio n. 14
0
// GetGlobalIndex returns the global index.
func (ms MessageServer) GetGlobalIndex(w http.ResponseWriter, r *http.Request) {
	var pubKey *message.Curve25519Key
	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.MaxIndexGlobal {
					count = ms.MaxIndexGlobal
				}
			}
		}
		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
		}
	} else {
		io.WriteString(w, "ERROR: Missing param\n")
		return
	}
	messages, found, err := ms.DB.GetGlobalIndex(start, count)
	if err != nil && err != ErrNoMore {
		log.Debugf("List:GetIndex: %s\n", err)
		log.Debugf("List:GetIndex: Key %s\n", utils.B58encode(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")
	}
}
Esempio n. 15
0
// 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
}
Esempio n. 16
0
// 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.Debugf("Fetch OK: %s\n", utils.B58encode(messageID[:]))
	if ms.Stat {
		stat.Input <- stat.Fetch
	}
	return
}
Esempio n. 17
0
// 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
}
Esempio n. 18
0
func (ms MessageServer) notifyPeer(PubKey *[ed25519.PublicKeySize]byte, url string) {
	rand.Seed(time.Now().UnixNano())
	maxSleep := ms.NotifyDuration - int64(timeout)
	if maxSleep > 0 {
		sleeptime := rand.Int63() % maxSleep
		time.Sleep(time.Duration(sleeptime) * time.Second)
	}
	now := time.Now().Unix() + ms.TimeSkew
	token := utils.B58encode(keyproof.SignProofToken(now, PubKey, ms.TokenPubKey, ms.TokenPrivKey)[:])
	// Socks call
	proto := repproto.New(ms.SocksProxy, "")
	err := proto.Notify(url, token)
	// Write result
	if err != nil {
		log.Debugf("Notify error: %s\n", err)
		ms.DB.UpdatePeerNotification(PubKey, true)
	} else {
		ms.DB.UpdatePeerNotification(PubKey, false)
	}
}
Esempio n. 19
0
// 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: %s, asshole.\n", utils.B58encode(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
}
Esempio n. 20
0
// 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)
}
Esempio n. 21
0
// fetchPeer downloads new messages from peer.
func (ms MessageServer) fetchPeer(PubKey *[ed25519.PublicKeySize]byte, url string) {
	// Get token, lastpos from database
	var doUpdate bool
	log.Debugf("fetch from peer: %s\n", url)
	peerStat := ms.DB.GetPeerStat(PubKey)
	if peerStat == nil { // Errors are ignored
		log.Debugf("fetch from peer: not found %s\n", url)
		return
	}
	if peerStat.LastNotifyFrom == 0 { // We never heard from him
		log.Debugf("fetch from peer: no notification %s\n", url)
		return
	}
	startDate := CurrentTime()
	// Check that LastNotifyFrom > LastFetch
	if ms.HubOnly {
		// Pre-Emptive fetch in hub-mode: every 4 times FetchDuration or when notified
		if peerStat.LastFetch != 0 && !(peerStat.LastFetch < peerStat.LastNotifyFrom || peerStat.LastFetch < uint64(startDate-(ms.FetchDuration*4))) {
			log.Debugf("fetch from peer: no fetch-force and no notifications since last fetch %s\n", url)
			log.Debugf("LastFetch: %s  LastNotifyFrom: %s\n", format(peerStat.LastFetch), format(peerStat.LastNotifyFrom))
			return // nothing new to gain
		}
	} else {
		if peerStat.LastFetch > peerStat.LastNotifyFrom && peerStat.LastFetch != 0 {
			log.Debugf("fetch from peer: no notifications since last fetch %s\n", url)
			log.Debugf("LastFetch: %s  LastNotifyFrom: %s\n", format(peerStat.LastFetch), format(peerStat.LastNotifyFrom))
			return // nothing new to gain
		}
	}
	rand.Seed(time.Now().UnixNano())
	maxSleep := ms.NotifyDuration - int64(timeout)
	if maxSleep > 0 {
		sleeptime := rand.Int63() % maxSleep
		log.Debugf("fetch from peer: sleeping %d %s\n", sleeptime, url)
		time.Sleep(time.Duration(sleeptime) * time.Second)
	}
	doUpdate = true
FetchLoop:
	for {
		// Make GetIndex call
		proto := repproto.New(ms.SocksProxy, "")
		nextPosition := int(peerStat.LastPosition)
		if nextPosition != 0 {
			nextPosition++
		}
		log.Debugf("GlobalIndex fetch: %s next: %d max: %d\n", url, nextPosition, ms.FetchMax)
		authtoken := utils.B58encode(peerStat.AuthToken[:])
		messages, more, err := proto.GetGlobalIndex(url, authtoken, nextPosition, int(ms.FetchMax))
		if err != nil {
			peerStat.ErrorCount++
			log.Debugf("GlobalIndex err: %s\n", err)
			// Only hit on proxy errors
			errstr := err.Error()
			if len(errstr) >= 6 && errstr[0:6] == "proxy:" {
				doUpdate = false
			}
			break FetchLoop
		}
		for _, msg := range messages {
			log.Debugf("Index: %d  Message: %s\n", msg.Counter, utils.B58encode(msg.MessageID[:]))
		}
	MessageLoop:
		for _, msg := range messages {
			log.Debugf("Fetching.  %d  %s\n", msg.Counter, utils.B58encode(msg.MessageID[:]))
			if startDate+ms.FetchDuration <= CurrentTime() { // We worked for long enough
				log.Debugf("FetchDuration timeout\n")
				break MessageLoop
			}
			// Check if message exists
			if ms.DB.MessageExists(msg.MessageID) {
				peerStat.LastPosition = msg.Counter
				log.Debugf("fetch from peer: exists %s %s\n", utils.B58encode(msg.MessageID[:]), url)
				continue MessageLoop // Message exists.
			}
			// Add message
			err := ms.FetchPost(url, authtoken, msg.MessageID, msg.ExpireTime)
			if err == nil || err == messagestore.ErrDuplicate {
				// Reduce fetch.ErrorCount when downloads are successful
				log.Debugf("fetch from peer: exists now %s %s\n", utils.B58encode(msg.MessageID[:]), url)
				if peerStat.ErrorCount >= 2 {
					peerStat.ErrorCount -= 2
				}
			} else if err != nil {
				peerStat.ErrorCount++
				log.Debugf("Fetch err: %s %s\n", url, err)
				doUpdate = false
				// LastPosition will only advance if future downloads work
				continue MessageLoop
			}
			log.Debugf("fetch from peer: added %s %s\n", utils.B58encode(msg.MessageID[:]), url)
			peerStat.LastPosition = msg.Counter
			ms.notifyChan <- true
		}
		if !more { // No more messages
			log.Debugf("Sync done. No More.\n")
			break FetchLoop
		}
		if startDate+ms.FetchDuration <= CurrentTime() { // We worked for long enough
			log.Debugf("Sync done. FetchDuration timeout.\n")
			break FetchLoop
		}
	}
	// Write peer update
	log.Debugf("fetch from peer: cycle done %s\n", url)
	if doUpdate {
		ms.DB.UpdatePeerFetchStat(PubKey, uint64(CurrentTime()), peerStat.LastPosition, peerStat.ErrorCount)
	} else {
		ms.DB.UpdatePeerFetchStat(PubKey, peerStat.LastFetch, peerStat.LastPosition, peerStat.ErrorCount)
	}
}
Esempio n. 22
0
// UpdatePeerFetchStat writes fetch-specific data
func (store Store) UpdatePeerFetchStat(pubkey *[ed25519.PublicKeySize]byte, lastFetch, lastPos, lastErrors uint64) {
	err := store.db.UpdatePeerStats(pubkey, lastFetch, lastPos, lastErrors)
	if err != nil {
		log.Errorf("UpdatePeerStats: %s, %s\n", err, utils.B58encode(pubkey[:]))
	}
}
Esempio n. 23
0
// UpdatePeerNotification updates the peer stat after notification send
func (store Store) UpdatePeerNotification(pubkey *[ed25519.PublicKeySize]byte, hasError bool) {
	err := store.db.UpdatePeerNotification(pubkey, hasError)
	if err != nil {
		log.Errorf("UpdatePeerNotification: %s, %s\n", err, utils.B58encode(pubkey[:]))
	}
}
Esempio n. 24
0
// 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
}
Esempio n. 25
0
// UpdatePeerAuthToken updates the peer record when a new auth token has been received
func (store Store) UpdatePeerAuthToken(senderPubKey *[ed25519.PublicKeySize]byte, signedToken *[keyproof.ProofTokenSignedSize]byte) {
	err := store.db.UpdatePeerToken(senderPubKey, signedToken)
	if err != nil {
		log.Errorf("UpdatePeerAuthToken: %s, %s\n", err, utils.B58encode(senderPubKey[:]))
	}
}
Esempio n. 26
0
// 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: %s\n", utils.B58encode(MessageID[:]))
	if ms.Stat {
		stat.Input <- stat.Post
	}
	return "SUCCESS: Connection close\n"
}
Esempio n. 27
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
}
Esempio n. 28
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
}
Esempio n. 29
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(CurrentTime() + 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 != ErrNoMore {
		log.Debugf("List:GetIndex: %s\n", err)
		log.Debugf("List:GetIndex: Key %s\n", utils.B58encode(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")
	}
}
Esempio n. 30
0
// 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
}