Advertisement
FlyFar

receiver.go

Jan 20th, 2024
877
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 2.40 KB | Cybersecurity | 0 0
  1. package main
  2.  
  3. /*
  4.  * receiver.go
  5.  * Receive data from the network, unpack/unencrypt it
  6.  * By J. Stuart McMurray
  7.  * Created 20160226
  8.  * Last Modified 20160226
  9.  */
  10.  
  11. import (
  12.     "fmt"
  13.     "io"
  14.     "net"
  15.  
  16.     "golang.org/x/crypto/nacl/secretbox"
  17. )
  18.  
  19. const (
  20.     IP4HLEN = 20 /* IPv4 Header Length */
  21.     IP6HLEN = 40 /* IPv6 Header Length */
  22. )
  23.  
  24. /* recv receives packets from in, decrypts them, and sends to out.  If there
  25. is an error, it will be sent to ec. */
  26. func recv(out io.Writer, in *net.IPConn, key [KEYLEN]byte, ec chan<- error) {
  27.     if err := xmit(out, in, key, unroll); nil != err {
  28.         ec <- err
  29.     }
  30.     ec <- nil
  31. }
  32.  
  33. /* unroll takes the packet in msg, chops off the IP header, decrypts the
  34. packet, puts the plaintext in buf, and returns buf.  Non-fatal errors will
  35. cause a log message to be printed, but no error will be returned. */
  36. func unroll(buf, msg []byte, key [KEYLEN]byte) ([]byte, error) {
  37.     buf = buf[0:0]
  38.     /* Get the nonce and ciphertext */
  39.     nonce, msg, err := splitPacket(msg)
  40.     if nil != err {
  41.         return buf, err
  42.     }
  43.     ok := false
  44.     buf, ok = secretbox.Open(buf, msg, &nonce, &key)
  45.     if !ok {
  46.         return buf, fmt.Errorf("decrypt failed")
  47.     }
  48.     return buf, nil
  49. }
  50.  
  51. /* splitPacket returns the nonce and payload from a packet. */
  52. func splitPacket(msg []byte) (
  53.     nonce [NONCELEN]byte,
  54.     payload []byte,
  55.     err error,
  56. ) {
  57.     /* Remove the header */
  58.     msg, err = chopHeader(msg)
  59.     if nil != err {
  60.         return nonce, msg, err
  61.     }
  62.  
  63.     /* If there's no bytes left, it's probably a heartbeet */
  64.     if 0 == len(msg) {
  65.         return nonce, msg, HeartBeetError
  66.     }
  67.  
  68.     /* Pull off the nonce */
  69.     if NONCELEN > len(msg) {
  70.         return nonce, msg, fmt.Errorf(
  71.             "packet body too small for nonce: %02X",
  72.             msg,
  73.         )
  74.     }
  75.     for i, _ := range nonce {
  76.         nonce[i] = msg[i]
  77.     }
  78.  
  79.     /* The rest is the payload */
  80.     payload = msg[NONCELEN:]
  81.  
  82.     return nonce, payload, err
  83. }
  84.  
  85. /* chopHeader reslices pkt to remove the IP header. */
  86. func chopHeader(pkt []byte) ([]byte, error) {
  87.     /* Switch by IP version */
  88.     switch (pkt[0] & 0xF0) >> 4 {
  89.     case 4:
  90.         if IP4HLEN > len(pkt) {
  91.             return pkt, fmt.Errorf(
  92.                 "message too small (<%v bytes)",
  93.                 IP4HLEN,
  94.             )
  95.         }
  96.         pkt = pkt[IP4HLEN:]
  97.     case 6:
  98.         if IP6HLEN > len(pkt) {
  99.             return pkt, fmt.Errorf(
  100.                 "message too small (<%v bytes)",
  101.                 IP6HLEN,
  102.             )
  103.         }
  104.         pkt = pkt[IP6HLEN:]
  105.     default:
  106.         return pkt, fmt.Errorf(
  107.             "unknown IP version: %02X",
  108.             pkt,
  109.         )
  110.     }
  111.     return pkt, nil
  112. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement