| 16 | ) |
| 17 | |
| 18 | func BruteUserQuery(inputname string, server string, threads int, outputFile string, secure bool) { |
| 19 | |
| 20 | var err error |
| 21 | var totalInputLines int |
| 22 | |
| 23 | // Open output file if specified |
| 24 | output := os.Stdout |
| 25 | if outputFile != "" { |
| 26 | output, err = os.Create(outputFile) |
| 27 | if err != nil { |
| 28 | log.Printf("Can't open %v: %v\n\n", outputFile, err) |
| 29 | } |
| 30 | defer output.Close() |
| 31 | } |
| 32 | |
| 33 | // Open input file |
| 34 | input := os.Stdin |
| 35 | if inputname != "" { |
| 36 | input, err = os.Open(inputname) |
| 37 | if err != nil { |
| 38 | log.Printf("Can't open %v: %v\n\n", inputname, err) |
| 39 | } |
| 40 | defer input.Close() |
| 41 | |
| 42 | if outputFile != "" { |
| 43 | // Count lines |
| 44 | linescanner := bufio.NewScanner(input) |
| 45 | linescanner.Split(bufio.ScanLines) |
| 46 | for linescanner.Scan() { |
| 47 | totalInputLines++ |
| 48 | } |
| 49 | input.Seek(0, io.SeekStart) |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | // Read users from file |
| 54 | names := bufio.NewScanner(input) |
| 55 | names.Split(bufio.ScanLines) |
| 56 | |
| 57 | // Create channels for parallel processing |
| 58 | inputBuffer := make(chan string, 128) |
| 59 | outputBuffer := make(chan string, 128) |
| 60 | |
| 61 | // Create mutex for connecting to LDAP |
| 62 | var connectMutex sync.Mutex |
| 63 | var connectError error |
| 64 | |
| 65 | // Use waitgroup to wait for all threads to finish |
| 66 | var jobs sync.WaitGroup |
| 67 | |
| 68 | bar := progressbar.NewOptions( |
| 69 | int(totalInputLines), |
| 70 | progressbar.OptionClearOnFinish(), |
| 71 | progressbar.OptionEnableColorCodes(true), |
| 72 | progressbar.OptionFullWidth(), |
| 73 | progressbar.OptionSetDescription(fmt.Sprintf("Querying %v", server)), |
| 74 | progressbar.OptionSetPredictTime(true), |
| 75 | progressbar.OptionSetTheme(progressbar.Theme{ |