removing sturn implementation

This commit is contained in:
Roland Osborne 2023-04-11 22:35:36 -07:00
parent 55e4bef78e
commit 3efe2f75ab
4 changed files with 0 additions and 1241 deletions

View File

@ -1,256 +0,0 @@
package sturn
import (
"crypto/md5"
"crypto/hmac"
"crypto/sha1"
"errors"
"strings"
"strconv"
"fmt"
)
func readAttribute(buf []byte, pos int) (error, *SturnAttribute, int) {
if len(buf) - pos < 4 {
return errors.New("invalid attribute length"), nil, 0
}
atrType := getAttributeType(buf[pos + 0], buf[pos + 1])
atrLength := int(buf[pos + 2]) * 256 + int(buf[pos + 3])
padLength := ((atrLength + 3) >> 2) << 2
if len(buf) - pos < 4 + padLength {
return errors.New("invalid attribute buffer"), nil, 0
}
attr := &SturnAttribute{ atrType: atrType }
if atrType == ATRRequestedTransport {
if buf[pos + 5] != 0x00 || buf[pos + 6] != 0x00 || buf[pos + 7] != 0x00 {
return errors.New("invalid attribute"), nil, 0
}
attr.intValue = int32(buf[pos + 4])
} else if atrType == ATRLifetime {
attr.intValue = 256 * (256 * (256 * int32(buf[pos + 4]) + int32(buf[pos + 5])) + int32(buf[pos + 6])) + int32(buf[pos + 7]);
} else if atrType == ATRNonce {
attr.strValue = string(buf[pos + 4:pos + 4+atrLength]);
} else if atrType == ATRUsername {
attr.strValue = string(buf[pos + 4:pos + 4+atrLength]);
} else if atrType == ATRRealm {
attr.strValue = string(buf[pos + 4:pos + 4+atrLength]);
} else if atrType == ATRMessageIntegrity {
//fmt.Println("HANDLE: ATRMessageIntegrity");
} else if atrType == ATRMessageIntegritySha256 {
//fmt.Println("HANDLE: ATRMessageIntegritySha256");
} else if atrType == ATRFingerprint {
//fmt.Println("HANDLE: ATRFingerprint");
} else if atrType == ATRXorPeerAddress {
if padLength != 8 {
return errors.New("invalid attribute size"), nil, 0
}
if buf[pos + 4] != 0 || buf[pos + 5] != FAMIPv4 {
return errors.New("unsupported protocol family"), nil, 0
}
attr.strValue = ""
attr.strValue += strconv.Itoa(int(buf[pos + 8] ^ 0x21))
attr.strValue += "."
attr.strValue += strconv.Itoa(int(buf[pos + 9] ^ 0x12))
attr.strValue += "."
attr.strValue += strconv.Itoa(int(buf[pos + 10] ^ 0xA4))
attr.strValue += "."
attr.strValue += strconv.Itoa(int(buf[pos + 11] ^ 0x42))
attr.intValue = int32(buf[pos + 6] ^ 0x21)
attr.intValue *= 256
attr.intValue += int32(buf[pos + 7] ^ 0x12)
} else if atrType == ATRData {
for i := 0; i < atrLength; i++ {
attr.binValue = append(attr.binValue, buf[pos + 4 + i])
}
} else {
fmt.Println("UNKNOWN ATTRIBUTE", atrType);
}
return nil, attr, 4 + padLength
}
func writeAttribute(attribute *SturnAttribute, buf []byte, pos int) (error, int) {
if len(buf) - pos < 4 {
return errors.New("invalid buffer size"), 0
}
if attribute.atrType == ATRXorMappedAddress {
if len(buf) - pos < 12 {
return errors.New("invalid buffer size"), 0
}
ip := 0
parts := strings.Split(attribute.strValue, ".");
for i := 0; i < 4; i++ {
val, _ := strconv.Atoi(parts[i]);
ip = (ip * 256) + val;
}
buf[pos + 1], buf[pos + 0] = setAttributeType(ATRXorMappedAddress);
buf[pos + 2] = 0x00
buf[pos + 3] = 0x08
buf[pos + 4] = 0x00
buf[pos + 5] = FAMIPv4
buf[pos + 6] = byte((attribute.intValue >> 8) % 256) ^ 0x21
buf[pos + 7] = byte((attribute.intValue) % 256) ^ 0x12
buf[pos + 8] = byte((ip >> 24) % 256) ^ 0x21
buf[pos + 9] = byte((ip >> 16) % 256) ^ 0x12
buf[pos + 10] = byte((ip >> 8) % 256) ^ 0xA4
buf[pos + 11] = byte(ip % 256) ^ 0x42
return nil, 12
} else if attribute.atrType == ATRXorRelayedAddress {
if len(buf) - pos < 12 {
return errors.New("invalid buffer size"), 0
}
ip := 0
parts := strings.Split(attribute.strValue, ".");
for i := 0; i < 4; i++ {
val, _ := strconv.Atoi(parts[i]);
ip = (ip * 256) + val;
}
buf[pos + 1], buf[pos + 0] = setAttributeType(ATRXorRelayedAddress);
buf[pos + 2] = 0x00
buf[pos + 3] = 0x08
buf[pos + 4] = 0x00
buf[pos + 5] = FAMIPv4
buf[pos + 6] = byte((attribute.intValue >> 8) % 256) ^ 0x21
buf[pos + 7] = byte(attribute.intValue % 256) ^ 0x12
buf[pos + 8] = byte((ip >> 24) % 256) ^ 0x21
buf[pos + 9] = byte((ip >> 16) % 256) ^ 0x12
buf[pos + 10] = byte((ip >> 8) % 256) ^ 0xA4
buf[pos + 11] = byte(ip % 256) ^ 0x42
return nil, 12
} else if attribute.atrType == ATRXorPeerAddress {
if len(buf) - pos < 12 {
return errors.New("invalid buffer size"), 0
}
ip := 0
parts := strings.Split(attribute.strValue, ".");
for i := 0; i < 4; i++ {
val, _ := strconv.Atoi(parts[i]);
ip = (ip * 256) + val;
}
buf[pos + 1], buf[pos + 0] = setAttributeType(ATRXorPeerAddress);
buf[pos + 2] = 0x00
buf[pos + 3] = 0x08
buf[pos + 4] = 0x00
buf[pos + 5] = FAMIPv4
buf[pos + 6] = byte((attribute.intValue >> 8) % 256) ^ 0x21
buf[pos + 7] = byte(attribute.intValue % 256) ^ 0x12
buf[pos + 8] = byte((ip >> 24) % 256) ^ 0x21
buf[pos + 9] = byte((ip >> 16) % 256) ^ 0x12
buf[pos + 10] = byte((ip >> 8) % 256) ^ 0xA4
buf[pos + 11] = byte(ip % 256) ^ 0x42
return nil, 12
} else if attribute.atrType == ATRData {
paddedLen := ((len(attribute.binValue) + 3) >> 2) << 2
if len(buf) - pos < 4 + paddedLen {
return errors.New("invalid buffer size"), 0
}
buf[pos + 1], buf[pos + 0] = setAttributeType(ATRData)
buf[pos + 2] = byte((len(attribute.binValue) >> 8) % 256)
buf[pos + 3] = byte(len(attribute.binValue) % 256)
for i := 0; i < len(attribute.binValue); i++ {
buf[pos + 4 + i] = attribute.binValue[i]
}
for i := len(attribute.binValue); i < paddedLen; i++ {
buf[pos + 4 + i] = 0x00
}
return nil, 4 + paddedLen
} else if attribute.atrType == ATRLifetime {
if len(buf) - pos < 8 {
return errors.New("invalid buffer size"), 0
}
buf[pos + 1], buf[pos + 0] = setAttributeType(ATRLifetime);
buf[pos + 2] = 0x00
buf[pos + 3] = 0x04
buf[pos + 4] = byte((attribute.intValue >> 24) % 256);
buf[pos + 5] = byte((attribute.intValue >> 16) % 256);
buf[pos + 6] = byte((attribute.intValue >> 8) % 256);
buf[pos + 7] = byte(attribute.intValue % 256);
return nil, 8
} else if attribute.atrType == ATRNonce {
raw := []byte(attribute.strValue)
rawLen := len(raw);
paddedLen := ((len(raw) + 3) >> 2) << 2
if paddedLen >= 256 {
return errors.New("invalid attribute size"), 0
}
if len(buf) - pos < 4 + paddedLen {
return errors.New("invalid buffer size"), 0
}
buf[pos + 1], buf[pos + 0] = setAttributeType(ATRNonce);
buf[pos + 2] = 0x00
buf[pos + 3] = byte(rawLen)
for i := 0; i < len(raw); i++ {
buf[pos + 4 + i] = raw[i];
}
for i := len(raw); i < paddedLen; i++ {
buf[pos + 4 + i] = 0x00;
}
return nil, 4 + paddedLen
} else if attribute.atrType == ATRRealm {
raw := []byte(attribute.strValue)
rawLen := len(raw);
paddedLen := ((len(raw) + 3) >> 2) << 2
if paddedLen >= 256 {
return errors.New("invalid attribute size"), 0
}
if len(buf) - pos < 4 + paddedLen {
return errors.New("invalid buffer size"), 0
}
buf[pos + 1], buf[pos + 0] = setAttributeType(ATRRealm);
buf[pos + 2] = 0x00
buf[pos + 3] = byte(rawLen);
for i := 0; i < len(raw); i++ {
buf[pos + 4 + i] = raw[i];
}
for i := len(raw); i < paddedLen; i++ {
buf[pos + 4 + i] = 0x00;
}
return nil, 4 + paddedLen
} else if attribute.atrType == ATRErrorCode {
if len(buf) - pos < 8 {
return errors.New("invalid buffer size"), 0
}
buf[pos + 1], buf[pos + 0] = setAttributeType(ATRErrorCode);
buf[pos + 2] = 0x00
buf[pos + 3] = 0x04
buf[pos + 4] = 0x00
buf[pos + 5] = 0x00
buf[pos + 6] = byte(attribute.intValue / 100)
buf[pos + 7] = byte(attribute.intValue % 100)
return nil, 8
} else if attribute.atrType == ATRMessageIntegrity {
buf[pos + 1], buf[pos + 0] = setAttributeType(ATRMessageIntegrity);
buf[pos + 2] = 0;
buf[pos + 3] = 0x14;
key := md5.Sum([]byte("user:databag.dweb:pass"));
// set hash size
lengthField0 := buf[2]
lengthField1 := buf[3]
hashLength := pos + 4
buf[2] = byte((hashLength >> 8) % 256);
buf[3] = byte(hashLength % 256);
hash := getHmac(key[:], buf[0:pos]);
buf[2] = lengthField0
buf[3] = lengthField1
for i := 0; i < 20; i++ {
buf[4 + pos + i] = hash[i];
}
return nil, 24
} else {
fmt.Println("UNKNOWN!");
}
return nil, 8
}
func getHmac(key []byte, data []byte) []byte {
mac := hmac.New(sha1.New, key)
mac.Write(data)
return mac.Sum(nil)
}

View File

@ -1,480 +0,0 @@
package sturn
import (
"net"
"fmt"
"errors"
"bytes"
"strings"
"strconv"
)
func readMessage(buf []byte) (error, *SturnMessage) {
if len(buf) < 20 {
return errors.New("invalid header size"), nil
}
if buf[0] & 0xC0 != 0 {
return errors.New("invalid message prefix"), nil
}
magic := []byte{0x21, 0x12, 0xA4, 0x42 }
if !bytes.Equal(magic, buf[4:8]) {
return errors.New("invalid message cookie"), nil
}
atrLength := int(buf[2]) * 256 + int(buf[3])
if atrLength + 20 != len(buf) {
return errors.New("invalid message length"), nil
}
class, method := getMessageType(buf[0], buf[1]);
transaction := buf[8:20];
var attributes []SturnAttribute
var pos int = 0
for pos < atrLength {
err, attr, n := readAttribute(buf, pos + 20)
if err != nil {
return err, nil
}
pos += n
attributes = append(attributes, *attr);
}
return nil, &SturnMessage{
class: class,
method: method,
transaction: transaction,
attributes: attributes,
}
}
func writeMessage(msg *SturnMessage, buf []byte) (error, int) {
if len(buf) < 20 {
return errors.New("invalid buffer length"), 0
}
// set prefix
buf[0], buf[1] = setMessageType(msg.class, msg.method)
// init size
buf[2] = 0x00
buf[3] = 0x00
// set cookie
buf[4] = 0x21
buf[5] = 0x12
buf[6] = 0xA4
buf[7] = 0x42
// set transaction
for i := 0; i < 12; i++ {
buf[8 + i] = msg.transaction[i];
}
// set each attribute
pos := 0
for _, attribute := range msg.attributes {
err, n := writeAttribute(&attribute, buf, 20 + pos);
if err != nil {
return err, 0
}
pos += n;
// set size
buf[2] = byte((pos >> 8) % 256);
buf[3] = byte(pos % 256);
}
return nil, pos + 20;
}
func (s *Sturn) handleMessage(buf []byte, addr net.Addr) {
err, msg := readMessage(buf);
if err != nil {
fmt.Println(err, addr.String(), buf);
return
}
if msg == nil {
return
}
if msg.class == CLSRequest && msg.method == MEHBinding {
fmt.Println("stun/turn binding request");
s.handleBindingRequest(msg, addr);
} else if msg.class == CLSRequest && msg.method == MEHAllocate {
fmt.Println("stun/turn allocate request");
s.handleAllocateRequest(msg, addr);
} else if msg.class == CLSRequest && msg.method == MEHRefresh {
fmt.Println("stun/turn refresh request");
s.handleRefreshRequest(msg, addr);
} else if msg.class == CLSRequest && msg.method == MEHCreatePermission {
fmt.Println("stun/turn create permission request");
s.handleCreatePermissionRequest(msg, addr);
} else if msg.class == CLSIndication && msg.method == MEHSend {
fmt.Println("stun/turn send");
s.handleSendIndication(msg, addr, buf);
} else {
fmt.Println("unsupported message", buf);
}
}
func (s *Sturn) sendRequestError(msg *SturnMessage, addr net.Addr, code int32) {
var attributes []SturnAttribute
attributes = append(attributes, SturnAttribute{
atrType: ATRErrorCode,
intValue: code,
})
attributes = append(attributes, SturnAttribute{
atrType: ATRNonce,
strValue: "",
})
attributes = append(attributes, SturnAttribute{
atrType: ATRRealm,
strValue: "databag.dweb",
})
response := &SturnMessage{
class: CLSError,
method: msg.method,
transaction: msg.transaction,
attributes: attributes,
};
err, n := writeMessage(response, s.buf);
if err != nil {
fmt.Printf("failed to write stun response");
} else {
(*s.conn).WriteTo(s.buf[:n], addr);
}
}
func (s *Sturn) handleCreatePermissionRequest(msg *SturnMessage, addr net.Addr) {
username := getAttribute(msg, ATRUsername)
if username == nil {
fmt.Println("no username", addr.String(), msg.transaction);
s.sendRequestError(msg, addr, 401)
return
}
permission := getAttribute(msg, ATRXorPeerAddress)
if permission == nil {
fmt.Println("no peer");
s.sendRequestError(msg, addr, 400)
return
}
s.sync.Lock();
defer s.sync.Unlock();
_, set := sturn.sessions[username.strValue]
if !set {
fmt.Println("no session", addr.String());
s.sendRequestError(msg, addr, 401)
return
}
source := addr.String()
allocation, found := s.allocations[source]
if !found {
fmt.Println("no allocation");
s.sendRequestError(msg, addr, 400)
return
}
allocation.permissions = append(allocation.permissions, permission.strValue);
var attributes []SturnAttribute
attributes = append(attributes, SturnAttribute{
atrType: ATRMessageIntegrity,
});
response := &SturnMessage{
class: CLSResponse,
method: MEHCreatePermission,
transaction: msg.transaction,
attributes: attributes,
};
err, n := writeMessage(response, s.buf);
if err != nil {
fmt.Printf("failed to write stun response");
} else {
(*s.conn).WriteTo(s.buf[:n], addr);
}
return
}
func (s *Sturn) handleSendIndication(msg *SturnMessage, addr net.Addr, buf []byte) {
peer := getAttribute(msg, ATRXorPeerAddress)
if peer == nil {
fmt.Println("no peer");
return
}
data := getAttribute(msg, ATRData)
if data == nil {
fmt.Println("no data");
return
}
s.sync.Lock();
defer s.sync.Unlock();
source := addr.String()
allocation, found := s.allocations[source]
if !found {
fmt.Println("no allocation");
return
}
set := false
for _, permission := range allocation.permissions {
if permission == peer.strValue {
address := fmt.Sprintf("%s:%d", peer.strValue, peer.intValue)
dst, err := net.ResolveUDPAddr("udp", address)
if err != nil {
fmt.Println("no resolve");
return
}
set = true
fmt.Println("stun/turn data", dst.String());
_, err = allocation.conn.WriteTo(data.binValue, dst)
if err != nil {
fmt.Println("write error");
}
}
}
if !set {
fmt.Println("dropped indication");
}
}
func (s *Sturn) handleBindingRequest(msg *SturnMessage, addr net.Addr) {
address := strings.Split(addr.String(), ":")
ip := address[0];
port, _ := strconv.Atoi(address[1]);
var attributes []SturnAttribute
attributes = append(attributes, SturnAttribute{
atrType: ATRXorMappedAddress,
byteValue: FAMIPv4,
intValue: int32(port),
strValue: ip,
});
response := &SturnMessage{
class: CLSResponse,
method: MEHBinding,
transaction: msg.transaction,
attributes: attributes,
};
err, n := writeMessage(response, s.buf);
if err != nil {
fmt.Printf("failed to write stun response");
} else {
(*s.conn).WriteTo(s.buf[:n], addr);
}
return
}
func (s *Sturn) handleRefreshRequest(msg *SturnMessage, addr net.Addr) {
response := &SturnMessage{
class: CLSResponse,
method: MEHRefresh,
transaction: msg.transaction,
attributes: []SturnAttribute{},
};
err, n := writeMessage(response, s.buf);
if err != nil {
fmt.Printf("failed to write stun response");
} else {
(*s.conn).WriteTo(s.buf[:n], addr);
}
return
}
func (s *Sturn) setAllocation(addr net.Addr, transaction []byte, response []byte, port int, conn net.PacketConn, session *SturnSession) (*SturnAllocation) {
source := addr.String()
allocation := &SturnAllocation{}
allocation.port = port
allocation.conn = conn
allocation.source = source
allocation.addr = addr
allocation.transaction = make([]byte, len(transaction))
copy(allocation.transaction, transaction)
allocation.response = make([]byte, len(response))
copy(allocation.response, response)
s.allocations[source] = allocation
return allocation
}
func (s *Sturn) getAllocation(source string, transaction []byte, session *SturnSession) (*SturnAllocation, error) {
for _, allocation := range s.allocations {
if allocation.source == source {
if len(allocation.transaction) == len(transaction) {
match := true
for i := 0; i < len(transaction); i++ {
if transaction[i] != allocation.transaction[i] {
match = false
}
}
if match {
return allocation, nil
}
}
return nil, errors.New("5-tuple collision")
}
}
return nil, nil
}
func (s *Sturn) handleAllocateRequest(msg *SturnMessage, addr net.Addr) {
username := getAttribute(msg, ATRUsername)
if username == nil {
fmt.Println("no username", addr.String(), msg.transaction);
s.sendRequestError(msg, addr, 401)
return
}
s.sync.Lock();
defer s.sync.Unlock();
session, set := sturn.sessions[username.strValue]
if !set {
fmt.Println("no session", addr.String());
s.sendRequestError(msg, addr, 401)
return
}
allocation, collision := s.getAllocation(addr.String(), msg.transaction, session)
if collision != nil {
fmt.Println("5tuple collision", addr.String())
s.sendRequestError(msg, addr, 403)
return
}
if allocation != nil {
fmt.Println("dup request", addr.String())
(*s.conn).WriteTo(allocation.response, addr)
return
}
relayPort, err := s.getRelayPort()
if err != nil {
fmt.Println(err);
s.sendRequestError(msg, addr, 508)
return
}
connAddress := fmt.Sprintf(":%d", relayPort)
conn, connErr := net.ListenPacket("udp", connAddress)
if connErr != nil {
s.sendRequestError(msg, addr, 500)
return
}
address := strings.Split(addr.String(), ":")
ip := address[0];
port, _ := strconv.Atoi(address[1]);
var attributes []SturnAttribute
attributes = append(attributes, SturnAttribute{
atrType: ATRXorRelayedAddress,
byteValue: FAMIPv4,
intValue: int32(relayPort),
//strValue: "192.168.13.233",
strValue: "98.234.232.221",
});
attributes = append(attributes, SturnAttribute{
atrType: ATRLifetime,
intValue: int32(600),
});
attributes = append(attributes, SturnAttribute{
atrType: ATRXorMappedAddress,
byteValue: FAMIPv4,
intValue: int32(port),
strValue: ip,
});
attributes = append(attributes, SturnAttribute{
atrType: ATRMessageIntegrity,
});
response := &SturnMessage{
class: CLSResponse,
method: MEHAllocate,
transaction: msg.transaction,
attributes: attributes,
};
err, n := writeMessage(response, s.buf)
if err != nil {
fmt.Printf("failed to write stun response")
} else {
allocation := s.setAllocation(addr, msg.transaction, s.buf[:n], relayPort, conn, session)
(*s.conn).WriteTo(s.buf[:n], addr)
fmt.Println("allocated: ", addr.String())
go s.relay(allocation);
}
return
}
func getAttribute(msg *SturnMessage, atrType int) (attr *SturnAttribute) {
for i, _ := range msg.attributes {
if msg.attributes[i].atrType == atrType {
attr = &msg.attributes[i];
}
}
return
}
func (s *Sturn) relay(allocation *SturnAllocation) {
data := make([]byte, SturnMaxSize)
buf := make([]byte, SturnMaxSize)
for {
n, addr, err := allocation.conn.ReadFrom(data)
if err != nil {
fmt.Println(err)
// CLEANUP ALLOCATION
return
}
s.sync.Lock();
split := strings.Split(addr.String(), ":")
ip := split[0]
port, _ := strconv.Atoi(split[1]);
set := false
for _, permission := range allocation.permissions {
if permission == ip {
var attributes []SturnAttribute
attributes = append(attributes, SturnAttribute{
atrType: ATRXorPeerAddress,
strValue: ip,
intValue: int32(port),
})
attributes = append(attributes, SturnAttribute{
atrType: ATRData,
binValue: data[:n],
})
relay := &SturnMessage{
class: CLSIndication,
method: MEHData,
transaction: []byte{ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
attributes: attributes,
};
err, l := writeMessage(relay, buf)
if err != nil {
fmt.Println("no resolve");
} else {
fmt.Println("---- stun/turn relay", allocation.addr.String());
_, err := allocation.conn.WriteTo(buf[:l], allocation.addr);
set = true
if err != nil {
fmt.Println("writeto failed");
}
}
}
}
if !set {
fmt.Println("dropped relay");
}
s.sync.Unlock();
}
}

View File

@ -1,171 +0,0 @@
package sturn
import (
// "encoding/json"
"encoding/hex"
"sync"
"github.com/theckman/go-securerandom"
// "time"
"errors"
"fmt"
"net"
)
var sturn *Sturn
const SturnKeepAlive = 3600
const SturnMaxSize = 1024
const SturnMaxBindFail = 16
const SturnNonceSize = 8
const SturnPassSize = 8
type SturnAllocation struct {
source string
transaction []byte
response []byte
port int
permissions []string
conn net.PacketConn
addr net.Addr
}
type SturnSession struct {
user string
auth string
relayPorts []int
}
type Sturn struct {
sync sync.Mutex
sessionId int
sessions map[string]*SturnSession
closing bool
port int
conn *net.PacketConn
closed chan bool
buf []byte
publicIp string
relayStart int
relayCount int
relayPorts map[int]bool
relayIndex int
allocations map[string]*SturnAllocation
}
func Listen(port int, relayStart int, relayCount int) (error) {
if (sturn != nil) {
(*sturn.conn).Close()
<-sturn.closed
sturn = nil
}
address := fmt.Sprintf(":%d", port)
conn, err := net.ListenPacket("udp", address)
if err != nil {
return err
}
relayPorts := make(map[int]bool)
for i := 0; i < relayCount; i++ {
relayPorts[i] = true
}
sturn = &Sturn{
sessionId: 0,
closing: false,
port: port,
relayStart: relayStart,
relayCount: relayCount,
relayPorts: relayPorts,
conn: &conn,
buf: make([]byte, SturnMaxSize),
sessions: make(map[string]*SturnSession),
allocations: make(map[string]*SturnAllocation),
}
go sturn.serve(conn);
return nil
}
func Close() {
if (sturn != nil) {
(*sturn.conn).Close()
<-sturn.closed
sturn = nil
}
}
func (s *Sturn) serve(conn net.PacketConn) {
for {
buf := make([]byte, SturnMaxSize)
n, addr, err := conn.ReadFrom(buf)
if err != nil {
fmt.Println(err)
return
}
s.handleMessage(buf[:n], addr);
}
s.sync.Lock()
s.closing = true
for _, session := range s.sessions {
// TODO cleanup session
fmt.Println(session)
}
s.sync.Unlock()
s.closed <- true
}
func TestSession() {
if sturn != nil {
sturn.sync.Lock()
defer sturn.sync.Unlock()
if sturn.closing {
return
}
session := &SturnSession{
user: "user",
auth: "pass",
}
sturn.sessions["user"] = session
}
}
func (s *Sturn) addSession() (*SturnSession, error) {
s.sync.Lock()
defer s.sync.Unlock()
if !s.closing {
return nil, errors.New("closing sturn")
}
s.sessionId += 1
user := fmt.Sprintf("%08d", s.sessionId)
authBin, authErr := securerandom.Bytes(SturnPassSize)
if authErr != nil {
return nil, authErr
}
session := &SturnSession{
user: user,
auth: hex.EncodeToString(authBin),
}
s.sessions[user] = session
return session, nil
}
func (s *Sturn) getRelayPort() (int, error) {
s.relayIndex += 1;
for i := 0; i < s.relayCount; i++ {
key := (i + s.relayIndex) % s.relayCount;
if s.relayPorts[key] {
s.relayPorts[key] = false
return s.relayStart + key, nil
}
}
return 0, errors.New("no available relay port")
}
func (s *Sturn) setRelayPort(port int) {
key := port - s.relayStart
s.relayPorts[key] = true
}

View File

@ -1,334 +0,0 @@
package sturn
const CLSUnknown = 0
const CLSRequest = 1
const CLSResponse = 2
const CLSError = 3
const CLSIndication = 4
const ATRUnknown = 0
const ATRMappedAddress = 1
const ATRUsername = 2
const ATRMessageIntegrity = 3
const ATRErrorCode = 4
const ATRUnknownAttributes = 5
const ATRRealm = 6
const ATRNonce = 7
const ATRXorMappedAddress = 8
const ATRSoftware = 9
const ATRAlternateServer = 10
const ATRFingerprint = 11
const ATRMessageIntegritySha256 = 12
const ATRPasswordAlgorithm = 13
const ATRUserHash = 14
const ATRPasswordAlgorithms = 15
const ATRAlternateDomain = 16
const ATRChannelNumber = 17
const ATRLifetime = 18
const ATRXorPeerAddress = 19
const ATRData = 20
const ATRXorRelayedAddress = 21
const ATREvenPort = 22
const ATRRequestedTransport = 23
const ATRDontFragment = 24
const ATRReservationToken = 25
const ATRAdditionalAddressFamily = 26
const ATRAddressErrorCode = 27
const ATRAddressIcmp = 28
const ATRRequestedAddressFamily = 29
const MEHUnknown = 0
const MEHBinding = 1
const MEHAllocate = 2
const MEHRefresh = 3
const MEHSend = 4
const MEHData = 5
const MEHCreatePermission = 6
const MEHChannelBind = 7
const FAMIPv4 = 1
const FAMIPv6 = 2
type SturnAttribute struct {
atrType int
byteValue byte
strValue string
intValue int32
binValue []byte
}
type SturnMessage struct {
class int
method int
transaction []byte
attributes []SturnAttribute
}
func getMessageType(b0 byte, b1 byte) (int, int) {
if b0 == 0x00 && b1 == 0x01 {
return CLSRequest, MEHBinding
}
if b0 == 0x01 && b1 == 0x01 {
return CLSResponse, MEHBinding
}
if b0 == 0x01 && b1 == 0x11 {
return CLSError, MEHBinding
}
if b0 == 0x00 && b1 == 0x03 {
return CLSRequest, MEHAllocate
}
if b0 == 0x01 && b1 == 0x03 {
return CLSResponse, MEHAllocate
}
if b0 == 0x01 && b1 == 0x13 {
return CLSError, MEHAllocate
}
if b0 == 0x00 && b1 == 0x04 {
return CLSRequest, MEHRefresh
}
if b0 == 0x01 && b1 == 0x04 {
return CLSResponse, MEHRefresh
}
if b0 == 0x01 && b1 == 0x14 {
return CLSError, MEHRefresh
}
if b0 == 0x00 && b1 == 0x08 {
return CLSRequest, MEHCreatePermission
}
if b0 == 0x01 && b1 == 0x08 {
return CLSResponse, MEHCreatePermission
}
if b0 == 0x01 && b1 == 0x18 {
return CLSError, MEHCreatePermission
}
if b0 == 0x00 && b1 == 0x09 {
return CLSRequest, MEHChannelBind
}
if b0 == 0x01 && b1 == 0x09 {
return CLSResponse, MEHChannelBind
}
if b0 == 0x01 && b1 == 0x19 {
return CLSError, MEHChannelBind
}
if b0 == 0x00 && b1 == 0x16 {
return CLSIndication, MEHSend
}
if b0 == 0x00 && b1 == 0x17 {
return CLSIndication, MEHData
}
return CLSUnknown, MEHUnknown
}
func setMessageType(class int, method int) (byte, byte) {
if class == CLSRequest && method == MEHBinding {
return 0x00, 0x01
}
if class == CLSResponse && method == MEHBinding {
return 0x01, 0x01
}
if class == CLSError && method == MEHBinding {
return 0x01, 0x11
}
if class == CLSRequest && method == MEHAllocate {
return 0x00, 0x03
}
if class == CLSResponse && method == MEHAllocate {
return 0x01, 0x03
}
if class == CLSError && method == MEHAllocate {
return 0x01, 0x13
}
if class == CLSResponse && method == MEHCreatePermission {
return 0x01, 0x08
}
if class == CLSError && method == MEHCreatePermission {
return 0x01, 0x18
}
if class == CLSIndication && method == MEHData {
return 0x00, 0x17
}
return 0x00, 0x00
}
func getAttributeType(b0 byte, b1 byte) (int) {
if b1 == 0x01 && b0 == 0x00 {
return ATRMappedAddress
}
if b1 == 0x06 && b0 == 0x00 {
return ATRUsername
}
if b1 == 0x08 && b0 == 0x00 {
return ATRMessageIntegrity
}
if b1 == 0x09 && b0 == 0x00 {
return ATRErrorCode
}
if b1 == 0x0A && b0 == 0x00 {
return ATRUnknownAttributes
}
if b1 == 0x14 && b0 == 0x00 {
return ATRRealm
}
if b1 == 0x15 && b0 == 0x00 {
return ATRNonce
}
if b1 == 0x20 && b0 == 0x00 {
return ATRXorMappedAddress
}
if b1 == 0x22 && b0 == 0x80 {
return ATRSoftware
}
if b1 == 0x23 && b0 == 0x80 {
return ATRAlternateServer
}
if b1 == 0x28 && b0 == 0x80 {
return ATRFingerprint
}
if b1 == 0x1C && b0 == 0x00 {
return ATRMessageIntegritySha256
}
if b1 == 0x1D && b0 == 0x00 {
return ATRPasswordAlgorithms
}
if b1 == 0x1E && b0 == 0x00 {
return ATRUserHash
}
if b1 == 0x02 && b0 == 0x80 {
return ATRPasswordAlgorithms
}
if b1 == 0x03 && b0 == 0x80 {
return ATRAlternateDomain
}
if b1 == 0x0C && b0 == 0x00 {
return ATRChannelNumber
}
if b1 == 0x0D && b0 == 0x00 {
return ATRLifetime
}
if b1 == 0x12 && b0 == 0x00 {
return ATRXorPeerAddress
}
if b1 == 0x13 && b0 == 0x00 {
return ATRData
}
if b1 == 0x16 && b0 == 0x00 {
return ATRXorRelayedAddress
}
if b1 == 0x17 && b0 == 0x00 {
return ATRRequestedAddressFamily
}
if b1 == 0x18 && b0 == 0x00 {
return ATREvenPort
}
if b1 == 0x19 && b0 == 0x00 {
return ATRRequestedTransport
}
if b1 == 0x1A && b0 == 0x00 {
return ATRDontFragment
}
if b1 == 0x22 && b0 == 0x00 {
return ATRReservationToken
}
if b1 == 0x00 && b0 == 0x80 {
return ATRAdditionalAddressFamily
}
if b1 == 0x01 && b0 == 0x80 {
return ATRAddressErrorCode
}
if b1 == 0x04 && b0 == 0x80 {
return ATRAddressIcmp
}
return ATRUnknown
}
func setAttributeType(atrType int) (byte, byte) {
if atrType == ATRMappedAddress {
return 0x01, 0x00
}
if atrType == ATRUsername {
return 0x06, 0x00
}
if atrType == ATRMessageIntegrity {
return 0x08, 0x00
}
if atrType == ATRErrorCode {
return 0x09, 0x00
}
if atrType == ATRUnknownAttributes {
return 0x0A, 0x00
}
if atrType == ATRRealm {
return 0x14, 0x00
}
if atrType == ATRNonce {
return 0x15, 0x00
}
if atrType == ATRXorMappedAddress {
return 0x20, 0x00
}
if atrType == ATRSoftware {
return 0x22, 0x80
}
if atrType == ATRAlternateServer {
return 0x23, 0x80
}
if atrType == ATRFingerprint {
return 0x28, 0x80
}
if atrType == ATRMessageIntegritySha256 {
return 0x1C, 0x00
}
if atrType == ATRPasswordAlgorithms {
return 0x1D, 0x00
}
if atrType == ATRUserHash {
return 0x1E, 0x00
}
if atrType == ATRPasswordAlgorithms {
return 0x02, 0x80
}
if atrType == ATRAlternateDomain {
return 0x03, 0x80
}
if atrType == ATRChannelNumber {
return 0x0C, 0x00
}
if atrType == ATRLifetime {
return 0x0D, 0x00
}
if atrType == ATRXorPeerAddress {
return 0x12, 0x00
}
if atrType == ATRData {
return 0x13, 0x00
}
if atrType == ATRXorRelayedAddress {
return 0x16, 0x00
}
if atrType == ATRRequestedAddressFamily {
return 0x17, 0x00
}
if atrType == ATREvenPort {
return 0x18, 0x00
}
if atrType == ATRRequestedTransport {
return 0x19, 0x00
}
if atrType == ATRDontFragment {
return 0x1A, 0x00
}
if atrType == ATRReservationToken {
return 0x22, 0x00
}
if atrType == ATRAdditionalAddressFamily {
return 0x00, 0x80
}
if atrType == ATRAddressErrorCode {
return 0x01, 0x80
}
if atrType == ATRAddressIcmp {
return 0x04, 0x80
}
return 0x00, 0x00
}