2018-01-09 00:24:51 +01:00
package main
import (
2018-10-15 17:56:04 +02:00
"bytes"
2018-01-09 19:47:24 +01:00
"encoding/binary"
"errors"
"net"
2018-10-15 17:56:04 +02:00
"os"
2024-02-20 02:11:03 +01:00
"path"
2018-01-17 17:03:42 +01:00
"strconv"
2018-01-17 16:06:30 +01:00
"strings"
"unicode"
2024-02-20 02:11:03 +01:00
"github.com/jedisct1/dlog"
2018-01-09 00:24:51 +01:00
)
type CryptoConstruction uint16
const (
UndefinedConstruction CryptoConstruction = iota
XSalsa20Poly1305
XChacha20Poly1305
)
2018-01-10 16:01:29 +01:00
const (
ClientMagicLen = 8
)
2018-02-04 11:31:54 +01:00
const (
2021-06-05 18:29:13 +02:00
MaxHTTPBodyLength = 1000000
2018-02-04 11:31:54 +01:00
)
2018-01-09 00:24:51 +01:00
var (
2019-10-12 21:15:39 +02:00
CertMagic = [ 4 ] byte { 0x44 , 0x4e , 0x53 , 0x43 }
ServerMagic = [ 8 ] byte { 0x72 , 0x36 , 0x66 , 0x6e , 0x76 , 0x57 , 0x6a , 0x38 }
MinDNSPacketSize = 12 + 5
MaxDNSPacketSize = 4096
MaxDNSUDPPacketSize = 4096
MaxDNSUDPSafePacketSize = 1252
InitialMinQuestionSize = 512
2018-01-09 00:24:51 +01:00
)
2018-06-13 16:52:41 +02:00
var (
2018-10-15 17:56:04 +02:00
FileDescriptors = make ( [ ] * os . File , 0 )
2020-06-18 23:51:50 +02:00
FileDescriptorNum = uintptr ( 0 )
)
const (
InheritedDescriptorsBase = uintptr ( 50 )
2018-06-13 16:52:41 +02:00
)
2018-01-09 19:47:24 +01:00
func PrefixWithSize ( packet [ ] byte ) ( [ ] byte , error ) {
2018-01-31 08:38:22 +01:00
packetLen := len ( packet )
if packetLen > 0xffff {
2018-01-09 19:47:24 +01:00
return packet , errors . New ( "Packet too large" )
}
packet = append ( append ( packet , 0 ) , 0 )
copy ( packet [ 2 : ] , packet [ : len ( packet ) - 2 ] )
binary . BigEndian . PutUint16 ( packet [ 0 : 2 ] , uint16 ( len ( packet ) - 2 ) )
return packet , nil
}
2018-06-06 15:54:51 +02:00
func ReadPrefixed ( conn * net . Conn ) ( [ ] byte , error ) {
2018-01-09 19:47:24 +01:00
buf := make ( [ ] byte , 2 + MaxDNSPacketSize )
packetLength , pos := - 1 , 0
for {
readnb , err := ( * conn ) . Read ( buf [ pos : ] )
if err != nil {
return buf , err
}
pos += readnb
if pos >= 2 && packetLength < 0 {
packetLength = int ( binary . BigEndian . Uint16 ( buf [ 0 : 2 ] ) )
if packetLength > MaxDNSPacketSize - 1 {
return buf , errors . New ( "Packet too large" )
}
2018-02-04 12:57:54 +01:00
if packetLength < MinDNSPacketSize {
return buf , errors . New ( "Packet too short" )
}
2018-01-09 19:47:24 +01:00
}
2018-04-16 02:05:28 +02:00
if packetLength >= 0 && pos >= 2 + packetLength {
2018-03-28 11:52:04 +02:00
return buf [ 2 : 2 + packetLength ] , nil
2018-01-09 19:47:24 +01:00
}
}
}
2018-01-09 16:40:37 +01:00
func Min ( a , b int ) int {
if a < b {
return a
}
return b
}
func Max ( a , b int ) int {
if a > b {
return a
}
return b
}
2018-01-17 02:40:47 +01:00
func StringReverse ( s string ) string {
r := [ ] rune ( s )
for i , j := 0 , len ( r ) - 1 ; i < len ( r ) / 2 ; i , j = i + 1 , j - 1 {
r [ i ] , r [ j ] = r [ j ] , r [ i ]
}
return string ( r )
}
2018-01-17 16:06:30 +01:00
func StringTwoFields ( str string ) ( string , string , bool ) {
if len ( str ) < 3 {
return "" , "" , false
}
pos := strings . IndexFunc ( str , unicode . IsSpace )
if pos == - 1 {
return "" , "" , false
}
2021-04-05 11:46:57 +02:00
a , b := strings . TrimSpace ( str [ : pos ] ) , strings . TrimSpace ( str [ pos + 1 : ] )
2018-01-17 16:06:30 +01:00
if len ( a ) == 0 || len ( b ) == 0 {
return a , b , false
}
return a , b , true
}
2018-01-17 17:03:42 +01:00
func StringQuote ( str string ) string {
str = strconv . QuoteToGraphic ( str )
return str [ 1 : len ( str ) - 1 ]
}
2018-03-28 11:52:04 +02:00
2019-10-12 22:22:28 +02:00
func StringStripSpaces ( str string ) string {
return strings . Map ( func ( r rune ) rune {
if unicode . IsSpace ( r ) {
return - 1
}
return r
} , str )
}
2020-01-25 15:45:23 +01:00
func TrimAndStripInlineComments ( str string ) string {
if idx := strings . LastIndexByte ( str , '#' ) ; idx >= 0 {
2020-01-30 16:16:05 +01:00
if idx == 0 || str [ 0 ] == '#' {
2020-01-25 15:45:23 +01:00
return ""
}
if prev := str [ idx - 1 ] ; prev == ' ' || prev == '\t' {
str = str [ : idx - 1 ]
}
}
2021-04-05 11:46:57 +02:00
return strings . TrimSpace ( str )
2020-01-25 15:45:23 +01:00
}
2018-03-28 12:08:05 +02:00
func ExtractHostAndPort ( str string , defaultPort int ) ( host string , port int ) {
host , port = str , defaultPort
if idx := strings . LastIndex ( str , ":" ) ; idx >= 0 && idx < len ( str ) - 1 {
if portX , err := strconv . Atoi ( str [ idx + 1 : ] ) ; err == nil {
host , port = host [ : idx ] , portX
}
}
return
}
2018-04-07 17:05:55 +02:00
2018-10-15 17:56:04 +02:00
func ReadTextFile ( filename string ) ( string , error ) {
2023-02-02 19:38:24 +01:00
bin , err := os . ReadFile ( filename )
2018-10-15 17:56:04 +02:00
if err != nil {
return "" , err
}
bin = bytes . TrimPrefix ( bin , [ ] byte { 0xef , 0xbb , 0xbf } )
return string ( bin ) , nil
}
2024-02-20 02:11:03 +01:00
2023-12-15 12:59:07 +01:00
func isDigit ( b byte ) bool { return b >= '0' && b <= '9' }
2024-02-20 02:11:03 +01:00
func maybeWritableByOtherUsers ( p string ) ( bool , string , error ) {
p = path . Clean ( p )
for p != "/" && p != "." {
st , err := os . Stat ( p )
if err != nil {
return false , p , err
}
mode := st . Mode ( )
2024-04-03 16:47:13 +02:00
if mode . Perm ( ) & 2 != 0 && ! ( st . IsDir ( ) && mode & os . ModeSticky == os . ModeSticky ) {
2024-02-20 02:11:03 +01:00
return true , p , nil
}
p = path . Dir ( p )
}
return false , "" , nil
}
func WarnIfMaybeWritableByOtherUsers ( p string ) {
if ok , px , err := maybeWritableByOtherUsers ( p ) ; ok {
if px == p {
dlog . Criticalf ( "[%s] is writable by other system users - If this is not intentional, it is recommended to fix the access permissions" , p )
} else {
dlog . Warnf ( "[%s] can be modified by other system users because [%s] is writable by other users - If this is not intentional, it is recommended to fix the access permissions" , p , px )
}
} else if err != nil {
dlog . Warnf ( "Error while checking if [%s] is accessible: [%s] : [%s]" , p , px , err )
}
}