github.com/DataDog/datadog-agent/pkg/security/secl@v0.55.0-devel.0.20240517055856-10c4965fea94/model/dns_helpers_linux.go (about) 1 // Unless explicitly stated otherwise all files in this repository are licensed 2 // under the Apache License Version 2.0. 3 // This product includes software developed at Datadog (https://www.datadoghq.com/). 4 // Copyright 2016-present Datadog, Inc. 5 6 //go:build linux 7 8 // Package model holds model related files 9 package model 10 11 import ( 12 "errors" 13 "strings" 14 ) 15 16 var ( 17 // ErrDNSNamePointerNotSupported reported because pointer compression is not supported 18 ErrDNSNamePointerNotSupported = errors.New("dns name pointer compression is not supported") 19 // ErrDNSNameOutOfBounds reported because name out of bound 20 ErrDNSNameOutOfBounds = errors.New("dns name out of bound") 21 // ErrDNSNameNonPrintableASCII reported because name non-printable ascii 22 ErrDNSNameNonPrintableASCII = errors.New("dns name non-printable ascii") 23 // ErrDNSNameMalformatted reported because name mal formatted (too short, missing dots, etc) 24 ErrDNSNameMalformatted = errors.New("dns name mal-formatted") 25 ) 26 27 // DNSPreallocSize defines DNS pre-alloc size 28 const DNSPreallocSize = 256 29 30 func decodeDNSName(raw []byte) (string, error) { 31 var ( 32 i = 0 33 rawLen = len(raw) 34 atStart = true 35 rep strings.Builder 36 err error 37 ) 38 39 rep.Grow(DNSPreallocSize) 40 41 LOOP: 42 for i < rawLen { 43 // Parse label length 44 labelLen := int(raw[i]) 45 i++ 46 47 if labelLen == 0 { 48 // end of name 49 break 50 } 51 52 if labelLen&0xC0 != 0 { 53 // pointer compression, we do not support this yet 54 err = ErrDNSNamePointerNotSupported 55 break 56 } 57 58 if rawLen < i+labelLen { 59 // out of bounds 60 err = ErrDNSNameOutOfBounds 61 break 62 } 63 64 labelRaw := raw[i : i+labelLen] 65 66 if !atStart { 67 rep.WriteRune('.') 68 } 69 for _, c := range labelRaw { 70 if c < ' ' || '~' < c { 71 // non-printable ascii char 72 err = ErrDNSNameNonPrintableASCII 73 break LOOP 74 } 75 } 76 rep.Write(labelRaw) 77 78 atStart = false 79 i += labelLen 80 } 81 82 return rep.String(), err 83 } 84 85 func validateDNSName(dns string) error { 86 if dns == "" { 87 return nil 88 } 89 90 // Maximum length of the DNS name field in the DNS protocol is 255 bytes: 91 // 92 // <------------- 255 ---------------> 93 // | X | ... | Y | ... | Z | ... | 0 | 94 // 95 // If you remove the trailing 0 and the first X (which isn't turned into a `.` in the string representation), you 96 // get a maximum printable characters length of 253. 97 if len(dns) > 253 { 98 return ErrDNSNameMalformatted 99 } 100 101 // Check that the DNS doesn't start or end with a dot. 102 if dns[0] == '.' || dns[len(dns)-1] == '.' { 103 return ErrDNSNameMalformatted 104 } 105 106 // Check that each label isn't empty and at most 63 characters. 107 previousIndex := -1 108 for previousIndex < len(dns) { 109 delta := strings.IndexByte(dns[previousIndex+1:], '.') 110 if delta < 0 { 111 break 112 } 113 114 if delta < 1 || delta > 63 { 115 return ErrDNSNameMalformatted 116 } 117 118 previousIndex += delta + 1 119 } 120 121 return nil 122 }