session_client.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. package smb
  2. import (
  3. "errors"
  4. "fmt"
  5. "net"
  6. "sync/atomic"
  7. "imuslab.com/smb/driver/mod/gss"
  8. "imuslab.com/smb/driver/mod/ntlmssp"
  9. )
  10. //TODO tcp发过去的消息会乱序, 需要用msgid chan来处理单独的协议. 马上send马上recv的消息可能msgId对不上
  11. type Options struct {
  12. Host string
  13. Port int
  14. Workstation string
  15. Domain string
  16. User string
  17. Password string
  18. }
  19. func validateOptions(opt Options) error {
  20. if opt.Host == "" {
  21. return errors.New("Missing required option: Host")
  22. }
  23. if opt.Port < 1 || opt.Port > 65535 {
  24. return errors.New("Invalid or missing value: Port")
  25. }
  26. return nil
  27. }
  28. type SessionC struct {
  29. session
  30. //client level
  31. trees map[string]uint32
  32. options Options
  33. messageID uint64 //for client msgId
  34. Challenge ntlmssp.Challenge
  35. }
  36. func NewSessionClient(opt Options, debug bool) (s *SessionC, err error) {
  37. if err := validateOptions(opt); err != nil {
  38. return nil, err
  39. }
  40. conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", opt.Host, opt.Port))
  41. if err != nil {
  42. return
  43. }
  44. s = &SessionC{
  45. session: session{
  46. IsSigningRequired: false,
  47. IsAuthenticated: false,
  48. debug: debug,
  49. conn: conn,
  50. securityMode: 0,
  51. sessionID: 0,
  52. dialect: 0,
  53. // trees: make(map[string]uint32),
  54. },
  55. options: opt,
  56. }
  57. s.Debug("Negotiating protocol", nil)
  58. err = s.NegotiateProtocolClient()
  59. if err != nil {
  60. return
  61. }
  62. return s, nil
  63. }
  64. func (s *SessionC) NegotiateProtocolClient() error {
  65. s.Debug("Sending NegotiateProtocol request", nil)
  66. // myMechType := gss.KRB5SSPMechTypeOid
  67. myMechType := gss.NtLmSSPMechTypeOid
  68. if true {
  69. requestNego := s.NewNegotiateRequest()
  70. responseNego := &NegotiateResponse{
  71. SecurityBlob: &gss.NegTokenInit{},
  72. }
  73. if err := s.RPC(requestNego, responseNego); err != nil {
  74. return err
  75. }
  76. if err := requestNego.ClientAction(s, responseNego); err != nil {
  77. return err
  78. }
  79. }
  80. if true {
  81. s.Debug("Sending SessionSetup1 request", nil)
  82. setupRequest1 := s.NewSessionSetup1Request(myMechType)
  83. setupResponse1 := &SessionSetup1Response{
  84. SecurityBlob: &gss.NegTokenResp{},
  85. }
  86. if err := s.RPC(setupRequest1, setupResponse1); err != nil {
  87. return err
  88. }
  89. setupRequest1.ClientAction(s, setupResponse1)
  90. }
  91. if true {
  92. s.Debug("Sending SessionSetup2 request", nil)
  93. setupRequest2, err := s.NewSessionSetup2Request()
  94. if err != nil {
  95. return err
  96. }
  97. setupResponse2 := &SessionSetup2Response{
  98. SecurityBlob: &gss.NegTokenResp{},
  99. }
  100. if err = s.RPC(setupRequest2, setupResponse2); err != nil {
  101. return err
  102. }
  103. setupRequest2.ClientAction(s, setupResponse2)
  104. }
  105. return nil
  106. }
  107. func (s *SessionC) Close() {
  108. s.Debug("Closing session", nil)
  109. for k, _ := range s.trees {
  110. s.TreeDisconnect(k)
  111. }
  112. s.Debug("Closing TCP connection", nil)
  113. s.conn.Close()
  114. s.Debug("Session close completed", nil)
  115. }
  116. func (s *SessionC) newHeader(cmd Command) Header {
  117. msgId := atomic.AddUint64(&s.messageID, 1)
  118. return newHeader(cmd, msgId, s.sessionID)
  119. // return Header{
  120. // ProtocolID: []byte(ProtocolSmb2),
  121. // HeaderLength: 64,
  122. // Command: cmd,
  123. // MessageID: msgId,
  124. // SessionID: s.sessionID,
  125. // Signature: make([]byte, 16),
  126. // CreditCharge: 1,
  127. // }
  128. }
  129. func newHeader(cmd Command, msgId, sessionId uint64) Header {
  130. return Header{
  131. ProtocolID: []byte(ProtocolSmb2),
  132. HeaderLength: 64,
  133. Command: cmd,
  134. MessageID: msgId,
  135. SessionID: sessionId, // s.sessionID,
  136. Signature: make([]byte, 16),
  137. CreditCharge: 1,
  138. }
  139. }