github.com/iDigitalFlame/xmt@v0.5.4/c2/cfg/convert.go (about)

     1  // Copyright (C) 2020 - 2023 iDigitalFlame
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU General Public License as published by
     5  // the Free Software Foundation, either version 3 of the License, or
     6  // any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU General Public License
    14  // along with this program.  If not, see <https://www.gnu.org/licenses/>.
    15  //
    16  
    17  package cfg
    18  
    19  import (
    20  	"sort"
    21  	"time"
    22  
    23  	"github.com/iDigitalFlame/xmt/c2/transform"
    24  	"github.com/iDigitalFlame/xmt/c2/wrapper"
    25  	"github.com/iDigitalFlame/xmt/com"
    26  	"github.com/iDigitalFlame/xmt/com/pipe"
    27  	"github.com/iDigitalFlame/xmt/com/wc2"
    28  	"github.com/iDigitalFlame/xmt/data/crypto"
    29  	"github.com/iDigitalFlame/xmt/util/text"
    30  	"github.com/iDigitalFlame/xmt/util/xerr"
    31  )
    32  
    33  func (c Config) next(i int) int {
    34  	if i > len(c) || i < 0 {
    35  		return -1
    36  	}
    37  	switch cBit(c[i]) {
    38  	case WrapHex, WrapZlib, WrapGzip, WrapBase64:
    39  		fallthrough
    40  	case SelectorLastValid, SelectorRoundRobin, SelectorRandom, SelectorSemiRandom, SelectorSemiRoundRobin:
    41  		fallthrough
    42  	case Separator, ConnectTCP, ConnectTLS, ConnectUDP, ConnectICMP, ConnectPipe, ConnectTLSNoVerify, TransformB64:
    43  		return i + 1
    44  	case valIP, valB64Shift, valJitter, valWeight, valTLSx:
    45  		return i + 2
    46  	case valCBK, valWorkHours:
    47  		return i + 6
    48  	case valSleep, valKillDate:
    49  		return i + 9
    50  	case valKeyPin:
    51  		return i + 5
    52  	case valWC2:
    53  		if i+7 >= len(c) {
    54  			return -1
    55  		}
    56  		_ = c[i+7]
    57  		n := i + 8 + (int(c[i+2]) | int(c[i+1])<<8) + (int(c[i+4]) | int(c[i+3])<<8) + (int(c[i+6]) | int(c[i+5])<<8)
    58  		if n >= len(c) {
    59  			return -1
    60  		}
    61  		if _ = c[n]; c[i+7] == 0 {
    62  			return n
    63  		}
    64  		for x := int(c[i+7]); x > 0 && n < len(c) && n > 0; x-- {
    65  			n += int(c[n]) + int(c[n+1]) + 2
    66  		}
    67  		return n
    68  	case valXOR, valHost:
    69  		if i+3 >= len(c) {
    70  			return -1
    71  		}
    72  		_ = c[i+2]
    73  		return i + 3 + int(c[i+2]) | int(c[i+1])<<8
    74  	case valAES:
    75  		if i+3 >= len(c) {
    76  			return -1
    77  		}
    78  		_ = c[i+2]
    79  		return i + 3 + int(c[i+1]) + int(c[i+2])
    80  	case valMuTLS:
    81  		if i+7 >= len(c) {
    82  			return -1
    83  		}
    84  		_ = c[i+7]
    85  		return i + 8 + (int(c[i+3]) | int(c[i+2])<<8) + (int(c[i+5]) | int(c[i+4])<<8) + (int(c[i+7]) | int(c[i+6])<<8)
    86  	case valTLSxCA:
    87  		if i+4 >= len(c) {
    88  			return -1
    89  		}
    90  		_ = c[i+3]
    91  		return i + 4 + int(c[i+3]) | int(c[i+2])<<8
    92  	case valTLSCert:
    93  		if i+6 >= len(c) {
    94  			return -1
    95  		}
    96  		_ = c[i+4]
    97  		return i + 6 + (int(c[i+3]) | int(c[i+2])<<8) + (int(c[i+5]) | int(c[i+4])<<8)
    98  	case valDNS:
    99  		if i+1 >= len(c) {
   100  			return -1
   101  		}
   102  		_ = c[i+1]
   103  		n := i + 2
   104  		for x := int(c[i+1]); x > 0 && n < len(c); x-- {
   105  			n += int(c[n]) + 1
   106  		}
   107  		return n
   108  	}
   109  	return -1
   110  }
   111  
   112  // Validate is similar to the 'Build' function but will instead only validate
   113  // that the supplied Config will build into a Profile without returning an
   114  // error. The error returned (if not nil) will be the same as the error returned
   115  // during a Build call.
   116  //
   117  // This function will return an 'ErrInvalidSetting' if any value in this Config
   118  // instance is invalid or 'ErrMultipleConnections' if more than one connection
   119  // is contained in this Config.
   120  //
   121  // The similar error 'ErrMultipleTransforms' is similar to 'ErrMultipleConnections'
   122  // but applies to Transforms, if more than one Transform is contained.
   123  //
   124  // Multiple 'c2.Wrapper' instances will be combined into a 'c2.MultiWrapper' in
   125  // the order they are found.
   126  //
   127  // Other functions that may return errors on creation, like encryption wrappers
   128  // for example, will stop the build process and will return that wrapped error.
   129  func (c Config) Validate() error {
   130  	if len(c) == 0 {
   131  		return nil
   132  	}
   133  	var (
   134  		n   int
   135  		err error
   136  	)
   137  	for i := 0; i < len(c); i = n {
   138  		if n, err = c.validate(i); err != nil {
   139  			return err
   140  		}
   141  		if n-i == 1 && c[i] == byte(Separator) {
   142  			continue
   143  		}
   144  	}
   145  	return nil
   146  }
   147  
   148  // Build will attempt to generate a 'c2.Profile' interface from this Config
   149  // instance.
   150  //
   151  // This function will return an 'ErrInvalidSetting' if any value in this Config
   152  // instance is invalid or 'ErrMultipleConnections' if more than one connection
   153  // is contained in this Config.
   154  //
   155  // The similar error 'ErrMultipleTransforms' is similar to 'ErrMultipleConnections'
   156  // but applies to Transforms, if more than one Transform is contained.
   157  //
   158  // Multiple 'c2.Wrapper' instances will be combined into a 'c2.MultiWrapper' in
   159  // the order they are found.
   160  //
   161  // Other functions that may return errors on creation, like encryption wrappers
   162  // for example, will stop the build process and will return that wrapped error.
   163  func (c Config) Build() (Profile, error) {
   164  	if len(c) == 0 {
   165  		return nil, nil
   166  	}
   167  	var (
   168  		e   []*profile
   169  		n   int
   170  		v   *profile
   171  		s   int8
   172  		g   uint8
   173  		err error
   174  	)
   175  	for i := 0; i < len(c); i = n {
   176  		if v, n, s, err = c.build(i); err != nil {
   177  			return nil, err
   178  		}
   179  		if v == nil || (n-i == 1 && c[i] == byte(Separator)) {
   180  			continue
   181  		}
   182  		if e = append(e, v); s >= 0 {
   183  			g = uint8(s)
   184  		}
   185  		v = nil
   186  	}
   187  	if len(e) == 0 {
   188  		return nil, nil
   189  	}
   190  	if len(e) == 1 {
   191  		e[0].src = c
   192  		return e[0], nil
   193  	}
   194  	r := &Group{sel: g, entries: e, src: c}
   195  	sort.Sort(r)
   196  	return r, nil
   197  }
   198  func (c Config) validate(x int) (int, error) {
   199  	var (
   200  		n    int
   201  		p, t bool
   202  	)
   203  loop:
   204  	for i := x; n >= 0 && n < len(c); i = n {
   205  		if n = c.next(i); n == i || n > len(c) || n == -1 || n < i {
   206  			n = len(c)
   207  		}
   208  		switch _ = c[n-1]; cBit(c[i]) {
   209  		case Separator:
   210  			break loop
   211  		case invalid:
   212  			return -1, ErrInvalidSetting
   213  		case valHost:
   214  			if i+3 >= n {
   215  				return -1, xerr.Wrap("host", ErrInvalidSetting)
   216  			}
   217  			if v := (int(c[i+2]) | int(c[i+1])<<8) + i; v > n || v < i {
   218  				return -1, xerr.Wrap("host", ErrInvalidSetting)
   219  			}
   220  		case valSleep:
   221  			if i+8 >= n {
   222  				return -1, xerr.Wrap("sleep", ErrInvalidSetting)
   223  			}
   224  		case valKeyPin:
   225  			if i+4 >= n {
   226  				return -1, xerr.Wrap("keypin", ErrInvalidSetting)
   227  			}
   228  		case valJitter:
   229  			if i+1 >= n {
   230  				return -1, xerr.Wrap("jitter", ErrInvalidSetting)
   231  			}
   232  		case valWeight:
   233  			if i+1 >= n {
   234  				return -1, xerr.Wrap("weight", ErrInvalidSetting)
   235  			}
   236  		case valKillDate:
   237  			if i+8 >= n {
   238  				return -1, xerr.Wrap("killdate", ErrInvalidSetting)
   239  			}
   240  		case valWorkHours:
   241  			if i+5 >= n {
   242  				return -1, xerr.Wrap("workhours", ErrInvalidSetting)
   243  			}
   244  			if c[i+2] > 23 || c[i+3] > 59 || c[i+4] > 23 || c[i+5] > 59 {
   245  				return -1, xerr.Wrap("workhours", ErrInvalidSetting)
   246  			}
   247  		case SelectorRoundRobin, SelectorLastValid, SelectorRandom, SelectorSemiRandom, SelectorSemiRoundRobin:
   248  		case ConnectTCP, ConnectTLS, ConnectUDP, ConnectICMP, ConnectPipe, ConnectTLSNoVerify:
   249  			if p {
   250  				return -1, ErrMultipleConnections
   251  			}
   252  			p = true
   253  		case valIP:
   254  			if p {
   255  				return -1, xerr.Wrap("ip", ErrMultipleConnections)
   256  			}
   257  			if p = true; i+1 >= n {
   258  				return -1, xerr.Wrap("ip", ErrInvalidSetting)
   259  			}
   260  			if c[i+1] == 0 {
   261  				return -1, xerr.Wrap("ip", ErrInvalidSetting)
   262  			}
   263  		case valWC2:
   264  			if p {
   265  				return -1, xerr.Wrap("wc2", ErrMultipleConnections)
   266  			}
   267  			if p = true; i+7 >= n {
   268  				return -1, xerr.Wrap("wc2", ErrInvalidSetting)
   269  			}
   270  			v, q := (int(c[i+2])|int(c[i+1])<<8)+i+8, i+8
   271  			if v > n || q > n || q < i || v < i {
   272  				return -1, xerr.Wrap("wc2", ErrInvalidSetting)
   273  			}
   274  			if v, q = (int(c[i+4])|int(c[i+3])<<8)+v, v; v > n || q > n || v < q || q < i || v < i {
   275  				return -1, xerr.Wrap("wc2", ErrInvalidSetting)
   276  			}
   277  			if v, q = (int(c[i+6])|int(c[i+5])<<8)+v, v; v > n || q > n || v < q || q < i || v < i {
   278  				return -1, xerr.Wrap("wc2", ErrInvalidSetting)
   279  			}
   280  			if c[i+7] > 0 {
   281  				for j := 0; v < n && q < n && j < n; {
   282  					q, j = v+2, int(c[v])+v+2
   283  					if v = int(c[v+1]) + j; q == j || j > n || q > n || v > n || v < j || j < q || q < i || j < i || v < i {
   284  						return -1, xerr.Wrap("wc2", ErrInvalidSetting)
   285  					}
   286  				}
   287  			}
   288  		case valTLSx:
   289  			if p {
   290  				return -1, xerr.Wrap("tls-ex", ErrMultipleConnections)
   291  			}
   292  			if p = true; i+1 >= n {
   293  				return -1, xerr.Wrap("tls-ex", ErrInvalidSetting)
   294  			}
   295  		case valMuTLS:
   296  			if p {
   297  				return -1, xerr.Wrap("mtls", ErrMultipleConnections)
   298  			}
   299  			if p = true; i+7 >= n {
   300  				return -1, xerr.Wrap("mtls", ErrInvalidSetting)
   301  			}
   302  			var (
   303  				a = (int(c[i+3]) | int(c[i+2])<<8) + i + 8
   304  				b = (int(c[i+5]) | int(c[i+4])<<8) + a
   305  				k = (int(c[i+7]) | int(c[i+6])<<8) + b
   306  			)
   307  			if a > n || b > n || k > n || b < a || k < b || a < i || b < i || k < i {
   308  				return -1, xerr.Wrap("mtls", ErrInvalidSetting)
   309  			}
   310  		case valTLSxCA:
   311  			if p {
   312  				return -1, xerr.Wrap("tls-ca", ErrMultipleConnections)
   313  			}
   314  			if p = true; i+4 >= n {
   315  				return -1, xerr.Wrap("tls-ca", ErrInvalidSetting)
   316  			}
   317  			if a := (int(c[i+3]) | int(c[i+2])<<8) + i + 4; a > n || a < i {
   318  				return -1, xerr.Wrap("tls-ca", ErrInvalidSetting)
   319  			}
   320  		case valTLSCert:
   321  			if p {
   322  				return -1, xerr.Wrap("tls-cert", ErrMultipleConnections)
   323  			}
   324  			if p = true; i+6 >= n {
   325  				return -1, xerr.Wrap("tls-cert", ErrInvalidSetting)
   326  			}
   327  			var (
   328  				b = (int(c[i+3]) | int(c[i+2])<<8) + i + 6
   329  				k = (int(c[i+5]) | int(c[i+4])<<8) + b
   330  			)
   331  			if b > n || k > n || b < i || k < i || k < b {
   332  				return -1, xerr.Wrap("tls-cert", ErrInvalidSetting)
   333  			}
   334  		case WrapHex, WrapZlib, WrapGzip, WrapBase64:
   335  		case valXOR:
   336  			if i+3 >= n {
   337  				return -1, xerr.Wrap("xor", ErrInvalidSetting)
   338  			}
   339  			if k := (int(c[i+2]) | int(c[i+1])<<8) + i; k > n || k < i {
   340  				return -1, xerr.Wrap("xor", ErrInvalidSetting)
   341  			}
   342  		case valCBK:
   343  			if i+5 >= n {
   344  				return -1, xerr.Wrap("cbk", ErrInvalidSetting)
   345  			}
   346  		case valAES:
   347  			if i+3 >= n {
   348  				return -1, xerr.Wrap("aes", ErrInvalidSetting)
   349  			}
   350  			var (
   351  				v = int(c[i+1]) + i + 3
   352  				z = int(c[i+2]) + v
   353  			)
   354  			if v == z || i+3 == v || z > n || v > n || z < i || v < i || z < v {
   355  				return -1, xerr.Wrap("aes", ErrInvalidSetting)
   356  			}
   357  			switch v - (i + 3) {
   358  			case 16, 24, 32:
   359  			default:
   360  				return -1, xerr.Wrap("aes", ErrInvalidSetting)
   361  			}
   362  			if z-v != 16 {
   363  				return -1, xerr.Wrap("aes", ErrInvalidSetting)
   364  			}
   365  		case TransformB64:
   366  			if t {
   367  				return -1, xerr.Wrap("base64T", ErrMultipleTransforms)
   368  			}
   369  			t = true
   370  		case valDNS:
   371  			if t {
   372  				return -1, xerr.Wrap("dns", ErrMultipleTransforms)
   373  			}
   374  			if t = true; i+1 >= n {
   375  				return -1, xerr.Wrap("dns", ErrInvalidSetting)
   376  			}
   377  			for x, v, e := int(c[i+1]), i+2, i+2; x > 0 && v < n; x-- {
   378  				if v += int(c[v]) + 1; e+1 > v || e+1 == v || v < e || v > n || e > n || x > n || e < i || v < i || x < i {
   379  					return -1, xerr.Wrap("dns", ErrInvalidSetting)
   380  				}
   381  				e = v
   382  			}
   383  		case valB64Shift:
   384  			if t {
   385  				return -1, xerr.Wrap("b64S", ErrMultipleTransforms)
   386  			}
   387  			if t = true; i+1 >= n {
   388  				return -1, xerr.Wrap("b64S", ErrInvalidSetting)
   389  			}
   390  		default:
   391  			return -1, ErrInvalidSetting
   392  		}
   393  	}
   394  	return n, nil
   395  }
   396  func (c Config) build(x int) (*profile, int, int8, error) {
   397  	var (
   398  		p profile
   399  		n int
   400  		z int8 = -1
   401  		w      = make([]Wrapper, 0, 4)
   402  	)
   403  loop:
   404  	for i := x; n >= 0 && n < len(c); i = n {
   405  		if n = c.next(i); n == i || n > len(c) || n == -1 || n < i {
   406  			n = len(c)
   407  		}
   408  		switch _ = c[n-1]; cBit(c[i]) {
   409  		case Separator:
   410  			break loop
   411  		case invalid:
   412  			return nil, -1, -1, ErrInvalidSetting
   413  		case valHost:
   414  			if i+3 >= n {
   415  				return nil, -1, -1, xerr.Wrap("host", ErrInvalidSetting)
   416  			}
   417  			v := (int(c[i+2]) | int(c[i+1])<<8) + i
   418  			if v > n || v < i {
   419  				return nil, -1, -1, xerr.Wrap("host", ErrInvalidSetting)
   420  			}
   421  			p.hosts = append(p.hosts, string(c[i+3:v+3]))
   422  		case valSleep:
   423  			if i+8 >= n {
   424  				return nil, -1, -1, xerr.Wrap("sleep", ErrInvalidSetting)
   425  			}
   426  			p.sleep = time.Duration(
   427  				uint64(c[i+8]) | uint64(c[i+7])<<8 | uint64(c[i+6])<<16 | uint64(c[i+5])<<24 |
   428  					uint64(c[i+4])<<32 | uint64(c[i+3])<<40 | uint64(c[i+2])<<48 | uint64(c[i+1])<<56,
   429  			)
   430  			if p.sleep < 0 {
   431  				p.sleep = DefaultSleep
   432  			}
   433  		case valJitter:
   434  			if i+1 >= n {
   435  				return nil, -1, -1, xerr.Wrap("jitter", ErrInvalidSetting)
   436  			}
   437  			if p.jitter = int8(c[i+1]); p.jitter > 100 {
   438  				p.jitter = 100
   439  			} else if p.jitter < -1 {
   440  				p.jitter = 0
   441  			}
   442  		case valKeyPin:
   443  			if i+4 >= n {
   444  				return nil, -1, -1, xerr.Wrap("keypin", ErrInvalidSetting)
   445  			}
   446  			p.keys = append(p.keys, uint32(c[i+4])|uint32(c[i+3])<<8|uint32(c[i+2])<<16|uint32(c[i+1])<<24)
   447  		case valWeight:
   448  			if i+1 >= n {
   449  				return nil, -1, -1, xerr.Wrap("weight", ErrInvalidSetting)
   450  			}
   451  			if p.weight = c[i+1]; p.weight > 100 {
   452  				p.weight = 100
   453  			}
   454  		case valKillDate:
   455  			if i+8 >= n {
   456  				return nil, -1, -1, xerr.Wrap("killdate", ErrInvalidSetting)
   457  			}
   458  			u := uint64(c[i+8]) | uint64(c[i+7])<<8 | uint64(c[i+6])<<16 | uint64(c[i+5])<<24 |
   459  				uint64(c[i+4])<<32 | uint64(c[i+3])<<40 | uint64(c[i+2])<<48 | uint64(c[i+1])<<56
   460  			if u == 0 {
   461  				p.kds, p.kill = true, time.Time{}
   462  			} else {
   463  				p.kds, p.kill = true, time.Unix(int64(u), 0)
   464  			}
   465  		case valWorkHours:
   466  			if i+5 >= n {
   467  				return nil, -1, -1, xerr.Wrap("workhours", ErrInvalidSetting)
   468  			}
   469  			if c[i+2] > 23 || c[i+3] > 59 || c[i+4] > 23 || c[i+5] > 59 {
   470  				return nil, -1, -1, xerr.Wrap("workhours", ErrInvalidSetting)
   471  			}
   472  			if c[i+1] == 0 && c[i+2] == 0 && c[i+3] == 0 && c[i+4] == 0 && c[i+5] == 0 {
   473  				p.work = &WorkHours{}
   474  			} else {
   475  				p.work = &WorkHours{Days: c[i+1], StartHour: c[i+2], StartMin: c[i+3], EndHour: c[i+4], EndMin: c[i+5]}
   476  			}
   477  		case SelectorRandom, SelectorRoundRobin, SelectorLastValid, SelectorSemiRandom, SelectorSemiRoundRobin:
   478  			z = int8(c[i] - byte(SelectorLastValid))
   479  		case ConnectTCP:
   480  			if p.conn != nil {
   481  				return nil, -1, -1, xerr.Wrap("tcp", ErrMultipleConnections)
   482  			}
   483  			p.conn = com.TCP
   484  		case ConnectTLS:
   485  			if p.conn != nil {
   486  				return nil, -1, -1, xerr.Wrap("tls", ErrMultipleConnections)
   487  			}
   488  			p.conn = com.TLS
   489  		case ConnectUDP:
   490  			if p.conn != nil {
   491  				return nil, -1, -1, xerr.Wrap("udp", ErrMultipleConnections)
   492  			}
   493  			p.conn = com.UDP
   494  		case ConnectICMP:
   495  			if p.conn != nil {
   496  				return nil, -1, -1, xerr.Wrap("icmp", ErrMultipleConnections)
   497  			}
   498  			p.conn = com.ICMP
   499  		case ConnectPipe:
   500  			if p.conn != nil {
   501  				return nil, -1, -1, xerr.Wrap("pipe", ErrMultipleConnections)
   502  			}
   503  			p.conn = pipe.Pipe
   504  		case ConnectTLSNoVerify:
   505  			if p.conn != nil {
   506  				return nil, -1, -1, xerr.Wrap("tls-insecure", ErrMultipleConnections)
   507  			}
   508  			p.conn = com.TLSInsecure
   509  		case valIP:
   510  			if p.conn != nil {
   511  				return nil, -1, -1, xerr.Wrap("ip", ErrMultipleConnections)
   512  			}
   513  			if i+1 >= n {
   514  				return nil, -1, -1, xerr.Wrap("ip", ErrInvalidSetting)
   515  			}
   516  			if c[i+1] == 0 {
   517  				return nil, -1, -1, xerr.Wrap("ip", ErrInvalidSetting)
   518  			}
   519  			p.conn = com.NewIP(com.DefaultTimeout, c[i+1])
   520  		case valWC2:
   521  			if p.conn != nil {
   522  				return nil, -1, -1, xerr.Wrap("wc2", ErrMultipleConnections)
   523  			}
   524  			if i+7 >= n {
   525  				return nil, -1, -1, xerr.Wrap("wc2", ErrInvalidSetting)
   526  			}
   527  			var (
   528  				v, q = (int(c[i+2]) | int(c[i+1])<<8) + i + 8, i + 8
   529  				t    wc2.Target
   530  			)
   531  			if v > n || q > n || q < i || v < i {
   532  				return nil, -1, -1, xerr.Wrap("wc2", ErrInvalidSetting)
   533  			}
   534  			if v > q {
   535  				t.URL = text.Matcher(c[q:v])
   536  			}
   537  			if v, q = (int(c[i+4])|int(c[i+3])<<8)+v, v; v > q {
   538  				if v > n || q > n || v < q || q < i || v < i {
   539  					return nil, -1, -1, xerr.Wrap("wc2", ErrInvalidSetting)
   540  				}
   541  				t.Host = text.Matcher(c[q:v])
   542  			}
   543  			if v, q = (int(c[i+6])|int(c[i+5])<<8)+v, v; v > q {
   544  				if v > n || q > n || v < q || q < i || v < i {
   545  					return nil, -1, -1, xerr.Wrap("wc2", ErrInvalidSetting)
   546  				}
   547  				t.Agent = text.Matcher(c[q:v])
   548  			}
   549  			if c[i+7] > 0 {
   550  				t.Headers = make(map[string]wc2.Stringer, c[i+7])
   551  				for j := 0; v < n && q < n && j < n; {
   552  					q, j = v+2, int(c[v])+v+2
   553  					if v = int(c[v+1]) + j; q == j || q > n || j > n || v > n || v < j || j < q || q < i || j < i || v < i {
   554  						return nil, -1, -1, xerr.Wrap("wc2", ErrInvalidSetting)
   555  					}
   556  					t.Header(string(c[q:j]), text.Matcher(c[j:v]))
   557  				}
   558  			}
   559  			p.conn = wc2.NewClient(com.DefaultTimeout, &t)
   560  		case valTLSx:
   561  			if p.conn != nil {
   562  				return nil, -1, -1, xerr.Wrap("tls-ex", ErrMultipleConnections)
   563  			}
   564  			if i+1 >= n {
   565  				return nil, -1, -1, xerr.Wrap("tls-ex", ErrInvalidSetting)
   566  			}
   567  			t, err := com.NewTLSConfig(false, uint16(c[i+1]), nil, nil, nil)
   568  			if err != nil {
   569  				return nil, -1, -1, xerr.Wrap("tls-ex", err)
   570  			}
   571  			p.conn = com.NewTLS(com.DefaultTimeout, t)
   572  		case valMuTLS:
   573  			if p.conn != nil {
   574  				return nil, -1, -1, xerr.Wrap("mtls", ErrMultipleConnections)
   575  			}
   576  			if i+7 >= n {
   577  				return nil, -1, -1, xerr.Wrap("mtls", ErrInvalidSetting)
   578  			}
   579  			var (
   580  				a = (int(c[i+3]) | int(c[i+2])<<8) + i + 8
   581  				b = (int(c[i+5]) | int(c[i+4])<<8) + a
   582  				k = (int(c[i+7]) | int(c[i+6])<<8) + b
   583  			)
   584  			if a > n || b > n || k > n || b < a || k < b || a < i || b < i || k < i {
   585  				return nil, -1, -1, xerr.Wrap("mtls", ErrInvalidSetting)
   586  			}
   587  			t, err := com.NewTLSConfig(true, uint16(c[i+1]), c[i+8:a], c[a:b], c[b:k])
   588  			if err != nil {
   589  				return nil, -1, -1, xerr.Wrap("mtls", err)
   590  			}
   591  			p.conn = com.NewTLS(com.DefaultTimeout, t)
   592  		case valTLSxCA:
   593  			if p.conn != nil {
   594  				return nil, -1, -1, xerr.Wrap("tls-ca", ErrMultipleConnections)
   595  			}
   596  			if i+4 >= n {
   597  				return nil, -1, -1, xerr.Wrap("tls-ca", ErrInvalidSetting)
   598  			}
   599  			a := (int(c[i+3]) | int(c[i+2])<<8) + i + 4
   600  			if a > n || a < i {
   601  				return nil, -1, -1, xerr.Wrap("tls-ca", ErrInvalidSetting)
   602  			}
   603  			t, err := com.NewTLSConfig(false, uint16(c[i+1]), c[i+4:a], nil, nil)
   604  			if err != nil {
   605  				return nil, -1, -1, xerr.Wrap("tls-ca", err)
   606  			}
   607  			p.conn = com.NewTLS(com.DefaultTimeout, t)
   608  		case valTLSCert:
   609  			if p.conn != nil {
   610  				return nil, -1, -1, xerr.Wrap("tls-cert", ErrMultipleConnections)
   611  			}
   612  			if i+6 >= n {
   613  				return nil, -1, -1, xerr.Wrap("tls-cert", ErrInvalidSetting)
   614  			}
   615  			var (
   616  				b = (int(c[i+3]) | int(c[i+2])<<8) + i + 6
   617  				k = (int(c[i+5]) | int(c[i+4])<<8) + b
   618  			)
   619  			if b > n || k > n || b < i || k < i || k < b {
   620  				return nil, -1, -1, xerr.Wrap("tls-cert", ErrInvalidSetting)
   621  			}
   622  			t, err := com.NewTLSConfig(true, uint16(c[i+1]), nil, c[i+6:b], c[b:k])
   623  			if err != nil {
   624  				return nil, -1, -1, xerr.Wrap("tls-cert", err)
   625  			}
   626  			p.conn = com.NewTLS(com.DefaultTimeout, t)
   627  		case WrapHex:
   628  			w = append(w, wrapper.Hex)
   629  		case WrapZlib:
   630  			w = append(w, wrapper.Zlib)
   631  		case WrapGzip:
   632  			w = append(w, wrapper.Gzip)
   633  		case WrapBase64:
   634  			w = append(w, wrapper.Base64)
   635  		case valXOR:
   636  			if i+3 >= n {
   637  				return nil, -1, -1, xerr.Wrap("xor", ErrInvalidSetting)
   638  			}
   639  			k := (int(c[i+2]) | int(c[i+1])<<8) + i
   640  			if k > n || k < i {
   641  				return nil, -1, -1, xerr.Wrap("xor", ErrInvalidSetting)
   642  			}
   643  			w = append(w, wrapper.NewXOR(c[i+3:k+3]))
   644  		case valCBK:
   645  			if i+5 >= n {
   646  				return nil, -1, -1, xerr.Wrap("cbk", ErrInvalidSetting)
   647  			}
   648  			w = append(w, wrapper.NewCBK(c[i+2], c[i+3], c[i+4], c[i+5], c[i+1]))
   649  		case valAES:
   650  			if i+3 >= n {
   651  				return nil, -1, -1, xerr.Wrap("aes", ErrInvalidSetting)
   652  			}
   653  			var (
   654  				v = int(c[i+1]) + i + 3
   655  				z = int(c[i+2]) + v
   656  			)
   657  			if v == z || i+3 == v || v > n || z > n || z < i || v < i || z < v {
   658  				return nil, -1, -1, xerr.Wrap("aes", ErrInvalidSetting)
   659  			}
   660  			b, err := crypto.NewAes(c[i+3 : v])
   661  			if err != nil {
   662  				return nil, -1, -1, xerr.Wrap("aes", err)
   663  			}
   664  			u, err := wrapper.NewBlock(b, c[v:z])
   665  			if err != nil {
   666  				return nil, -1, -1, xerr.Wrap("aes", err)
   667  			}
   668  			w = append(w, u)
   669  		case TransformB64:
   670  			if p.t != nil {
   671  				return nil, -1, -1, xerr.Wrap("base64T", ErrMultipleTransforms)
   672  			}
   673  			p.t = transform.Base64
   674  		case valDNS:
   675  			if p.t != nil {
   676  				return nil, -1, -1, xerr.Wrap("dns", ErrMultipleTransforms)
   677  			}
   678  			if i+1 >= n {
   679  				return nil, -1, -1, xerr.Wrap("dns", ErrInvalidSetting)
   680  			}
   681  			_ = c[i+1]
   682  			d := make(transform.DNSTransform, 0, c[i+1])
   683  			for x, v, e := int(c[i+1]), i+2, i+2; x > 0 && v < n; x-- {
   684  				if v += int(c[v]) + 1; e+1 > v || e+1 == v || v < e || v > n || e > n || x > n || e < i || v < i || x < i {
   685  					return nil, -1, -1, xerr.Wrap("dns", ErrInvalidSetting)
   686  				}
   687  				d = append(d, string(c[e+1:v]))
   688  				e = v
   689  			}
   690  			p.t = d
   691  		case valB64Shift:
   692  			if p.t != nil {
   693  				return nil, -1, -1, xerr.Wrap("b64S", ErrMultipleTransforms)
   694  			}
   695  			if i+1 >= n {
   696  				return nil, -1, -1, xerr.Wrap("b64S", ErrInvalidSetting)
   697  			}
   698  			p.t = transform.B64(c[i+1])
   699  		default:
   700  			return nil, -1, -1, ErrInvalidSetting
   701  		}
   702  	}
   703  	if len(w) > 1 {
   704  		p.w = MultiWrapper(w)
   705  	} else if len(w) == 1 {
   706  		p.w = w[0]
   707  	}
   708  	return &p, n, z, nil
   709  }