Exemple #1
0
// CmdPost posts a message
func CmdPost() int {
	var inData []byte
	var err error
	if OptionsVar.Server == "" {
		log.Fatal("Server must be specified: --server")
		return 1
	}

	maxInData := int64(GlobalConfigVar.BodyLength-(message.Curve25519KeySize*2)) * 5
	inData, err = inputData(OptionsVar.Infile, maxInData)
	if err != nil {
		log.Fatalf("No input data: %s\n", err)
		return 1
	}
	log.Datas("STATUS (Process):\tPOST\n")
	proto := repproto.New(OptionsVar.Socksserver, OptionsVar.Server)
	err = proto.PostSpecific(OptionsVar.Server, inData)
	if err != nil {
		log.Fatalf("Output failed: %s\n", err)
		log.Datas("STATUS (Result):\tFAIL\n")
	} else {
		log.Datas("STATUS (Result):\tDONE\n")
	}

	log.Sync()
	return 0
}
Exemple #2
0
func loadStoreMessage(server string, messageID []byte, outfile string) error {
	proto := repproto.New(OptionsVar.Socksserver, server)
	log.Dataf("STATUS (Process):\tFETCH\n")
	inData, err := proto.GetSpecific(server, messageID)
	if err != nil {
		log.Dataf("STATUS (Process):\tFAIL\n")
		log.Fatalf("Fetch error: %s\n", err)
		return err
	}
	err = outputData(outfile, inData)
	if err != nil {
		log.Dataf("STATUS (Process):\tFAIL\n")
		log.Fatalf("Output failed: %s\n", err)
		return err
	}
	return nil
}
Exemple #3
0
// CmdPeerList fetches the peerlist and returns a new configfile
func CmdPeerList() int {
	err := getPeers(true)
	if err != nil {
		log.Fatalf("Peer discovery failed: %s\n", err)
		return 1
	}
	return CmdShowConfig()
}
Exemple #4
0
// CmdSTM does an STM run to specific server and from specific stmdir
func CmdSTM() int {
	if OptionsVar.Server == "" {
		log.Fatal("Server must be specified: --server\n")
		return 1
	}
	if OptionsVar.Stmdir == "" {
		log.Fatal("Missing parameter: --stmdir\n")
		return 1
	}
	if !isDir(OptionsVar.Stmdir) {
		log.Fatalf("stmdir does not exist or is no directory: %s\n", OptionsVar.Stmdir)
		return 1
	}
	err := listSTM(OptionsVar.Stmdir) // Todo: Test if dir exists
	if err != nil {
		log.Errorf("STM Process errors: %s\n", err)
		return 1
	}
	return 0
}
Exemple #5
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
}
Exemple #6
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
}
Exemple #7
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
}
Exemple #8
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
}