github-vet / github-vet/rangeloop-pointer-findings

rhowell7/startTLS_go: smtpConnection.go; 170 LoC

Open
#16,711 0 comments 0 reactions 0 assignees View on GitHub
fresh large
Dominant language
No language data
Stars
0
Forks
0
PR merge metrics
PR metrics pending

Description

Found a possible issue in [rhowell7/startTLS_go](https://www.github.com/rhowell7/startTLS_go) at [smtpConnection.go](https://github.com/rhowell7/startTLS_go/blob/a529003c2f46188f63a201c707729ee701e922b3/smtpConnection.go#L232-L401)

Below is the message reported by the analyzer for this snippet of code. Beware that the analyzer only reports the first issue it finds, so please do not limit your consideration to the contents of the below message.

> range-loop variable ip used in defer or goroutine at line 239

[Click here to see the code in its original context.](https://github.com/rhowell7/startTLS_go/blob/a529003c2f46188f63a201c707729ee701e922b3/smtpConnection.go#L232-L401)

Click here to show the 170 line(s) of Go which triggered the analyzer.

```go
for ip := range input_chan {
//------------ Get an IP Address from input_chan -------------//
m.Lock()
in_process[ip] = c
m.Unlock()
defer func() {
m.Lock()
delete(in_process, ip)
m.Unlock()
}()

target := ip+":25"
fmt.Print("\nTarget: ", ip)

//------------------ Open the SMTP connection ----------------//
timeOut := time.Duration(3) * time.Second
conn, err := net.DialTimeout("tcp", target, timeOut)
if err != nil {
fmt.Println("\ndial error:", err)
continue
}
defer conn.Close()

// Wait for 220 banner
banner, err := bufio.NewReader(conn).ReadString('\n')
// fmt.Println(banner)

// Are we being greylisted/blacklisted?
bannerGood, err := regexp.MatchString("220 ", string(banner))

if !bannerGood {
fmt.Println("\nThis server did not give us a good banner: ",
target)
fmt.Println(banner)
continue
}

//---------------- Send EHLO, receive Extensions -------------//
conn.Write([]byte("EHLO ME\r\n"))
bufReader := bufio.NewReader(conn)
for {
// Read tokens delimited by newline
extensions, err := bufReader.ReadBytes('\n')
if err != nil { // if there's an error
fmt.Println()
break
}
// fmt.Printf("%s", extensions)

done, err := regexp.MatchString("250 ", string(extensions))
if done {
// Extensions start with 250-, except the last one is just 250
// fmt.Println("Found the last extension\n")
fmt.Println()
break
}

// 500 5.5.1 Command unrecognized: "XXXX ME"
ehloError, err := regexp.MatchString("500 ", string(extensions))
if ehloError {
// fmt.Println("got a 500 error: ", string(extensions))
// fmt.Println("Sending 'HELO' instead")
conn.Write([]byte("HELO ME\r\n"))
}
} // for (receiving extensions)

//----------------- Send magic StartTLS packets ------------------//
tcpResponseChan := make(chan []byte)
hostTimeoutChan := make(chan bool)

//--------------------- TCP Listener -------------------------//
w.Add(1)
go func() {
defer w.Done()
defer fmt.Println("TCP Listener goroutine has finished")
tlsResponse, err := bufReader.ReadBytes('\n')
if err != nil { // if there's an error
fmt.Println()
// break
hostTimeoutChan <- true
}
tcpResponseChan <- tlsResponse
}() // TCP Listener

hostDone := false
results := Output{TargetIP: ip}

// Fork a new ipv4 connection from the original one
startTlsConn := ipv4.NewConn(conn)
if err != nil {
fmt.Println("Forking conn error:", err)
return
}
defer startTlsConn.Close()

// Send the fudged StartTLS packets
ttl := minTTL
for ; ttl < maxTTL && !hostDone; ttl++ {
startTlsConn.SetTTL(ttl)
startTlsConn.Write([]byte("STARTTLS\r\n"))
// fmt.Println("\n\nSent STARTTLS packet with TTL: ", ttl)
hopDone := false

for !hopDone && !hostDone {
select {
case icmpPkt := <- c:
// got an icmp packet, add it to results
hopDone = true
hop_ip := icmpPkt.ReachedIPv4
hop_response := strings.Replace(icmpPkt.Data, "\n", "", -1)
hop_response = strings.Replace(hop_response, "\u0000", "", -1)

hop_result := Hop{IP: hop_ip, HopOutput: hop_response, Hop: ttl}
results.Hops = append(results.Hops, hop_result)

hop_censored, _ := regexp.MatchString("XXX", hop_response)
if hop_censored && results.FirstCensoredIP == "" {
// fmt.Println("First censored hop: ", ttl, ": ", hop_ip)
results.FirstCensoredHop = ttl
results.FirstCensoredIP = hop_ip
}

hop_uncensored, _ := regexp.MatchString("STARTTLS", hop_response)
if hop_uncensored {
// fmt.Println("Uncensored hop: ", ttl, ": ", hop_ip)
results.LastUncensoredHop = ttl
results.LastUncensoredIP = hop_ip
}

fmt.Print("Hop ", ttl, ": ", hop_ip)
fmt.Println("\tICMP Packet: ", hop_response)

continue
case tcpBytes := <- tcpResponseChan:
// got a TCP packet, add it to results and break
hostDone = true
hopDone = true

tcpResponse := string(tcpBytes)

hop_censored, _ := regexp.MatchString("XXX", tcpResponse)
if hop_censored && results.FirstCensoredIP == "" {
// fmt.Println("First censored hop: ", ttl, ": ", ip)
results.FirstCensoredHop = ttl
results.FirstCensoredIP = ip
results.TcpResponse = tcpResponse
results.Censored = true
}

output_chan <- results

fmt.Print("Hop ", ttl, ": ")
fmt.Print(ip)
fmt.Println("\tTCP Response: ", tcpResponse)
break
case <-time.After(hopTimeout * time.Second):
hopDone = true
continue
case <-time.After(hostTimeout * time.Second):
hostDone = true
fmt.Println("Host timed out")
break

} // select: ICMP, TCP, or timeout?
} // for !hopDone && !hostDone
} // for ; ttl < maxTTL && !hostDone
} // for ip := range input_chan

```

Leave a reaction on this issue to contribute to the project by classifying this instance as a **Bug** :-1:, **Mitigated** :+1:, or **Desirable Behavior** :rocket:
See the descriptions of the classifications [here](https://github.com/github-vet/rangeclosure-findings#how-can-i-help) for more information.

commit ID: a529003c2f46188f63a201c707729ee701e922b3

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.