session_ser.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. package smb
  2. import (
  3. "bufio"
  4. "bytes"
  5. "encoding/binary"
  6. "encoding/hex"
  7. "fmt"
  8. "log"
  9. "net"
  10. "path/filepath"
  11. "strings"
  12. "time"
  13. "github.com/izouxv/logx"
  14. "imuslab.com/smb/driver/mod/gss"
  15. "imuslab.com/smb/driver/mod/smb/encoder"
  16. "golang.org/x/net/webdav"
  17. )
  18. type HookCondition int
  19. const (
  20. FileClose HookCondition = iota
  21. )
  22. type SessionS struct {
  23. session
  24. fileNum uint64
  25. //tree
  26. openedFiles map[GUID]webdav.File
  27. srvsvc GUID
  28. //server level
  29. SessionKey []byte
  30. ServerChallenge uint64
  31. getPwd GetPwdFunc
  32. getTree GetAnchorFun
  33. anchors map[string]*Anchor
  34. activeAnchorKey string //当前的anchor
  35. //current anchor key, TODO 每次切换的时候都会新建一个tree. 但是这个treeid不会变. 来回切换anchor多线程怎么处理? 还没理解.
  36. //dcerpc for IPC$
  37. pdb PDUHeaderStruct
  38. notify map[GUID]*ChangeNotifyRequest
  39. }
  40. func NewSessionServer(debug bool, conn net.Conn, getPwd GetPwdFunc, getTree GetAnchorFun) (s *SessionS) {
  41. s = &SessionS{
  42. session: session{
  43. IsSigningRequired: false,
  44. IsAuthenticated: false,
  45. debug: debug,
  46. securityMode: 0,
  47. sessionID: uint64(time.Now().UnixNano()),
  48. dialect: 0,
  49. conn: conn,
  50. },
  51. anchors: make(map[string]*Anchor),
  52. openedFiles: make(map[GUID]webdav.File),
  53. notify: make(map[GUID]*ChangeNotifyRequest),
  54. getPwd: getPwd,
  55. getTree: getTree,
  56. // latestFileId: NilGUID,
  57. }
  58. s.Debug("Negotiating protocol", nil)
  59. return s
  60. }
  61. func (s *SessionS) NegotiateProtocolServer() (err error) {
  62. //TODO 在这里做所有协议的nego. 需要通过OID来判断, 不管多少个流程, 都在这一个函数里处理.
  63. s.Debug("Sending NegotiateProtocolServer2 request", nil)
  64. rw := bufio.NewReadWriter(bufio.NewReader(s.conn), bufio.NewWriter(s.conn))
  65. simpleReqAction := func(reqMsg []byte, cmd Command, data DataI) error {
  66. ctx := NewDataCtx(s, s.conn, nil)
  67. err = encoder.Unmarshal(reqMsg, data)
  68. if err != nil {
  69. return err
  70. }
  71. respBuf, err := ServerAction(ctx, cmd, data)
  72. if err != nil {
  73. return err
  74. }
  75. fmt.Print(cmd)
  76. fmt.Printf("respBuf: \n%v", hex.Dump(respBuf))
  77. return s.Send(respBuf, rw)
  78. }
  79. simpleReq := func(data DataI, cmd Command) error {
  80. log.Println(data, cmd)
  81. reqMsg, _, err := s.Recv(rw)
  82. if err != nil {
  83. return err
  84. }
  85. return simpleReqAction(reqMsg, cmd, data)
  86. }
  87. reqMsg, ver, err := s.Recv(rw)
  88. if err != nil {
  89. return err
  90. }
  91. if ver == ProtocolSmb {
  92. //优先处理smb1
  93. fmt.Println("SMB1 warning!")
  94. var reqSmb1Negotiate NegotiateSmb1Request
  95. if err = simpleReqAction(reqMsg, CommandNegotiate, &reqSmb1Negotiate); err != nil {
  96. logx.Errorf("reqNegotiate, err: %v", err)
  97. return err
  98. }
  99. //处理完后,再取新数据
  100. reqMsg, ver, err = s.Recv(rw)
  101. if err != nil {
  102. return err
  103. }
  104. }
  105. var reqNegotiate NegotiateRequest
  106. if err = simpleReqAction(reqMsg, CommandNegotiate, &reqNegotiate); err != nil {
  107. logx.Errorf("reqNegotiate, err: %v", err)
  108. return err
  109. }
  110. // var reqNegotiate NegotiateRequest
  111. // if data, ver, err = simpleReq(&reqNegotiate); err != nil {
  112. // if err != nil && ver == ProtocolSmb {
  113. // var reqSmb1Negotiate NegotiateSmb1Request
  114. // } else {
  115. // fmt.Errorf("reqNegotiate, err: %v", err)
  116. // return err
  117. // }
  118. // }
  119. requestSetUp1 := SessionSetup1Request{SecurityBlob: &gss.NegTokenInit{}}
  120. log.Println("1")
  121. if err = simpleReq(&requestSetUp1, CommandSessionSetup); err != nil {
  122. logx.Errorf("requestSetUp1, err: %v", err)
  123. return err
  124. }
  125. /*
  126. requestSetUp2 := SessionSetup2Request{SecurityBlob: &gss.NegTokenResp{ }}
  127. NegResult: asn1.Enumerated(gss.Accept_completed),
  128. */
  129. requestSetUp2 := SessionSetup2Request{SecurityBlob: &gss.NegTokenResp{}}
  130. log.Println("23333", requestSetUp2)
  131. if err = simpleReq(&requestSetUp2, CommandSessionSetup); err != nil {
  132. logx.Errorf("requestSetUp2, err: %v", err)
  133. return err
  134. }
  135. fmt.Println("SETUP2 DONE")
  136. return nil
  137. }
  138. func (session *SessionS) SetActiveAnchorKey(activeAnchorKey string) bool {
  139. activeAnchorKey = strings.ToUpper(activeAnchorKey)
  140. _, ok := session.anchors[activeAnchorKey]
  141. if ok {
  142. session.activeAnchorKey = activeAnchorKey
  143. }
  144. return ok
  145. }
  146. func (session *SessionS) GetAbsPath(path string) string {
  147. anchor, _ := session.anchors[session.activeAnchorKey]
  148. root := anchor.RootPath
  149. fullpath := filepath.Join(root, filepath.ToSlash(path))
  150. return fullpath
  151. }
  152. func (session *SessionS) SetAnchor(fileNum uint64, items []*Anchor) {
  153. for _, item := range items {
  154. session.anchors[strings.ToUpper(item.Name)] = item
  155. }
  156. }
  157. func (s *SessionS) GetAnchor(name string) *Anchor {
  158. item, ok := s.anchors[strings.ToUpper(name)]
  159. if !ok {
  160. return nil
  161. }
  162. return item
  163. }
  164. type DataCtx struct {
  165. session *SessionS
  166. conn net.Conn
  167. handle func(string) *Handler
  168. //batch message var
  169. latestFileId GUID
  170. closeAction func()
  171. }
  172. func (d *DataCtx) Handle() *Handler {
  173. return d.handle(d.session.activeAnchorKey)
  174. }
  175. func (s *DataCtx) IsVer_2_1() bool {
  176. return s.session.dialect == uint16(DialectSmb_2_1)
  177. }
  178. func (s *DataCtx) IsVer_2_0() bool {
  179. return s.session.dialect == uint16(DialectSmb_2_0_2)
  180. }
  181. func (s *DataCtx) FileID(fileid GUID) GUID {
  182. if fileid.IsEqual(LastGUID) {
  183. fileid = s.latestFileId
  184. }
  185. return fileid
  186. }
  187. func NewDataCtx(s *SessionS, conn net.Conn, Handle func(string) *Handler) *DataCtx {
  188. return &DataCtx{session: s, conn: conn, handle: Handle, latestFileId: NilGUID}
  189. }
  190. type DataI interface {
  191. ServerAction(ctx *DataCtx) (interface{}, error)
  192. }
  193. var commandRequestMap = make(map[Command]func() DataI)
  194. // //////////////////////
  195. func ActionParserFunc(ctx *DataCtx, msgs []byte) ([]DataI, []Command, Status) {
  196. tmp := msgs
  197. var items []DataI
  198. var cmds []Command
  199. for {
  200. if tmp == nil {
  201. break
  202. }
  203. chainOffset := binary.LittleEndian.Uint32(tmp[20:])
  204. oneMsg := tmp
  205. if chainOffset > 0 {
  206. oneMsg = tmp[:chainOffset]
  207. tmp = tmp[chainOffset:]
  208. } else {
  209. tmp = nil
  210. }
  211. item, stat, cmd := ActionParserOneMsgFunc(ctx, oneMsg)
  212. if stat != StatusOk {
  213. return nil, nil, stat
  214. }
  215. cmds = append(cmds, cmd)
  216. items = append(items, item)
  217. }
  218. return items, cmds, StatusOk
  219. }
  220. func ActionFunc(ctx *DataCtx, msgs []byte) ([]byte, Command, Status) {
  221. //有可能是多个消息合并到一起. 需要单独分开.
  222. var respTotal [][]byte
  223. datas, cmds, stat := ActionParserFunc(ctx, msgs)
  224. if stat != StatusOk {
  225. return nil, 0, stat
  226. }
  227. for i, data := range datas {
  228. cmd := cmds[i]
  229. respBuf, err := ServerAction(ctx, cmd, data)
  230. if err != nil {
  231. return nil, 0, STATUS_INVALID_PARAMETER
  232. }
  233. respTotal = append(respTotal, respBuf)
  234. }
  235. //change chain offset
  236. for i := 0; i < len(respTotal); i++ {
  237. resp := respTotal[i]
  238. if i != len(respTotal)-1 {
  239. binary.LittleEndian.PutUint32(resp[20:], uint32(len(resp)))
  240. }
  241. }
  242. return bytes.Join(respTotal, []byte{}), cmds[0], StatusOk
  243. }
  244. func ActionParserOneMsgFunc(ctx *DataCtx, msg []byte) (dd DataI, ss Status, cc Command) {
  245. commandNum := binary.LittleEndian.Uint16(msg[12:])
  246. command := Command(commandNum)
  247. sessionId := binary.LittleEndian.Uint64(msg[40:])
  248. if ctx.session.sessionID != sessionId {
  249. return nil, StatusUserSessionDeleted, command
  250. // binary.LittleEndian.PutUint32(msg[8:], uint32(StatusUserSessionDeleted))
  251. // return nil, msg, nil
  252. }
  253. Flags := binary.LittleEndian.Uint32(msg[16:])
  254. if Flags&^uint32(SMB2_FLAGS_PRIORITY_MASK) != 0 {
  255. // binary.LittleEndian.PutUint32(msg[8:], uint32(STATUS_NOT_SUPPORTED))
  256. // return nil, msg, nil
  257. }
  258. fff, ok := commandRequestMap[command]
  259. if !ok {
  260. return nil, STATUS_NOT_IMPLEMENTED, command
  261. // binary.LittleEndian.PutUint32(msg[8:], uint32(STATUS_NOT_IMPLEMENTED))
  262. // return nil,
  263. }
  264. data := fff()
  265. _, err := encoder.Unmarshal2(msg, data)
  266. if err != nil {
  267. return nil, STATUS_INVALID_PARAMETER, command
  268. }
  269. return data, StatusOk, command
  270. // return ServerAction(ctx, msg, data)
  271. }
  272. var signaturBlank = make([]byte, 16)
  273. func ServerAction(ctx *DataCtx, cmd Command, data DataI) (bbb []byte, eee error) {
  274. startTime := time.Now()
  275. logx.Infof("[CMD] cmd, %v", cmd)
  276. defer func() {
  277. takeT := time.Since(startTime)
  278. if takeT > 100*time.Millisecond {
  279. logx.Printf("[TIME] command: %v, taketime: %v", cmd, takeT)
  280. }
  281. if eee != nil {
  282. logx.Infof("[CMD] data, %v, ss: %v, err: %v", cmd, eee, eee)
  283. }
  284. }()
  285. resp, err := data.ServerAction(ctx)
  286. if err != nil {
  287. return nil, err
  288. }
  289. respBuf, err := encoder.Marshal(resp)
  290. if err != nil {
  291. return nil, err
  292. }
  293. if true {
  294. // // copy(respBuf[48:64], signaturBlank)
  295. // //sign
  296. // if len(ctx.session.SessionKey) > 0 {
  297. // content := respBuf[64:]
  298. // sig, err := CalculateSignature(ctx.session.SessionKey, content, ctx.session.dialect)
  299. // if err != nil {
  300. // fmt.Errorf("err: %v", err)
  301. // return nil, err
  302. // }
  303. // copy(respBuf[48:64], sig[:16])
  304. // }
  305. }
  306. return respBuf, nil
  307. }