ajp13.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. package ajp13
  2. import (
  3. "encoding/binary"
  4. "fmt"
  5. "net"
  6. "reflect"
  7. )
  8. // ForwardRequest marks that this request is an actual request
  9. const ForwardRequest = 2
  10. // Shutdown marks that this is a shutdown request
  11. const Shutdown = 7
  12. // Ping marks that this is a ping request
  13. const Ping = 8
  14. // CPing marks that this is a cping request
  15. const CPing = 10
  16. // AJP13 represents the apache java protocol
  17. type AJP13 struct {
  18. len uint16
  19. Type uint8
  20. method HTTPMethod
  21. Version string // e.g. HTTP/1.1
  22. URI string
  23. RemoteAddr net.IP
  24. RemoteHost string
  25. Server string
  26. Port uint16
  27. SSL bool
  28. headers map[string]string
  29. }
  30. // Parse takes a []byte payload and builds
  31. func Parse(payload []byte) (*AJP13, error) {
  32. if !reflect.DeepEqual(payload[0:2], []byte{0x12, 0x34}) {
  33. return nil, fmt.Errorf("The magic signature is not 0x12 0x34 but %v", payload[0:2])
  34. }
  35. a := &AJP13{}
  36. // the data length
  37. a.len = binary.BigEndian.Uint16(payload[2:4])
  38. data := payload[4 : a.len+4]
  39. // the request type
  40. a.Type = uint8(data[0])
  41. var err error
  42. switch a.Type {
  43. case ForwardRequest:
  44. err = a.parseForwardRequest(data)
  45. if err != nil {
  46. return nil, err
  47. }
  48. }
  49. return a, nil
  50. }
  51. func checkLength(data []byte, minLen int, location string) error {
  52. dataLen := len(data)
  53. if dataLen < minLen {
  54. return fmt.Errorf("%s: need %d bytes but have %d", location, minLen, dataLen)
  55. }
  56. return nil
  57. }
  58. func (a *AJP13) parseForwardRequest(data []byte) error {
  59. // Method
  60. a.method = HTTPMethod(uint8(data[1]))
  61. offset := uint16(2)
  62. // Version
  63. if !reflect.DeepEqual(data[offset:offset+2], []byte{0xff, 0xff}) {
  64. versionLen := binary.BigEndian.Uint16(data[offset : offset+2])
  65. if err := checkLength(data, int(offset+2+versionLen+1), "parseForwardRequest/Version"); err != nil {
  66. return err
  67. }
  68. a.Version = string(data[offset+2 : offset+2+versionLen])
  69. offset += versionLen + 1
  70. }
  71. offset += 2
  72. // URI
  73. if !reflect.DeepEqual(data[offset:offset+2], []byte{0xff, 0xff}) {
  74. uriLen := binary.BigEndian.Uint16(data[offset : offset+2])
  75. if err := checkLength(data, int(offset+2+uriLen+1), "parseForwardRequest/URI"); err != nil {
  76. return err
  77. }
  78. a.URI = string(data[offset+2 : offset+2+uriLen])
  79. offset += uriLen + 1
  80. }
  81. offset += 2
  82. // RemoteAddr
  83. if !reflect.DeepEqual(data[offset:offset+2], []byte{0xff, 0xff}) {
  84. raddrLen := binary.BigEndian.Uint16(data[offset : offset+2])
  85. if err := checkLength(data, int(offset+2+raddrLen+1), "parseForwardRequest/RemoteAddr"); err != nil {
  86. return err
  87. }
  88. a.RemoteAddr = net.ParseIP(string(data[offset+2 : offset+2+raddrLen]))
  89. offset += raddrLen + 1
  90. }
  91. offset += 2
  92. // RemoteHost
  93. if !reflect.DeepEqual(data[offset:offset+2], []byte{0xff, 0xff}) {
  94. rhostLen := binary.BigEndian.Uint16(data[offset : offset+2])
  95. if err := checkLength(data, int(offset+2+rhostLen+1), "parseForwardRequest/RemoteHost"); err != nil {
  96. return err
  97. }
  98. a.RemoteHost = string(data[offset+2 : offset+2+rhostLen])
  99. offset += rhostLen + 1
  100. }
  101. offset += 2
  102. // Server
  103. if !reflect.DeepEqual(data[offset:offset+2], []byte{0xff, 0xff}) {
  104. len := binary.BigEndian.Uint16(data[offset : offset+2])
  105. if err := checkLength(data, int(offset+2+len+1), "parseForwardRequest/Server"); err != nil {
  106. return err
  107. }
  108. a.Server = string(data[offset+2 : offset+2+len])
  109. offset += len + 1
  110. }
  111. offset += 2
  112. // Port
  113. a.Port = binary.BigEndian.Uint16(data[offset : offset+2])
  114. offset += 2
  115. // SSL
  116. if data[offset] == 0x1 {
  117. a.SSL = true
  118. }
  119. offset++
  120. // Headers
  121. numHeaders := binary.BigEndian.Uint16(data[offset : offset+2])
  122. offset += 2
  123. headers := make(map[string]string)
  124. for idx := uint16(0); idx < numHeaders; idx++ {
  125. if data[offset] == 0xa0 { // encoded header name
  126. len := binary.BigEndian.Uint16(data[offset+2 : offset+4])
  127. hdrName := HTTPHeader(binary.BigEndian.Uint16(data[offset : offset+2])).String()
  128. if hdrName != "UNKNOWN" {
  129. headers[hdrName] = string(data[offset+4 : offset+4+len])
  130. }
  131. offset = offset + 5 + len
  132. } else { // plain text header name
  133. length := binary.BigEndian.Uint16(data[offset : offset+2])
  134. key := string(data[offset+2 : offset+2+length])
  135. offset = offset + 3 + length
  136. length = binary.BigEndian.Uint16(data[offset : offset+2])
  137. val := string(data[offset+2 : offset+2+length])
  138. headers[key] = val
  139. offset = offset + 3 + length
  140. }
  141. }
  142. a.headers = headers
  143. // don't need Attributes for the time being
  144. return nil
  145. }
  146. // Length returns the length of the data this AJP13 request consists of
  147. func (a *AJP13) Length() uint16 {
  148. return a.len
  149. }
  150. // Method returns the name of the method used
  151. func (a *AJP13) Method() string {
  152. return a.method.String()
  153. }
  154. // Header returns the header value refered to by key
  155. func (a *AJP13) Header(key string) (string, bool) {
  156. val, ok := a.headers[key]
  157. return val, ok
  158. }
  159. // Headers returns all headers
  160. func (a *AJP13) Headers() map[string]string {
  161. return a.headers
  162. }