mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-09-14 05:56:46 +08:00
133 lines
3.2 KiB
Go
133 lines
3.2 KiB
Go
package imap
|
||
|
||
import (
|
||
"bufio"
|
||
"context"
|
||
"crypto/tls"
|
||
"fmt"
|
||
"io"
|
||
"net"
|
||
"strings"
|
||
"time"
|
||
|
||
"github.com/shadow1ng/fscan/common"
|
||
"github.com/shadow1ng/fscan/plugins/base"
|
||
)
|
||
|
||
// IMAPConnection IMAP连接包装器
|
||
type IMAPConnection struct {
|
||
conn net.Conn
|
||
reader *bufio.Reader
|
||
target string
|
||
}
|
||
|
||
// IMAPConnector IMAP连接器实现
|
||
type IMAPConnector struct {
|
||
host string
|
||
port string
|
||
}
|
||
|
||
// NewIMAPConnector 创建IMAP连接器
|
||
func NewIMAPConnector() *IMAPConnector {
|
||
return &IMAPConnector{}
|
||
}
|
||
|
||
// Connect 连接到IMAP服务
|
||
func (c *IMAPConnector) Connect(ctx context.Context, info *common.HostInfo) (interface{}, error) {
|
||
c.host = info.Host
|
||
c.port = info.Ports
|
||
|
||
target := fmt.Sprintf("%s:%s", c.host, c.port)
|
||
|
||
// 根据端口选择连接类型
|
||
var conn net.Conn
|
||
var err error
|
||
|
||
if c.port == "993" {
|
||
// IMAPS端口,使用TLS连接
|
||
tlsConfig := &tls.Config{
|
||
InsecureSkipVerify: true,
|
||
}
|
||
conn, err = common.WrapperTlsWithContext(ctx, "tcp", target, tlsConfig)
|
||
} else {
|
||
// IMAP端口,使用普通连接
|
||
conn, err = common.WrapperTcpWithContext(ctx, "tcp", target)
|
||
}
|
||
|
||
if err != nil {
|
||
return nil, fmt.Errorf("IMAP连接失败: %v", err)
|
||
}
|
||
|
||
reader := bufio.NewReader(conn)
|
||
|
||
// 设置IMAP特殊超时:默认超时时间 + 5秒
|
||
imapTimeout := time.Duration(common.Timeout+5) * time.Second
|
||
conn.SetReadDeadline(time.Now().Add(imapTimeout))
|
||
|
||
// 读取IMAP欢迎消息
|
||
if _, readErr := reader.ReadString('\n'); readErr != nil {
|
||
conn.Close()
|
||
return nil, fmt.Errorf("IMAP欢迎消息读取失败: %v", readErr)
|
||
}
|
||
|
||
return &IMAPConnection{
|
||
conn: conn,
|
||
reader: reader,
|
||
target: target,
|
||
}, nil
|
||
}
|
||
|
||
// Authenticate 认证
|
||
func (c *IMAPConnector) Authenticate(ctx context.Context, conn interface{}, cred *base.Credential) error {
|
||
imapConn, ok := conn.(*IMAPConnection)
|
||
if !ok {
|
||
return fmt.Errorf("无效的连接类型")
|
||
}
|
||
|
||
// 设置IMAP特殊超时:默认超时时间 + 5秒
|
||
imapTimeout := time.Duration(common.Timeout+5) * time.Second
|
||
imapConn.conn.SetDeadline(time.Now().Add(imapTimeout))
|
||
|
||
// 发送LOGIN命令
|
||
loginCmd := fmt.Sprintf("a001 LOGIN \"%s\" \"%s\"\r\n", cred.Username, cred.Password)
|
||
_, err := imapConn.conn.Write([]byte(loginCmd))
|
||
if err != nil {
|
||
return fmt.Errorf("发送登录命令失败: %v", err)
|
||
}
|
||
|
||
// 读取认证响应
|
||
for {
|
||
select {
|
||
case <-ctx.Done():
|
||
return fmt.Errorf("IMAP认证超时: %v", ctx.Err())
|
||
default:
|
||
// 设置读取超时,避免无限等待(使用IMAP特殊超时)
|
||
imapTimeout := time.Duration(common.Timeout+5) * time.Second
|
||
imapConn.conn.SetReadDeadline(time.Now().Add(imapTimeout))
|
||
|
||
response, err := imapConn.reader.ReadString('\n')
|
||
if err != nil {
|
||
if err == io.EOF {
|
||
return fmt.Errorf("IMAP认证失败")
|
||
}
|
||
return fmt.Errorf("读取响应失败: %v", err)
|
||
}
|
||
|
||
if strings.Contains(response, "a001 OK") {
|
||
return nil // 认证成功
|
||
}
|
||
|
||
if strings.Contains(response, "a001 NO") || strings.Contains(response, "a001 BAD") {
|
||
return fmt.Errorf("IMAP认证失败")
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// Close 关闭连接
|
||
func (c *IMAPConnector) Close(conn interface{}) error {
|
||
if imapConn, ok := conn.(*IMAPConnection); ok && imapConn.conn != nil {
|
||
return imapConn.conn.Close()
|
||
}
|
||
return nil
|
||
} |