예제 #1
0
func TestRoundWork(t *testing.T) {

	db, err := openDB()

	defer db.Close()

	round_len := time.Minute * 2

	_, err = steward.CurrentRound(db.db)
	if err == nil {
		log.Fatalln("Current round in empty database already exist")
	}

	var i int
	for i = 1; i < 5; i++ {
		new_round, err := steward.NewRound(db.db, round_len)
		if err != nil {
			log.Fatalln("Start new round fail:", err)
		}
		if new_round != i {
			log.Fatalln("New round number invalid", new_round, i)
		}

		current_round, err := steward.CurrentRound(db.db)
		if err != nil {
			log.Fatalln("Get current round fail:", err)
		}
		if current_round.ID != new_round {
			log.Fatalln("Current round number invalid")
		}
		if current_round.Len != round_len {
			log.Fatalln("Current round len invalid")
		}
		if time.Now().Sub(current_round.StartTime) > 5*time.Second {
			log.Fatalln("Time must be ~ current:",
				current_round.StartTime)
		}
	}
}
예제 #2
0
func TestCountRound(*testing.T) {

	db, err := openDB()
	if err != nil {
		log.Fatalln("Open database failed:", err)
	}

	defer db.Close()

	fillTestTeams(db.db)

	fillTestServices(db.db)

	priv, err := vexillary.GenerateKey()
	if err != nil {
		log.Fatalln("Generate key failed:", err)
	}

	round, err := steward.NewRound(db.db, time.Minute)
	if err != nil {
		log.Fatalln("Create new round failed:", err)
	}

	teams, err := steward.GetTeams(db.db)
	if err != nil {
		log.Fatalln("Get teams failed:", err)
	}

	services, err := steward.GetServices(db.db)
	if err != nil {
		log.Fatalln("Get services failed:", err)
	}

	flags := make([]string, 0)

	for _, team := range teams {
		for _, svc := range services {

			flag, err := vexillary.GenerateFlag(priv)
			if err != nil {
				log.Fatalln("Generate flag failed:", err)
			}

			flags = append(flags, flag)

			flg := steward.Flag{ID: -1, Flag: flag, Round: round,
				TeamID: team.ID, ServiceID: svc.ID, Cred: ""}

			err = steward.AddFlag(db.db, flg)
			if err != nil {
				log.Fatalln("Add flag to database failed:", err)
			}

			err = steward.PutStatus(db.db, steward.Status{
				Round: round, TeamID: team.ID,
				ServiceID: svc.ID, State: steward.StatusUP})
			if err != nil {
				log.Fatalln("Put status to database failed:", err)
			}
		}
	}

	flag1, err := steward.GetFlagInfo(db.db, flags[2])
	if err != nil {
		log.Fatalln("Get flag info failed:", err)
	}

	err = steward.CaptureFlag(db.db, flag1.ID, teams[2].ID)
	if err != nil {
		log.Fatalln("Capture flag failed:", err)
	}

	flag2, err := steward.GetFlagInfo(db.db, flags[7])
	if err != nil {
		log.Fatalln("Get flag info failed:", err)
	}

	err = steward.CaptureFlag(db.db, flag2.ID, teams[3].ID)
	if err != nil {
		log.Fatalln("Capture flag failed:", err)
	}

	err = counter.CountRound(db.db, round, teams, services)
	if err != nil {
		log.Fatalln("Count round failed:", err)
	}

	res, err := steward.GetRoundResult(db.db, teams[0].ID, round)
	if err != nil || res.AttackScore != 0.0 || res.DefenceScore != 1.75 {
		log.Fatalln("Invalid result:", res)
	}

	res, err = steward.GetRoundResult(db.db, teams[1].ID, round)
	if err != nil || res.AttackScore != 0.0 || res.DefenceScore != 1.75 {
		log.Fatalln("Invalid result:", res)
	}

	res, err = steward.GetRoundResult(db.db, teams[2].ID, round)
	if err != nil || res.AttackScore != 0.25 || res.DefenceScore != 2.0 {
		log.Fatalln("Invalid result:", res)
	}

	res, err = steward.GetRoundResult(db.db, teams[3].ID, round)
	if err != nil || res.AttackScore != 0.25 || res.DefenceScore != 2.0 {
		log.Fatalln("Invalid result:", res)
	}

}
예제 #3
0
// Round start new round
func (g Game) Round(counters *sync.WaitGroup) (err error) {

	roundNo, err := steward.NewRound(g.db, g.roundLen)
	if err != nil {
		return
	}

	log.Println("New round", roundNo)

	err = checker.PutFlags(g.db, g.priv, roundNo, g.teams, g.services)
	if err != nil {
		return
	}

	round, err := steward.CurrentRound(g.db)
	if err != nil {
		return
	}

	roundEnd := round.StartTime.Add(round.Len)

	for time.Now().Before(roundEnd) {

		log.Println("Round", round.ID, "check start")

		err = checker.CheckFlags(g.db, round.ID, g.teams, g.services)
		if err != nil {
			return
		}

		timeout := RandomizeTimeout(g.timeout, g.timeout/3)

		if time.Now().Add(timeout).After(roundEnd) {
			break
		}

		log.Println("Round", round.ID, "check end, timeout", timeout)

		time.Sleep(timeout)
	}

	log.Println("Check", round.ID, "over, wait", time.Now().Sub(roundEnd))

	for time.Now().Before(roundEnd) {
		time.Sleep(time.Second / 10)
	}

	counters.Add(1)
	go func() {
		defer counters.Done()

		log.Println("Count round", round.ID, "start", time.Now())

		err = counter.CountRound(g.db, round.ID, g.teams, g.services)
		if err != nil {
			log.Println("Count round", round.ID, "failed:", err)
		}

		log.Println("Count round", round.ID, "end", time.Now())
	}()

	return
}
예제 #4
0
func TestFlagsWork(t *testing.T) {

	db, err := openDB()
	if err != nil {
		log.Fatalln("Open database failed:", err)
	}

	defer db.Close()

	min_port_num := 1024
	max_port_num := 65535

	rand.Seed(time.Now().UnixNano())

	port := min_port_num + rand.Intn(max_port_num-min_port_num)

	log.Println("Use port", port)

	service := newDummyService("python-api/dummy_service.py", port)
	service.Stop() // if already run

	priv, err := vexillary.GenerateKey()
	if err != nil {
		log.Fatalln("Generate key failed:", err)
	}

	fillTestTeams(db.db)

	checker_path := "python-api/dummy_checker.py"

	for _, service := range []string{"Foo", "Bar", "Baz"} {

		err = steward.AddService(db.db,
			steward.Service{ID: -1, Name: service, Port: port,
				CheckerPath: checker_path, UDP: false})
		if err != nil {
			log.Fatalln("Add service failed:", err)
		}
	}

	round, err := steward.NewRound(db.db, time.Minute)
	if err != nil {
		log.Fatalln("Create new round failed:", err)
	}

	teams, err := steward.GetTeams(db.db)
	if err != nil {
		log.Fatalln("Get teams failed:", err)
	}

	services, err := steward.GetServices(db.db)
	if err != nil {
		log.Fatalln("Get services failed:", err)
	}

	err = checker.PutFlags(db.db, priv, round, teams, services)
	if err != nil {
		log.Fatalln("Put flags failed:", err)
	}

	// No services -> all down
	checkServicesStatus(db.db, round, teams, services, steward.StatusDown)

	// Start service
	service.Start()

	time.Sleep(time.Second)

	service.BrokeLogic()

	err = checker.PutFlags(db.db, priv, round, teams, services)
	if err != nil {
		log.Fatalln("Put flags failed:", err)
	}

	checkServicesStatus(db.db, round, teams, services, steward.StatusMumble)

	service.RestoreLogic()

	time.Sleep(time.Second)

	round, err = steward.NewRound(db.db, time.Minute)
	if err != nil {
		log.Fatalln("Create new round failed:", err)
	}

	log.Println("Put flags to correct service...")

	err = checker.PutFlags(db.db, priv, round, teams, services)
	if err != nil {
		log.Fatalln("Put flags failed:", err)
	}

	checkServicesStatus(db.db, round, teams, services, steward.StatusUP)

	log.Println("Check flags of correct service...")

	err = checker.CheckFlags(db.db, round, teams, services)
	if err != nil {
		log.Fatalln("Check flags failed:", err)
	}

	checkServicesStatus(db.db, round, teams, services, steward.StatusUP)

	service.ClearFlags()

	log.Println("Check flags of service with removed flags...")

	err = checker.CheckFlags(db.db, round, teams, services)
	if err != nil {
		log.Fatalln("Check flags failed:", err)
	}

	checkServicesStatus(db.db, round, teams, services, steward.StatusCorrupt)

	log.Println("Stop service...")
	service.Stop()

	log.Println("Check flags of stopped service...")

	err = checker.CheckFlags(db.db, round, teams, services)
	if err != nil {
		log.Fatalln("Check flags failed:", err)
	}

	checkServicesStatus(db.db, round, teams, services, steward.StatusDown)
}
예제 #5
0
func TestReceiver(*testing.T) {

	db, err := openDB()
	if err != nil {
		log.Fatalln("Open database failed:", err)
	}

	defer db.Close()

	priv, err := vexillary.GenerateKey()
	if err != nil {
		log.Fatalln("Generate key failed:", err)
	}

	addr := "127.0.0.1:65000"

	flag, err := vexillary.GenerateFlag(priv)
	if err != nil {
		log.Fatalln("Generate flag failed:", err)
	}

	err = steward.AddFlag(db.db, steward.Flag{-1, flag, 1, 8, 1, ""})
	if err != nil {
		log.Fatalln("Add flag failed:", err)
	}

	firstRound, err := steward.NewRound(db.db, time.Minute*2)
	if err != nil {
		log.Fatalln("New round failed:", err)
	}

	attackFlow := make(chan scoreboard.Attack)

	go FlagReceiver(db.db, priv, addr, time.Nanosecond, time.Minute, attackFlow)

	time.Sleep(time.Second) // wait for init listener

	// The attacker must appear to be a team (e.g. jury cannot attack)
	testFlag(addr, flag, invalidTeamMsg)

	t := steward.Team{ID: -1, Name: "TestTeam", Subnet: "127.0.0.1/24",
		Vulnbox: "1"}

	// Correct flag must be captured
	teamID, err := steward.AddTeam(db.db, t)
	if err != nil {
		log.Fatalln("Add team failed:", err)
	}

	serviceID := 1

	// Flag must be captured only if service status ok
	steward.PutStatus(db.db, steward.Status{firstRound, teamID, serviceID,
		steward.StatusUP})

	testFlag(addr, flag, capturedMsg)

	// Correct flag must be captured only one
	testFlag(addr, flag, alreadyCapturedMsg)

	// Incorrect (non-signed or signed on other key) flag must be invalid
	testFlag(addr, "1e7b642f2282886377d1655af6097dd6101eac5b=",
		invalidFlagMsg)

	// Correct flag that does not exist in database must not be captured
	newFlag, err := vexillary.GenerateFlag(priv)
	if err != nil {
		log.Fatalln("Generate flag failed:", err)
	}

	testFlag(addr, newFlag, flagDoesNotExistMsg)

	// Submitted flag does not belongs to the attacking team
	flag4, err := vexillary.GenerateFlag(priv)
	if err != nil {
		log.Fatalln("Generate flag failed:", err)
	}

	err = steward.AddFlag(db.db, steward.Flag{-1, flag4, 1, teamID, 1, ""})
	if err != nil {
		log.Fatalln("Add flag failed:", err)
	}

	testFlag(addr, flag4, flagYoursMsg)

	// Correct flag from another round must not be captured
	flag2, err := vexillary.GenerateFlag(priv)
	if err != nil {
		log.Fatalln("Generate flag failed:", err)
	}

	curRound, err := steward.CurrentRound(db.db)

	err = steward.AddFlag(db.db, steward.Flag{-1, flag2, curRound.ID, 8, 1, ""})
	if err != nil {
		log.Fatalln("Add flag failed:", err)
	}

	_, err = steward.NewRound(db.db, time.Minute*2)
	if err != nil {
		log.Fatalln("New round failed:", err)
	}

	testFlag(addr, flag2, flagExpiredMsg)

	// Correct flag from expired round must not be captured
	roundLen := time.Second
	roundID, err := steward.NewRound(db.db, roundLen)
	if err != nil {
		log.Fatalln("New round failed:", err)
	}

	flag3, err := vexillary.GenerateFlag(priv)
	if err != nil {
		log.Fatalln("Generate flag failed:", err)
	}

	err = steward.AddFlag(db.db, steward.Flag{-1, flag3, roundID, 8, 1, ""})
	if err != nil {
		log.Fatalln("Add flag failed:", err)
	}

	time.Sleep(roundLen) // wait end of round

	testFlag(addr, flag3, flagExpiredMsg)

	// If service status down flag must not be captured
	roundID, err = steward.NewRound(db.db, time.Minute)
	if err != nil {
		log.Fatalln("New round failed:", err)
	}

	flag5, err := vexillary.GenerateFlag(priv)
	if err != nil {
		log.Fatalln("Generate flag failed:", err)
	}

	err = steward.AddFlag(db.db, steward.Flag{-1, flag5, roundID, 8,
		serviceID, ""})
	if err != nil {
		log.Fatalln("Add flag failed:", err)
	}

	steward.PutStatus(db.db, steward.Status{roundID, teamID, serviceID,
		steward.StatusDown})

	testFlag(addr, flag5, serviceNotUpMsg)

	steward.PutStatus(db.db, steward.Status{roundID, teamID, serviceID,
		steward.StatusUP})

	// If attempts limit exceeded flag must not be captured
	newAddr := "127.0.0.1:64000"

	// Start new receiver for test timeouts
	go FlagReceiver(db.db, priv, newAddr, time.Second, time.Minute, attackFlow)

	time.Sleep(time.Second) // wait for init listener

	// Just for take timeout
	testFlag(newAddr, flag3, flagExpiredMsg)

	// Can't use testFlag, if attempts limit exceeded server does not send
	// greeting message, and client has not able to send flag
	conn, err := net.DialTimeout("tcp", newAddr, time.Second)
	if err != nil {
		log.Fatalln("Connect to receiver failed:", err)
	}

	msg, err := bufio.NewReader(conn).ReadString('\n')
	if err != nil {
		log.Fatalln("Invalid response:", err)
	}

	response := attemptsLimitMsg

	if msg != response {
		log.Fatalf("Invalid message [%v] instead [%v]",
			strings.Trim(msg, "\n"),
			strings.Trim(response, "\n"))
	}
}