Package opensmtpd implements OpenSMTPD-extras in Go
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. package opensmtpd
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "errors"
  6. "fmt"
  7. "io"
  8. "net"
  9. "os"
  10. )
  11. const (
  12. ibufReadSize = 65535
  13. imsgMaxSize = 16384
  14. imsgHeaderSize = 4 + 2 + 2 + 4 + 4
  15. imsgVersion = 14
  16. maxLocalPartSize = (255 + 1)
  17. maxDomainPartSize = (255 + 1)
  18. )
  19. // messageHeader is the header of an imsg frame (struct imsg_hdr)
  20. type messageHeader struct {
  21. Type uint32
  22. Len uint16
  23. Flags uint16
  24. PeerID uint32
  25. PID uint32
  26. }
  27. // message implements OpenBSD imsg
  28. type message struct {
  29. Header messageHeader
  30. // Data is the message payload.
  31. Data []byte
  32. // rpos is the read position in the current Data
  33. rpos int
  34. // buf is what we read from the socket (and remains)
  35. buf []byte
  36. }
  37. func (m *message) reset() {
  38. m.Header.Type = 0
  39. m.Header.Len = 0
  40. m.Header.Flags = 0
  41. m.Header.PeerID = imsgVersion
  42. m.Header.PID = uint32(os.Getpid())
  43. m.Data = m.Data[:0]
  44. m.rpos = 0
  45. m.buf = m.buf[:0]
  46. }
  47. // ReadFrom reads a message from the specified net.Conn, parses the header and
  48. // reads the data payload.
  49. func (m *message) ReadFrom(r io.Reader) error {
  50. m.reset()
  51. head := make([]byte, imsgHeaderSize)
  52. if _, err := r.Read(head); err != nil {
  53. return err
  54. }
  55. buf := bytes.NewBuffer(head)
  56. if err := binary.Read(buf, binary.LittleEndian, &m.Header); err != nil {
  57. return err
  58. }
  59. debugf("imsg header: %+v\n", m.Header)
  60. data := make([]byte, m.Header.Len-imsgHeaderSize)
  61. if _, err := r.Read(data); err != nil {
  62. return err
  63. }
  64. m.Data = data
  65. debugf("imsg data: %d / %q\n", len(m.Data), m.Data)
  66. return nil
  67. }
  68. // WriteTo marshals the message to wire format and sends it to the net.Conn
  69. func (m *message) WriteTo(w io.Writer) error {
  70. m.Header.Len = uint16(len(m.Data)) + imsgHeaderSize
  71. buf := new(bytes.Buffer)
  72. debugf("imsg header: %+v\n", m.Header)
  73. if err := binary.Write(buf, binary.LittleEndian, &m.Header); err != nil {
  74. return err
  75. }
  76. buf.Write(m.Data)
  77. debugf("imsg send: %d / %q\n", buf.Len(), buf.Bytes())
  78. _, err := w.Write(buf.Bytes())
  79. return err
  80. }
  81. func (m *message) GetInt() (int, error) {
  82. if m.rpos+4 > len(m.Data) {
  83. return 0, io.ErrShortBuffer
  84. }
  85. i := binary.LittleEndian.Uint32(m.Data[m.rpos:])
  86. m.rpos += 4
  87. return int(i), nil
  88. }
  89. func (m *message) GetUint32() (uint32, error) {
  90. if m.rpos+4 > len(m.Data) {
  91. return 0, io.ErrShortBuffer
  92. }
  93. u := binary.LittleEndian.Uint32(m.Data[m.rpos:])
  94. m.rpos += 4
  95. return u, nil
  96. }
  97. func (m *message) GetSize() (uint64, error) {
  98. if m.rpos+8 > len(m.Data) {
  99. return 0, io.ErrShortBuffer
  100. }
  101. u := binary.LittleEndian.Uint64(m.Data[m.rpos:])
  102. m.rpos += 8
  103. return u, nil
  104. }
  105. func (m *message) GetString() (string, error) {
  106. o := bytes.IndexByte(m.Data[m.rpos:], 0)
  107. if o < 0 {
  108. return "", errors.New("imsg: string not NULL-terminated")
  109. }
  110. s := string(m.Data[m.rpos : m.rpos+o])
  111. m.rpos += o
  112. return s, nil
  113. }
  114. func (m *message) GetID() (uint64, error) {
  115. if m.rpos+8 > len(m.Data) {
  116. return 0, io.ErrShortBuffer
  117. }
  118. u := binary.LittleEndian.Uint64(m.Data[m.rpos:])
  119. m.rpos += 8
  120. return u, nil
  121. }
  122. // Sockaddr emulates the mess that is struct sockaddr
  123. type Sockaddr []byte
  124. func (sa Sockaddr) IP() net.IP {
  125. switch len(sa) {
  126. case 16: // IPv4, sockaddr_in
  127. return net.IP(sa[4:8])
  128. case 28: // IPv6, sockaddr_in6
  129. return net.IP(sa[8:24])
  130. default:
  131. return nil
  132. }
  133. }
  134. func (sa Sockaddr) Port() uint16 {
  135. switch len(sa) {
  136. case 16: // IPv4, sockaddr_in
  137. return binary.LittleEndian.Uint16(sa[2:4])
  138. case 28: // IPv6, sockaddr_in6
  139. return binary.LittleEndian.Uint16(sa[2:4])
  140. default:
  141. return 0
  142. }
  143. }
  144. func (sa Sockaddr) Network() string {
  145. return "bla"
  146. }
  147. func (sa Sockaddr) String() string {
  148. return fmt.Sprintf("%s:%d", sa.IP(), sa.Port())
  149. }
  150. func (m *message) GetSockaddr() (net.Addr, error) {
  151. s, err := m.GetSize()
  152. if err != nil {
  153. return nil, err
  154. }
  155. if m.rpos+int(s) > len(m.Data) {
  156. return nil, io.ErrShortBuffer
  157. }
  158. a := make(Sockaddr, s)
  159. copy(a[:], m.Data[m.rpos:])
  160. m.rpos += int(s)
  161. return a, nil
  162. }
  163. func (m *message) GetMailaddr() (user, domain string, err error) {
  164. var buf [maxLocalPartSize + maxDomainPartSize]byte
  165. if maxLocalPartSize+maxDomainPartSize > len(m.Data[m.rpos:]) {
  166. return "", "", io.ErrShortBuffer
  167. }
  168. copy(buf[:], m.Data[m.rpos:])
  169. m.rpos += maxLocalPartSize + maxDomainPartSize
  170. user = string(buf[:maxLocalPartSize])
  171. domain = string(buf[maxLocalPartSize:])
  172. return
  173. }
  174. func (m *message) GetType(t uint8) error {
  175. if m.rpos >= len(m.Data) {
  176. return io.ErrShortBuffer
  177. }
  178. b := m.Data[m.rpos]
  179. m.rpos++
  180. if b != t {
  181. return mprocTypeErr{t, b}
  182. }
  183. return nil
  184. }
  185. func (m *message) GetTypeInt() (int, error) {
  186. if err := m.GetType(mINT); err != nil {
  187. return 0, err
  188. }
  189. return m.GetInt()
  190. }
  191. func (m *message) GetTypeUint32() (uint32, error) {
  192. if err := m.GetType(mUINT32); err != nil {
  193. return 0, err
  194. }
  195. return m.GetUint32()
  196. }
  197. func (m *message) GetTypeSize() (uint64, error) {
  198. if err := m.GetType(mSIZET); err != nil {
  199. return 0, err
  200. }
  201. return m.GetSize()
  202. }
  203. func (m *message) GetTypeString() (string, error) {
  204. if err := m.GetType(mSTRING); err != nil {
  205. return "", err
  206. }
  207. return m.GetString()
  208. }
  209. func (m *message) GetTypeID() (uint64, error) {
  210. if err := m.GetType(mID); err != nil {
  211. return 0, err
  212. }
  213. return m.GetID()
  214. }
  215. func (m *message) GetTypeSockaddr() (net.Addr, error) {
  216. if err := m.GetType(mSOCKADDR); err != nil {
  217. return nil, err
  218. }
  219. return m.GetSockaddr()
  220. }
  221. func (m *message) GetTypeMailaddr() (user, domain string, err error) {
  222. if err = m.GetType(mMAILADDR); err != nil {
  223. return
  224. }
  225. return m.GetMailaddr()
  226. }
  227. func (m *message) PutInt(v int) {
  228. var b [4]byte
  229. binary.LittleEndian.PutUint32(b[:], uint32(v))
  230. m.Data = append(m.Data, b[:]...)
  231. m.Header.Len += 4
  232. }
  233. func (m *message) PutUint32(v uint32) {
  234. var b [4]byte
  235. binary.LittleEndian.PutUint32(b[:], v)
  236. m.Data = append(m.Data, b[:]...)
  237. m.Header.Len += 4
  238. }
  239. func (m *message) PutString(s string) {
  240. m.Data = append(m.Data, append([]byte(s), 0)...)
  241. m.Header.Len += uint16(len(s)) + 1
  242. }
  243. func (m *message) PutID(id uint64) {
  244. var b [8]byte
  245. binary.LittleEndian.PutUint64(b[:], id)
  246. m.Data = append(m.Data, b[:]...)
  247. m.Header.Len += 8
  248. }
  249. func (m *message) PutType(t uint8) {
  250. m.Data = append(m.Data, t)
  251. m.Header.Len += 1
  252. }
  253. func (m *message) PutTypeInt(v int) {
  254. m.PutType(mINT)
  255. m.PutInt(v)
  256. }
  257. func (m *message) PutTypeUint32(v uint32) {
  258. m.PutType(mUINT32)
  259. m.PutUint32(v)
  260. }
  261. func (m *message) PutTypeString(s string) {
  262. m.PutType(mSTRING)
  263. m.PutString(s)
  264. }
  265. func (m *message) PutTypeID(id uint64) {
  266. m.PutType(mID)
  267. m.PutID(id)
  268. }