func (r *Realm) parseLines(name string, lines []string) (err error) {
	r.Realm = name
	var adminServerFinal bool
	var KDCFinal bool
	var kpasswdServerFinal bool
	var masterKDCFinal bool
	var ignore bool
	var c int  
	for _, line := range lines {
		if ignore && c > 0 && !strings.Contains(line, "{") && !strings.Contains(line, "}") {
			continue
		}
		if idx := strings.IndexAny(line, "#;"); idx != -1 {
			line = line[:idx]
		}
		line = strings.TrimSpace(line)
		if line == "" {
			continue
		}
		if !strings.Contains(line, "=") && !strings.Contains(line, "}") {
			return InvalidErrorf("realms section line (%s)", line)
		}
		if strings.Contains(line, "v4_") {
			ignore = true
			err = UnsupportedDirective{"v4 configurations are not supported"}
		}
		if strings.Contains(line, "{") {
			c++
			if ignore {
				continue
			}
		}
		if strings.Contains(line, "}") {
			c--
			if c < 0 {
				return InvalidErrorf("unpaired curly brackets")
			}
			if ignore {
				if c < 1 {
					c = 0
					ignore = false
				}
				continue
			}
		}
		p := strings.Split(line, "=")
		key := strings.TrimSpace(strings.ToLower(p[0]))
		v := strings.TrimSpace(p[1])
		switch key {
		case "admin_server":
			appendUntilFinal(&r.AdminServer, v, &adminServerFinal)
		case "default_domain":
			r.DefaultDomain = v
		case "kdc":
			if !strings.Contains(v, ":") {
				if strings.HasSuffix(v, `*`) {
					v = strings.TrimSpace(strings.TrimSuffix(v, `*`)) + ":88*"
				} else {
					v = strings.TrimSpace(v) + ":88"
				}
			}
			appendUntilFinal(&r.KDC, v, &KDCFinal)
		case "kpasswd_server":
			appendUntilFinal(&r.KPasswdServer, v, &kpasswdServerFinal)
		case "master_kdc":
			appendUntilFinal(&r.MasterKDC, v, &masterKDCFinal)
		}
	}
	if len(r.KPasswdServer) < 1 {
		for _, a := range r.AdminServer {
			s := strings.Split(a, ":")
			r.KPasswdServer = append(r.KPasswdServer, s[0]+":464")
		}
	}
	return
}
Parse the lines of a [realms] entry into the Realm struct.
package config
import (
	"bufio"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net"
	"os"
	"os/user"
	"regexp"
	"strconv"
	"strings"
	"time"
	"github.com/jcmturner/gofork/encoding/asn1"
	"github.com/jcmturner/gokrb5/v8/iana/etypeID"
)
type Config struct {
	LibDefaults LibDefaults
	Realms      []Realm
	DomainRealm DomainRealm
}
const WeakETypeList = "des-cbc-crc des-cbc-md4 des-cbc-md5 des-cbc-raw des3-cbc-raw des-hmac-sha1 arcfour-hmac-exp rc4-hmac-exp arcfour-hmac-md5-exp des"
func New() *Config {
	d := make(DomainRealm)
	return &Config{
		LibDefaults: newLibDefaults(),
		DomainRealm: d,
	}
}
type LibDefaults struct {
	AllowWeakCrypto bool  
	Canonicalize bool           
	CCacheType   int            
	Clockskew    time.Duration  
	DefaultClientKeytabName string  
	DefaultKeytabName       string  
	DefaultRealm            string
	DefaultTGSEnctypes      []string  
	DefaultTktEnctypes      []string  
	DefaultTGSEnctypeIDs    []int32   
	DefaultTktEnctypeIDs    []int32   
	DNSCanonicalizeHostname bool      
	DNSLookupKDC            bool      
	DNSLookupRealm          bool
	ExtraAddresses          []net.IP        
	Forwardable             bool            
	IgnoreAcceptorHostname  bool            
	K5LoginAuthoritative    bool            
	K5LoginDirectory        string          
	KDCDefaultOptions       asn1.BitString  
	KDCTimeSync             int             
	NoAddresses         bool      
	PermittedEnctypes   []string  
	PermittedEnctypeIDs []int32
	PreferredPreauthTypes []int          
	Proxiable             bool           
	RDNS                  bool           
	RealmTryDomains       int            
	RenewLifetime         time.Duration  
	SafeChecksumType      int            
	TicketLifetime        time.Duration  
	UDPPreferenceLimit    int            
	VerifyAPReqNofail     bool           
}
func newLibDefaults() LibDefaults {
	uid := "0"
	var hdir string
	usr, _ := user.Current()
	if usr != nil {
		uid = usr.Uid
		hdir = usr.HomeDir
	}
	opts := asn1.BitString{}
	opts.Bytes, _ = hex.DecodeString("00000010")
	opts.BitLength = len(opts.Bytes) * 8
	return LibDefaults{
		CCacheType:              4,
		Clockskew:               time.Duration(300) * time.Second,
		DefaultClientKeytabName: fmt.Sprintf("/usr/local/var/krb5/user/%s/client.keytab", uid),
		DefaultKeytabName:       "/etc/krb5.keytab",
		DefaultTGSEnctypes:      []string{"aes256-cts-hmac-sha1-96", "aes128-cts-hmac-sha1-96", "des3-cbc-sha1", "arcfour-hmac-md5", "camellia256-cts-cmac", "camellia128-cts-cmac", "des-cbc-crc", "des-cbc-md5", "des-cbc-md4"},
		DefaultTktEnctypes:      []string{"aes256-cts-hmac-sha1-96", "aes128-cts-hmac-sha1-96", "des3-cbc-sha1", "arcfour-hmac-md5", "camellia256-cts-cmac", "camellia128-cts-cmac", "des-cbc-crc", "des-cbc-md5", "des-cbc-md4"},
		DNSCanonicalizeHostname: true,
		K5LoginDirectory:        hdir,
		KDCDefaultOptions:       opts,
		KDCTimeSync:             1,
		NoAddresses:             true,
		PermittedEnctypes:       []string{"aes256-cts-hmac-sha1-96", "aes128-cts-hmac-sha1-96", "des3-cbc-sha1", "arcfour-hmac-md5", "camellia256-cts-cmac", "camellia128-cts-cmac", "des-cbc-crc", "des-cbc-md5", "des-cbc-md4"},
		RDNS:                    true,
		RealmTryDomains:         -1,
		SafeChecksumType:        8,
		TicketLifetime:          time.Duration(24) * time.Hour,
		UDPPreferenceLimit:      1465,
		PreferredPreauthTypes:   []int{17, 16, 15, 14},
	}
}
func (l *LibDefaults) parseLines(lines []string) error {
	for _, line := range lines {
		if idx := strings.IndexAny(line, "#;"); idx != -1 {
			line = line[:idx]
		}
		line = strings.TrimSpace(line)
		if line == "" {
			continue
		}
		if !strings.Contains(line, "=") {
			return InvalidErrorf("libdefaults section line (%s)", line)
		}
		p := strings.Split(line, "=")
		key := strings.TrimSpace(strings.ToLower(p[0]))
		switch key {
		case "allow_weak_crypto":
			v, err := parseBoolean(p[1])
			if err != nil {
				return InvalidErrorf("libdefaults section line (%s): %v", line, err)
			}
			l.AllowWeakCrypto = v
		case "canonicalize":
			v, err := parseBoolean(p[1])
			if err != nil {
				return InvalidErrorf("libdefaults section line (%s): %v", line, err)
			}
			l.Canonicalize = v
		case "ccache_type":
			p[1] = strings.TrimSpace(p[1])
			v, err := strconv.ParseUint(p[1], 10, 32)
			if err != nil || v < 0 || v > 4 {
				return InvalidErrorf("libdefaults section line (%s)", line)
			}
			l.CCacheType = int(v)
		case "clockskew":
			d, err := parseDuration(p[1])
			if err != nil {
				return InvalidErrorf("libdefaults section line (%s): %v", line, err)
			}
			l.Clockskew = d
		case "default_client_keytab_name":
			l.DefaultClientKeytabName = strings.TrimSpace(p[1])
		case "default_keytab_name":
			l.DefaultKeytabName = strings.TrimSpace(p[1])
		case "default_realm":
			l.DefaultRealm = strings.TrimSpace(p[1])
		case "default_tgs_enctypes":
			l.DefaultTGSEnctypes = strings.Fields(p[1])
		case "default_tkt_enctypes":
			l.DefaultTktEnctypes = strings.Fields(p[1])
		case "dns_canonicalize_hostname":
			v, err := parseBoolean(p[1])
			if err != nil {
				return InvalidErrorf("libdefaults section line (%s): %v", line, err)
			}
			l.DNSCanonicalizeHostname = v
		case "dns_lookup_kdc":
			v, err := parseBoolean(p[1])
			if err != nil {
				return InvalidErrorf("libdefaults section line (%s): %v", line, err)
			}
			l.DNSLookupKDC = v
		case "dns_lookup_realm":
			v, err := parseBoolean(p[1])
			if err != nil {
				return InvalidErrorf("libdefaults section line (%s): %v", line, err)
			}
			l.DNSLookupRealm = v
		case "extra_addresses":
			ipStr := strings.TrimSpace(p[1])
			for _, ip := range strings.Split(ipStr, ",") {
				if eip := net.ParseIP(ip); eip != nil {
					l.ExtraAddresses = append(l.ExtraAddresses, eip)
				}
			}
		case "forwardable":
			v, err := parseBoolean(p[1])
			if err != nil {
				return InvalidErrorf("libdefaults section line (%s): %v", line, err)
			}
			l.Forwardable = v
		case "ignore_acceptor_hostname":
			v, err := parseBoolean(p[1])
			if err != nil {
				return InvalidErrorf("libdefaults section line (%s): %v", line, err)
			}
			l.IgnoreAcceptorHostname = v
		case "k5login_authoritative":
			v, err := parseBoolean(p[1])
			if err != nil {
				return InvalidErrorf("libdefaults section line (%s): %v", line, err)
			}
			l.K5LoginAuthoritative = v
		case "k5login_directory":
			l.K5LoginDirectory = strings.TrimSpace(p[1])
		case "kdc_default_options":
			v := strings.TrimSpace(p[1])
			v = strings.Replace(v, "0x", "", -1)
			b, err := hex.DecodeString(v)
			if err != nil {
				return InvalidErrorf("libdefaults section line (%s): %v", line, err)
			}
			l.KDCDefaultOptions.Bytes = b
			l.KDCDefaultOptions.BitLength = len(b) * 8
		case "kdc_timesync":
			p[1] = strings.TrimSpace(p[1])
			v, err := strconv.ParseInt(p[1], 10, 32)
			if err != nil || v < 0 {
				return InvalidErrorf("libdefaults section line (%s)", line)
			}
			l.KDCTimeSync = int(v)
		case "noaddresses":
			v, err := parseBoolean(p[1])
			if err != nil {
				return InvalidErrorf("libdefaults section line (%s): %v", line, err)
			}
			l.NoAddresses = v
		case "permitted_enctypes":
			l.PermittedEnctypes = strings.Fields(p[1])
		case "preferred_preauth_types":
			p[1] = strings.TrimSpace(p[1])
			t := strings.Split(p[1], ",")
			var v []int
			for _, s := range t {
				i, err := strconv.ParseInt(s, 10, 32)
				if err != nil {
					return InvalidErrorf("libdefaults section line (%s): %v", line, err)
				}
				v = append(v, int(i))
			}
			l.PreferredPreauthTypes = v
		case "proxiable":
			v, err := parseBoolean(p[1])
			if err != nil {
				return InvalidErrorf("libdefaults section line (%s): %v", line, err)
			}
			l.Proxiable = v
		case "rdns":
			v, err := parseBoolean(p[1])
			if err != nil {
				return InvalidErrorf("libdefaults section line (%s): %v", line, err)
			}
			l.RDNS = v
		case "realm_try_domains":
			p[1] = strings.TrimSpace(p[1])
			v, err := strconv.ParseInt(p[1], 10, 32)
			if err != nil || v < -1 {
				return InvalidErrorf("libdefaults section line (%s)", line)
			}
			l.RealmTryDomains = int(v)
		case "renew_lifetime":
			d, err := parseDuration(p[1])
			if err != nil {
				return InvalidErrorf("libdefaults section line (%s): %v", line, err)
			}
			l.RenewLifetime = d
		case "safe_checksum_type":
			p[1] = strings.TrimSpace(p[1])
			v, err := strconv.ParseInt(p[1], 10, 32)
			if err != nil || v < 0 {
				return InvalidErrorf("libdefaults section line (%s)", line)
			}
			l.SafeChecksumType = int(v)
		case "ticket_lifetime":
			d, err := parseDuration(p[1])
			if err != nil {
				return InvalidErrorf("libdefaults section line (%s): %v", line, err)
			}
			l.TicketLifetime = d
		case "udp_preference_limit":
			p[1] = strings.TrimSpace(p[1])
			v, err := strconv.ParseUint(p[1], 10, 32)
			if err != nil || v > 32700 {
				return InvalidErrorf("libdefaults section line (%s)", line)
			}
			l.UDPPreferenceLimit = int(v)
		case "verify_ap_req_nofail":
			v, err := parseBoolean(p[1])
			if err != nil {
				return InvalidErrorf("libdefaults section line (%s): %v", line, err)
			}
			l.VerifyAPReqNofail = v
		}
	}
	l.DefaultTGSEnctypeIDs = parseETypes(l.DefaultTGSEnctypes, l.AllowWeakCrypto)
	l.DefaultTktEnctypeIDs = parseETypes(l.DefaultTktEnctypes, l.AllowWeakCrypto)
	l.PermittedEnctypeIDs = parseETypes(l.PermittedEnctypes, l.AllowWeakCrypto)
	return nil
}
type Realm struct {
	Realm       string
	AdminServer []string
	DefaultDomain string
	KDC           []string
	KPasswdServer []string  
	MasterKDC     []string
}