/* Remove a host from the template list, give the reason as r and decrement nA. If r is the empty string, no message will be printed. */ func removeHost(ts *tslist.List, a attempt, r string, nA *lockedint.TInt) { /* Tell the user what's going on */ if r != "" { log.Printf("[%v] Removing %v from attack queue: %v", a.Tasknum, a.Host, r) } /* Mark a bunch of hosts for removal */ for e := ts.Head(); e != nil; e = e.Next() { if c, ok := e.Value().(*template); !ok { printTemplateNotOk(e) os.Exit(-10) } else if ok && c.Host == a.Host { e.RemoveMark() } } /* Remove the marked hosts */ ts.RemoveMarked() /* Decrement the number of attempts in the wild */ nA.Dec() }
/* channelAttemptMaker reads passwords from passwordc and sends attempts out on attemptc based on the templates in templates. When passwordc is closed (i.e. all its passwords have been read), attemptc will be closed and the attempt maker will terminate. The attempts will have a version string of version. */ func channelAttemptMaker(templates *tslist.List, passwordc chan string, version string, attemptc chan attempt) { defer close(attemptc) for { select { case p, ok := <-passwordc: if !ok { return } /* New attempt for each combination. */ for e := templates.Head(); nil != e; e = e.Next() { a, ok := e.Value().(*template) if !ok { printTemplateNotOk(e) os.Exit(-14) } attemptc <- a.New(p, version) } } } }
func broker(internalc, filec, stdinc chan attempt, ntask int, sf *os.File, tries, onepw, errdb bool, wait, pause time.Duration, ts *tslist.List, skip int) { /* Channels for communication with spawned tasks */ failc := make(chan attempt) successc := make(chan attempt) retryc := make(chan attempt) /* Number of sshtasks running */ nRunning := lockedint.New() /* Number of attempts in play */ nAttempts := lockedint.New() /* Number of attempts made so far */ totalTasks := 0 /* Closure (yuck) to die when we're out of attempts and all channels are closed */ doneNote := false dieIfDone := func() { /* Don't execute if something's still going on */ if stdinc == nil && internalc == nil && filec == nil { if 0 == nRunning.Val() { log.Printf("All done.") os.Exit(0) } else if !doneNote { log.Printf("Giving %v tasks time to "+ "finish. This shouldn't take much "+ "more than %v.", nRunning.Val(), wait) doneNote = true } } } /* startTask starts an sshtask against a. */ startTask := func(a attempt) { if !(totalTasks <= skip) { go sshTask(a, nRunning, failc, successc, totalTasks, tries, wait, pause) nRunning.Inc() } totalTasks++ /* TODO: Fix wait */ } /* Closures (yuck) to handle channel inputs */ successh := func(a attempt, ok bool) { if !ok { log.Printf("Success channel closed. This is a " + "really bad bug. Please tell the developers.") os.Exit(-13) } /* Print a success message */ log.Printf("SUCCESS: %v@%v %v", a.User, a.Host, textIfBlank(a.Pass)) /* Log to the success file if we have one */ if sf != nil { logSuccess(sf, a) } /* Remove either the host or template, as appropriate */ if onepw { removeHost(ts, a, "", nAttempts) } else { /* Search list for matching template */ for e := ts.Head(); e != nil; e = e.Next() { v, ok := e.Value().(*template) if !ok { printTemplateNotOk(e) os.Exit(-15) } /* Remove template when found */ if v.User == a.User && v.Host == a.Host { e.Remove() } } /* One fewer attempt is in play */ nAttempts.Dec() } _ = onepw /* DEBUG */ dieIfDone() } failh := func(a attempt, ok bool) { if !ok { log.Printf("Fail channel closed. This is a really " + "bad bug. Please tell the developers.") os.Exit(-12) } /* Handle failures.*/ parseFail(a, retryc, errdb, nAttempts, ts) dieIfDone() } retryh := func(a attempt, ok bool) { if !ok { log.Printf("Retry channel closed. This is a really " + "bad bug. Please tell the developers.") os.Exit(-11) } startTask(a) } /* Main loop */ for { if nRunning.Val() < ntask { /* When we don't have enough running tasks, accept input from all channels */ select { case a, ok := <-retryc: retryh(a, ok) case a, ok := <-internalc: if !ok { internalc = nil dieIfDone() continue } startTask(a) case a, ok := <-filec: if !ok { filec = nil dieIfDone() continue } startTask(a) case a, ok := <-stdinc: if !ok { stdinc = nil dieIfDone() continue } startTask(a) case a, ok := <-failc: failh(a, ok) case a, ok := <-successc: successh(a, ok) } } else { /* When we have enough running tasks, only read from channels that signal tasks are done. */ select { case a, ok := <-failc: failh(a, ok) case a, ok := <-successc: successh(a, ok) } } } }