Example #1
0
func injectDummy() {
	// Populate public keyring
	Pubring = keymgr.NewPubring(
		cfg.Files.Pubring,
		cfg.Files.Mlist2,
	)
	Pubring.ImportPubring()
	dummy()
}
Example #2
0
// Start the server process.  If run with --daemon, this will loop forever.
func loopServer() (err error) {
	// Initialize the Public Keyring
	Pubring = keymgr.NewPubring(
		cfg.Files.Pubring,
		cfg.Files.Mlist2,
	)
	// Fetch keyring and stats URLs
	timedURLFetch(cfg.Urls.Pubring, cfg.Files.Pubring)
	timedURLFetch(cfg.Urls.Mlist2, cfg.Files.Mlist2)
	// Initialize the Secret Keyring
	secret := keymgr.NewSecring(cfg.Files.Secring, cfg.Files.Pubkey)
	Pubring.ImportPubring()
	secret.ImportSecring()
	// Tell the secret keyring some basic info about this remailer
	secret.SetName(cfg.Remailer.Name)
	secret.SetAddress(cfg.Remailer.Address)
	secret.SetExit(cfg.Remailer.Exit)
	secret.SetValidity(cfg.Remailer.Keylife, cfg.Remailer.Keygrace)
	secret.SetVersion(version)
	// Create some dirs if they don't already exist
	createDirs()

	// Open the IDlog
	Trace.Printf("Opening ID Log: %s", cfg.Files.IDlog)
	// NewInstance takes the filename and entry validity in days
	IdDb = idlog.NewIDLog(cfg.Files.IDlog, cfg.Remailer.IDexp)
	defer IdDb.Close()
	// Open the chunk DB
	Trace.Printf("Opening the Chunk DB: %s", cfg.Files.ChunkDB)
	ChunkDb = OpenChunk(cfg.Files.ChunkDB)
	ChunkDb.SetExpire(cfg.Remailer.ChunkExpire)

	// Expire old entries in the ID Log
	idLogExpire()
	// Clean the chunk DB
	chunkClean()
	// Complain about poor configs
	nagOperator()
	// Run a key purge
	if purgeSecring(secret) == 0 {
		// If there are zero active keys, generate a new one.
		generateKeypair(secret)
	} else {
		/*
			If the operator changes his configuration, (such as
			upgrading to a new version or switching from exit to
			middleman), the published key will not match the
			configuration.  This element of code writes a new
			key.txt file with current settings.  This only needs to
			be done if we haven't generated a new key.
		*/
		refreshPubkey(secret)
	}

	Info.Printf("Secret keyring contains %d keys", secret.Count())

	// Define triggers for timed events
	daily := time.Now()
	hourly := time.Now()
	dayOfMonth := time.Now().Day()
	oneDay := time.Duration(dayLength) * time.Second

	// Determine if this is a single run or the start of a Daemon
	runAsDaemon := cfg.Remailer.Daemon || flag_daemon

	// Actually start the server loop
	if runAsDaemon {
		Info.Printf("Starting YAMN server: %s", cfg.Remailer.Name)
		Info.Printf("Detaching Pool processing")
		go serverPoolOutboundSend()
	} else {
		Info.Printf("Performing routine remailer functions for: %s",
			cfg.Remailer.Name)
	}
	for {
		// Panic if the pooldir doesn't exist
		assertIsPath(cfg.Files.Pooldir)
		// Process the inbound Pool
		processInpool("i", secret)
		// Process the Maildir
		processMail(secret)

		// Midnight events
		if time.Now().Day() != dayOfMonth {
			Info.Println("Performing midnight events")
			// Remove expired keys from memory and rewrite a
			// secring file without expired keys.
			if purgeSecring(secret) == 0 {
				generateKeypair(secret)
			}
			// Expire entries in the ID Log
			idLogExpire()
			// Expire entries in the chunker
			chunkClean()
			// Report daily throughput and reset to zeros
			stats.report()
			stats.reset()
			// Reset dayOfMonth to today
			dayOfMonth = time.Now().Day()
		}
		// Daily events
		if time.Since(daily) > oneDay {
			Info.Println("Performing daily events")
			// Complain about poor configs
			nagOperator()
			// Reset today so we don't do these tasks for the next
			// 24 hours.
			daily = time.Now()
		}
		// Hourly events
		if time.Since(hourly) > time.Hour {
			Trace.Println("Performing hourly events")
			/*
				The following two conditions try to import new
				pubring and mlist2 URLs.  If they fail, a
				warning is logged but no further action is
				taken.  It's better to have old keys/stats than
				none.
			*/
			// Retrieve Mlist2 and Pubring URLs
			if cfg.Urls.Fetch {
				timedURLFetch(
					cfg.Urls.Pubring,
					cfg.Files.Pubring,
				)
				timedURLFetch(
					cfg.Urls.Mlist2,
					cfg.Files.Mlist2,
				)
			}
			// Test to see if the pubring.mix file has been updated
			if Pubring.KeyRefresh() {
				Trace.Printf(
					"Reimporting Public Keyring: %s",
					cfg.Files.Pubring,
				)
				Pubring.ImportPubring()
			}
			// Report throughput
			stats.report()
			hourly = time.Now()
		}

		// Break out of the loop if we're not running as a daemon
		if !runAsDaemon {
			break
		}

		// And rest a while
		time.Sleep(60 * time.Second)
	} // End of server loop
	return
}
Example #3
0
// mixprep fetches the plaintext and prepares it for mix encoding
func mixprep() {
	var err error
	err = os.MkdirAll(cfg.Files.Pooldir, 0700)
	if err != nil {
		panic(err)
	}
	// plain will contain the byte version of the plain text message
	var plain []byte
	// final is consistent across multiple copies so we define it early
	final := newSlotFinal()
	if len(flag_args) == 0 {
		//fmt.Println("Enter message, complete with headers.  Ctrl-D to finish")
		plain, err = ioutil.ReadAll(os.Stdin)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
	} else if len(flag_args) == 1 {
		// A single arg should be the filename
		plain = readMessage(flag_args[0])
	} else if len(flag_args) >= 2 {
		// Two args should be recipient and filename
		flag_to = flag_args[0]
		plain = readMessage(flag_args[1])
	}
	// plainLen is the length of the plain byte message and can exceed
	// the total body size of the payload.
	plainLen := len(plain)
	if plainLen == 0 {
		fmt.Fprintln(os.Stderr, "No bytes in message")
		os.Exit(1)
	}

	// Download stats URLs if the time is right
	if cfg.Urls.Fetch {
		// Retrieve Mlist2 and Pubring URLs
		timedURLFetch(cfg.Urls.Pubring, cfg.Files.Pubring)
		timedURLFetch(cfg.Urls.Mlist2, cfg.Files.Mlist2)
	}

	// Create the Public Keyring
	Pubring = keymgr.NewPubring(
		cfg.Files.Pubring,
		cfg.Files.Mlist2,
	)
	// Set the Use Expired flag to include remailers with expired keys as
	// candidates.
	if cfg.Stats.UseExpired {
		Pubring.UseExpired()
	}
	err = Pubring.ImportPubring()
	if err != nil {
		Warn.Printf("Pubring import failed: %s", cfg.Files.Pubring)
		return
	}
	// Read the chain from flag or config
	var in_chain []string
	if flag_chain == "" {
		in_chain = strings.Split(cfg.Stats.Chain, ",")
	} else {
		in_chain = strings.Split(flag_chain, ",")
	}
	if len(in_chain) == 0 {
		err = errors.New("Empty input chain")
		return
	}
	var cnum int // Chunk number
	var numc int // Number of chunks
	numc = int(math.Ceil(float64(plainLen) / float64(maxFragLength)))
	final.setNumChunks(numc)
	var exitnode string // Address of exit node (for multiple copy chains)
	var got_exit bool   // Flag to indicate an exit node has been selected
	var first_byte int  // First byte of message slice
	var last_byte int   // Last byte of message slice
	// Fragments loop begins here
	for cnum = 1; cnum <= numc; cnum++ {
		final.setChunkNum(cnum)
		// First byte of message fragment
		first_byte = (cnum - 1) * maxFragLength
		last_byte = first_byte + maxFragLength
		// Don't slice beyond the end of the message
		if last_byte > plainLen {
			last_byte = plainLen
		}
		got_exit = false
		// If no copies flag is specified, use the config file NUMCOPIES
		if flag_copies == 0 {
			flag_copies = cfg.Stats.Numcopies
		}
		if flag_copies > maxCopies {
			// Limit copies to a maximum of 10
			flag_copies = maxCopies
		}
		// Copies loop begins here
		for n := 0; n < flag_copies; n++ {
			if got_exit {
				// Set the last node in the chain to the
				// previously select exitnode
				in_chain[len(in_chain)-1] = exitnode
			}
			var chain []string
			chain, err = makeChain(in_chain)
			if err != nil {
				Error.Println(err)
				os.Exit(0)
			}
			if len(chain) != len(in_chain) {
				err = fmt.Errorf(
					"Chain length mismatch.  In=%d, Out=%d",
					len(in_chain), len(chain))
				panic(err)
			}
			//fmt.Println(chain)
			if !got_exit {
				exitnode = chain[len(chain)-1]
				got_exit = true
			}
			// Retain the entry hop.  We need to mail the message to it.
			sendTo := chain[0]
			// Report the chain if we're running as a client.
			if flag_client {
				fmt.Printf("Chain: %s\n", strings.Join(chain, ","))
			}
			yamnMsg := encodeMsg(
				plain[first_byte:last_byte],
				chain,
				*final,
			)
			writeMessageToPool(sendTo, yamnMsg)
		} // End of copies loop
	} // End of fragments loop

	// Decide if we want to inject a dummy
	if !flag_nodummy && Pubring.HaveStats() && dice() < 80 {
		dummy()
	}
}